diff --git a/.github/actions/deps/external/action.yml b/.github/actions/deps/external/action.yml index 5db7c04686..9e32e733a2 100644 --- a/.github/actions/deps/external/action.yml +++ b/.github/actions/deps/external/action.yml @@ -9,54 +9,31 @@ inputs: - cache - restore - platform: + port: required: false default: none - type: choice - options: - - arm - - aarch - - esp - - riscv - - none + type: string runs: using: composite steps: - # aarch - - name: Get aarch toolchain - if: inputs.platform == 'aarch' - 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 - sudo apt-get install -y mtools - shell: bash - - name: Install mkfs.fat - if: inputs.platform == 'aarch' - run: | - wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz - tar -xaf dosfstools-4.2.tar.gz - cd dosfstools-4.2 - ./configure - make -j 2 - cd src - echo >> $GITHUB_PATH $(pwd) - shell: bash - # arm - name: Get arm toolchain - if: inputs.platform == 'aarch' || inputs.platform == 'arm' + if: >- + inputs.port != 'none' && + inputs.port != 'litex' && + inputs.port != 'espressif' uses: carlosperate/arm-none-eabi-gcc-action@v1 with: release: '10-2020-q4' - # esp - - name: Get esp toolchain - if: inputs.platform == 'esp' + # espressif + - name: Get espressif toolchain + if: inputs.port == 'espressif' run: sudo apt-get install -y ninja-build shell: bash - name: Install IDF tools - if: inputs.platform == 'esp' + if: inputs.port == 'espressif' run: | echo "Installing ESP-IDF tools" $IDF_PATH/tools/idf_tools.py --non-interactive install required @@ -66,24 +43,16 @@ runs: rm -rf $IDF_TOOLS_PATH/dist shell: bash - name: Set environment - if: inputs.platform == 'esp' + if: inputs.port == 'espressif' run: | source $IDF_PATH/export.sh echo >> $GITHUB_ENV "IDF_PYTHON_ENV_PATH=$IDF_PYTHON_ENV_PATH" echo >> $GITHUB_PATH "$PATH" shell: bash - # riscv - - name: Get riscv toolchain - if: inputs.platform == 'riscv' - run: | - wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz - sudo tar -C /usr --strip-components=1 -xaf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz - shell: bash - # common - name: Cache python dependencies - if: inputs.platform != 'esp' + if: inputs.port != 'espressif' uses: ./.github/actions/deps/python with: action: ${{ inputs.action }} diff --git a/.github/actions/deps/ports/action.yml b/.github/actions/deps/ports/action.yml new file mode 100644 index 0000000000..8125de2acc --- /dev/null +++ b/.github/actions/deps/ports/action.yml @@ -0,0 +1,36 @@ +name: Fetch port deps + +inputs: + board: + required: true + type: string + +outputs: + port: + value: ${{ steps.board-to-port.outputs.port }} + +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' + uses: ./.github/actions/deps/ports/broadcom + + - name: Set up espressif + if: steps.board-to-port.outputs.port == 'espressif' + uses: ./.github/actions/deps/ports/espressif + + - name: Set up litex + if: steps.board-to-port.outputs.port == 'litex' + uses: ./.github/actions/deps/ports/litex + + - name: Set up nrf + if: steps.board-to-port.outputs.port == 'nrf' + uses: ./.github/actions/deps/ports/nrf diff --git a/.github/actions/deps/ports/broadcom/action.yml b/.github/actions/deps/ports/broadcom/action.yml new file mode 100644 index 0000000000..bd76c78262 --- /dev/null +++ b/.github/actions/deps/ports/broadcom/action.yml @@ -0,0 +1,21 @@ +name: Fetch broadcom port deps + +runs: + using: composite + 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 + sudo apt-get install -y mtools + shell: bash + - name: Install mkfs.fat + run: | + wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz + tar -xaf dosfstools-4.2.tar.gz + cd dosfstools-4.2 + ./configure + make -j 2 + cd src + echo >> $GITHUB_PATH $(pwd) + shell: bash diff --git a/.github/actions/deps/ports/litex/action.yml b/.github/actions/deps/ports/litex/action.yml new file mode 100644 index 0000000000..a89a222505 --- /dev/null +++ b/.github/actions/deps/ports/litex/action.yml @@ -0,0 +1,10 @@ +name: Fetch litex port deps + +runs: + using: composite + steps: + - name: Get litex toolchain + run: | + wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz + sudo tar -C /usr --strip-components=1 -xaf riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-centos6.tar.gz + shell: bash diff --git a/.github/actions/deps/ports/nrf/action.yml b/.github/actions/deps/ports/nrf/action.yml new file mode 100644 index 0000000000..d977c937b3 --- /dev/null +++ b/.github/actions/deps/ports/nrf/action.yml @@ -0,0 +1,17 @@ +name: Fetch nrf port deps + +runs: + using: composite + steps: + - name: Get nrfutil 7+ + run: | + wget https://developer.nordicsemi.com/.pc-tools/nrfutil/x64-linux/nrfutil + chmod +x nrfutil + ./nrfutil install nrf5sdk-tools + mkdir -p $HOME/.local/bin + mv nrfutil $HOME/.local/bin + echo "$HOME/.local/bin" >> $GITHUB_PATH + shell: bash + - name: Print nrfutil version + run: nrfutil -V + shell: bash diff --git a/.github/workflows/build-boards.yml b/.github/workflows/build-boards.yml index 457fce5b98..85e789bf87 100644 --- a/.github/workflows/build-boards.yml +++ b/.github/workflows/build-boards.yml @@ -3,9 +3,6 @@ name: Build boards on: workflow_call: inputs: - platform: - required: true - type: string boards: required: true type: string @@ -19,7 +16,7 @@ on: required: false jobs: - build: + board: runs-on: ubuntu-22.04 env: CP_VERSION: ${{ inputs.cp-version }} @@ -38,15 +35,17 @@ jobs: with: python-version: 3.x - name: Set up port - if: inputs.platform == 'esp' - uses: ./.github/actions/deps/ports/espressif + id: set-up-port + uses: ./.github/actions/deps/ports + with: + board: ${{ matrix.board }} - name: Set up submodules id: set-up-submodules uses: ./.github/actions/deps/submodules - name: Set up external uses: ./.github/actions/deps/external with: - platform: ${{ inputs.platform }} + port: ${{ steps.set-up-port.outputs.port }} - name: Set up mpy-cross if: steps.set-up-submodules.outputs.frozen == 'True' uses: ./.github/actions/mpy_cross diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 00c7f8749f..4383153fd1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,8 +9,6 @@ on: pull_request: release: types: [published] - check_suite: - types: [rerequested] concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} @@ -18,15 +16,11 @@ concurrency: jobs: scheduler: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 outputs: - build-doc: ${{ steps.set-matrix.outputs.build-doc }} - build-boards: ${{ steps.set-matrix.outputs.build-boards }} - boards-aarch: ${{ steps.set-matrix.outputs.boards-aarch }} - boards-arm: ${{ steps.set-matrix.outputs.boards-arm }} - boards-esp: ${{ steps.set-matrix.outputs.boards-esp }} - boards-riscv: ${{ steps.set-matrix.outputs.boards-riscv }} - boards-rpi: ${{ steps.set-matrix.outputs.boards-rpi }} + docs: ${{ steps.set-matrix.outputs.docs }} + ports: ${{ steps.set-matrix.outputs.ports }} + windows: ${{ steps.set-matrix.outputs.windows }} cp-version: ${{ steps.set-up-submodules.outputs.version }} steps: - name: Dump GitHub context @@ -54,53 +48,59 @@ jobs: uses: ./.github/actions/deps/external with: action: cache - # Disabled: Needs to be updated - # - name: Get last commit with checks - # id: get-last-commit-with-checks - # if: github.event_name == 'pull_request' - # working-directory: tools - # run: python3 -u ci_changes_per_commit.py - # env: - # REPO: ${{ github.repository }} - # PULL: ${{ github.event.number }} - # GITHUB_TOKEN: ${{ github.token }} - # EXCLUDE_COMMIT: ${{ github.event.after }} - name: Set up mpy-cross uses: ./.github/actions/mpy_cross with: download: false - - name: Set head sha + - name: Get last commit with checks + id: get-last-commit-with-checks if: github.event_name == 'pull_request' - run: echo "HEAD_SHA=$(git show -s --format=%s $GITHUB_SHA | grep -o -P "(?<=Merge ).*(?= into)")" >> $GITHUB_ENV - - name: Set base sha + working-directory: tools + run: python3 -u ci_changes_per_commit.py + env: + REPO: ${{ github.repository }} + PULL: ${{ github.event.number }} + GITHUB_TOKEN: ${{ github.token }} + 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 + - name: Set base sha (pull) if: github.event_name == 'pull_request' run: | git fetch --no-tags --no-recurse-submodules --depth=$((DEPTH + 1)) origin $HEAD_SHA echo "BASE_SHA=$(git rev-list $HEAD_SHA --skip=$DEPTH --max-count=1)" >> $GITHUB_ENV env: DEPTH: ${{ steps.get-last-commit-with-checks.outputs.commit_depth || github.event.pull_request.commits }} + - name: Set head sha (push) + if: github.event_name == 'push' + run: echo "HEAD_SHA=${{ github.event.after }}" >> $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 + env: + SHA: ${{ github.event.before }} - name: Get changes id: get-changes - if: github.event_name == 'pull_request' + if: env.BASE_SHA && env.HEAD_SHA run: echo $(git diff $BASE_SHA...$HEAD_SHA --name-only) | echo "changed_files=[\"$(sed "s/ /\", \"/g")\"]" >> $GITHUB_OUTPUT - name: Set matrix id: set-matrix - working-directory: tools run: python3 -u ci_set_matrix.py + working-directory: tools env: CHANGED_FILES: ${{ steps.get-changes.outputs.changed_files }} LAST_FAILED_JOBS: ${{ steps.get-last-commit-with-checks.outputs.check_runs }} tests: needs: scheduler - if: needs.scheduler.outputs.build-boards == 'True' uses: ./.github/workflows/run-tests.yml with: cp-version: ${{ needs.scheduler.outputs.cp-version }} mpy-cross: needs: scheduler - if: needs.scheduler.outputs.build-boards == 'True' + if: needs.scheduler.outputs.ports != '{}' uses: ./.github/workflows/build-mpy-cross.yml secrets: inherit with: @@ -109,7 +109,7 @@ jobs: mpy-cross-mac: runs-on: macos-11 needs: scheduler - if: ${{ needs.scheduler.outputs.build-boards == 'True' }} + if: needs.scheduler.outputs.ports != '{}' env: CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} steps: @@ -161,10 +161,10 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - build-doc: + docs: runs-on: ubuntu-22.04 needs: scheduler - if: ${{ needs.scheduler.outputs.build-doc == 'True' }} + if: needs.scheduler.outputs.docs == 'True' env: CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} steps: @@ -219,52 +219,83 @@ jobs: [ -z "$TWINE_USERNAME" ] || echo "Uploading dev release to PyPi" [ -z "$TWINE_USERNAME" ] || twine upload circuitpython-stubs/dist/* - aarch: - needs: [scheduler, mpy-cross, tests] - if: ${{ needs.scheduler.outputs.boards-aarch != '[]' }} - uses: ./.github/workflows/build-boards.yml - secrets: inherit - with: - platform: aarch - boards: ${{ needs.scheduler.outputs.boards-aarch }} - cp-version: ${{ needs.scheduler.outputs.cp-version }} + windows: + runs-on: windows-2022 + needs: scheduler + if: needs.scheduler.outputs.windows == 'True' + env: + CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} + defaults: + run: + # We define a custom shell script here, although `msys2.cmd` does neither exist nor is it available in the PATH yet + shell: msys2 {0} + steps: + # We want to change the configuration of the git command that actions/checkout will be using + # (since it is not possible to set autocrlf through the action yet, see actions/checkout#226). + - run: git config --global core.autocrlf input + shell: bash + - name: Check python coding (cmd) + run: python -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))" + shell: cmd + # We use a JS Action, which calls the system terminal or other custom terminals directly, if required + - uses: msys2/setup-msys2@v2 + with: + install: base-devel git wget unzip gcc python-pip + # The goal of this was to test how things worked when the default file encoding (locale.getpreferedencoding()) + # was not UTF-8. However, msys2 python does use utf-8 as the preferred file encoding, and using actions/setup-python + # python3.8 gave a broken build, so we're not really testing what we wanted to test. + # However, commandline length limits are being tested so that does some good. + - name: Check python coding (msys2) + run: | + locale -v + which python; python --version + python -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))" + which python3; python3 --version + 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-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.zip + unzip -q -d /tmp gcc-arm.zip + tar -C /tmp/gcc-arm-none-* -cf - . | tar -C /usr/local -xf - + pip install wheel + # requirements_dev.txt doesn't install on windows. (with msys2 python) + # instead, pick a subset for what we want to do + pip install cascadetoml jinja2 typer click intelhex + # check that installed packages work....? + which python; python --version; python -c "import cascadetoml" + which python3; python3 --version; python3 -c "import cascadetoml" + - name: Set up repository + uses: actions/checkout@v3 + with: + submodules: false + fetch-depth: 1 + - name: Set up submodules + uses: ./.github/actions/deps/submodules + - name: build mpy-cross + run: make -j2 -C mpy-cross + - name: build rp2040 + run: make -j2 -C ports/raspberrypi BOARD=adafruit_feather_rp2040 TRANSLATION=de_DE + - name: build samd21 + run: make -j2 -C ports/atmel-samd BOARD=feather_m0_express TRANSLATION=zh_Latn_pinyin + - name: build samd51 + run: make -j2 -C ports/atmel-samd BOARD=feather_m4_express TRANSLATION=es + - name: build nrf + run: make -j2 -C ports/nrf BOARD=feather_nrf52840_express TRANSLATION=fr + - name: build stm + run: make -j2 -C ports/stm BOARD=feather_stm32f405_express TRANSLATION=pt_BR + # I gave up trying to do esp builds on windows when I saw + # ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported + # https://github.com/espressif/esp-idf/issues/7062 - arm: + ports: needs: [scheduler, mpy-cross, tests] - if: ${{ needs.scheduler.outputs.boards-arm != '[]' }} + if: needs.scheduler.outputs.ports != '{}' uses: ./.github/workflows/build-boards.yml secrets: inherit + strategy: + fail-fast: false + matrix: + port: ${{ fromJSON(needs.scheduler.outputs.ports).ports }} with: - platform: arm - boards: ${{ needs.scheduler.outputs.boards-arm }} - cp-version: ${{ needs.scheduler.outputs.cp-version }} - - esp: - needs: [scheduler, mpy-cross, tests] - if: ${{ needs.scheduler.outputs.boards-esp != '[]' }} - uses: ./.github/workflows/build-boards.yml - secrets: inherit - with: - platform: esp - boards: ${{ needs.scheduler.outputs.boards-esp }} - cp-version: ${{ needs.scheduler.outputs.cp-version }} - - riscv: - needs: [scheduler, mpy-cross, tests] - if: ${{ needs.scheduler.outputs.boards-riscv != '[]' }} - uses: ./.github/workflows/build-boards.yml - secrets: inherit - with: - platform: riscv - boards: ${{ needs.scheduler.outputs.boards-riscv }} - cp-version: ${{ needs.scheduler.outputs.cp-version }} - - rpi: - needs: [scheduler, mpy-cross, tests] - if: ${{ needs.scheduler.outputs.boards-rpi != '[]' }} - uses: ./.github/workflows/build-boards.yml - secrets: inherit - with: - platform: arm - boards: ${{ needs.scheduler.outputs.boards-rpi }} + boards: ${{ toJSON(fromJSON(needs.scheduler.outputs.ports)[matrix.port]) }} cp-version: ${{ needs.scheduler.outputs.cp-version }} diff --git a/.github/workflows/create_website_pr.yml b/.github/workflows/create-website-pr.yml similarity index 96% rename from .github/workflows/create_website_pr.yml rename to .github/workflows/create-website-pr.yml index eeae8c8299..7f047d4b1e 100644 --- a/.github/workflows/create_website_pr.yml +++ b/.github/workflows/create-website-pr.yml @@ -6,7 +6,7 @@ name: Update CircuitPython.org on: release: - types: [published, rerequested] + types: [published] jobs: website: diff --git a/.github/workflows/build-boards-custom.yml b/.github/workflows/custom-board-build.yml similarity index 74% rename from .github/workflows/build-boards-custom.yml rename to .github/workflows/custom-board-build.yml index 22ba0f62f4..aa8044b0d2 100644 --- a/.github/workflows/build-boards-custom.yml +++ b/.github/workflows/custom-board-build.yml @@ -32,16 +32,6 @@ run-name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ in jobs: build: runs-on: ubuntu-22.04 - env: - PLATFORM_atmel-samd: arm - PLATFORM_broadcom: aarch - PLATFORM_cxd56: arm - PLATFORM_espressif: esp - PLATFORM_litex: riscv - PLATFORM_mimxrt10xx: arm - PLATFORM_nrf: arm - PLATFORM_raspberrypi: arm - PLATFORM_stm: arm steps: - name: Set up repository run: | @@ -51,20 +41,15 @@ jobs: if: inputs.debug || inputs.flags != '' run: | > custom-build && git add custom-build - - name: Get port - id: get-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 - - name: Port to platform - run: echo >> $GITHUB_ENV "PLATFORM=${{ env[format('PLATFORM_{0}', steps.get-port.outputs.port)] }}" - name: Set up python uses: actions/setup-python@v4 with: python-version: 3.x - name: Set up port - if: env.PLATFORM == 'esp' - uses: ./.github/actions/deps/ports/espressif + id: set-up-port + uses: ./.github/actions/deps/ports + with: + board: ${{ inputs.board }} - name: Set up submodules id: set-up-submodules uses: ./.github/actions/deps/submodules @@ -75,7 +60,7 @@ jobs: uses: ./.github/actions/deps/external with: action: cache - platform: ${{ env.PLATFORM }} + port: ${{ steps.set-up-port.outputs.port }} - name: Set up mpy-cross if: steps.set-up-submodules.outputs.frozen == 'True' uses: ./.github/actions/mpy_cross @@ -96,9 +81,9 @@ jobs: mkfs.fat --version || true - name: Build board run: make -j2 ${{ inputs.flags }} BOARD=${{ inputs.board }} DEBUG=${{ inputs.debug && '1' || '0' }} TRANSLATION=${{ inputs.language }} - working-directory: ports/${{ steps.get-port.outputs.port }} + working-directory: ports/${{ steps.set-up-port.outputs.port }} - name: Upload artifact uses: actions/upload-artifact@v3 with: name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }} - path: ports/${{ steps.get-port.outputs.port }}/build-${{ inputs.board }}/firmware.* + path: ports/${{ steps.set-up-port.outputs.port }}/build-${{ inputs.board }}/firmware.* diff --git a/.github/workflows/notify.yml b/.github/workflows/notify-on-issue-label.yml similarity index 100% rename from .github/workflows/notify.yml rename to .github/workflows/notify-on-issue-label.yml diff --git a/.github/workflows/ports_windows.yml b/.github/workflows/ports_windows.yml deleted file mode 100644 index ba2042660a..0000000000 --- a/.github/workflows/ports_windows.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: windows port - -on: - push: - pull_request: - paths: - - '.github/workflows/ports_windows.yml' - - 'extmod/**' - - 'lib/**' - - 'mpy-cross/**' - - 'ports/unix/**' - - 'ports/windows/**' - - 'py/**' - - 'requirements*.txt' - - 'tools/**' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - windows: - runs-on: windows-2022 - defaults: - run: - # We define a custom shell script here, although `msys2.cmd` does neither exist nor is it available in the PATH yet - shell: msys2 {0} - steps: - - # We want to change the configuration of the git command that actions/checkout will be using (since it is not possible to set autocrlf through the action yet, see actions/checkout#226). - - run: git config --global core.autocrlf input - shell: bash - - - name: Check python coding (cmd) - run: python -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))" - shell: cmd - - # We use a JS Action, which calls the system terminal or other custom terminals directly, if required - - uses: msys2/setup-msys2@v2 - with: - update: true - install: base-devel git wget unzip gcc python-pip - - # The goal of this was to test how things worked when the default file - # encoding (locale.getpreferedencoding()) was not UTF-8. However, msys2 - # python does use utf-8 as the preferred file encoding, and using - # actions/setup-python python3.8 gave a broken build, so we're not really - # testing what we wanted to test. - # - # however, commandline length limits are being tested so that does some - # good. - - name: Check python coding (msys2) - run: | - locale -v - which python; python --version - python -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))" - which python3; python3 --version - 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-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-win32.zip - unzip -q -d /tmp gcc-arm.zip - tar -C /tmp/gcc-arm-none-* -cf - . | tar -C /usr/local -xf - - pip install wheel - # requirements_dev.txt doesn't install on windows. (with msys2 python) - # instead, pick a subset for what we want to do - pip install cascadetoml jinja2 typer click intelhex - # check that installed packages work....? - which python; python --version; python -c "import cascadetoml" - which python3; python3 --version; python3 -c "import cascadetoml" - - - name: Set up repository - uses: actions/checkout@v3 - with: - submodules: false - fetch-depth: 1 - - - name: Set up submodules - uses: ./.github/actions/deps/submodules - with: - version: true - - - name: build mpy-cross - run: make -j2 -C mpy-cross - - - name: build rp2040 - run: make -j2 -C ports/raspberrypi BOARD=adafruit_feather_rp2040 TRANSLATION=de_DE - - - name: build samd21 - run: make -j2 -C ports/atmel-samd BOARD=feather_m0_express TRANSLATION=zh_Latn_pinyin - - - name: build samd51 - run: make -j2 -C ports/atmel-samd BOARD=feather_m4_express TRANSLATION=es - - - name: build nrf - run: make -j2 -C ports/nrf BOARD=feather_nrf52840_express TRANSLATION=fr - - - name: build stm - run: make -j2 -C ports/stm BOARD=feather_stm32f405_express TRANSLATION=pt_BR - -# I gave up trying to do esp32 builds on windows when I saw -# ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported -# https://github.com/espressif/esp-idf/issues/7062 -# -# - name: prepare esp -# run: ports/espressif/esp-idf/install.bat -# shell: cmd -# -# - name: build esp -# run: . ports/espressif/esp-idf/export.sh && make -j2 -C ports/espressif BOARD=adafruit_metro_esp32s2 diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index c0dff33564..2a3fcf9439 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -5,8 +5,8 @@ name: pre-commit on: - pull_request: push: + pull_request: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 12e8d2ef74..44146662f2 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,7 +9,7 @@ on: jobs: run: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: @@ -31,7 +31,7 @@ jobs: - name: Set up python uses: actions/setup-python@v4 with: - python-version: 3.x + python-version: 3.8 - name: Set up submodules uses: ./.github/actions/deps/submodules with: diff --git a/.gitmodules b/.gitmodules index dfd718630c..2ba84b4305 100644 --- a/.gitmodules +++ b/.gitmodules @@ -187,10 +187,6 @@ [submodule "frozen/Adafruit_CircuitPython_APDS9960"] path = frozen/Adafruit_CircuitPython_APDS9960 url = https://github.com/adafruit/Adafruit_CircuitPython_APDS9960 -[submodule "ports/broadcom/peripherals"] - path = ports/broadcom/peripherals - url = https://github.com/adafruit/broadcom-peripherals.git - branch = main-build [submodule "rpi-firmware"] path = ports/broadcom/firmware url = https://github.com/raspberrypi/rpi-firmware.git @@ -313,8 +309,7 @@ branch = circuitpython [submodule "ports/raspberrypi/lib/cyw43-driver"] path = ports/raspberrypi/lib/cyw43-driver - url = https://github.com/adafruit/cyw43-driver.git - branch = circuitpython8 + url = https://github.com/georgerobotics/cyw43-driver.git [submodule "ports/raspberrypi/lib/lwip"] path = ports/raspberrypi/lib/lwip url = https://github.com/adafruit/lwip.git @@ -328,3 +323,7 @@ [submodule "frozen/Adafruit_CircuitPython_SSD1680"] path = frozen/Adafruit_CircuitPython_SSD1680 url = https://github.com/adafruit/Adafruit_CircuitPython_SSD1680 +[submodule "ports/broadcom/peripherals"] + path = ports/broadcom/peripherals + url = https://github.com/adafruit/broadcom-peripherals.git + branch = main-build diff --git a/BUILDING.md b/BUILDING.md index 4793824cf1..f108675b7c 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -109,7 +109,7 @@ Pre-commit also requires some additional programs to be installed through your p * Standard Unix tools such as make, find, etc * The gettext package, any modern version - * uncrustify version 0.71 (0.72 is also tested) + * uncrustify version 0.71 (0.72 is also tested and OK; 0.75 is not OK) Each time you create a git commit, the pre-commit quality checks will be run. You can also run them e.g., with `pre-commit run foo.c` or `pre-commit run --all` to run on all files whether modified or not. diff --git a/data/nvm.toml b/data/nvm.toml index 2d292ad4e6..73fafcbe4c 160000 --- a/data/nvm.toml +++ b/data/nvm.toml @@ -1 +1 @@ -Subproject commit 2d292ad4e67890d4b85b027431ba9fef7bf561fd +Subproject commit 73fafcbe4c66b23df63be31e9227353b695abb08 diff --git a/frozen/Adafruit_CircuitPython_Display_Text b/frozen/Adafruit_CircuitPython_Display_Text index 1590d81f7d..911201504a 160000 --- a/frozen/Adafruit_CircuitPython_Display_Text +++ b/frozen/Adafruit_CircuitPython_Display_Text @@ -1 +1 @@ -Subproject commit 1590d81f7d1474b25aed6a0cb793c7e6dc7634ec +Subproject commit 911201504a269dbfc49b04ca59bc54adabd4716a diff --git a/frozen/Adafruit_CircuitPython_DotStar b/frozen/Adafruit_CircuitPython_DotStar index d645fc2ade..187279a95e 160000 --- a/frozen/Adafruit_CircuitPython_DotStar +++ b/frozen/Adafruit_CircuitPython_DotStar @@ -1 +1 @@ -Subproject commit d645fc2aded3606e5b0c17689e9f29e7e56bb612 +Subproject commit 187279a95e5cdd634d233af59352558cea4c1227 diff --git a/frozen/Adafruit_CircuitPython_IS31FL3731 b/frozen/Adafruit_CircuitPython_IS31FL3731 index 8e0f081a0f..5433ba3760 160000 --- a/frozen/Adafruit_CircuitPython_IS31FL3731 +++ b/frozen/Adafruit_CircuitPython_IS31FL3731 @@ -1 +1 @@ -Subproject commit 8e0f081a0fcc94053b8ef480a916b10855a3c0d5 +Subproject commit 5433ba3760ca605267223de883a44cb8394f40a5 diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index 61ca58788a..240fe51935 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit 61ca58788aabd53558e10c32064a1304aa7454f2 +Subproject commit 240fe51935f4a9def33ef347d40b13862a60b7ac diff --git a/frozen/Adafruit_CircuitPython_Motor b/frozen/Adafruit_CircuitPython_Motor index f26bead58d..9c3de3abce 160000 --- a/frozen/Adafruit_CircuitPython_Motor +++ b/frozen/Adafruit_CircuitPython_Motor @@ -1 +1 @@ -Subproject commit f26bead58d3c4036eced586d275396816e92e80a +Subproject commit 9c3de3abce00b50ba936f4f8daad0a8a6bee34a6 diff --git a/frozen/Adafruit_CircuitPython_RFM69 b/frozen/Adafruit_CircuitPython_RFM69 index 96b4a05c8a..af1cba8a7e 160000 --- a/frozen/Adafruit_CircuitPython_RFM69 +++ b/frozen/Adafruit_CircuitPython_RFM69 @@ -1 +1 @@ -Subproject commit 96b4a05c8a225ad7ddc392be7fb69efebe151981 +Subproject commit af1cba8a7e4e3950fcc5367e9c55a024d9ab9f64 diff --git a/frozen/Adafruit_CircuitPython_Requests b/frozen/Adafruit_CircuitPython_Requests index 203d0b1489..558fff7223 160000 --- a/frozen/Adafruit_CircuitPython_Requests +++ b/frozen/Adafruit_CircuitPython_Requests @@ -1 +1 @@ -Subproject commit 203d0b1489cb90a39f8a780570287f1a5bd610a0 +Subproject commit 558fff7223178eae6228e5262f3a08d3a4101394 diff --git a/frozen/Adafruit_CircuitPython_SSD1680 b/frozen/Adafruit_CircuitPython_SSD1680 index 168624262c..91b6867aca 160000 --- a/frozen/Adafruit_CircuitPython_SSD1680 +++ b/frozen/Adafruit_CircuitPython_SSD1680 @@ -1 +1 @@ -Subproject commit 168624262c18f5ee80ec392c0844d6a4c6548760 +Subproject commit 91b6867aca2b0511571fed14ab051d37f1f1544c diff --git a/lib/AnimatedGIF/AnimatedGIF.cpp b/lib/AnimatedGIF/AnimatedGIF.cpp new file mode 100644 index 0000000000..ad79b212b8 --- /dev/null +++ b/lib/AnimatedGIF/AnimatedGIF.cpp @@ -0,0 +1,236 @@ +// +// GIF Animator +// written by Larry Bank +// bitbank@pobox.com +// Arduino port started 7/5/2020 +// Original GIF code written 20+ years ago :) +// The goal of this code is to decode images up to 480x320 +// using no more than 22K of RAM (if sent directly to an LCD display) +// +// Copyright 2020 BitBank Software, Inc. All Rights Reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//=========================================================================== +#include "AnimatedGIF.h" + +// Here is all of the actual code... +#include "gif.inl" + +// +// Memory initialization +// +int AnimatedGIF::open(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw) +{ + _gif.iError = GIF_SUCCESS; + _gif.pfnRead = readMem; + _gif.pfnSeek = seekMem; + _gif.pfnDraw = pfnDraw; + _gif.pfnOpen = NULL; + _gif.pfnClose = NULL; + _gif.GIFFile.iSize = iDataSize; + _gif.GIFFile.pData = pData; + return GIFInit(&_gif); +} /* open() */ + +int AnimatedGIF::openFLASH(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw) +{ + _gif.iError = GIF_SUCCESS; + _gif.pfnRead = readFLASH; + _gif.pfnSeek = seekMem; + _gif.pfnDraw = pfnDraw; + _gif.pfnOpen = NULL; + _gif.pfnClose = NULL; + _gif.GIFFile.iSize = iDataSize; + _gif.GIFFile.pData = pData; + return GIFInit(&_gif); +} /* openFLASH() */ + +// +// Returns the first comment block found (if any) +// +int AnimatedGIF::getComment(char *pDest) +{ +int32_t iOldPos; + + iOldPos = _gif.GIFFile.iPos; // keep old position + (*_gif.pfnSeek)(&_gif.GIFFile, _gif.iCommentPos); + (*_gif.pfnRead)(&_gif.GIFFile, (uint8_t *)pDest, _gif.sCommentLen); + (*_gif.pfnSeek)(&_gif.GIFFile, iOldPos); + pDest[_gif.sCommentLen] = 0; // zero terminate the string + return (int)_gif.sCommentLen; +} /* getComment() */ + +// +// Allocate a block of memory to hold the entire canvas (as 8-bpp) +// +int AnimatedGIF::allocFrameBuf(GIF_ALLOC_CALLBACK *pfnAlloc) +{ + if (_gif.iCanvasWidth > 0 && _gif.iCanvasHeight > 0 && _gif.pFrameBuffer == NULL) + { + // Allocate a little extra space for the current line + // as RGB565 or RGB888 + int iCanvasSize = _gif.iCanvasWidth * (_gif.iCanvasHeight+3); + _gif.pFrameBuffer = (unsigned char *)(*pfnAlloc)(iCanvasSize); + if (_gif.pFrameBuffer == NULL) + return GIF_ERROR_MEMORY; + return GIF_SUCCESS; + } + return GIF_INVALID_PARAMETER; +} /* allocFrameBuf() */ +// +// Set the DRAW callback behavior to RAW (default) +// or COOKED (requires allocating a frame buffer) +// +int AnimatedGIF::setDrawType(int iType) +{ + if (iType != GIF_DRAW_RAW && iType != GIF_DRAW_COOKED) + return GIF_INVALID_PARAMETER; // invalid drawing mode + _gif.ucDrawType = (uint8_t)iType; + return GIF_SUCCESS; +} /* setDrawType() */ +// +// Release the memory used by the frame buffer +// +int AnimatedGIF::freeFrameBuf(GIF_FREE_CALLBACK *pfnFree) +{ + if (_gif.pFrameBuffer) + { + (*pfnFree)(_gif.pFrameBuffer); + _gif.pFrameBuffer = NULL; + return GIF_SUCCESS; + } + return GIF_INVALID_PARAMETER; +} /* freeFrameBuf() */ +// +// Return a pointer to the frame buffer (if it was allocated) +// +uint8_t * AnimatedGIF::getFrameBuf() +{ + return _gif.pFrameBuffer; +} /* getFrameBuf() */ + +int AnimatedGIF::getCanvasWidth() +{ + return _gif.iCanvasWidth; +} /* getCanvasWidth() */ + +int AnimatedGIF::getCanvasHeight() +{ + return _gif.iCanvasHeight; +} /* getCanvasHeight() */ + +int AnimatedGIF::getLoopCount() +{ + return _gif.iRepeatCount; +} /* getLoopCount() */ + +int AnimatedGIF::getInfo(GIFINFO *pInfo) +{ + return GIF_getInfo(&_gif, pInfo); +} /* getInfo() */ + +int AnimatedGIF::getLastError() +{ + return _gif.iError; +} /* getLastError() */ + +// +// File (SD/MMC) based initialization +// +int AnimatedGIF::open(const char *szFilename, GIF_OPEN_CALLBACK *pfnOpen, GIF_CLOSE_CALLBACK *pfnClose, GIF_READ_CALLBACK *pfnRead, GIF_SEEK_CALLBACK *pfnSeek, GIF_DRAW_CALLBACK *pfnDraw) +{ + _gif.iError = GIF_SUCCESS; + _gif.pfnRead = pfnRead; + _gif.pfnSeek = pfnSeek; + _gif.pfnDraw = pfnDraw; + _gif.pfnOpen = pfnOpen; + _gif.pfnClose = pfnClose; + _gif.GIFFile.fHandle = (*pfnOpen)(szFilename, &_gif.GIFFile.iSize); + if (_gif.GIFFile.fHandle == NULL) { + _gif.iError = GIF_FILE_NOT_OPEN; + return 0; + } + return GIFInit(&_gif); + +} /* open() */ + +void AnimatedGIF::close() +{ + if (_gif.pfnClose) + (*_gif.pfnClose)(_gif.GIFFile.fHandle); +} /* close() */ + +void AnimatedGIF::reset() +{ + (*_gif.pfnSeek)(&_gif.GIFFile, 0); +} /* reset() */ + +void AnimatedGIF::begin(unsigned char ucPaletteType) +{ + memset(&_gif, 0, sizeof(_gif)); + if (ucPaletteType != GIF_PALETTE_RGB565_LE && ucPaletteType != GIF_PALETTE_RGB565_BE && ucPaletteType != GIF_PALETTE_RGB888) + _gif.iError = GIF_INVALID_PARAMETER; + _gif.ucPaletteType = ucPaletteType; + _gif.ucDrawType = GIF_DRAW_RAW; // assume RAW pixel handling + _gif.pFrameBuffer = NULL; +} /* begin() */ +// +// Play a single frame +// returns: +// 1 = good result and more frames exist +// 0 = no more frames exist, a frame may or may not have been played: use getLastError() and look for GIF_SUCCESS to know if a frame was played +// -1 = error +int AnimatedGIF::playFrame(bool bSync, int *delayMilliseconds, void *pUser) +{ +int rc; +#if !defined( __MACH__ ) && !defined( __LINUX__ ) +long lTime = millis(); +#endif + + if (_gif.GIFFile.iPos >= _gif.GIFFile.iSize-1) // no more data exists + { + (*_gif.pfnSeek)(&_gif.GIFFile, 0); // seek to start + } + if (GIFParseInfo(&_gif, 0)) + { + _gif.pUser = pUser; + if (_gif.iError == GIF_EMPTY_FRAME) // don't try to decode it + return 0; + rc = DecodeLZW(&_gif, 0); + if (rc != 0) // problem + return -1; + } + else + { + // The file is "malformed" in that there is a bunch of non-image data after + // the last frame. Return as if all is well, though if needed getLastError() + // can be used to see if a frame was actually processed: + // GIF_SUCCESS -> frame processed, GIF_EMPTY_FRAME -> no frame processed + if (_gif.iError == GIF_EMPTY_FRAME) + { + if (delayMilliseconds) + *delayMilliseconds = 0; + return 0; + } + return -1; // error parsing the frame info, we may be at the end of the file + } + // Return 1 for more frames or 0 if this was the last frame + if (bSync) + { +#if !defined( __MACH__ ) && !defined( __LINUX__ ) + lTime = millis() - lTime; + if (lTime < _gif.iFrameDelay) // need to pause a bit + delay(_gif.iFrameDelay - lTime); +#endif // __LINUX__ + } + if (delayMilliseconds) // if not NULL, return the frame delay time + *delayMilliseconds = _gif.iFrameDelay; + return (_gif.GIFFile.iPos < _gif.GIFFile.iSize-10); +} /* playFrame() */ diff --git a/lib/AnimatedGIF/AnimatedGIF.h b/lib/AnimatedGIF/AnimatedGIF.h new file mode 100644 index 0000000000..e1868bb6cd --- /dev/null +++ b/lib/AnimatedGIF/AnimatedGIF.h @@ -0,0 +1,216 @@ +// Copyright 2020 BitBank Software, Inc. All Rights Reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//=========================================================================== + +#ifndef __ANIMATEDGIF__ +#define __ANIMATEDGIF__ +#if defined( PICO_BUILD ) || defined( __MACH__ ) || defined( __LINUX__ ) || defined( __MCUXPRESSO ) +#include +#include +#include +#include +#define memcpy_P memcpy +#define PROGMEM +#else +#include +#endif +// +// GIF Animator +// Written by Larry Bank +// Copyright (c) 2020 BitBank Software, Inc. +// bitbank@pobox.com +// +// Designed to decode images up to 480x320 +// using less than 22K of RAM +// + +/* GIF Defines and variables */ +#define MAX_CHUNK_SIZE 255 +#define LZW_BUF_SIZE (6*MAX_CHUNK_SIZE) +#define LZW_HIGHWATER (4*MAX_CHUNK_SIZE) +#ifdef __LINUX__ +#define MAX_WIDTH 2048 +#else +#define MAX_WIDTH 320 +#endif // __LINUX__ +#define FILE_BUF_SIZE 4096 + +#define PIXEL_FIRST 0 +#define PIXEL_LAST 4096 +#define LINK_UNUSED 5911 // 0x1717 to use memset +#define LINK_END 5912 +#define MAX_HASH 5003 +#define MAXMAXCODE 4096 + +enum { + GIF_PALETTE_RGB565_LE = 0, // little endian (default) + GIF_PALETTE_RGB565_BE, // big endian + GIF_PALETTE_RGB888 // original 24-bpp entries +}; +// for compatibility with older code +#define LITTLE_ENDIAN_PIXELS GIF_PALETTE_RGB565_LE +#define BIG_ENDIAN_PIXELS GIF_PALETTE_RGB565_BE +// +// Draw callback pixel type +// RAW = 8-bit palettized pixels requiring transparent pixel handling +// COOKED = 16 or 24-bpp fully rendered pixels ready for display +// +enum { + GIF_DRAW_RAW = 0, + GIF_DRAW_COOKED +}; + +enum { + GIF_SUCCESS = 0, + GIF_DECODE_ERROR, + GIF_TOO_WIDE, + GIF_INVALID_PARAMETER, + GIF_UNSUPPORTED_FEATURE, + GIF_FILE_NOT_OPEN, + GIF_EARLY_EOF, + GIF_EMPTY_FRAME, + GIF_BAD_FILE, + GIF_ERROR_MEMORY +}; + +typedef struct gif_file_tag +{ + int32_t iPos; // current file position + int32_t iSize; // file size + uint8_t *pData; // memory file pointer + void * fHandle; // class pointer to File/SdFat or whatever you want +} GIFFILE; + +typedef struct gif_info_tag +{ + int32_t iFrameCount; // total frames in file + int32_t iDuration; // duration of animation in milliseconds + int32_t iMaxDelay; // maximum frame delay + int32_t iMinDelay; // minimum frame delay +} GIFINFO; + +typedef struct gif_draw_tag +{ + int iX, iY; // Corner offset of this frame on the canvas + int y; // current line being drawn (0 = top line of image) + int iWidth, iHeight; // size of this frame + void *pUser; // user supplied pointer + uint8_t *pPixels; // 8-bit source pixels for this line + uint16_t *pPalette; // little or big-endian RGB565 palette entries (default) + uint8_t *pPalette24; // RGB888 palette (optional) + uint8_t ucTransparent; // transparent color + uint8_t ucHasTransparency; // flag indicating the transparent color is in use + uint8_t ucDisposalMethod; // frame disposal method + uint8_t ucBackground; // background color + uint8_t ucIsGlobalPalette; // Flag to indicate that a global palette, rather than a local palette is being used +} GIFDRAW; + +// Callback function prototypes +typedef int32_t (GIF_READ_CALLBACK)(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen); +typedef int32_t (GIF_SEEK_CALLBACK)(GIFFILE *pFile, int32_t iPosition); +typedef void (GIF_DRAW_CALLBACK)(GIFDRAW *pDraw); +typedef void * (GIF_OPEN_CALLBACK)(const char *szFilename, int32_t *pFileSize); +typedef void (GIF_CLOSE_CALLBACK)(void *pHandle); +typedef void * (GIF_ALLOC_CALLBACK)(uint32_t iSize); +typedef void (GIF_FREE_CALLBACK)(void *buffer); +// +// our private structure to hold a GIF image decode state +// +typedef struct gif_image_tag +{ + int iWidth, iHeight, iCanvasWidth, iCanvasHeight; + int iX, iY; // GIF corner offset + int iBpp; + int iError; // last error + int iFrameDelay; // delay in milliseconds for this frame + int iRepeatCount; // NETSCAPE animation repeat count. 0=forever + int iXCount, iYCount; // decoding position in image (countdown values) + int iLZWOff; // current LZW data offset + int iLZWSize; // current quantity of data in the LZW buffer + int iCommentPos; // file offset of start of comment data + short sCommentLen; // length of comment + GIF_READ_CALLBACK *pfnRead; + GIF_SEEK_CALLBACK *pfnSeek; + GIF_DRAW_CALLBACK *pfnDraw; + GIF_OPEN_CALLBACK *pfnOpen; + GIF_CLOSE_CALLBACK *pfnClose; + GIFFILE GIFFile; + void *pUser; + unsigned char *pFrameBuffer; + unsigned char *pPixels, *pOldPixels; + unsigned char ucLineBuf[MAX_WIDTH]; // current line + unsigned char ucFileBuf[FILE_BUF_SIZE]; // holds temp data and pixel stack + unsigned short pPalette[384]; // can hold RGB565 or RGB888 - set in begin() + unsigned short pLocalPalette[384]; // color palettes for GIF images + unsigned char ucLZW[LZW_BUF_SIZE]; // holds 6 chunks (6x255) of GIF LZW data packed together + unsigned short usGIFTable[4096]; + unsigned char ucGIFPixels[8192]; + unsigned char bEndOfFrame; + unsigned char ucGIFBits, ucBackground, ucTransparent, ucCodeStart, ucMap, bUseLocalPalette; + unsigned char ucPaletteType; // RGB565 or RGB888 + unsigned char ucDrawType; // RAW or COOKED +} GIFIMAGE; + +#ifdef __cplusplus +// +// The GIF class wraps portable C code which does the actual work +// +class AnimatedGIF +{ + public: + int open(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw); + int openFLASH(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw); + int open(const char *szFilename, GIF_OPEN_CALLBACK *pfnOpen, GIF_CLOSE_CALLBACK *pfnClose, GIF_READ_CALLBACK *pfnRead, GIF_SEEK_CALLBACK *pfnSeek, GIF_DRAW_CALLBACK *pfnDraw); + void close(); + void reset(); + void begin(unsigned char ucPaletteType = GIF_PALETTE_RGB565_LE); + void begin(int iEndian, unsigned char ucPaletteType) { begin(ucPaletteType); }; + int playFrame(bool bSync, int *delayMilliseconds, void *pUser = NULL); + int getCanvasWidth(); + int allocFrameBuf(GIF_ALLOC_CALLBACK *pfnAlloc); + int setDrawType(int iType); + int freeFrameBuf(GIF_FREE_CALLBACK *pfnFree); + uint8_t *getFrameBuf(); + int getCanvasHeight(); + int getLoopCount(); + int getInfo(GIFINFO *pInfo); + int getLastError(); + int getComment(char *destBuffer); + + private: + GIFIMAGE _gif; +}; +#else +// C interface + int GIF_openRAM(GIFIMAGE *pGIF, uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw); + int GIF_openFile(GIFIMAGE *pGIF, const char *szFilename, GIF_DRAW_CALLBACK *pfnDraw); + void GIF_close(GIFIMAGE *pGIF); + void GIF_begin(GIFIMAGE *pGIF, unsigned char ucPaletteType); + void GIF_reset(GIFIMAGE *pGIF); + int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser); + int GIF_getCanvasWidth(GIFIMAGE *pGIF); + int GIF_getCanvasHeight(GIFIMAGE *pGIF); + int GIF_getComment(GIFIMAGE *pGIF, char *destBuffer); + int GIF_getInfo(GIFIMAGE *pGIF, GIFINFO *pInfo); + int GIF_getLastError(GIFIMAGE *pGIF); + int GIF_getLoopCount(GIFIMAGE *pGIF); +#endif // __cplusplus + +// Due to unaligned memory causing an exception, we have to do these macros the slow way +#define INTELSHORT(p) ((*p) + (*(p+1)<<8)) +#define INTELLONG(p) ((*p) + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24)) +#define MOTOSHORT(p) (((*(p))<<8) + (*(p+1))) +#define MOTOLONG(p) (((*p)<<24) + ((*(p+1))<<16) + ((*(p+2))<<8) + (*(p+3))) + +// Must be a 32-bit target processor +#define REGISTER_WIDTH 32 + +#endif // __ANIMATEDGIF__ diff --git a/lib/AnimatedGIF/AnimatedGIF_circuitpy.h b/lib/AnimatedGIF/AnimatedGIF_circuitpy.h new file mode 100644 index 0000000000..c1f359194f --- /dev/null +++ b/lib/AnimatedGIF/AnimatedGIF_circuitpy.h @@ -0,0 +1,182 @@ +// Copyright 2020 BitBank Software, Inc. All Rights Reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// =========================================================================== +// +// Modified 2023 by Mark Komus to work for CircuitPython +// + +#ifndef __ANIMATEDGIF__ +#define __ANIMATEDGIF__ +#include +#include +#include +#include +// +// GIF Animator +// Written by Larry Bank +// Copyright (c) 2020 BitBank Software, Inc. +// bitbank@pobox.com +// +// Designed to decode images up to 480x320 +// using less than 22K of RAM +// + +/* GIF Defines and variables */ +#define MAX_CHUNK_SIZE 255 +#define LZW_BUF_SIZE (6 * MAX_CHUNK_SIZE) +#define LZW_HIGHWATER (4 * MAX_CHUNK_SIZE) +#define MAX_WIDTH 320 +#define FILE_BUF_SIZE 4096 + +#define PIXEL_FIRST 0 +#define PIXEL_LAST 4096 +#define LINK_UNUSED 5911 // 0x1717 to use memset +#define LINK_END 5912 +#define MAX_HASH 5003 +#define MAXMAXCODE 4096 + +enum { + GIF_PALETTE_RGB565_LE = 0, // little endian (default) + GIF_PALETTE_RGB565_BE, // big endian + GIF_PALETTE_RGB888 // original 24-bpp entries +}; +// for compatibility with older code +#define LITTLE_ENDIAN_PIXELS GIF_PALETTE_RGB565_LE +#define BIG_ENDIAN_PIXELS GIF_PALETTE_RGB565_BE +// +// Draw callback pixel type +// RAW = 8-bit palettized pixels requiring transparent pixel handling +// COOKED = 16 or 24-bpp fully rendered pixels ready for display +// +enum { + GIF_DRAW_RAW = 0, + GIF_DRAW_COOKED +}; + +enum { + GIF_SUCCESS = 0, + GIF_DECODE_ERROR, + GIF_TOO_WIDE, + GIF_INVALID_PARAMETER, + GIF_UNSUPPORTED_FEATURE, + GIF_FILE_NOT_OPEN, + GIF_EARLY_EOF, + GIF_EMPTY_FRAME, + GIF_BAD_FILE, + GIF_ERROR_MEMORY +}; + +typedef struct gif_file_tag +{ + int32_t iPos; // current file position + int32_t iSize; // file size + uint8_t *pData; // memory file pointer + void *fHandle; // class pointer to File/SdFat or whatever you want +} GIFFILE; + +typedef struct gif_info_tag +{ + int32_t iFrameCount; // total frames in file + int32_t iDuration; // duration of animation in milliseconds + int32_t iMaxDelay; // maximum frame delay + int32_t iMinDelay; // minimum frame delay +} GIFINFO; + +typedef struct gif_draw_tag +{ + int iX, iY; // Corner offset of this frame on the canvas + int y; // current line being drawn (0 = top line of image) + int iWidth, iHeight; // size of this frame + void *pUser; // user supplied pointer + uint8_t *pPixels; // 8-bit source pixels for this line + uint16_t *pPalette; // little or big-endian RGB565 palette entries (default) + uint8_t *pPalette24; // RGB888 palette (optional) + uint8_t ucTransparent; // transparent color + uint8_t ucHasTransparency; // flag indicating the transparent color is in use + uint8_t ucDisposalMethod; // frame disposal method + uint8_t ucBackground; // background color + uint8_t ucIsGlobalPalette; // Flag to indicate that a global palette, rather than a local palette is being used +} GIFDRAW; + +// Callback function prototypes +typedef int32_t (GIF_READ_CALLBACK)(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen); +typedef int32_t (GIF_SEEK_CALLBACK)(GIFFILE *pFile, int32_t iPosition); +typedef void (GIF_DRAW_CALLBACK)(GIFDRAW *pDraw); +typedef void * (GIF_OPEN_CALLBACK)(const char *szFilename, int32_t *pFileSize); +typedef void (GIF_CLOSE_CALLBACK)(void *pHandle); +typedef void * (GIF_ALLOC_CALLBACK)(uint32_t iSize); +typedef void (GIF_FREE_CALLBACK)(void *buffer); +// +// our private structure to hold a GIF image decode state +// +typedef struct gif_image_tag +{ + int iWidth, iHeight, iCanvasWidth, iCanvasHeight; + int iX, iY; // GIF corner offset + int iBpp; + int iError; // last error + int iFrameDelay; // delay in milliseconds for this frame + int iRepeatCount; // NETSCAPE animation repeat count. 0=forever + int iXCount, iYCount; // decoding position in image (countdown values) + int iLZWOff; // current LZW data offset + int iLZWSize; // current quantity of data in the LZW buffer + int iCommentPos; // file offset of start of comment data + short sCommentLen; // length of comment + GIF_READ_CALLBACK *pfnRead; + GIF_SEEK_CALLBACK *pfnSeek; + GIF_DRAW_CALLBACK *pfnDraw; + GIF_OPEN_CALLBACK *pfnOpen; + GIF_CLOSE_CALLBACK *pfnClose; + GIFFILE GIFFile; + void *pUser; + //unsigned char *pFrameBuffer; + unsigned int *pFrameBuffer; + unsigned char *pPixels, *pOldPixels; + unsigned char ucLineBuf[MAX_WIDTH]; // current line + unsigned char ucFileBuf[FILE_BUF_SIZE]; // holds temp data and pixel stack + unsigned short pPalette[384]; // can hold RGB565 or RGB888 - set in begin() + unsigned short pLocalPalette[384]; // color palettes for GIF images + unsigned char ucLZW[LZW_BUF_SIZE]; // holds 6 chunks (6x255) of GIF LZW data packed together + unsigned short usGIFTable[4096]; + unsigned char ucGIFPixels[8192]; + unsigned char bEndOfFrame; + unsigned char ucGIFBits, ucBackground, ucTransparent, ucCodeStart, ucMap, bUseLocalPalette; + unsigned char ucPaletteType; // RGB565 or RGB888 + unsigned char ucDrawType; // RAW or COOKED +} GIFIMAGE; + +// C interface +int GIF_openRAM(GIFIMAGE *pGIF, uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw); +int GIF_openFile(GIFIMAGE *pGIF, const char *szFilename, GIF_DRAW_CALLBACK *pfnDraw); +void GIF_close(GIFIMAGE *pGIF); +void GIF_begin(GIFIMAGE *pGIF, unsigned char ucPaletteType); +void GIF_reset(GIFIMAGE *pGIF); +int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser); +int GIF_getCanvasWidth(GIFIMAGE *pGIF); +int GIF_getCanvasHeight(GIFIMAGE *pGIF); +int GIF_getComment(GIFIMAGE *pGIF, char *destBuffer); +int GIF_getInfo(GIFIMAGE *pGIF, GIFINFO *pInfo); +int GIF_getLastError(GIFIMAGE *pGIF); +int GIF_getLoopCount(GIFIMAGE *pGIF); +int GIF_init(GIFIMAGE *pGIF); +void GIF_setDrawCallback(GIFIMAGE *pGIF, GIF_DRAW_CALLBACK *pfnDraw); +void GIF_scaleHalf(uint16_t *pCurrent, uint16_t *pPrev, int iWidth, int bBigEndian); + +// Due to unaligned memory causing an exception, we have to do these macros the slow way +#define INTELSHORT(p) ((*p) + (*(p + 1) << 8)) +#define INTELLONG(p) ((*p) + (*(p + 1) << 8) + (*(p + 2) << 16) + (*(p + 3) << 24)) +#define MOTOSHORT(p) (((*(p)) << 8) + (*(p + 1))) +#define MOTOLONG(p) (((*p) << 24) + ((*(p + 1)) << 16) + ((*(p + 2)) << 8) + (*(p + 3))) + +// Must be a 32-bit target processor +#define REGISTER_WIDTH 32 + +#endif // __ANIMATEDGIF__ diff --git a/lib/AnimatedGIF/README.md b/lib/AnimatedGIF/README.md new file mode 100644 index 0000000000..25b8cd59b7 --- /dev/null +++ b/lib/AnimatedGIF/README.md @@ -0,0 +1,5 @@ +This library is from the AnimatedGIF Arduino GIF decoder by Larry Bank. +Released under the Apache License 2.0 +[AnimatedGIF](https://github.com/bitbank2/AnimatedGIF) + +It has been modified for use in CircuitPython by Mark Komus. diff --git a/lib/AnimatedGIF/gif.c b/lib/AnimatedGIF/gif.c new file mode 100644 index 0000000000..0822b608c1 --- /dev/null +++ b/lib/AnimatedGIF/gif.c @@ -0,0 +1,1043 @@ +// +// GIF Animator +// written by Larry Bank +// bitbank@pobox.com +// Arduino port started 7/5/2020 +// Original GIF code written 20+ years ago :) +// The goal of this code is to decode images up to 480x320 +// using no more than 22K of RAM (if sent directly to an LCD display) +// +// Copyright 2020 BitBank Software, Inc. All Rights Reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//=========================================================================== +// +// Modified 2023 by Mark Komus to work for CircuitPython +// +#include "AnimatedGIF_circuitpy.h" + +#ifdef HAL_ESP32_HAL_H_ +#define memcpy_P memcpy +#endif + +static const unsigned char cGIFBits[9] = {1,4,4,4,8,8,8,8,8}; // convert odd bpp values to ones we can handle + +// forward references +static int GIFInit(GIFIMAGE *pGIF); +static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly); +static int GIFGetMoreData(GIFIMAGE *pPage); +static void GIFMakePels(GIFIMAGE *pPage, unsigned int code); +static int DecodeLZW(GIFIMAGE *pImage, int iOptions); +static int32_t readMem(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen); +static int32_t seekMem(GIFFILE *pFile, int32_t iPosition); +int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo); + +#if defined ( __LINUX__ ) || defined( __MCUXPRESSO ) +static int32_t readFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen); +static int32_t seekFile(GIFFILE *pFile, int32_t iPosition); +static void closeFile(void *handle); +#endif + +// C API +int GIF_openRAM(GIFIMAGE *pGIF, uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw) +{ + pGIF->iError = GIF_SUCCESS; + pGIF->pfnRead = readMem; + pGIF->pfnSeek = seekMem; + pGIF->pfnDraw = pfnDraw; + pGIF->pfnOpen = NULL; + pGIF->pfnClose = NULL; + pGIF->GIFFile.iSize = iDataSize; + pGIF->GIFFile.pData = pData; + return GIFInit(pGIF); +} /* GIF_openRAM() */ + +#ifdef __LINUX__ +int GIF_openFile(GIFIMAGE *pGIF, const char *szFilename, GIF_DRAW_CALLBACK *pfnDraw) +{ + pGIF->iError = GIF_SUCCESS; + pGIF->pfnRead = readFile; + pGIF->pfnSeek = seekFile; + pGIF->pfnDraw = pfnDraw; + pGIF->pfnOpen = NULL; + pGIF->pfnClose = closeFile; + pGIF->GIFFile.fHandle = fopen(szFilename, "r+b"); + if (pGIF->GIFFile.fHandle == NULL) + return 0; + fseek((FILE *)pGIF->GIFFile.fHandle, 0, SEEK_END); + pGIF->GIFFile.iSize = (int)ftell((FILE *)pGIF->GIFFile.fHandle); + fseek((FILE *)pGIF->GIFFile.fHandle, 0, SEEK_SET); + return GIFInit(pGIF); +} /* GIF_openFile() */ +#endif + +void GIF_close(GIFIMAGE *pGIF) +{ + if (pGIF->pfnClose) + (*pGIF->pfnClose)(pGIF->GIFFile.fHandle); +} /* GIF_close() */ + +void GIF_begin(GIFIMAGE *pGIF, unsigned char ucPaletteType) +{ + memset(pGIF, 0, sizeof(GIFIMAGE)); + pGIF->ucPaletteType = ucPaletteType; +} /* GIF_begin() */ + +void GIF_reset(GIFIMAGE *pGIF) +{ + (*pGIF->pfnSeek)(&pGIF->GIFFile, 0); +} /* GIF_reset() */ + +// +// Return value: +// 1 = good decode, more frames exist +// 0 = good decode, no more frames +// -1 = error +// +int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser) +{ +int rc; + + if (delayMilliseconds) + *delayMilliseconds = 0; // clear any old valid + if (pGIF->GIFFile.iPos >= pGIF->GIFFile.iSize-1) // no more data exists + { + (*pGIF->pfnSeek)(&pGIF->GIFFile, 0); // seek to start + } + if (GIFParseInfo(pGIF, 0)) + { + pGIF->pUser = pUser; + if (pGIF->iError == GIF_EMPTY_FRAME) // don't try to decode it + return 0; + rc = DecodeLZW(pGIF, 0); + if (rc != 0) // problem + return 0; + } + else + { + return 0; // error parsing the frame info, we may be at the end of the file + } + // Return 1 for more frames or 0 if this was the last frame + if (delayMilliseconds) // if not NULL, return the frame delay time + *delayMilliseconds = pGIF->iFrameDelay; + return (pGIF->GIFFile.iPos < pGIF->GIFFile.iSize-1); +} /* GIF_playFrame() */ + +int GIF_getCanvasWidth(GIFIMAGE *pGIF) +{ + return pGIF->iCanvasWidth; +} /* GIF_getCanvasWidth() */ + +int GIF_getCanvasHeight(GIFIMAGE *pGIF) +{ + return pGIF->iCanvasHeight; +} /* GIF_getCanvasHeight() */ + +int GIF_getLoopCount(GIFIMAGE *pGIF) +{ + return pGIF->iRepeatCount; +} /* GIF_getLoopCount() */ + +int GIF_getComment(GIFIMAGE *pGIF, char *pDest) +{ +int32_t iOldPos; + + iOldPos = pGIF->GIFFile.iPos; // keep old position + (*pGIF->pfnSeek)(&pGIF->GIFFile, pGIF->iCommentPos); + (*pGIF->pfnRead)(&pGIF->GIFFile, (uint8_t *)pDest, pGIF->sCommentLen); + (*pGIF->pfnSeek)(&pGIF->GIFFile, iOldPos); + pDest[pGIF->sCommentLen] = 0; // zero terminate the string + return (int)pGIF->sCommentLen; + +} /* GIF_getComment() */ + +int GIF_getLastError(GIFIMAGE *pGIF) +{ + return pGIF->iError; +} /* GIF_getLastError() */ + +int GIF_init(GIFIMAGE *pGIF) { + return GIFInit(pGIF); +} + +// +// Helper functions for memory based images +// +static int32_t readMem(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) +{ + int32_t iBytesRead; + + iBytesRead = iLen; + if ((pFile->iSize - pFile->iPos) < iLen) + iBytesRead = pFile->iSize - pFile->iPos; + if (iBytesRead <= 0) + return 0; + memmove(pBuf, &pFile->pData[pFile->iPos], iBytesRead); + pFile->iPos += iBytesRead; + return iBytesRead; +} /* readMem() */ + +#ifndef CIRCUITPY +static int32_t readFLASH(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) +{ + int32_t iBytesRead; + + iBytesRead = iLen; + if ((pFile->iSize - pFile->iPos) < iLen) + iBytesRead = pFile->iSize - pFile->iPos; + if (iBytesRead <= 0) + return 0; + memcpy_P(pBuf, &pFile->pData[pFile->iPos], iBytesRead); + pFile->iPos += iBytesRead; + return iBytesRead; +} /* readFLASH() */ +#endif + +static int32_t seekMem(GIFFILE *pFile, int32_t iPosition) +{ + if (iPosition < 0) iPosition = 0; + else if (iPosition >= pFile->iSize) iPosition = pFile->iSize-1; + pFile->iPos = iPosition; + return iPosition; +} /* seekMem() */ + +#if defined ( __LINUX__ ) || defined( __MCUXPRESSO ) +static void closeFile(void *handle) +{ + fclose((FILE *)handle); +} /* closeFile() */ + +static int32_t seekFile(GIFFILE *pFile, int32_t iPosition) +{ + if (iPosition < 0) iPosition = 0; + else if (iPosition >= pFile->iSize) iPosition = pFile->iSize-1; + pFile->iPos = iPosition; + fseek((FILE *)pFile->fHandle, iPosition, SEEK_SET); + return iPosition; +} /* seekMem() */ + +static int32_t readFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) +{ + int32_t iBytesRead; + + iBytesRead = iLen; + if ((pFile->iSize - pFile->iPos) < iLen) + iBytesRead = pFile->iSize - pFile->iPos; + if (iBytesRead <= 0) + return 0; + iBytesRead = (int)fread(pBuf, 1, iBytesRead, (FILE *)pFile->fHandle); + pFile->iPos += iBytesRead; + return iBytesRead; +} /* readFile() */ + +#endif // __LINUX__ +// +// The following functions are written in plain C and have no +// 3rd party dependencies, not even the C runtime library +// +// +// Initialize a GIF file and callback access from a file on SD or memory +// returns 1 for success, 0 for failure +// Fills in the canvas size of the GIFIMAGE structure +// +static int GIFInit(GIFIMAGE *pGIF) +{ + pGIF->GIFFile.iPos = 0; // start at beginning of file + if (!GIFParseInfo(pGIF, 1)) // gather info for the first frame + return 0; // something went wrong; not a GIF file? + (*pGIF->pfnSeek)(&pGIF->GIFFile, 0); // seek back to start of the file + if (pGIF->iCanvasWidth > MAX_WIDTH) { // need to allocate more space + pGIF->iError = GIF_TOO_WIDE; + return 0; + } + return 1; +} /* GIFInit() */ + +// +// Parse the GIF header, gather the size and palette info +// If called with bInfoOnly set to true, it will test for a valid file +// and return the canvas size only +// Returns 1 for success, 0 for failure +// +static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly) +{ + int i, j, iColorTableBits; + int iBytesRead; + unsigned char c, *p; + int32_t iOffset = 0; + int32_t iStartPos = pPage->GIFFile.iPos; // starting file position + int iReadSize; + + pPage->bUseLocalPalette = 0; // assume no local palette + pPage->bEndOfFrame = 0; // we're just getting started + pPage->iFrameDelay = 0; // may not have a gfx extension block + pPage->iRepeatCount = -1; // assume NETSCAPE loop count is not specified + iReadSize = (bInfoOnly) ? 12 : MAX_CHUNK_SIZE; + // If you try to read past the EOF, the SD lib will return garbage data + if (iStartPos + iReadSize > pPage->GIFFile.iSize) + iReadSize = (pPage->GIFFile.iSize - iStartPos - 1); + p = pPage->ucFileBuf; + iBytesRead = (*pPage->pfnRead)(&pPage->GIFFile, pPage->ucFileBuf, iReadSize); // 255 is plenty for now + + if (iBytesRead != iReadSize) // we're at the end of the file + { + pPage->iError = GIF_EARLY_EOF; + return 0; + } + if (iStartPos == 0) // start of the file + { // canvas size + if (memcmp(p, "GIF89", 5) != 0 && memcmp(p, "GIF87", 5) != 0) // not a GIF file + { + pPage->iError = GIF_BAD_FILE; + return 0; + } + pPage->iCanvasWidth = pPage->iWidth = INTELSHORT(&p[6]); + pPage->iCanvasHeight = pPage->iHeight = INTELSHORT(&p[8]); + pPage->iBpp = ((p[10] & 0x70) >> 4) + 1; + if (bInfoOnly) + return 1; // we've got the info we needed, leave + iColorTableBits = (p[10] & 7) + 1; // Log2(size) of the color table + pPage->ucBackground = p[11]; // background color + pPage->ucGIFBits = 0; + iOffset = 13; + if (p[10] & 0x80) // global color table? + { // by default, convert to byte-reversed RGB565 for immediate use + // Read enough additional data for the color table + iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], 3*(1<ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) + { + for (i=0; i<(1<> 3) << 11); // R + usRGB565 |= ((p[iOffset+1] >> 2) << 5); // G + usRGB565 |= (p[iOffset+2] >> 3); // B + if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE) + pPage->pPalette[i] = usRGB565; + else + pPage->pPalette[i] = __builtin_bswap16(usRGB565); // SPI wants MSB first + iOffset += 3; + } + } + else // just copy it as-is + { + memcpy(pPage->pPalette, &p[iOffset], (1<ucGIFBits = p[iOffset+1]; // packed fields + pPage->iFrameDelay = (INTELSHORT(&p[iOffset+2]))*10; // delay in ms + if (pPage->iFrameDelay <= 1) // 0-1 is going to make it run at 60fps; use 100 (10fps) as a reasonable substitute + pPage->iFrameDelay = 100; + if (pPage->ucGIFBits & 1) // transparent color is used + pPage->ucTransparent = p[iOffset+4]; // transparent color index + iOffset += 6; + } + // else // error + break; + case 0xff: /* App extension */ + c = 1; + while (c) /* Skip all data sub-blocks */ + { + c = p[iOffset++]; /* Block length */ + if ((iBytesRead - iOffset) < (c+32)) // need to read more data first + { + memmove(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset], (iBytesRead-iOffset)); // move existing data down + iBytesRead -= iOffset; + iStartPos += iOffset; + iOffset = 0; + iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], c+32); + } + if (c == 11) // fixed block length + { // Netscape app block contains the repeat count + if (memcmp(&p[iOffset], "NETSCAPE2.0", 11) == 0) + { + if (p[iOffset+11] == 3 && p[iOffset+12] == 1) // loop count + pPage->iRepeatCount = INTELSHORT(&p[iOffset+13]); + } + } + iOffset += (int)c; /* Skip to next sub-block */ + } + break; + case 0x01: /* Text extension */ + c = 1; + j = 0; + while (c) /* Skip all data sub-blocks */ + { + c = p[iOffset++]; /* Block length */ + if (j == 0) // use only first block + { + j = c; + if (j > 127) // max comment length = 127 + j = 127; + // memcpy(pPage->szInfo1, &p[iOffset], j); + // pPage->szInfo1[j] = '\0'; + j = 1; + } + iOffset += (int)c; /* Skip this sub-block */ + } + break; + case 0xfe: /* Comment */ + c = 1; + while (c) /* Skip all data sub-blocks */ + { + c = p[iOffset++]; /* Block length */ + if ((iBytesRead - iOffset) < (c+32)) // need to read more data first + { + memmove(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset], (iBytesRead-iOffset)); // move existing data down + iBytesRead -= iOffset; + iStartPos += iOffset; + iOffset = 0; + iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], c+32); + } + if (pPage->iCommentPos == 0) // Save first block info + { + pPage->iCommentPos = iStartPos + iOffset; + pPage->sCommentLen = c; + } + iOffset += (int)c; /* Skip this sub-block */ + } + break; + default: + /* Bad header info */ + pPage->iError = GIF_DECODE_ERROR; + return 0; + } /* switch */ + } + else // invalid byte, stop decoding + { + if (pPage->GIFFile.iSize - iStartPos < 32) // non-image bytes at end of file? + pPage->iError = GIF_EMPTY_FRAME; + else + /* Bad header info */ + pPage->iError = GIF_DECODE_ERROR; + return 0; + } + } /* while */ + if (p[iOffset] == ';') { // end of file, quit and return a correct error code + pPage->iError = GIF_EMPTY_FRAME; + return 1; + } + + if (p[iOffset] == ',') + iOffset++; + // This particular frame's size and position on the main frame (if animated) + pPage->iX = INTELSHORT(&p[iOffset]); + pPage->iY = INTELSHORT(&p[iOffset+2]); + pPage->iWidth = INTELSHORT(&p[iOffset+4]); + pPage->iHeight = INTELSHORT(&p[iOffset+6]); + iOffset += 8; + + /* Image descriptor + 7 6 5 4 3 2 1 0 M=0 - use global color map, ignore pixel + M I 0 0 0 pixel M=1 - local color map follows, use pixel + I=0 - Image in sequential order + I=1 - Image in interlaced order + pixel+1 = # bits per pixel for this image + */ + pPage->ucMap = p[iOffset++]; + if (pPage->ucMap & 0x80) // local color table? + {// by default, convert to byte-reversed RGB565 for immediate use + j = (1<<((pPage->ucMap & 7)+1)); + // Read enough additional data for the color table + iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], j*3); + if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) + { + for (i=0; i> 3) << 11); // R + usRGB565 |= ((p[iOffset+1] >> 2) << 5); // G + usRGB565 |= (p[iOffset+2] >> 3); // B + if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE) + pPage->pLocalPalette[i] = usRGB565; + else + pPage->pLocalPalette[i] = __builtin_bswap16(usRGB565); // SPI wants MSB first + iOffset += 3; + } + } + else // just copy it as-is + { + memcpy(pPage->pLocalPalette, &p[iOffset], j * 3); + iOffset += j*3; + } + pPage->bUseLocalPalette = 1; + } + pPage->ucCodeStart = p[iOffset++]; /* initial code size */ + /* Since GIF can be 1-8 bpp, we only allow 1,4,8 */ + pPage->iBpp = cGIFBits[pPage->ucCodeStart]; + // we are re-using the same buffer turning GIF file data + // into "pure" LZW + pPage->iLZWSize = 0; // we're starting with no LZW data yet + c = 1; // get chunk length + while (c && iOffset < iBytesRead) + { +// Serial.printf("iOffset=%d, iBytesRead=%d\n", iOffset, iBytesRead); + c = p[iOffset++]; // get chunk length +// Serial.printf("Chunk size = %d\n", c); + if (c <= (iBytesRead - iOffset)) + { + memcpy(&pPage->ucLZW[pPage->iLZWSize], &p[iOffset], c); + pPage->iLZWSize += c; + iOffset += c; + } + else // partial chunk in our buffer + { + int iPartialLen = (iBytesRead - iOffset); + memcpy(&pPage->ucLZW[pPage->iLZWSize], &p[iOffset], iPartialLen); + pPage->iLZWSize += iPartialLen; + iOffset += iPartialLen; + (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucLZW[pPage->iLZWSize], c - iPartialLen); + pPage->iLZWSize += (c - iPartialLen); + } + if (c == 0) + pPage->bEndOfFrame = 1; // signal not to read beyond the end of the frame + } +// seeking on an SD card is VERY VERY SLOW, so use the data we've already read by de-chunking it +// in this case, there's too much data, so we have to seek backwards a bit + if (iOffset < iBytesRead) + { +// Serial.printf("Need to seek back %d bytes\n", iBytesRead - iOffset); + (*pPage->pfnSeek)(&pPage->GIFFile, iStartPos + iOffset); // position file to new spot + } + return 1; // we are now at the start of the chunk data +} /* GIFParseInfo() */ +// +// Gather info about an animated GIF file +// +int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo) +{ + int iOff, iNumFrames; + int iDelay, iMaxDelay, iMinDelay, iTotalDelay; + int iReadAmount; + int iDataAvailable = 0; + int iDataRemaining = 0; + uint32_t lFileOff = 0; + int bDone = 0; + int bExt; + uint8_t c, *cBuf; + + iMaxDelay = iTotalDelay = 0; + iMinDelay = 10000; + iNumFrames = 1; + iDataRemaining = pPage->GIFFile.iSize; + cBuf = (uint8_t *) pPage->ucFileBuf; + (*pPage->pfnSeek)(&pPage->GIFFile, 0); + iDataAvailable = (*pPage->pfnRead)(&pPage->GIFFile, cBuf, FILE_BUF_SIZE); + iDataRemaining -= iDataAvailable; + lFileOff += iDataAvailable; + iOff = 10; + c = cBuf[iOff]; // get info bits + iOff += 3; /* Skip flags, background color & aspect ratio */ + if (c & 0x80) /* Deal with global color table */ + { + c &= 7; /* Get the number of colors defined */ + iOff += (2<pfnRead)(&pPage->GIFFile, &cBuf[iDataAvailable], FILE_BUF_SIZE-iDataAvailable); + iDataAvailable += iReadAmount; + iDataRemaining -= iReadAmount; + lFileOff += iReadAmount; + } + switch(cBuf[iOff]) + { + case 0x3b: /* End of file */ + /* we were fooled into thinking there were more pages */ + iNumFrames--; + goto gifpagesz; + // F9 = Graphic Control Extension (fixed length of 4 bytes) + // FE = Comment Extension + // FF = Application Extension + // 01 = Plain Text Extension + case 0x21: /* Extension block */ + if (cBuf[iOff+1] == 0xf9 && cBuf[iOff+2] == 4) // Graphic Control Extension + { + //cBuf[iOff+3]; // page disposition flags + iDelay = cBuf[iOff+4]; // delay low byte + iDelay |= ((uint16_t)(cBuf[iOff+5]) << 8); // delay high byte + if (iDelay < 2) // too fast, provide a default + iDelay = 2; + iDelay *= 10; // turn JIFFIES into milliseconds + iTotalDelay += iDelay; + if (iDelay > iMaxDelay) iMaxDelay = iDelay; + else if (iDelay < iMinDelay) iMinDelay = iDelay; + // (cBuf[iOff+6]; // transparent color index + } + iOff += 2; /* skip to length */ + iOff += (int)cBuf[iOff]; /* Skip the data block */ + iOff++; + // block terminator or optional sub blocks + c = cBuf[iOff++]; /* Skip any sub-blocks */ + while (c) + { + iOff += (int)c; + c = cBuf[iOff++]; + if ((iDataAvailable - iOff) < (c+258)) // need to read more data first + { + memmove(cBuf, &cBuf[iOff], (iDataAvailable-iOff)); // move existing data down + iDataAvailable -= iOff; + iOff = 0; + iReadAmount = (*pPage->pfnRead)(&pPage->GIFFile, &cBuf[iDataAvailable], FILE_BUF_SIZE-iDataAvailable); + iDataAvailable += iReadAmount; + iDataRemaining -= iReadAmount; + lFileOff += iReadAmount; + } + } + if (c != 0) // problem, we went past the end + { + iNumFrames--; // possible corrupt data; stop + goto gifpagesz; + } + break; + case 0x2c: /* Start of image data */ + bExt = 0; /* Stop doing extension blocks */ + break; + default: + /* Corrupt data, stop here */ + iNumFrames--; + goto gifpagesz; + } // switch + } // while + if (iOff >= iDataAvailable) // problem + { + iNumFrames--; // possible corrupt data; stop + goto gifpagesz; + } + /* Start of image data */ + c = cBuf[iOff+9]; /* Get the flags byte */ + iOff += 10; /* Skip image position and size */ + if (c & 0x80) /* Local color table */ + { + c &= 7; + iOff += (2<pfnRead)(&pPage->GIFFile, &cBuf[iDataAvailable], FILE_BUF_SIZE-iDataAvailable); + iDataAvailable += iReadAmount; + iDataRemaining -= iReadAmount; + lFileOff += iReadAmount; + } + c = cBuf[iOff++]; + while (c) /* While there are more data blocks */ + { + if (iOff > (3*FILE_BUF_SIZE/4) && iDataRemaining > 0) /* Near end of buffer, re-align */ + { + memmove(cBuf, &cBuf[iOff], (iDataAvailable-iOff)); // move existing data down + iDataAvailable -= iOff; + iOff = 0; + iReadAmount = (FILE_BUF_SIZE - iDataAvailable); + if (iReadAmount > iDataRemaining) + iReadAmount = iDataRemaining; + iReadAmount = (*pPage->pfnRead)(&pPage->GIFFile, &cBuf[iDataAvailable], iReadAmount); + iDataAvailable += iReadAmount; + iDataRemaining -= iReadAmount; + lFileOff += iReadAmount; + } + iOff += (int)c; /* Skip this data block */ +// if ((int)lFileOff + iOff > pPage->GIFFile.iSize) // past end of file, stop +// { +// iNumFrames--; // don't count this page +// break; // last page is corrupted, don't use it +// } + c = cBuf[iOff++]; /* Get length of next */ + } + /* End of image data, check for more pages... */ + if (cBuf[iOff] == 0x3b || (iDataRemaining == 0 && (iDataAvailable - iOff) < 32)) + { + bDone = 1; /* End of file has been reached */ + } + else /* More pages to scan */ + { + iNumFrames++; + // read new page data starting at this offset + if (pPage->GIFFile.iSize > FILE_BUF_SIZE && iDataRemaining > 0) // since we didn't read the whole file in one shot + { + memmove(cBuf, &cBuf[iOff], (iDataAvailable-iOff)); // move existing data down + iDataAvailable -= iOff; + iOff = 0; + iReadAmount = (FILE_BUF_SIZE - iDataAvailable); + if (iReadAmount > iDataRemaining) + iReadAmount = iDataRemaining; + iReadAmount = (*pPage->pfnRead)(&pPage->GIFFile, &cBuf[iDataAvailable], iReadAmount); + iDataAvailable += iReadAmount; + iDataRemaining -= iReadAmount; + lFileOff += iReadAmount; + } + } + } /* while !bDone */ +gifpagesz: + pInfo->iFrameCount = iNumFrames; + pInfo->iMaxDelay = iMaxDelay; + pInfo->iMinDelay = iMinDelay; + pInfo->iDuration = iTotalDelay; + return 1; +} /* GIF_getInfo() */ + +// +// Unpack more chunk data for decoding +// returns 1 to signify more data available for this image +// 0 indicates there is no more data +// +static int GIFGetMoreData(GIFIMAGE *pPage) +{ + int iDelta = (pPage->iLZWSize - pPage->iLZWOff); + unsigned char c = 1; + // move any existing data down + if (pPage->bEndOfFrame || iDelta >= (LZW_BUF_SIZE - MAX_CHUNK_SIZE) || iDelta <= 0) + return 1; // frame is finished or buffer is already full; no need to read more data + if (pPage->iLZWOff != 0) + { +// NB: memcpy() fails on some systems because the src and dest ptrs overlap +// so copy the bytes in a simple loop to avoid problems + for (int i=0; iiLZWSize - pPage->iLZWOff; i++) { + pPage->ucLZW[i] = pPage->ucLZW[i + pPage->iLZWOff]; + } + pPage->iLZWSize -= pPage->iLZWOff; + pPage->iLZWOff = 0; + } + while (c && pPage->GIFFile.iPos < pPage->GIFFile.iSize && pPage->iLZWSize < (LZW_BUF_SIZE-MAX_CHUNK_SIZE)) + { + (*pPage->pfnRead)(&pPage->GIFFile, &c, 1); // current length + (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucLZW[pPage->iLZWSize], c); + pPage->iLZWSize += c; + } + if (c == 0) // end of frame + pPage->bEndOfFrame = 1; + return (c != 0 && pPage->GIFFile.iPos < pPage->GIFFile.iSize); // more data available? +} /* GIFGetMoreData() */ +// +// Handle transparent pixels and disposal method +// Used only when a frame buffer is allocated +// +static void DrawNewPixels(GIFIMAGE *pPage, GIFDRAW *pDraw) +{ + uint8_t *d, *s; + int x, iPitch = pPage->iCanvasWidth; + + s = pDraw->pPixels; + d = (uint8_t*)&pPage->pFrameBuffer[pDraw->iX + (pDraw->y + pDraw->iY) * iPitch]; // dest pointer in our complete canvas buffer + if (pDraw->ucDisposalMethod == 2) // restore to background color + { + memset(d, pDraw->ucBackground, pDraw->iWidth); + } + // Apply the new pixels to the main image + if (pDraw->ucHasTransparency) // if transparency used + { + uint8_t c, ucTransparent = pDraw->ucTransparent; + for (x=0; xiWidth; x++) + { + c = *s++; + if (c != ucTransparent) + *d = c; + d++; + } + } + else + { + memcpy(d, s, pDraw->iWidth); // just overwrite the old pixels + } +} /* DrawNewPixels() */ +// +// Convert current line of pixels through the palette +// to either RGB565 or RGB888 output +// Used only when a frame buffer has been allocated +// +static void ConvertNewPixels(GIFIMAGE *pPage, GIFDRAW *pDraw) +{ + uint8_t *d, *s; + int x; + + s = (uint8_t*)&pPage->pFrameBuffer[(pPage->iCanvasWidth * (pDraw->iY + pDraw->y)) + pDraw->iX]; + d = (uint8_t*)&pPage->pFrameBuffer[pPage->iCanvasHeight * pPage->iCanvasWidth]; // point past bottom of frame buffer + if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) + { + uint16_t *pPal, *pu16; + pPal = (uint16_t *)pDraw->pPalette; + pu16 = (uint16_t *)&pPage->pFrameBuffer[pPage->iCanvasHeight * pPage->iCanvasWidth]; + for (x=0; xiWidth; x++) + { + *pu16++ = pPal[*s++]; // convert to RGB565 pixels + } + } + else + { + uint8_t *pPal; + int pixel; + pPal = (uint8_t *)pDraw->pPalette; + for (x=0; xiWidth; x++) + { + pixel = *s++; + *d++ = pPal[(pixel * 3) + 0]; // convert to RGB888 pixels + *d++ = pPal[(pixel * 3) + 1]; + *d++ = pPal[(pixel * 3) + 2]; + } + } +} /* ConvertNewPixels() */ + +// +// GIFMakePels +// +static void GIFMakePels(GIFIMAGE *pPage, unsigned int code) +{ + int iPixCount; + unsigned short *giftabs; + unsigned char *buf, *s, *pEnd, *gifpels; + unsigned char ucNeedMore = 0; + /* Copy this string of sequential pixels to output buffer */ + // iPixCount = 0; + s = pPage->ucFileBuf + FILE_BUF_SIZE; /* Pixels will come out in reversed order */ + buf = pPage->ucLineBuf + (pPage->iWidth - pPage->iXCount); + giftabs = pPage->usGIFTable; + gifpels = &pPage->ucGIFPixels[PIXEL_LAST]; + while (code < LINK_UNUSED) + { + if (s == pPage->ucFileBuf) /* Houston, we have a problem */ + { + return; /* Exit with error */ + } + *(--s) = gifpels[code]; + code = giftabs[code]; + } + iPixCount = (int)(intptr_t)(pPage->ucFileBuf + FILE_BUF_SIZE - s); + + while (iPixCount && pPage->iYCount > 0) + { + if (pPage->iXCount > iPixCount) /* Pixels fit completely on the line */ + { + // memcpy(buf, s, iPixCount); + // buf += iPixCount; + pEnd = buf + iPixCount; + while (buf < pEnd) + { + *buf++ = *s++; + } + pPage->iXCount -= iPixCount; + // iPixCount = 0; + if (ucNeedMore) + GIFGetMoreData(pPage); // check if we need to read more LZW data every 4 lines + return; + } + else /* Pixels cross into next line */ + { + GIFDRAW gd; + pEnd = buf + pPage->iXCount; + while (buf < pEnd) + { + *buf++ = *s++; + } + iPixCount -= pPage->iXCount; + pPage->iXCount = pPage->iWidth; /* Reset pixel count */ + // Prepare GIDRAW structure for callback + gd.iX = pPage->iX; + gd.iY = pPage->iY; + gd.iWidth = pPage->iWidth; + gd.iHeight = pPage->iHeight; + gd.pPixels = pPage->ucLineBuf; + gd.pPalette = (pPage->bUseLocalPalette) ? pPage->pLocalPalette : pPage->pPalette; + gd.pPalette24 = (uint8_t *)gd.pPalette; // just cast the pointer for RGB888 + gd.ucIsGlobalPalette = pPage->bUseLocalPalette==1?0:1; + gd.y = pPage->iHeight - pPage->iYCount; + // Ugly logic to handle the interlaced line position, but it + // saves having to have another set of state variables + if (pPage->ucMap & 0x40) { // interlaced? + int height = pPage->iHeight-1; + if (gd.y > height / 2) + gd.y = gd.y * 2 - (height | 1); + else if (gd.y > height / 4) + gd.y = gd.y * 4 - ((height & ~1) | 2); + else if (gd.y > height / 8) + gd.y = gd.y * 8 - ((height & ~3) | 4); + else + gd.y = gd.y * 8; + } + gd.ucDisposalMethod = (pPage->ucGIFBits & 0x1c)>>2; + gd.ucTransparent = pPage->ucTransparent; + gd.ucHasTransparency = pPage->ucGIFBits & 1; + gd.ucBackground = pPage->ucBackground; + gd.pUser = pPage->pUser; + if (pPage->pFrameBuffer) // update the frame buffer + { + DrawNewPixels(pPage, &gd); + if (pPage->ucDrawType == GIF_DRAW_COOKED) + { + ConvertNewPixels(pPage, &gd); // prepare for output + gd.pPixels = (uint8_t*)&pPage->pFrameBuffer[pPage->iCanvasWidth * pPage->iCanvasHeight]; + } + } + (*pPage->pfnDraw)(&gd); // callback to handle this line + pPage->iYCount--; + buf = pPage->ucLineBuf; + if ((pPage->iYCount & 3) == 0) // since we support only small images... + ucNeedMore = 1; + } + } /* while */ + if (ucNeedMore) + GIFGetMoreData(pPage); // check if we need to read more LZW data every 4 lines + return; +} /* GIFMakePels() */ +// +// Macro to extract a variable length code +// +#define GET_CODE if (bitnum > (REGISTER_WIDTH - codesize)) { pImage->iLZWOff += (bitnum >> 3); \ + bitnum &= 7; ulBits = INTELLONG(&p[pImage->iLZWOff]); } \ + code = (unsigned short) (ulBits >> bitnum); /* Read a 32-bit chunk */ \ + code &= sMask; bitnum += codesize; + +// +// Decode LZW into an image +// +static int DecodeLZW(GIFIMAGE *pImage, int iOptions) +{ + int i, bitnum; + unsigned short oldcode, codesize, nextcode, nextlim; + unsigned short *giftabs, cc, eoi; + signed short sMask; + unsigned char *gifpels, *p; + // int iStripSize; + //unsigned char **index; + uint32_t ulBits; + unsigned short code; + (void)iOptions; // not used for now + // if output can be used for string table, do it faster + // if (bGIF && (OutPage->cBitsperpixel == 8 && ((OutPage->iWidth & 3) == 0))) + // return PILFastLZW(InPage, OutPage, bGIF, iOptions); + p = pImage->ucLZW; // un-chunked LZW data + sMask = 0xffff << (pImage->ucCodeStart + 1); + sMask = 0xffff - sMask; + cc = (sMask >> 1) + 1; /* Clear code */ + eoi = cc + 1; + giftabs = pImage->usGIFTable; + gifpels = pImage->ucGIFPixels; + pImage->iYCount = pImage->iHeight; // count down the lines + pImage->iXCount = pImage->iWidth; + bitnum = 0; + pImage->iLZWOff = 0; // Offset into compressed data + GIFGetMoreData(pImage); // Read some data to start + + // Initialize code table + // this part only needs to be initialized once + for (i = 0; i < cc; i++) + { + gifpels[PIXEL_FIRST + i] = gifpels[PIXEL_LAST + i] = (unsigned short) i; + giftabs[i] = LINK_END; + } +init_codetable: + codesize = pImage->ucCodeStart + 1; + sMask = 0xffff << (pImage->ucCodeStart + 1); + sMask = 0xffff - sMask; + nextcode = cc + 2; + nextlim = (unsigned short) ((1 << codesize)); + // This part of the table needs to be reset multiple times + memset(&giftabs[cc], LINK_UNUSED, (4096 - cc)*sizeof(short)); + ulBits = INTELLONG(&p[pImage->iLZWOff]); // start by reading 4 bytes of LZW data + GET_CODE + if (code == cc) // we just reset the dictionary, so get another code + { + GET_CODE + } + oldcode = code; + GIFMakePels(pImage, code); // first code is output as the first pixel + // Main decode loop + while (code != eoi && pImage->iYCount > 0) // && y < pImage->iHeight+1) /* Loop through all lines of the image (or strip) */ + { + GET_CODE + if (code == cc) /* Clear code?, and not first code */ + goto init_codetable; + if (code != eoi) + { + if (nextcode < nextlim) // for deferred cc case, don't let it overwrite the last entry (fff) + { + giftabs[nextcode] = oldcode; + gifpels[PIXEL_FIRST + nextcode] = gifpels[PIXEL_FIRST + oldcode]; + if (giftabs[code] == LINK_UNUSED) /* Old code */ + gifpels[PIXEL_LAST + nextcode] = gifpels[PIXEL_FIRST + oldcode]; + else + gifpels[PIXEL_LAST + nextcode] = gifpels[PIXEL_FIRST + code]; + } + nextcode++; + if (nextcode >= nextlim && codesize < 12) + { + codesize++; + nextlim <<= 1; + sMask = (sMask << 1) | 1; + } + GIFMakePels(pImage, code); + oldcode = code; + } + } /* while not end of LZW code stream */ + return 0; +//gif_forced_error: +// free(pImage->pPixels); +// pImage->pPixels = NULL; +// return -1; +} /* DecodeLZW() */ + +void GIF_setDrawCallback(GIFIMAGE *pGIF, GIF_DRAW_CALLBACK *pfnDraw) +{ + pGIF->pfnDraw = pfnDraw; +} /* GIF_setDrawCallback() */ +// +// Scale 2 scanlines down by 50% with pixel averaging +// writes new values over previous line +// expects RGB565 little endian pixels as input +// +void GIF_scaleHalf(uint16_t *pCurrent, uint16_t *pPrev, int iWidth, int bBigEndian) +{ +int x; +uint16_t *d = pPrev; +uint32_t gSum, rbSum, pix0,pix1,pix2,pix3; +const uint32_t RBMask = 0xf81f, GMask = 0x7e0; + + for (x=0; x> 2) & GMask; // for rounding towards 1 + rbSum = (pix0 & RBMask) + (pix1 & RBMask) + (pix2 & RBMask) + (pix3 & RBMask); + rbSum = ((rbSum + 0x1002) >> 2) & RBMask; + if (bBigEndian) + *d++ = __builtin_bswap16((uint16_t)(gSum + rbSum)); + else + *d++ = (uint16_t)(gSum + rbSum); // store finished pixel + } // for x +} /* GIF_scaleHalf() */ diff --git a/lib/oofatfs/ff.c b/lib/oofatfs/ff.c index 9d3c67cf7d..dbcfa3efc3 100644 --- a/lib/oofatfs/ff.c +++ b/lib/oofatfs/ff.c @@ -278,6 +278,12 @@ typedef struct { /* SBCS up-case tables (\x80-\xFF) */ +// Optimize the 437-only case with a truncated lookup table. +#if FF_CODE_PAGE == 437 +#define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5} +#else #define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ @@ -286,6 +292,7 @@ typedef struct { 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#endif #define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ @@ -2887,7 +2894,12 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not } #elif FF_CODE_PAGE < 900 /* SBCS cfg */ wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ + // Optimize the 437-only case with a truncated lookup table. +#if FF_CODE_PAGE == 437 + if (wc & 0x80 && wc < (0xA5 - 0x80)) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ +#else if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ +#endif #else /* DBCS cfg */ wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ #endif diff --git a/lib/oofatfs/ffunicode.c b/lib/oofatfs/ffunicode.c index 4153f9131c..a04577616a 100644 --- a/lib/oofatfs/ffunicode.c +++ b/lib/oofatfs/ffunicode.c @@ -499,6 +499,13 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ DWORD uni /* Unicode code point to be up-converted */ ) { + #if FF_FS_CASE_INSENSITIVE_COMPARISON_ASCII_ONLY + // Only uppercase ASCII characters. Everything else will require the user to + // pass in an uppercase version. + if ('a' <= uni && uni <= 'z') { + uni -= 32; + } + #else const WORD *p; WORD uc, bc, nc, cmd; static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ @@ -619,6 +626,7 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ } uni = uc; } + #endif return uni; } diff --git a/locale/ID.po b/locale/ID.po index 8c0b3066f8..f6960665b4 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -30,6 +30,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -139,7 +147,7 @@ msgstr "%q indeks di luar batas" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -183,6 +191,10 @@ msgstr "%q harus <= %d" msgid "%q must be >= %d" msgstr "%q harus >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -217,10 +229,6 @@ msgstr "" msgid "%q out of range" msgstr "%q di luar jangkauan" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "pin %q tidak valid" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -237,7 +245,7 @@ msgstr "%q, %q, dan %q semuanya harus memiliki panjang yang sama" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s kesalahan 0x%x" @@ -505,6 +513,7 @@ msgstr "Sudah disebarkan." msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -678,7 +687,7 @@ msgstr "Blok CBC harus merupakan kelipatan 16 byte" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -815,6 +824,14 @@ msgid "" msgstr "" "Koneksi telah terputus dan tidak dapat lagi digunakan. Buat koneksi baru." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "File .mpy rusak" @@ -1066,7 +1083,7 @@ msgstr "Fungsinya membutuhkan kunci" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1225,9 +1242,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "%q pada tidak valid" @@ -1249,8 +1268,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Argumen tidak valid" @@ -1276,7 +1294,7 @@ msgstr "Ukuran potongan format tidak valid" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1285,7 +1303,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1317,7 +1335,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1678,11 +1696,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "Waktu habis" @@ -1690,7 +1708,7 @@ msgstr "Waktu habis" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Kehabisan memori" @@ -1873,7 +1891,7 @@ msgstr "Baca-saja" msgid "Read-only filesystem" msgstr "sistem file (filesystem) bersifat Read-only" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1893,7 +1911,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "Mode AES yang diminta tidak didukung" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -2008,10 +2026,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Berikan setidaknya satu pin UART" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2191,6 +2205,11 @@ msgstr "Tidak dapat mengalokasikan buffer untuk signed conversion" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2209,10 +2228,20 @@ msgstr "Tidak dapat menemukan GCLK yang kosong" msgid "Unable to init parser" msgstr "Tidak dapat memulai parser" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Tidak dapat membaca data palet warna" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2337,7 +2366,7 @@ msgstr "Panjang nilai != Panjang tetap yang dibutuhkan" msgid "Value length > max_length" msgstr "Panjang nilai > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2415,6 +2444,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4149,8 +4186,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: 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" @@ -4372,6 +4407,12 @@ msgstr "zi harus berjenis float" msgid "zi must be of shape (n_section, 2)" msgstr "Zi harus berbentuk (n_section, 2)" +#~ msgid "Supply at least one UART pin" +#~ msgstr "Berikan setidaknya satu pin UART" + +#~ msgid "%q pin invalid" +#~ msgstr "pin %q tidak valid" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 082ea7bfa9..560dffe6a4 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -28,6 +28,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -136,7 +144,7 @@ msgstr "" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -180,6 +188,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -214,10 +226,6 @@ msgstr "" msgid "%q out of range" msgstr "" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -234,7 +242,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "" @@ -502,6 +510,7 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -673,7 +682,7 @@ msgstr "" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -805,6 +814,14 @@ msgid "" "connection." msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -1056,7 +1073,7 @@ msgstr "" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1213,9 +1230,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "" @@ -1237,8 +1256,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "" @@ -1264,7 +1282,7 @@ msgstr "" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1273,7 +1291,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1305,7 +1323,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1661,11 +1679,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1673,7 +1691,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1849,7 +1867,7 @@ msgstr "" msgid "Read-only filesystem" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1869,7 +1887,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -1982,10 +2000,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2165,6 +2179,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2183,10 +2202,20 @@ msgstr "" msgid "Unable to init parser" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2309,7 +2338,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2387,6 +2416,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4120,8 +4157,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "" diff --git a/locale/cs.po b/locale/cs.po index c18e714f75..0ffdbdcc67 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -32,6 +32,14 @@ msgstr "" "\n" "Kód byl zastaven kvůli automatickému načtení. K načtení dojde brzy.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -140,7 +148,7 @@ msgstr "Index %q je mimo rozsah" msgid "%q init failed" msgstr "Inicializace %q selhala" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -184,6 +192,10 @@ msgstr "%q musí být <= %d" msgid "%q must be >= %d" msgstr "%q musí být >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -218,10 +230,6 @@ msgstr "%q je mimo hranice" msgid "%q out of range" msgstr "%q je mimo rozsah" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "pin %q není platný" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -238,7 +246,7 @@ msgstr "%q, %q, a %q musí mít všechny shodnou délku" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s chyba 0x%x" @@ -506,6 +514,7 @@ msgstr "Již propagujeme." msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -679,7 +688,7 @@ msgstr "Bloky CBC musí být násobky 16 bajtů" msgid "CIRCUITPY drive could not be found or created." msgstr "Disk CIRCUITPY nelze nalézt nebo vytvořit." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -813,6 +822,14 @@ msgid "" msgstr "" "Připojení bylo odpojeno a nelze jej dále používat. Vytvořte nové připojení." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Poškozený soubor .mpy" @@ -1066,7 +1083,7 @@ msgstr "Funkce vyžaduje zámek" msgid "GNSS init" msgstr "Inicializace GNSS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Základní chyba" @@ -1225,9 +1242,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Neplatný pin %q" @@ -1249,8 +1268,7 @@ msgstr "Chybné BSSID" msgid "Invalid MAC address" msgstr "Chybná MAC adresa" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Neplatný argument" @@ -1276,7 +1294,7 @@ msgstr "Neplatná velikost bloku" msgid "Invalid multicast MAC address" msgstr "Chybná multicastová MAC adresa" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Chybná velikost" @@ -1285,7 +1303,7 @@ msgstr "Chybná velikost" msgid "Invalid socket for TLS" msgstr "Chybný soket pro TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Chybný stav" @@ -1317,7 +1335,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC adresa byla chybná" @@ -1674,11 +1692,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1686,7 +1704,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1864,7 +1882,7 @@ msgstr "" msgid "Read-only filesystem" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1884,7 +1902,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -1997,10 +2015,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2180,6 +2194,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2198,10 +2217,20 @@ msgstr "" msgid "Unable to init parser" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2324,7 +2353,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2402,6 +2431,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4135,8 +4172,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "" @@ -4358,6 +4393,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q pin invalid" +#~ msgstr "pin %q není platný" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/de_DE.po b/locale/de_DE.po index 4569dfb508..9f2c83e8cc 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: 2023-01-13 18:51+0000\n" +"PO-Revision-Date: 2023-03-01 17:39+0000\n" "Last-Translator: Ettore Atalan \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 4.15.1-dev\n" +"X-Generator: Weblate 4.16\n" #: main.c msgid "" @@ -31,6 +31,18 @@ msgstr "" "\n" "Code wurde durch automatisches Neuladen gestoppt. Wird bald neu geladen.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" +"\n" +"Ungültige CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\n" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -49,6 +61,8 @@ msgid "" "\n" "You are in safe mode because:\n" msgstr "" +"\n" +"Sie befinden sich im abgesicherten Modus, weil:\n" #: py/obj.c msgid " File \"%q\"" @@ -141,7 +155,7 @@ msgstr "Der Index %q befindet sich außerhalb des Bereiches" msgid "%q init failed" msgstr "%q Initialisierung ist gescheitert" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%q ist %q" @@ -185,6 +199,10 @@ msgstr "%q muss <= %d sein" msgid "%q must be >= %d" msgstr "%q muss >= %d sein" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -220,10 +238,6 @@ msgstr "%q außerhalb der Grenzen" msgid "%q out of range" msgstr "%q außerhalb des Bereichs" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q Pin ungültig" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "Schritt %q kann nicht Null sein" @@ -241,7 +255,7 @@ msgstr "%q, %q und %q müssen alle die gleiche Länge haben" msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s Fehler 0x%x" @@ -509,6 +523,7 @@ msgstr "Bereits am Anbieten (advertising)." msgid "Already have all-matches listener" msgstr "All-Matchers-Listener bereits vorhanden" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -682,7 +697,7 @@ msgstr "CBC-Blöcke müssen ein Vielfaches von 16 Bytes sein" msgid "CIRCUITPY drive could not be found or created." msgstr "CIRCUITPY-Laufwerk konnte nicht gefunden oder erzeugt werden." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC oder Checksumme ungültig" @@ -821,6 +836,14 @@ msgstr "" "Die Verbindung wurde getrennt und kann nicht mehr verwendet werden. Erstelle " "eine neue Verbindung." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Beschädigte .mpy Datei" @@ -1079,7 +1102,7 @@ msgstr "Die Funktion erwartet, dass der 'lock'-Befehl zuvor ausgeführt wurde" msgid "GNSS init" msgstr "GNSS-Initialisierung" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Generischer Fehler" @@ -1242,9 +1265,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "Ungültiger %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Ungültiger %q Pin" @@ -1266,8 +1291,7 @@ msgstr "Ungültige BSSID" msgid "Invalid MAC address" msgstr "Ungültige MAC-Adresse" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Ungültiges Argument" @@ -1293,7 +1317,7 @@ msgstr "Ungültige format chunk size" msgid "Invalid multicast MAC address" msgstr "Ungültige Multicast-MAC-Adresse" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Ungültige Größe" @@ -1302,7 +1326,7 @@ msgstr "Ungültige Größe" msgid "Invalid socket for TLS" msgstr "Ungültiges Socket für TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Ungültiger Zustand" @@ -1334,7 +1358,7 @@ msgstr "Ebene ist bereits in der Gruppe" msgid "Layer must be a Group or TileGrid subclass" msgstr "Ebene muss eine Gruppe oder eine TileGrid Subklasse sein" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC Adresse war ungültig" @@ -1697,11 +1721,11 @@ msgstr "Nur eine Farbe kann transparent sein zu einer Zeit" msgid "Operation not permitted" msgstr "Operation nicht erlaubt" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "Vorgang oder Funktion wird nicht unterstützt" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "Zeit für Vorgang abgelaufen" @@ -1709,7 +1733,7 @@ msgstr "Zeit für Vorgang abgelaufen" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Kein Speicher mehr verfügbar" @@ -1891,7 +1915,7 @@ msgstr "Nur lesen möglich, da Schreibgeschützt" msgid "Read-only filesystem" msgstr "Schreibgeschützte Dateisystem" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "Erhaltene Antwort ist ungültig" @@ -1911,7 +1935,7 @@ msgstr "RemoteTransmissionRequests limitiert auf 8 Bytes" msgid "Requested AES mode is unsupported" msgstr "Der angeforderte AES-Modus wird nicht unterstützt" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "Angefragte Ressource nicht gefunden" @@ -2024,10 +2048,6 @@ msgstr "Stereo rechts muss sich auf PWM-Kanal B befinden" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Gib mindestens einen UART-Pin an" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "Gib entweder monotonic_time oder epoch_time an" @@ -2213,6 +2233,11 @@ msgstr "Konnte keine Buffer für Vorzeichenumwandlung allozieren" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "Lock kann nicht erzeugt werden" @@ -2231,10 +2256,20 @@ msgstr "Konnte keinen freien GCLK finden" msgid "Unable to init parser" msgstr "Parser konnte nicht gestartet werden" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Konnte Farbpalettendaten nicht lesen" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2361,7 +2396,7 @@ msgstr "Wert Länge != Erforderliche feste Länge" msgid "Value length > max_length" msgstr "Länge des Wertes > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "Version ist ungültig" @@ -2449,6 +2484,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4207,8 +4250,6 @@ msgstr "twai_driver_install gab esp-idf-Fehler zurück #%d" msgid "twai_start returned esp-idf error #%d" msgstr "twai_start gab esp-idf-Fehler zurück #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx und rx können nicht beide None sein" @@ -4432,6 +4473,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Gib mindestens einen UART-Pin an" + +#~ msgid "%q pin invalid" +#~ msgstr "%q Pin ungültig" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/el.po b/locale/el.po index c939577cd5..81118aa8fd 100644 --- a/locale/el.po +++ b/locale/el.po @@ -35,6 +35,14 @@ msgstr "" "Ο κώδικας σταμάτησε λόγω της αυτόματης επαναφόρτωσης. Η επαναφόρτωση θα " "γίνει σύντομα.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -144,7 +152,7 @@ msgstr "%q δείκτης εκτός εμβέλειας" msgid "%q init failed" msgstr "%q εκκίνηση απέτυχε" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -188,6 +196,10 @@ msgstr "%q πρέπει να είναι <= %d" msgid "%q must be >= %d" msgstr "%q πρέπει να είναι >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -222,10 +234,6 @@ msgstr "%q εκτός ορίων" msgid "%q out of range" msgstr "%q εκτός εμβέλειας" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q άκυρο pin" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -242,7 +250,7 @@ msgstr "%q, %q, και %q πρέπει να είναι όλα του ιδίου msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s σφάλμα 0x%x" @@ -511,6 +519,7 @@ msgstr "Ήδη διαφημίζουμε." msgid "Already have all-matches listener" msgstr "Ύπάρχει ήδη all-matches ακροατής" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -684,7 +693,7 @@ msgstr "CBC blocks πρέπει να είναι πολλαπλάσια του 16 msgid "CIRCUITPY drive could not be found or created." msgstr "Ο CIRCUITPY δίσκος δεν μπόρεσε να βρεθεί ή να δημιουργηθεί." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC ή checksum ήταν άκυρο" @@ -826,6 +835,14 @@ msgstr "" "Έχει γίνει αποσύνδεση και αυτή η συνδεση δεν μπορεί να χρησιμοποιηθεί. " "Δημιουργήστε μια νέα σύνδεση." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Κατεστραμένο .mpy αρχείο" @@ -1077,7 +1094,7 @@ msgstr "" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1234,9 +1251,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "" @@ -1258,8 +1277,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "" @@ -1285,7 +1303,7 @@ msgstr "" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1294,7 +1312,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1326,7 +1344,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1682,11 +1700,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1694,7 +1712,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1872,7 +1890,7 @@ msgstr "" msgid "Read-only filesystem" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1892,7 +1910,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -2005,10 +2023,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2188,6 +2202,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2206,10 +2225,20 @@ msgstr "" msgid "Unable to init parser" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2332,7 +2361,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2410,6 +2439,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4143,8 +4180,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "" @@ -4366,6 +4401,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q pin invalid" +#~ msgstr "%q άκυρο pin" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/en_GB.po b/locale/en_GB.po index e960651197..9ced3137b9 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -34,6 +34,14 @@ msgstr "" "\n" "Code stopped by auto-reload. Reloading soon.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -143,7 +151,7 @@ msgstr "%q index out of range" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -187,6 +195,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "%q must be >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -221,10 +233,6 @@ msgstr "" msgid "%q out of range" msgstr "%q out of range" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q pin invalid" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -241,7 +249,7 @@ msgstr "%q, %q, and %q must all be the same length" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s error 0x%x" @@ -509,6 +517,7 @@ msgstr "Already advertising." msgid "Already have all-matches listener" msgstr "Already have all-matches listener" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -682,7 +691,7 @@ msgstr "CBC blocks must be multiples of 16 bytes" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC or checksum was invalid" @@ -816,6 +825,14 @@ msgstr "" "Connection has been disconnected and can no longer be used. Create a new " "connection." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Corrupt .mpy file" @@ -1067,7 +1084,7 @@ msgstr "Function requires lock" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Generic Failure" @@ -1226,9 +1243,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "Invalid %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Invalid %q pin" @@ -1250,8 +1269,7 @@ msgstr "Invalid BSSID" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Invalid argument" @@ -1277,7 +1295,7 @@ msgstr "Invalid format chunk size" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Invalid size" @@ -1286,7 +1304,7 @@ msgstr "Invalid size" msgid "Invalid socket for TLS" msgstr "Invalid socket for TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Invalid state" @@ -1318,7 +1336,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC address was invalid" @@ -1678,11 +1696,11 @@ msgstr "Only one colour can be transparent at a time" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "Operation or feature not supported" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "Operation timed out" @@ -1690,7 +1708,7 @@ msgstr "Operation timed out" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Out of memory" @@ -1870,7 +1888,7 @@ msgstr "Read-only" msgid "Read-only filesystem" msgstr "Read-only filesystem" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "Received response was invalid" @@ -1890,7 +1908,7 @@ msgstr "RemoteTransmissionRequests limited to 8 bytes" msgid "Requested AES mode is unsupported" msgstr "Requested AES mode is unsupported" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "Requested resource not found" @@ -2003,10 +2021,6 @@ msgstr "Stereo right must be on PWM channel B" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Supply at least one UART pin" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "Supply one of monotonic_time or epoch_time" @@ -2186,6 +2200,11 @@ msgstr "Unable to allocate buffers for signed conversion" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "Unable to create lock" @@ -2204,10 +2223,20 @@ msgstr "Unable to find free GCLK" msgid "Unable to init parser" msgstr "Unable to init parser" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Unable to read colour palette data" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2332,7 +2361,7 @@ msgstr "Value length != required fixed length" msgid "Value length > max_length" msgstr "Value length > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "Version was invalid" @@ -2410,6 +2439,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4146,8 +4183,6 @@ msgstr "twai_driver_install returned esp-idf error #%d" msgid "twai_start returned esp-idf error #%d" msgstr "twai_start returned esp-idf error #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx and rx cannot both be None" @@ -4369,6 +4404,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Supply at least one UART pin" + +#~ msgid "%q pin invalid" +#~ msgstr "%q pin invalid" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/es.po b/locale/es.po index 3ca89f4430..ee2af9d603 100644 --- a/locale/es.po +++ b/locale/es.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-02-17 20:38+0000\n" +"PO-Revision-Date: 2023-03-09 10:38+0000\n" "Last-Translator: Jose David M \n" "Language-Team: \n" "Language: es\n" @@ -16,7 +16,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 4.16-dev\n" +"X-Generator: Weblate 4.16.2-dev\n" #: main.c msgid "" @@ -34,6 +34,18 @@ msgstr "" "\n" "Código detenido por la auto-recarga. Recargando pronto.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" +"\n" +"CIRCUITPY_PYSTACK_SIZE inválido\n" +"\n" +"\n" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -50,7 +62,7 @@ msgid "" "Press reset to exit safe mode.\n" msgstr "" "\n" -"Presione reset para salir de safe mode.\n" +"Presione reset para salir del modo seguro.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -58,7 +70,7 @@ msgid "" "You are in safe mode because:\n" msgstr "" "\n" -"Estas in safe mode porque:\n" +"Estas en modo seguro porque:\n" #: py/obj.c msgid " File \"%q\"" @@ -145,13 +157,13 @@ msgstr "%q está siendo utilizado" #: py/objstr.c py/objstrunicode.c msgid "%q index out of range" -msgstr "%q indice fuera de rango" +msgstr "%q índice fuera de rango" #: shared-module/bitbangio/SPI.c msgid "%q init failed" msgstr "%q inicializado fallido" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%q es %q" @@ -161,19 +173,19 @@ msgstr "%q es solamente de lectura en esta tarjeta" #: py/argcheck.c shared-bindings/usb_hid/Device.c msgid "%q length must be %d" -msgstr "%q tamaño debe ser %d" +msgstr "%q longitud debe ser %d" #: py/argcheck.c msgid "%q length must be %d-%d" -msgstr "%q tamaño debe ser %d-%d" +msgstr "%q longitud debe ser %d-%d" #: py/argcheck.c msgid "%q length must be <= %d" -msgstr "%q tamaño debe ser <= %d" +msgstr "%q longitud debe ser <= %d" #: py/argcheck.c msgid "%q length must be >= %d" -msgstr "%q tamaño debe ser >= %d" +msgstr "%q longitud debe ser >= %d" #: py/argcheck.c msgid "%q must be %d" @@ -195,9 +207,13 @@ msgstr "%q debe ser <= %d" msgid "%q must be >= %d" msgstr "%q debe ser >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "%q debe ser un arreglo de tipo 'H'" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" -msgstr "%q debe ser un byte-matriz o matriz de tipo 'H' o 'B'" +msgstr "%q debe ser un bytearray o array de tipo 'H' o 'B'" #: shared-bindings/audiocore/RawSample.c msgid "%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'" @@ -229,10 +245,6 @@ msgstr "%q fuera de limites" msgid "%q out of range" msgstr "%q fuera de rango" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "pin inválido %q" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q paso no puede ser cero" @@ -243,13 +255,13 @@ msgstr "%q() toma %d argumentos posicionales pero %d fueron dados" #: shared-bindings/usb_hid/Device.c msgid "%q, %q, and %q must all be the same length" -msgstr "%q, %q, y %q deben tener el mismo largo" +msgstr "%q, %q, y %q deben tener la misma longitud" #: py/objint.c shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s error 0x%x" @@ -349,7 +361,7 @@ msgstr "'=' alineación no permitida en el especificador string format" #: shared-module/struct/__init__.c msgid "'S' and 'O' are not supported format types" -msgstr "'S' y 'O' no son compatibles con los tipos de formato" +msgstr "'S' y 'O' no son tipos de formato soportados" #: py/compile.c msgid "'align' requires 1 argument" @@ -423,7 +435,7 @@ msgstr "tipos de 64 bit" #: ports/atmel-samd/common-hal/countio/Counter.c #: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c msgid "A hardware interrupt channel is already in use" -msgstr "El canal EXTINT ya está siendo utilizado" +msgstr "Un canal de interrupción por hardware ya está en uso" #: ports/espressif/common-hal/analogio/AnalogIn.c msgid "ADC2 is being used by WiFi" @@ -432,7 +444,7 @@ msgstr "ADC2 está siendo usado por WiFi" #: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" -msgstr "La dirección debe tener %d bytes de largo" +msgstr "La dirección debe tener %d bytes de longitud" #: ports/espressif/common-hal/memorymap/AddressRange.c msgid "Address range not allowed" @@ -446,7 +458,7 @@ msgstr "Todos los periféricos CAN están en uso" #: ports/espressif/common-hal/i2ctarget/I2CTarget.c #: ports/nrf/common-hal/busio/I2C.c msgid "All I2C peripherals are in use" -msgstr "Todos los periféricos I2C están siendo usados" +msgstr "Todos los periféricos I2C están en uso" #: ports/espressif/common-hal/countio/Counter.c #: ports/espressif/common-hal/frequencyio/FrequencyIn.c @@ -462,36 +474,36 @@ msgstr "Todos los FIFOs de RX en uso" #: ports/espressif/common-hal/busio/SPI.c ports/nrf/common-hal/busio/SPI.c msgid "All SPI peripherals are in use" -msgstr "Todos los periféricos SPI están siendo usados" +msgstr "Todos los periféricos SPI están en uso" #: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c msgid "All UART peripherals are in use" -msgstr "Todos los periféricos UART están siendo usados" +msgstr "Todos los periféricos UART están en uso" #: ports/nrf/common-hal/countio/Counter.c #: ports/nrf/common-hal/pulseio/PulseIn.c #: ports/nrf/common-hal/rotaryio/IncrementalEncoder.c #: shared-bindings/pwmio/PWMOut.c msgid "All channels in use" -msgstr "Todos los canales esta en uso" +msgstr "Todos los canales están en uso" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "All event channels in use" -msgstr "Todos los canales de eventos estan siendo usados" +msgstr "Todos los canales de eventos están en uso" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "All state machines in use" -msgstr "Todas las máquinas de estado en uso" +msgstr "Todas las máquinas de estado están en uso" #: ports/atmel-samd/audio_dma.c msgid "All sync event channels in use" msgstr "" "Todos los canales de eventos de sincronización (sync event channels) están " -"siendo utilizados" +"en uso" #: shared-bindings/pwmio/PWMOut.c msgid "All timers for this pin are in use" -msgstr "Todos los timers para este pin están siendo utilizados" +msgstr "Todos los timers para este pin están en uso" #: ports/atmel-samd/common-hal/_pew/PewPew.c #: ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -519,6 +531,7 @@ msgstr "Ya se encuentra publicando." msgid "Already have all-matches listener" msgstr "Ya se tiene un escucha de todas las coincidencias" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -560,7 +573,7 @@ msgstr "Tratando de localizar %d bloques" #: ports/raspberrypi/audio_dma.c msgid "Audio conversion not implemented" -msgstr "Conversión de audio no esta implementada" +msgstr "Conversión de audio no está implementada" #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" @@ -579,12 +592,12 @@ msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" msgstr "" -"Auto-reload habilitado. Simplemente guarda los archivos via USB para " -"ejecutarlos o entra al REPL para desabilitarlos.\n" +"Auto-reload habilitado. Simplemente guarda los archivos vía USB para " +"ejecutarlos o entra al REPL para deshabilitarlo.\n" #: ports/espressif/common-hal/canio/CAN.c msgid "Baudrate not supported by peripheral" -msgstr "El periférico no maneja el Baudrate" +msgstr "Baudrate no soportado por el periférico" #: shared-module/displayio/Display.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -593,7 +606,8 @@ 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 pins" -msgstr "Le reloj de bit y de selector de palabra deben ser pines secuenciales" +msgstr "" +"Los pines de reloj de bit y de selector de palabra deben ser secuenciales" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must share a clock unit" @@ -605,7 +619,7 @@ msgstr "Bits depth debe ser múltiplo de 8." #: shared-bindings/bitmaptools/__init__.c msgid "Bitmap size and bits per value must match" -msgstr "El tamaño del mapa de bits y los bits por valor deben cotejar" +msgstr "El tamaño del mapa de bits y los bits por valor deben coincidir" #: supervisor/shared/safe_mode.c msgid "Boot device must be first (interface #0)." @@ -634,44 +648,44 @@ msgstr "El brillo no se puede ajustar" #: shared-bindings/_bleio/UUID.c #, c-format msgid "Buffer + offset too small %d %d %d" -msgstr "Búfer + compensado muy pequeños %d %d %d" +msgstr "Buffer + offset muy pequeños %d %d %d" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" -msgstr "" -"Los elementos del búfer deben de ser de una longitud de 4 bytes o menos" +msgstr "Los elementos del buffer deben tener una longitud de 4 bytes o menos" #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Buffer is not a bytearray." -msgstr "Búfer no es un bytearray." +msgstr "Buffer no es un bytearray." #: ports/cxd56/common-hal/camera/Camera.c shared-bindings/displayio/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Buffer is too small" -msgstr "Búfer es muy pequeño" +msgstr "Buffer es muy pequeño" #: ports/stm/common-hal/audiopwmio/PWMAudioOut.c #, c-format msgid "Buffer length %d too big. It must be less than %d" -msgstr "Longitud del búfer %d es demasiado grande. Tiene que ser menor a %d" +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 búfer debe ser múltiplo de 512" +msgstr "El tamaño del buffer debe ser múltiplo de 512" #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c msgid "Buffer must be a multiple of 512 bytes" -msgstr "Búfer deber ser un múltiplo de 512 bytes" +msgstr "El buffer deber ser un múltiplo de 512 bytes" #: shared-bindings/_bleio/PacketBuffer.c #, c-format msgid "Buffer too short by %d bytes" -msgstr "Búfer muy corto por %d bytes" +msgstr "Buffer muy corto por %d bytes" #: ports/espressif/common-hal/imagecapture/ParallelImageCapture.c msgid "Buffers must be same size" -msgstr "Búferes deben ser del mismo tamaño" +msgstr "Los buffers deben ser del mismo tamaño" #: ports/atmel-samd/common-hal/paralleldisplay/ParallelBus.c #: ports/espressif/common-hal/paralleldisplay/ParallelBus.c @@ -693,7 +707,7 @@ msgstr "Los bloques CBC deben ser múltiplos de 16 bytes" msgid "CIRCUITPY drive could not be found or created." msgstr "El dispositivo CIRCUITPY no pudo ser encontrado o creado." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC o suma de comprobación inválida" @@ -758,7 +772,7 @@ msgstr "" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Cannot pull on input-only pin." -msgstr "No puede hacer pull en un pin de entrada sola." +msgstr "No puede hacer pull en un pin de solo entrada." #: shared-bindings/audiobusio/PDMIn.c msgid "Cannot record to a file" @@ -833,6 +847,14 @@ msgstr "" "La conexión se ha desconectado y ya no se puede usar. Crea una nueva " "conexión." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "Las matrices de coordenadas tienen diferentes longitudes" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "Las matrices de coordenadas tienen diferentes tamaños" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Archivo .mpy corrupto" @@ -1091,7 +1113,7 @@ msgstr "La función requiere lock" msgid "GNSS init" msgstr "Inicialización GNSS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Fallo Genérico" @@ -1258,9 +1280,11 @@ msgid "Interrupt error." msgstr "Error de interrupción." #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "%q inválido" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Pin %q inválido" @@ -1282,8 +1306,7 @@ msgstr "BSSID inválido" msgid "Invalid MAC address" msgstr "Dirección MAC inválida" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Argumento inválido" @@ -1309,7 +1332,7 @@ msgstr "Formato de fragmento de formato no válido" msgid "Invalid multicast MAC address" msgstr "Dirección MAC de multidifusión inválida" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Tamaño incorrecto" @@ -1318,7 +1341,7 @@ msgstr "Tamaño incorrecto" msgid "Invalid socket for TLS" msgstr "socket invalido para TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Estado invalido" @@ -1350,7 +1373,7 @@ msgstr "El Layer ya esta en un grupo" msgid "Layer must be a Group or TileGrid subclass" msgstr "El Layer debe ser un grupo o una subclase de TileGrid" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "La dirección MAC es incorrecta" @@ -1716,11 +1739,11 @@ msgstr "Solo un color puede ser transparente a la vez" msgid "Operation not permitted" msgstr "La operación no es permitida" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "Operación no característica no soportada" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "Tiempo de espera agotado" @@ -1728,7 +1751,7 @@ msgstr "Tiempo de espera agotado" msgid "Out of MDNS service slots" msgstr "No hay slots MDNS de servicio" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Memoria agotada" @@ -1844,7 +1867,7 @@ msgstr "" #: main.c msgid "Pretending to deep sleep until alarm, CTRL-C or file write.\n" msgstr "" -"Pretendiendo ir a deep sleep hasta la alarma, CTRL-C or una escritura de " +"Pretendiendo ir a deep sleep hasta la alarma, CTRL-C o una escritura de " "archivo\n" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -1912,7 +1935,7 @@ msgstr "Solo-lectura" msgid "Read-only filesystem" msgstr "Sistema de archivos de solo-Lectura" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "La respuesta recibida es invalida" @@ -1932,7 +1955,7 @@ msgstr "RemoteTransmissionRequests limitado a 8 bytes" msgid "Requested AES mode is unsupported" msgstr "El modo AES solicitado no es compatible" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "Recurso solicitado no encontrado" @@ -2046,10 +2069,6 @@ msgstr "Estéreo derecho debe estar en el canal PWM B" msgid "Stopping AP is not supported." msgstr "Parar el AP no esta soportado." -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Suministre al menos un pin UART" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "Suministre monotonic_time o epoch_time" @@ -2182,7 +2201,7 @@ msgstr "Inicialización de UART" #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" -msgstr "" +msgstr "Periférico UART en uso" #: ports/stm/common-hal/busio/UART.c msgid "UART re-init" @@ -2235,6 +2254,11 @@ msgstr "No se pudieron asignar buffers para la conversión con signo" msgid "Unable to allocate the heap." msgstr "Imposible de asignar el heap." +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "Imposible de configurar el controlador ADC DMA , código de error:%d" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "No se puede crear bloqueo" @@ -2253,10 +2277,21 @@ msgstr "No se pudo encontrar un GCLK libre" msgid "Unable to init parser" msgstr "Incapaz de inicializar el parser" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" +"No es posible de inicializar el controlador ADC DMA, código de error:%d" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "No se pudo leer los datos de la paleta de colores" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "Imposible de iniciar el controlador ADC DMA, código de error:%d" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2381,7 +2416,7 @@ msgstr "Tamaño del valor != del tamaño fijo requerido" msgid "Value length > max_length" msgstr "Tamaño de valor > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "La versión era invalida" @@ -2461,34 +2496,42 @@ msgstr "Usted presionó ambos botones al iniciar." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h msgid "You pressed button A at start up." -msgstr "Usted presionó el boton A al iniciar." +msgstr "Usted presionó el botón A al iniciar." #: supervisor/shared/safe_mode.c msgid "You pressed the BOOT button at start up" -msgstr "Usted presionó el boton BOOT al iniciar" +msgstr "Usted presionó el botón BOOT al iniciar" + +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "Presionaste el botón GPIO0 al inicio." + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "Presionó el botón Rec al inicio." #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." -msgstr "Usted presionó el boton SW38 al iniciar." +msgstr "Presionó el botón SW38 al iniciar." #: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h msgid "You pressed the VOLUME button at start up." -msgstr "Usted presionó el boton de Volumén al iniciar." +msgstr "Usted presionó el botón de volumen al iniciar." #: 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 "Usted presionó el boton central al iniciar." +msgstr "Usted presionó el botón central al iniciar." #: ports/nrf/boards/aramcon2_badge/mpconfigboard.h msgid "You pressed the left button at start up." -msgstr "Usted presionó el boton izquierdo al iniciar." +msgstr "Usted presionó el botón izquierdo al iniciar." #: supervisor/shared/safe_mode.c msgid "You pressed the reset button during boot." -msgstr "Usted presionó el boton izquierdo al iniciar." +msgstr "Presionó el botón de reinicio durante el arranque." #: supervisor/shared/micropython.c msgid "[truncated due to length]" @@ -4217,8 +4260,6 @@ msgstr "twai_driver_install devolvió esp-idf error #%d" msgid "twai_start returned esp-idf error #%d" msgstr "twai_start devolvió esp-idf error #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: 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" @@ -4440,6 +4481,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Suministre al menos un pin UART" + +#~ msgid "%q pin invalid" +#~ msgstr "pin inválido %q" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/fil.po b/locale/fil.po index d5857a53ea..f943746a34 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -29,6 +29,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -137,7 +145,7 @@ msgstr "%q indeks wala sa sakop" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -181,6 +189,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -215,10 +227,6 @@ msgstr "" msgid "%q out of range" msgstr "" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -236,7 +244,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "" @@ -505,6 +513,7 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -679,7 +688,7 @@ msgstr "" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -812,6 +821,14 @@ msgid "" "connection." msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -1066,7 +1083,7 @@ msgstr "Function nangangailangan ng lock" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1225,9 +1242,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Mali ang %q pin" @@ -1249,8 +1268,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Maling argumento" @@ -1276,7 +1294,7 @@ msgstr "Mali ang format ng chunk size" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1285,7 +1303,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1317,7 +1335,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1676,11 +1694,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1688,7 +1706,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1865,7 +1883,7 @@ msgstr "Basahin-lamang" msgid "Read-only filesystem" msgstr "Basahin-lamang mode" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1885,7 +1903,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -1998,10 +2016,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2181,6 +2195,11 @@ msgstr "Hindi ma-allocate ang buffers para sa naka-sign na conversion" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2199,10 +2218,20 @@ msgstr "Hindi mahanap ang libreng GCLK" msgid "Unable to init parser" msgstr "Hindi ma-init ang parser" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2327,7 +2356,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2405,6 +2434,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4156,8 +4193,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx at rx hindi pwedeng parehas na None" diff --git a/locale/fr.po b/locale/fr.po index 19f75abfac..424e16a1b5 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,14 +8,14 @@ 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: 2022-12-27 18:02+0000\n" -"Last-Translator: Blinka CircuitPython \n" +"PO-Revision-Date: 2023-02-26 06:37+0000\n" +"Last-Translator: Neradoc \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 4.15.1-dev\n" +"X-Generator: Weblate 4.16-dev\n" #: main.c msgid "" @@ -34,6 +34,18 @@ msgstr "" "Le code a été arrêté par l'actualisation automatique. Rechargement " "prochain.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" +"\n" +"CIRCUITPY_PYSTACK_SIZE invalide\n" +"\n" +"\n" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -46,12 +58,16 @@ msgid "" "\n" "Press reset to exit safe mode.\n" msgstr "" +"\n" +"Appuyer sur reset pour sortir du mode sûr.\n" #: supervisor/shared/safe_mode.c msgid "" "\n" "You are in safe mode because:\n" msgstr "" +"\n" +"Le mode sûr est actif:\n" #: py/obj.c msgid " File \"%q\"" @@ -127,7 +143,7 @@ msgstr "Échec de %q : %d" #: py/argcheck.c msgid "%q in %q must be of type %q, not %q" -msgstr "" +msgstr "%q dans %q doit être de type %q, pas %q" #: ports/espressif/common-hal/espulp/ULP.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -144,13 +160,13 @@ msgstr "index %q hors de portée" msgid "%q init failed" msgstr "échec de l'initialisation %q" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "%q is read-only for this board" -msgstr "" +msgstr "%q est en lecture seule sur cette carte" #: py/argcheck.c shared-bindings/usb_hid/Device.c msgid "%q length must be %d" @@ -188,9 +204,13 @@ msgstr "%q doit être <= %d" msgid "%q must be >= %d" msgstr "%q doit être >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" -msgstr "" +msgstr "%q doit être un bytearray ou matrice de type 'H' ou 'B'" #: shared-bindings/audiocore/RawSample.c msgid "%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'" @@ -199,11 +219,11 @@ msgstr "%q doit être a bytearray ou array de type 'h', 'H', 'b', ou 'B'" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/canio/CAN.c shared-bindings/digitalio/Pull.c msgid "%q must be of type %q or %q, not %q" -msgstr "" +msgstr "%q doit être de type %q ou %q, pas %q" #: py/argcheck.c py/obj.c py/objstrunicode.c msgid "%q must be of type %q, not %q" -msgstr "" +msgstr "%q doit être de type %q, pas %q" #: ports/atmel-samd/common-hal/busio/UART.c msgid "%q must be power of 2" @@ -222,13 +242,9 @@ msgstr "%q est hors limites" msgid "%q out of range" msgstr "%q est hors de porté" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "broche %q invalide" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" -msgstr "" +msgstr "le pas ne peut être zéro dans %q" #: py/bc.c py/objnamedtuple.c msgid "%q() takes %d positional arguments but %d were given" @@ -242,7 +258,7 @@ msgstr "%q, %q, et %q doivent tous être de la même longueur" msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s erreur 0x%x" @@ -429,7 +445,7 @@ msgstr "L'adresse doit être longue de %d octets" #: ports/espressif/common-hal/memorymap/AddressRange.c msgid "Address range not allowed" -msgstr "" +msgstr "Plage d'adresses non autorisée" #: ports/espressif/common-hal/canio/CAN.c msgid "All CAN peripherals are in use" @@ -510,6 +526,7 @@ msgstr "S'annonce déjà." msgid "Already have all-matches listener" msgstr "Il y a déjà un auditeur all-matches" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -524,7 +541,7 @@ msgstr "Déjà à la recherche des réseaux wifi" #: shared-module/os/getenv.c #, c-format msgid "An error occurred while retrieving '%s':\n" -msgstr "" +msgstr "Erreur survenue en récupérant '%s':\n" #: ports/stm/common-hal/audiopwmio/PWMAudioOut.c msgid "Another PWMAudioOut is already active" @@ -685,7 +702,7 @@ msgstr "Les blocs CBC doivent être des multiples de 16 octets" msgid "CIRCUITPY drive could not be found or created." msgstr "L'appareil CIRCUITPY ne peut pas être trouvé ou créé." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC ou somme de contrôle invalide" @@ -831,6 +848,14 @@ msgstr "" "La connexion a été déconnectée et ne peut plus être utilisée. Créez une " "nouvelle connexion." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Fichier .mpy corrompu" @@ -921,7 +946,7 @@ msgstr "" #: py/obj.c msgid "During handling of the above exception, another exception occurred:" -msgstr "" +msgstr "Pendant la gestion de cette exception, un autre s'est produite:" #: shared-bindings/aesio/aes.c msgid "ECB only operates on 16 bytes at a time" @@ -950,7 +975,7 @@ msgstr "Erreur dans l'expression régulière" #: supervisor/shared/safe_mode.c msgid "Error in safemode.py." -msgstr "" +msgstr "Erreur dans safemode.py." #: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c msgid "Error: Failure to bind" @@ -958,7 +983,7 @@ msgstr "Erreur : Impossible de lier" #: shared-bindings/alarm/__init__.c msgid "Expected a kind of %q" -msgstr "" +msgstr "Argument de type %q attendu" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nrf/common-hal/_bleio/Adapter.c @@ -1035,7 +1060,7 @@ msgstr "Le fichier existe" #: shared-module/os/getenv.c msgid "File not found" -msgstr "" +msgstr "Fichier non trouvé" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c @@ -1091,7 +1116,7 @@ msgstr "La fonction nécessite un verrou ('lock')" msgid "GNSS init" msgstr "Initialisation GNSS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Échec génerique" @@ -1123,12 +1148,12 @@ msgstr "Matériel utilisé, essayez d'autres broches" #: supervisor/shared/safe_mode.c msgid "Heap allocation when VM not running." -msgstr "" +msgstr "Allocation du tas en dehors de la MV." #: supervisor/shared/safe_mode.c msgid "" "Heap was corrupted because the stack was too small. Increase stack size." -msgstr "" +msgstr "Tas corrompu parce que la pile était trop petite. Augmenter la pile." #: extmod/vfs_posix_file.c py/objstringio.c msgid "I/O operation on closed file" @@ -1141,7 +1166,7 @@ msgstr "Erreur d'initialisation I2C" #: ports/raspberrypi/common-hal/busio/I2C.c #: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c msgid "I2C peripheral in use" -msgstr "périphérique I2C utilisé" +msgstr "Périphérique I2C utilisé" #: shared-bindings/audiobusio/I2SOut.c msgid "I2SOut not available" @@ -1258,12 +1283,14 @@ msgstr "Le minuteur du watchdog interne a expiré." #: supervisor/shared/safe_mode.c msgid "Interrupt error." -msgstr "" +msgstr "Erreur d'interruption." #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "%q invalide" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Broche invalide pour '%q'" @@ -1285,8 +1312,7 @@ msgstr "BSSID invalide" msgid "Invalid MAC address" msgstr "Adresse MAC invalide" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Paramètre invalide" @@ -1297,7 +1323,7 @@ msgstr "Bits par valeur invalides" #: shared-module/os/getenv.c #, c-format msgid "Invalid byte %.*s" -msgstr "" +msgstr "Octet invalide %.*s" #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format @@ -1312,7 +1338,7 @@ msgstr "Taille de bloc de formatage invalide" msgid "Invalid multicast MAC address" msgstr "Adresse MAC multicast invalide" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Taille invalide" @@ -1321,13 +1347,13 @@ msgstr "Taille invalide" msgid "Invalid socket for TLS" msgstr "Socket non valide pour TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "État invalide" #: shared-module/os/getenv.c msgid "Invalid unicode escape" -msgstr "" +msgstr "Séquence unicode invalide" #: shared-bindings/aesio/aes.c msgid "Key must be 16, 24, or 32 bytes long" @@ -1335,7 +1361,7 @@ msgstr "La clé doit comporter 16, 24 ou 32 octets" #: shared-module/os/getenv.c msgid "Key not found" -msgstr "" +msgstr "Clé non trouvée" #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" @@ -1353,7 +1379,7 @@ msgstr "Ce calque est déjà dans un groupe" msgid "Layer must be a Group or TileGrid subclass" msgstr "Le calque doit être une sous-classe de Group ou TileGrid" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "Adresse physique (MAC) invalide" @@ -1448,7 +1474,7 @@ msgstr "Erreur NVS" #: shared-bindings/socketpool/SocketPool.c msgid "Name or service not known" -msgstr "" +msgstr "Nom ou service inconnu" #: py/qstr.c msgid "Name too long" @@ -1693,7 +1719,7 @@ msgstr "Une seul %q autorisée en sommeil profond." #: ports/espressif/common-hal/espulp/ULPAlarm.c msgid "Only one %q can be set." -msgstr "" +msgstr "Un seul %q peut être défini." #: ports/espressif/common-hal/i2ctarget/I2CTarget.c #: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c @@ -1719,19 +1745,19 @@ msgstr "Une seule couleur peut être transparente à la fois" msgid "Operation not permitted" msgstr "Cette opération n'est pas permise" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "Opération ou fonction non supportée" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "Timeout de l'opération" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Out of MDNS service slots" -msgstr "" +msgstr "À cours de services MDNS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Mémoire insuffisante" @@ -1865,7 +1891,7 @@ msgstr "Taille du programme invalide" #: ports/espressif/common-hal/espulp/ULP.c msgid "Program too long" -msgstr "" +msgstr "Programme trop long" #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." @@ -1916,7 +1942,7 @@ msgstr "Lecture seule" msgid "Read-only filesystem" msgstr "Système de fichier en lecture seule" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "Réponse reçue invalide" @@ -1936,7 +1962,7 @@ msgstr "RemoteTransmissionRequests limité à 8 octets" msgid "Requested AES mode is unsupported" msgstr "Le mode AES demandé n'est pas supporté" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "Resource demandée non trouvée" @@ -2047,11 +2073,7 @@ msgstr "Canal stéréo droit doit être sur le canal PWM B" #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "Stopping AP is not supported." -msgstr "" - -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Fournissez au moins une broche UART" +msgstr "Stopper n'est pas supporté." #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" @@ -2067,11 +2089,11 @@ 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 "" +msgstr "Le module microcontroller a été utilisé pour démarrer en mode sûr." #: py/obj.c msgid "The above exception was the direct cause of the following exception:" -msgstr "" +msgstr "L'exception précédente est la cause directe de l'exception suivante:" #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" @@ -2079,7 +2101,7 @@ msgstr "La taille de rgb_pins doit être 6, 12, 18, 24 ou 30" #: supervisor/shared/safe_mode.c msgid "The power dipped. Make sure you are providing enough power." -msgstr "" +msgstr "La puissance a chu. Assurez vous de fournir assez de puissance." #: shared-module/audiomixer/MixerVoice.c msgid "The sample's bits_per_sample does not match the mixer's" @@ -2100,7 +2122,7 @@ msgstr "Le signe de l'échantillon ne correspond pas à celui du mixer" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." -msgstr "" +msgstr "Erreur fatale de logiciel système tierce partie." #: shared-module/imagecapture/ParallelImageCapture.c msgid "This microcontroller does not support continuous capture." @@ -2182,7 +2204,7 @@ msgstr "Initialisation UART" #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" -msgstr "" +msgstr "Périphérique UART utilisé" #: ports/stm/common-hal/busio/UART.c msgid "UART re-init" @@ -2237,6 +2259,11 @@ msgstr "Impossible d'allouer des tampons pour une conversion signée" #: supervisor/shared/safe_mode.c msgid "Unable to allocate the heap." +msgstr "Impossible d'allouer le tas." + +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" msgstr "" #: ports/espressif/common-hal/busio/I2C.c @@ -2257,10 +2284,20 @@ msgstr "Impossible de trouver un GCLK libre" msgid "Unable to init parser" msgstr "Impossible d'initialiser le parser" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Impossible de lire les données de la palette de couleurs" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2268,7 +2305,7 @@ msgstr "Impossible de lancer la requête mDNS" #: shared-bindings/memorymap/AddressRange.c msgid "Unable to write to address." -msgstr "" +msgstr "L'écriture a échoué." #: shared-bindings/nvm/ByteArray.c msgid "Unable to write to nvm." @@ -2386,7 +2423,7 @@ msgstr "Longueur de valeur != Longueur fixe requise" msgid "Value length > max_length" msgstr "Longueur de la valeur > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "Version est invalide" @@ -2437,15 +2474,15 @@ msgstr "Wi-Fi : " #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "Wifi is in access point mode." -msgstr "" +msgstr "Wifi en mode point d'accès." #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "Wifi is in station mode." -msgstr "" +msgstr "Wifi en mode station." #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "Wifi is not enabled" -msgstr "" +msgstr "Le wifi n'est pas activé" #: main.c msgid "Woken up by alarm.\n" @@ -2461,44 +2498,52 @@ 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 "" +msgstr "Vous avez appuyé 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 msgid "You pressed button A at start up." -msgstr "" +msgstr "Vous avez appuyé le bouton A 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" + +#: 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." + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." msgstr "" #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." -msgstr "" +msgstr "Vous avez appuyé le bouton SW38 au démarrage." #: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h msgid "You pressed the VOLUME button at start up." -msgstr "" +msgstr "Vous avez appuyé le bouton VOLUME au démarrage." #: 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 "Vous avez appuyé le bouton central au démarrage." #: ports/nrf/boards/aramcon2_badge/mpconfigboard.h msgid "You pressed the left button at start up." -msgstr "" +msgstr "Vous avez appuyé le bouton gauche au démarrage." #: supervisor/shared/safe_mode.c msgid "You pressed the reset button during boot." -msgstr "" +msgstr "Vous avez appuyé le bouton reset au démarrage." #: supervisor/shared/micropython.c msgid "[truncated due to length]" -msgstr "" +msgstr "[taille limite atteinte]" #: py/objtype.c msgid "__init__() should return None" @@ -2571,7 +2616,7 @@ msgstr "la tableau à trop de dimensions" #: extmod/ulab/code/ndarray.c msgid "array is too big" -msgstr "" +msgstr "matrice trop grande" #: py/objarray.c shared-bindings/alarm/SleepMemory.c #: shared-bindings/memorymap/AddressRange.c shared-bindings/nvm/ByteArray.c @@ -2798,7 +2843,7 @@ msgstr "attribut non modifiable" #: py/runtime.c msgid "can't set attribute '%q'" -msgstr "" +msgstr "attribut '%q' non modifiable" #: py/emitnative.c msgid "can't store '%q'" @@ -3064,6 +3109,8 @@ msgid "" "espcamera.Camera requires reserved PSRAM to be configured. See the " "documentation for instructions." msgstr "" +"espcamera.Camera a besoin de PSRAM réservée. Voir la documentation pour les " +"instructions." #: py/runtime.c msgid "exceptions must derive from BaseException" @@ -3281,7 +3328,7 @@ msgstr "l'index est hors limites" #: shared-bindings/_pixelmap/PixelMap.c msgid "index must be tuple or int" -msgstr "" +msgstr "l'index doit être un tuple ou entier" #: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c #: ports/espressif/common-hal/pulseio/PulseIn.c @@ -3667,7 +3714,7 @@ msgstr "compte de décalage négatif" #: shared-bindings/_pixelmap/PixelMap.c msgid "nested index must be int" -msgstr "" +msgstr "sous index doit être entier" #: shared-module/sdcardio/SDCard.c msgid "no SD card" @@ -3839,7 +3886,7 @@ msgstr "seul bit_depth = 16 est pris en charge" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only mono is supported" -msgstr "" +msgstr "seul mono est supporté" #: extmod/ulab/code/numpy/create.c msgid "only ndarrays can be concatenated" @@ -3847,7 +3894,7 @@ msgstr "" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only oversample=64 is supported" -msgstr "" +msgstr "seul oversample=64 supporté" #: ports/nrf/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c @@ -4232,8 +4279,6 @@ msgstr "twai_driver_install a renvoyé l'erreur esp-idf #%d" msgid "twai_start returned esp-idf error #%d" msgstr "twai_start a renvoyé l'erreur esp-idf #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx et rx ne peuvent être 'None' tous les deux" @@ -4455,6 +4500,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Fournissez au moins une broche UART" + +#~ msgid "%q pin invalid" +#~ msgstr "broche %q invalide" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/hi.po b/locale/hi.po index 70bda4ec7c..94a42e19f8 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -28,6 +28,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -136,7 +144,7 @@ msgstr "" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -180,6 +188,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -214,10 +226,6 @@ msgstr "" msgid "%q out of range" msgstr "" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -234,7 +242,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "" @@ -502,6 +510,7 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -673,7 +682,7 @@ msgstr "" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -805,6 +814,14 @@ msgid "" "connection." msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -1056,7 +1073,7 @@ msgstr "" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1213,9 +1230,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "" @@ -1237,8 +1256,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "" @@ -1264,7 +1282,7 @@ msgstr "" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1273,7 +1291,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1305,7 +1323,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1661,11 +1679,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1673,7 +1691,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1849,7 +1867,7 @@ msgstr "" msgid "Read-only filesystem" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1869,7 +1887,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -1982,10 +2000,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2165,6 +2179,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2183,10 +2202,20 @@ msgstr "" msgid "Unable to init parser" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2309,7 +2338,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2387,6 +2416,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4120,8 +4157,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "" diff --git a/locale/it_IT.po b/locale/it_IT.po index d3b91d4c3d..5fb7e50d6b 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -31,6 +31,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -140,7 +148,7 @@ msgstr "indice %q fuori intervallo" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -184,6 +192,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -218,10 +230,6 @@ msgstr "" msgid "%q out of range" msgstr "%q oltre il limite" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q pin non valido" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -238,7 +246,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s errore 0x%x" @@ -508,6 +516,7 @@ msgstr "" msgid "Already have all-matches listener" msgstr "Già in possesso di tutti i listener abbinati" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -682,7 +691,7 @@ msgstr "I blocchi CBC devono essere multipli di 16 bytes" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC o controllo totale è risultato non valido" @@ -815,6 +824,14 @@ msgid "" "connection." msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -1068,7 +1085,7 @@ msgstr "" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1227,9 +1244,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Pin %q non valido" @@ -1251,8 +1270,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Argomento non valido" @@ -1278,7 +1296,7 @@ msgstr "" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1287,7 +1305,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1319,7 +1337,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1680,11 +1698,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1692,7 +1710,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1872,7 +1890,7 @@ msgstr "Sola lettura" msgid "Read-only filesystem" msgstr "Filesystem in sola lettura" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1892,7 +1910,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -2005,10 +2023,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2188,6 +2202,11 @@ msgstr "Ipossibilitato ad allocare buffer per la conversione con segno" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2206,10 +2225,20 @@ msgstr "Impossibile trovare un GCLK libero" msgid "Unable to init parser" msgstr "Inizilizzazione del parser non possibile" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2334,7 +2363,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2412,6 +2441,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4166,8 +4203,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx e rx non possono essere entrambi None" @@ -4391,6 +4426,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q pin invalid" +#~ msgstr "%q pin non valido" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/ja.po b/locale/ja.po index dca26f752b..7e63cb55c3 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -34,6 +34,14 @@ msgstr "" "\n" "オートリロードでコード実行は中止された。まもなくリロードする。\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -143,7 +151,7 @@ msgstr "%q インデックスは範囲外" msgid "%q init failed" msgstr "%qは初期化には失敗" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%qは%q" @@ -187,6 +195,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -221,10 +233,6 @@ msgstr "" msgid "%q out of range" msgstr "%q が範囲外" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q ピンは無効" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -241,7 +249,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "" @@ -509,6 +517,7 @@ msgstr "すでにアドバータイズ中" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -682,7 +691,7 @@ msgstr "CBCブロックは16バイトの整数倍でなければなりません" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -816,6 +825,14 @@ msgid "" "connection." msgstr "接続は切断済みでもう使えません。新しい接続を作成してください" +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "破損した .mpy ファイル" @@ -1067,7 +1084,7 @@ msgstr "" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1226,9 +1243,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "不正な %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "不正な%qピン" @@ -1250,8 +1269,7 @@ msgstr "不正なBSSID" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "不正な引数" @@ -1277,7 +1295,7 @@ msgstr "フォーマットチャンクのサイズが不正" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1286,7 +1304,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1318,7 +1336,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1676,11 +1694,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1688,7 +1706,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1865,7 +1883,7 @@ msgstr "読み込み専用" msgid "Read-only filesystem" msgstr "読み込み専用のファイルシステム" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1885,7 +1903,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "要求のAESモードは非対応" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -1998,10 +2016,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "少なくとも1つのUARTピンが必要" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2182,6 +2196,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2200,10 +2219,20 @@ msgstr "" msgid "Unable to init parser" msgstr "パーザを初期化できません" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "カラーパレットデータを読み込めません" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2326,7 +2355,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2404,6 +2433,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4144,8 +4181,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "txとrxを両方ともNoneにできません" @@ -4367,6 +4402,12 @@ msgstr "ziはfloat値でなければなりません" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Supply at least one UART pin" +#~ msgstr "少なくとも1つのUARTピンが必要" + +#~ msgid "%q pin invalid" +#~ msgstr "%q ピンは無効" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/ko.po b/locale/ko.po index c08aa5b714..129c9b4bcd 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -29,6 +29,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -137,7 +145,7 @@ msgstr "%q 인덱스 범위를 벗어났습니다" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -181,6 +189,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -215,10 +227,6 @@ msgstr "" msgid "%q out of range" msgstr "" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -235,7 +243,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "" @@ -503,6 +511,7 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -676,7 +685,7 @@ msgstr "" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -808,6 +817,14 @@ msgid "" "connection." msgstr "" +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "" @@ -1059,7 +1076,7 @@ msgstr "" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1216,9 +1233,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "" @@ -1240,8 +1259,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "" @@ -1267,7 +1285,7 @@ msgstr "형식 청크 크기가 잘못되었습니다" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1276,7 +1294,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1308,7 +1326,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1664,11 +1682,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1676,7 +1694,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1852,7 +1870,7 @@ msgstr "" msgid "Read-only filesystem" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1872,7 +1890,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -1985,10 +2003,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2169,6 +2183,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2187,10 +2206,20 @@ msgstr "" msgid "Unable to init parser" msgstr "파서를 초기화(init) 할 수 없습니다" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2313,7 +2342,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2391,6 +2420,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4124,8 +4161,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "" diff --git a/locale/nl.po b/locale/nl.po index 9f5a7d382f..87fdb61c60 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -28,6 +28,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -136,7 +144,7 @@ msgstr "%q index buiten bereik" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -180,6 +188,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -214,10 +226,6 @@ msgstr "" msgid "%q out of range" msgstr "%q buiten bereik" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q pin onjuist" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -234,7 +242,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "" @@ -502,6 +510,7 @@ msgstr "Advertising is al bezig." msgid "Already have all-matches listener" msgstr "Heeft al een luisteraar voor 'all-matches'" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -675,7 +684,7 @@ msgstr "CBC blocks moeten meervouden van 16 bytes zijn" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -810,6 +819,14 @@ msgstr "" "Verbinding is verbroken en kan niet langer gebruikt worden. Creëer een " "nieuwe verbinding." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Corrupt .mpy bestand" @@ -1062,7 +1079,7 @@ msgstr "Functie vereist lock" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1221,9 +1238,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "Ongeldige %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Ongeldige %q pin" @@ -1245,8 +1264,7 @@ msgstr "Ongeldig BSSID" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Ongeldig argument" @@ -1272,7 +1290,7 @@ msgstr "Ongeldig formaat stuk grootte" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "" @@ -1281,7 +1299,7 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "" @@ -1313,7 +1331,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1675,11 +1693,11 @@ msgstr "Er kan maar één kleur per keer transparant zijn" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1687,7 +1705,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1870,7 +1888,7 @@ msgstr "Alleen-lezen" msgid "Read-only filesystem" msgstr "Alleen-lezen bestandssysteem" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1890,7 +1908,7 @@ msgstr "RemoteTransmissionRequests is beperkt tot 8 bytes" msgid "Requested AES mode is unsupported" msgstr "Gevraagde AES modus is niet ondersteund" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -2003,10 +2021,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Geef op zijn minst 1 UART pin op" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "Geef monotonic_time of epoch_time" @@ -2186,6 +2200,11 @@ msgstr "Niet in staat buffers voor gesigneerde conversie te alloceren" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "Kan vergrendeling niet maken" @@ -2204,10 +2223,20 @@ msgstr "Niet in staat een vrije GCLK te vinden" msgid "Unable to init parser" msgstr "Niet in staat om de parser te initialiseren" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Niet in staat kleurenpalet data te lezen" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2332,7 +2361,7 @@ msgstr "Waarde lengte != vereist vaste lengte" msgid "Value length > max_length" msgstr "Waarde length > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2414,6 +2443,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4154,8 +4191,6 @@ msgstr "twai_driver_install geeft esp-idf fout #%d" msgid "twai_start returned esp-idf error #%d" msgstr "twai_start geeft esp-idf error #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx en rx kunnen niet beiden None zijn" @@ -4377,6 +4412,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Geef op zijn minst 1 UART pin op" + +#~ msgid "%q pin invalid" +#~ msgstr "%q pin onjuist" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/pl.po b/locale/pl.po index 6320ff566f..1348c0f321 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -30,6 +30,14 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -138,7 +146,7 @@ msgstr "%q poza zakresem" msgid "%q init failed" msgstr "" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "" @@ -182,6 +190,10 @@ msgstr "" msgid "%q must be >= %d" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "" @@ -216,10 +228,6 @@ msgstr "" msgid "%q out of range" msgstr "%q poza zakresem" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "nieprawidłowy pin %q" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -236,7 +244,7 @@ msgstr "" msgid "%q=%q" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "" @@ -504,6 +512,7 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -677,7 +686,7 @@ msgstr "Bloki CBC muszą być wielokrotnościami 16 bajtów" msgid "CIRCUITPY drive could not be found or created." msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "" @@ -811,6 +820,14 @@ msgstr "" "Połączenie zostało rozłączone i nie można go już używać. Utwórz nowe " "połączenie." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Uszkodzony plik .mpy" @@ -1062,7 +1079,7 @@ msgstr "Funkcja wymaga blokady" msgid "GNSS init" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1221,9 +1238,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "Nieprawidłowe %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Zła nóżka %q" @@ -1245,8 +1264,7 @@ msgstr "" msgid "Invalid MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Zły argument" @@ -1272,7 +1290,7 @@ msgstr "Zła wielkość fragmentu formatu" msgid "Invalid multicast MAC address" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Nieprawidłowy rozmiar" @@ -1281,7 +1299,7 @@ msgstr "Nieprawidłowy rozmiar" msgid "Invalid socket for TLS" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Nieprawidłowy stan" @@ -1313,7 +1331,7 @@ msgstr "" msgid "Layer must be a Group or TileGrid subclass" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "" @@ -1669,11 +1687,11 @@ msgstr "W danym momencie przezroczysty może być tylko jeden kolor" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1681,7 +1699,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Brak pamięci" @@ -1857,7 +1875,7 @@ msgstr "Tylko do odczytu" msgid "Read-only filesystem" msgstr "System plików tylko do odczytu" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "Otrzymana odpowiedź była nieprawidłowa" @@ -1877,7 +1895,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "Żądany tryb AES nie jest obsługiwany" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "Nie znaleziono żądanego zasobu" @@ -1990,10 +2008,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Podaj co najmniej jeden pin UART" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2173,6 +2187,11 @@ msgstr "Nie udała się alokacja buforów do konwersji ze znakiem" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2191,10 +2210,20 @@ msgstr "Brak wolnego GCLK" msgid "Unable to init parser" msgstr "Błąd ustawienia parsera" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Nie można odczytać danych palety" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2317,7 +2346,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2395,6 +2424,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4130,8 +4167,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx i rx nie mogą być oba None" @@ -4353,6 +4388,12 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Supply at least one UART pin" +#~ msgstr "Podaj co najmniej jeden pin UART" + +#~ msgid "%q pin invalid" +#~ msgstr "nieprawidłowy pin %q" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index eab698b723..fdf2eaaf31 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -6,7 +6,7 @@ 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-02-17 20:38+0000\n" +"PO-Revision-Date: 2023-03-08 07:10+0000\n" "Last-Translator: Wellington Terumi Uemura \n" "Language-Team: \n" "Language: pt_BR\n" @@ -14,7 +14,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 4.16-dev\n" +"X-Generator: Weblate 4.16.2-dev\n" #: main.c msgid "" @@ -32,6 +32,18 @@ msgstr "" "\n" "O código parou pela recarga automática. Recarregando em breve.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" +"\n" +"CIRCUITPY_PYSTACK_SIZE inválido\n" +"\n" +"\n" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -149,7 +161,7 @@ msgstr "O índice %q está fora do intervalo" msgid "%q init failed" msgstr "a inicialização do %q falhou" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%q é %q" @@ -193,6 +205,10 @@ msgstr "%q deve ser <= %d" msgid "%q must be >= %d" msgstr "o %q deve ser >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "%q deve ser uma matriz do tipo 'H'" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "%q deve ser um bytearray ou uma matriz do tipo 'H' ou 'B'" @@ -227,10 +243,6 @@ msgstr "%q fora dos limites" msgid "%q out of range" msgstr "%q fora do alcance" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q pino inválido" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "A etapa %q não pode ser zero" @@ -247,7 +259,7 @@ msgstr "todos os %q, %q, e %q devem ter mesmo comprimento" msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s erro 0x%x" @@ -519,6 +531,7 @@ msgstr "Já está anunciando." msgid "Already have all-matches listener" msgstr "Já há um ouvinte com todas as correspondências" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -694,7 +707,7 @@ msgstr "Os blocos CBC devem ter múltiplos de 16 bytes" msgid "CIRCUITPY drive could not be found or created." msgstr "A unidade CIRCUITPY não pôde ser encontrada nem criada." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC ou checksum inválido" @@ -833,6 +846,14 @@ msgid "" msgstr "" "A conexão foi desconectada e não pode mais ser usada. Crie uma nova conexão." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "As coordenadas das matrizes possuem comprimentos diferentes" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "Os tipos das coordenadas das matrizes possuem tamanhos diferentes" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Arquivo .mpy corrompido" @@ -1088,7 +1109,7 @@ msgstr "A função requer bloqueio" msgid "GNSS init" msgstr "Inicialização do GNSS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Falha Genérica" @@ -1255,9 +1276,11 @@ msgid "Interrupt error." msgstr "Erro de interrupção." #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "%q Inválido" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Pino do %q inválido" @@ -1279,8 +1302,7 @@ msgstr "BSSID Inválido" msgid "Invalid MAC address" msgstr "Endereço MAC inválido" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Argumento inválido" @@ -1306,7 +1328,7 @@ msgstr "Tamanho do pedaço de formato inválido" msgid "Invalid multicast MAC address" msgstr "Endereço MAC multicast inválido" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Tamanho inválido" @@ -1315,7 +1337,7 @@ msgstr "Tamanho inválido" msgid "Invalid socket for TLS" msgstr "Soquete inválido para o TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Estado inválido" @@ -1347,7 +1369,7 @@ msgstr "Camada já está num grupo" msgid "Layer must be a Group or TileGrid subclass" msgstr "A camada deve ser uma subclasse Group ou TileGrid" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "Endereço MAC inválido" @@ -1710,11 +1732,11 @@ msgstr "Apenas uma cor pode ser transparente de cada vez" msgid "Operation not permitted" msgstr "A operação não é permitida" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "A operação ou o recurso não é suportado" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "A operação expirou" @@ -1722,7 +1744,7 @@ msgstr "A operação expirou" msgid "Out of MDNS service slots" msgstr "Sem slots do serviço MDNS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Sem memória" @@ -1908,7 +1930,7 @@ msgstr "Somente leitura" msgid "Read-only filesystem" msgstr "Sistema de arquivos somente leitura" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "A resposta recebida foi inválida" @@ -1928,7 +1950,7 @@ msgstr "As requisições de transmissões remotas é limitada a 8 bytes" msgid "Requested AES mode is unsupported" msgstr "O modo AES solicitado não é compatível" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "O recurso solicitado não foi encontrado" @@ -2041,10 +2063,6 @@ msgstr "O estéreo à direita deve estar no canal PWM B" msgid "Stopping AP is not supported." msgstr "Não há suporte para a interrupção do AP." -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Forneça pelo menos um pino UART" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "Forneça um de monotonic_time ou de epoch_time" @@ -2177,7 +2195,7 @@ msgstr "inicialização do UART" #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" -msgstr "" +msgstr "Periférico UART em uso" #: ports/stm/common-hal/busio/UART.c msgid "UART re-init" @@ -2231,6 +2249,11 @@ msgstr "Não é possível alocar buffers para conversão assinada" msgid "Unable to allocate the heap." msgstr "Não é possível alocar a área de alocação dinâmica de variáveis." +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "Não foi possível configurar o controlador ADC DMA, ErrorCode:%d" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "Não é possível criar um lock" @@ -2249,10 +2272,20 @@ msgstr "Não é possível encontrar GCLK livre" msgid "Unable to init parser" msgstr "Não foi possível iniciar o analisador" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "Não foi possível inicializar o controlador ADC DMA, ErrorCode:%d" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Não foi possível ler os dados da paleta de cores" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "Não foi possível iniciar o controlador ADC DMA, ErrorCode:%d" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2377,7 +2410,7 @@ msgstr "Comprimento do valor != comprimento fixo necessário" msgid "Value length > max_length" msgstr "O comprimento do valor é > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "A versão era inválida" @@ -2464,6 +2497,14 @@ msgstr "Você pressionou o botão A na inicialização." msgid "You pressed the BOOT button at start up" msgstr "Você pressionou o botão BOOT na inicialização" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "Você pressionou o botão GPIO0 durante a inicialização." + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "Você pressionou o botão Rec durante a inicialização." + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "Você pressionou o botão SW38 na inicialização." @@ -4219,8 +4260,6 @@ msgstr "o twai_driver_install retornou um erro esp-idf #%d" msgid "twai_start returned esp-idf error #%d" msgstr "o twai_start retornou um erro esp-idf #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "TX e RX não podem ser ambos" @@ -4442,6 +4481,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Forneça pelo menos um pino UART" + +#~ msgid "%q pin invalid" +#~ msgstr "%q pino inválido" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/ru.po b/locale/ru.po index 7f73a33083..0fe6cfac97 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -34,6 +34,14 @@ msgstr "" "\n" "Программа остановлена автоматической перезагрузкой. Скоро перезагрузка.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -143,7 +151,7 @@ msgstr "Индекс %q вне диапазона" msgid "%q init failed" msgstr "Инициализация %q не удалась" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%q является %q" @@ -187,6 +195,10 @@ msgstr "%q должно быть <= %d" msgid "%q must be >= %d" msgstr "%q должно быть >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "%q должно быть bytearray или array типа 'H' или 'B'" @@ -221,10 +233,6 @@ msgstr "%q за пределом" msgid "%q out of range" msgstr "%q вне диапазона" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "Пин %q не допустим" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "Шаг %q не может быть нулём" @@ -241,7 +249,7 @@ msgstr "%q, %q, и %q должны быть одной длинны" msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s ошибка 0x%x" @@ -509,6 +517,7 @@ msgstr "Уже объявляемся (advertising)." msgid "Already have all-matches listener" msgstr "Уже есть универсальный слушатель" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -686,7 +695,7 @@ msgstr "Блоки CBC должны быть кратны 16 байтам" msgid "CIRCUITPY drive could not be found or created." msgstr "Не удалось найти или создать диск CIRCUITPY." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC или контрольная сумма неправильная" @@ -830,6 +839,14 @@ msgstr "" "Соединение было отключено и больше не может использоваться. Создайте новое " "соединение." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Файл .mpy поврежден" @@ -1093,7 +1110,7 @@ msgstr "Функция требует блокировки" msgid "GNSS init" msgstr "Инициализация GNSS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Общий сбой" @@ -1258,9 +1275,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "Недопустимый %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Недопустимый пин %q" @@ -1282,8 +1301,7 @@ msgstr "Неверный BSSID" msgid "Invalid MAC address" msgstr "Неверный MAC-адрес" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Недопустимый аргумент" @@ -1309,7 +1327,7 @@ msgstr "Неверный размер блока формата" msgid "Invalid multicast MAC address" msgstr "Неверный MAC-адрес multicast" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Неверный размер" @@ -1318,7 +1336,7 @@ msgstr "Неверный размер" msgid "Invalid socket for TLS" msgstr "Неверный сокет для TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Неверное состояние" @@ -1352,7 +1370,7 @@ msgstr "Слой уже в группе (Group)" msgid "Layer must be a Group or TileGrid subclass" msgstr "Слой должен быть группой (Group) или субклассом TileGrid." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC адрес был недействительным" @@ -1717,11 +1735,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1729,7 +1747,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1910,7 +1928,7 @@ msgstr "" msgid "Read-only filesystem" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1930,7 +1948,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -2043,10 +2061,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Предоставьте хотяб один пин UART" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2228,6 +2242,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2246,10 +2265,20 @@ msgstr "" msgid "Unable to init parser" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2372,7 +2401,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2450,6 +2479,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4183,8 +4220,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "" @@ -4406,6 +4441,12 @@ msgstr "zi должно быть типа float" msgid "zi must be of shape (n_section, 2)" msgstr "zi должен иметь форму (n_section, 2)" +#~ msgid "Supply at least one UART pin" +#~ msgstr "Предоставьте хотяб один пин UART" + +#~ msgid "%q pin invalid" +#~ msgstr "Пин %q не допустим" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/sv.po b/locale/sv.po index cfd6fd582c..84ce4b6ecb 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -6,7 +6,7 @@ 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-02-17 20:38+0000\n" +"PO-Revision-Date: 2023-03-08 07:10+0000\n" "Last-Translator: Jonny Bergdahl \n" "Language-Team: LANGUAGE \n" "Language: sv\n" @@ -14,7 +14,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 4.16-dev\n" +"X-Generator: Weblate 4.16.2-dev\n" #: main.c msgid "" @@ -32,6 +32,18 @@ msgstr "" "\n" "Koden stoppades av automatisk laddning. Omladdning sker strax.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" +"\n" +"Ogiltig CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\n" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -148,7 +160,7 @@ msgstr "Index %q ligger utanför intervallet" msgid "%q init failed" msgstr "%q init misslyckades" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%q är %q" @@ -192,6 +204,10 @@ msgstr "%q måste vara <= %d" msgid "%q must be >= %d" msgstr "%q måste vara >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "%q måste vara en array av typen 'H'" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "%q måste vara en bytearray eller array av typen 'H' eller 'B'" @@ -228,10 +244,6 @@ msgstr "%q är utanför gränserna" msgid "%q out of range" msgstr "%q utanför intervallet" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "Pinne %q ogiltig" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q steg kan inte vara noll" @@ -248,7 +260,7 @@ msgstr "%q, %q och %q måste vara lika långa" msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s fel 0x%x" @@ -516,6 +528,7 @@ msgstr "Annonserar redan." msgid "Already have all-matches listener" msgstr "Har redan lyssnare för all-matchningar" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -689,7 +702,7 @@ msgstr "CBC-block måste vara multiplar om 16 byte" msgid "CIRCUITPY drive could not be found or created." msgstr "CIRCUITPY-enheten kunde inte hittas eller skapas." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC eller checksumma var ogiltig" @@ -825,6 +838,14 @@ msgstr "" "Anslutningen har kopplats bort och kan inte längre användas. Skapa en ny " "anslutning." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "Arrayer för koordinater har olika längd" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "Arrayer för koordinater har olika storlek" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Skadad .mpy-fil" @@ -1079,7 +1100,7 @@ msgstr "Funktionen kräver lås" msgid "GNSS init" msgstr "GNSS start" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "Allmänt fel" @@ -1240,9 +1261,11 @@ msgid "Interrupt error." msgstr "Interrupt-fel." #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "Ogiltig %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Ogiltig %q-pinne" @@ -1264,8 +1287,7 @@ msgstr "Ogiltig BSSID" msgid "Invalid MAC address" msgstr "Ogiltig MAC-adress" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Ogiltigt argument" @@ -1291,7 +1313,7 @@ msgstr "Ogiltig formatsegmentstorlek" msgid "Invalid multicast MAC address" msgstr "Ogiltig MAC-adress för multicast" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Ogiltig storlek" @@ -1300,7 +1322,7 @@ msgstr "Ogiltig storlek" msgid "Invalid socket for TLS" msgstr "Ogiltig socket för TLS" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Ogiltigt tillstånd" @@ -1332,7 +1354,7 @@ msgstr "Layer är redan med i en grupp" msgid "Layer must be a Group or TileGrid subclass" msgstr "Layer måste vara en underklass av Group eller TileGrid" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC-adressen var ogiltig" @@ -1694,11 +1716,11 @@ msgstr "Bara en färg kan vara genomskinlig i taget" msgid "Operation not permitted" msgstr "Åtgärden inte tillåten" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "Operation eller funktion stöds inte" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "Åtgärden orsakade timeout" @@ -1706,7 +1728,7 @@ msgstr "Åtgärden orsakade timeout" msgid "Out of MDNS service slots" msgstr "Slut på MDNS-serviceplatser" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "Slut på minne" @@ -1889,7 +1911,7 @@ msgstr "Skrivskyddad" msgid "Read-only filesystem" msgstr "Skrivskyddat filsystem" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "Mottaget svar var ogiltigt" @@ -1909,7 +1931,7 @@ msgstr "RemoteTransmissionRequests begränsad till 8 byte" msgid "Requested AES mode is unsupported" msgstr "Det begärda AES-läget stöds inte" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "Begärd resurs hittades inte" @@ -2022,10 +2044,6 @@ msgstr "Höger stereokanal måste använda PWM kanal B" msgid "Stopping AP is not supported." msgstr "Stoppa AP stöds inte." -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Ange minst en UART-pinne" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "Ange en av monotonic_time eller epoch_time" @@ -2154,7 +2172,7 @@ msgstr "UART start" #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" -msgstr "" +msgstr "UART-enhet används redan" #: ports/stm/common-hal/busio/UART.c msgid "UART re-init" @@ -2207,6 +2225,11 @@ msgstr "Det går inte att allokera buffert för signerad konvertering" msgid "Unable to allocate the heap." msgstr "Kan inte allokera heap." +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "Kan inte konfigurera ADC DMA controller, Felkod:%d" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "Kan inte skapa lås" @@ -2225,10 +2248,20 @@ msgstr "Det gick inte att hitta ledig GCLK" msgid "Unable to init parser" msgstr "Kan inte initiera tolken" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "Kan inte konfigurera ADC DMA controller, Felkod:%d" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Det går inte att läsa färgpalettdata" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "Kan inte starta ADC DMA controller, Felkod:%d" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2353,7 +2386,7 @@ msgstr "Värdets längde ! = krävd fast längd" msgid "Value length > max_length" msgstr "Värdets längd > max_length" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "Versionen var ogiltig" @@ -2437,6 +2470,14 @@ msgstr "Du tryckte ner knapp A vid start." msgid "You pressed the BOOT button at start up" msgstr "Du tryckte ner BOOT-knappen vid start" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "Du tryckte på GPIO0-knappen vid start." + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "Du tryckte ned Rec-knappen vid start." + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "Du tryckte ned SW38-knappen vid start." @@ -4181,8 +4222,6 @@ msgstr "twai_driver_install returnerade esp-idf-fel #%d" msgid "twai_start returned esp-idf error #%d" msgstr "twai_start returnerade esp-idf-fel #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx och rx kan inte båda vara None" @@ -4404,6 +4443,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Ange minst en UART-pinne" + +#~ msgid "%q pin invalid" +#~ msgstr "Pinne %q ogiltig" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/tr.po b/locale/tr.po index 1adac6b08d..67a73375ea 100644 --- a/locale/tr.po +++ b/locale/tr.po @@ -34,6 +34,14 @@ msgstr "" "Program otomatik yeniden yükleme tarafından durduruldu. Birazdan tekrar " "yüklenecek.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "" "\n" @@ -144,7 +152,7 @@ msgstr "%q indeksi aralık dışında" msgid "%q init failed" msgstr "%q init başarısız oldu" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%q %q dir" @@ -188,6 +196,10 @@ msgstr "%q <= %d olmalıdır" msgid "%q must be >= %d" msgstr "%q >= %d olmalıdır" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "%q 'H' ya da 'B' tipi bir bytearray ya da array olmalıdır" @@ -222,10 +234,6 @@ msgstr "%q sınırların dışında" msgid "%q out of range" msgstr "%q aralık dışında" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q pini geçersiz" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q sıfır olamaz" @@ -242,7 +250,7 @@ msgstr "%q, %q ve %q aynı uzunlukta olmalıdır" msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s hatası 0x%x" @@ -511,6 +519,7 @@ msgstr "Halihazırda duyuruluyor." msgid "Already have all-matches listener" msgstr "Tüm eşleşmelerle eşleşen dinleyiciniz var" +#: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -684,7 +693,7 @@ msgstr "CBC blokları 16 baytın katları şeklinde olmalı" msgid "CIRCUITPY drive could not be found or created." msgstr "CIRCUITPY sürücüsü bulunamadı veya oluşturulamadı." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC yada checksum geçersiz" @@ -817,6 +826,14 @@ msgid "" "connection." msgstr "Bağlantı koparıldı ve tekrar kullanılamaz. Yeni bir bağlantı kurun." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "Bozuk .mpy dosyası" @@ -1072,7 +1089,7 @@ msgstr "Fonksiyon kilit gerektirir" msgid "GNSS init" msgstr "GNSS init" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "" @@ -1231,9 +1248,11 @@ msgid "Interrupt error." msgstr "" #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "Geçersiz %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Geersi %q pin" @@ -1255,8 +1274,7 @@ msgstr "Geçersiz BSSID" msgid "Invalid MAC address" msgstr "Geçersiz MAC adresi" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Geçersiz argüman" @@ -1283,7 +1301,7 @@ msgstr "Geçersiz biçim yığın boyutu" msgid "Invalid multicast MAC address" msgstr "Geçersiz multicast MAC adresi" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "Geçersiz boyut" @@ -1292,7 +1310,7 @@ msgstr "Geçersiz boyut" msgid "Invalid socket for TLS" msgstr "TLS için geçersiz soket" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "Geçersiz durum" @@ -1324,7 +1342,7 @@ msgstr "Katman zaten bir grupta" msgid "Layer must be a Group or TileGrid subclass" msgstr "Katman, bir Grup ya da TileGrid alt sınıfı olmalıdır" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC adresi geçersiz" @@ -1680,11 +1698,11 @@ msgstr "" msgid "Operation not permitted" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "" @@ -1692,7 +1710,7 @@ msgstr "" msgid "Out of MDNS service slots" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "" @@ -1871,7 +1889,7 @@ msgstr "" msgid "Read-only filesystem" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "" @@ -1891,7 +1909,7 @@ msgstr "" msgid "Requested AES mode is unsupported" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "" @@ -2004,10 +2022,6 @@ msgstr "" msgid "Stopping AP is not supported." msgstr "" -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2187,6 +2201,11 @@ msgstr "" msgid "Unable to allocate the heap." msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" msgstr "" @@ -2205,10 +2224,20 @@ msgstr "" msgid "Unable to init parser" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2331,7 +2360,7 @@ msgstr "" msgid "Value length > max_length" msgstr "" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "" @@ -2409,6 +2438,14 @@ msgstr "" msgid "You pressed the BOOT button at start up" msgstr "" +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "" + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "" + #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." msgstr "" @@ -4142,8 +4179,6 @@ msgstr "" msgid "twai_start returned esp-idf error #%d" msgstr "" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "" @@ -4365,6 +4400,9 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q pin invalid" +#~ msgstr "%q pini geçersiz" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 5b180eaec1..485c30353d 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: 2023-01-25 03:47+0000\n" +"PO-Revision-Date: 2023-03-01 17:39+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 4.16-dev\n" +"X-Generator: Weblate 4.16\n" #: main.c msgid "" @@ -34,24 +34,43 @@ msgstr "" "dài mǎ yīn zì dòng chóng xīn jiā zǎi ér tíng zhǐ. jí jiāng chóng xīn jiā " "zǎi.\n" +#: main.c +msgid "" +"\n" +"Invalid CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\r" +msgstr "" +"\n" +"wú xiào CIRCUITPY_PYSTACK_SIZE\n" +"\n" +"\n" + #: supervisor/shared/safe_mode.c msgid "" "\n" "Please file an issue with your program at https://github.com/adafruit/" "circuitpython/issues." msgstr "" +"\n" +"qǐng zài https://github.com/adafruit/circuitpython/issues tí jiāo nín de " +"chéng xù wèn tí." #: supervisor/shared/safe_mode.c msgid "" "\n" "Press reset to exit safe mode.\n" msgstr "" +"\n" +"àn chóng zhì tuì chū ān quán mó shì.\n" #: supervisor/shared/safe_mode.c msgid "" "\n" "You are in safe mode because:\n" msgstr "" +"\n" +"nín chǔ yú ān quán mó shì, yīn wéi:\n" #: py/obj.c msgid " File \"%q\"" @@ -144,7 +163,7 @@ msgstr "%q suǒyǐn chāochū fànwéi" msgid "%q init failed" msgstr "%q chūshǐhuà shībài" -#: shared-bindings/dualbank/__init__.c +#: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" msgstr "%q shì %q" @@ -188,6 +207,10 @@ msgstr "%q bìxū <= %d" msgid "%q must be >= %d" msgstr "%q bìxū >= %d" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +msgid "%q must be array of type 'H'" +msgstr "%q bì xū shì lèi xíng wéi 'H' de shù zǔ" + #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" msgstr "%q bì xū shì zì jié shù zǔ huò lèi xíng wéi 'H' huò 'B' de shù zǔ" @@ -223,10 +246,6 @@ msgstr "%q chāo chū jiè xiàn" msgid "%q out of range" msgstr "%q chāochū fànwéi" -#: ports/atmel-samd/common-hal/microcontroller/Pin.c -msgid "%q pin invalid" -msgstr "%q yǐn jiǎo wúxiào" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q bù cháng bù néng wéi líng" @@ -243,7 +262,7 @@ msgstr "%q, %q, hé %q bì xū cháng dù xiāng tóng" msgid "%q=%q" msgstr "%q=%q" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c #, c-format msgid "%s error 0x%x" msgstr "%s cuò wù 0x%x" @@ -511,6 +530,7 @@ 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/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c @@ -601,7 +621,7 @@ msgstr "wèi tú dàxiǎo hé měi gè zhí de wèi shù bìxū pǐpèi" #: supervisor/shared/safe_mode.c msgid "Boot device must be first (interface #0)." -msgstr "" +msgstr "yǐn dǎo shè bèi bì xū shì dì yī gè (jiē kǒu #0)." #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" @@ -684,7 +704,7 @@ msgstr "CBC kuài bìxū shì 16 zìjié de bèishù" msgid "CIRCUITPY drive could not be found or created." msgstr "zhǎo bú dào huò chuàng jiàn CIRCUITPY qū dòng qì." -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" msgstr "CRC huò jiàoyàn hé wúxiào" @@ -819,6 +839,14 @@ msgid "" "connection." msgstr "Liánjiē yǐ duàn kāi, wúfǎ zài shǐyòng. Chuàngjiàn yīgè xīn de liánjiē." +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays have different lengths" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +msgid "Coordinate arrays types have different sizes" +msgstr "" + #: py/persistentcode.c msgid "Corrupt .mpy file" msgstr "sǔnhuài de .mpy wénjiàn" @@ -938,7 +966,7 @@ msgstr "Zhèngzé biǎodá shì cuòwù" #: supervisor/shared/safe_mode.c msgid "Error in safemode.py." -msgstr "" +msgstr "safemode.py cuò wù." #: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c msgid "Error: Failure to bind" @@ -1014,7 +1042,7 @@ msgstr "Wúfǎ xiě rù nèibù shǎncún." #: supervisor/shared/safe_mode.c msgid "Fault detected by hardware." -msgstr "" +msgstr "yìng jiàn jiǎn cè dào gù zhàng." #: py/moduerrno.c msgid "File exists" @@ -1076,7 +1104,7 @@ msgstr "Hánshù xūyào suǒdìng" msgid "GNSS init" msgstr "GNSS chūshǐhuà" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" msgstr "tōng yòng gù zhàng" @@ -1107,12 +1135,12 @@ msgstr "Shǐyòng de yìngjiàn, qǐng chángshì qítā yǐn jiǎo" #: supervisor/shared/safe_mode.c msgid "Heap allocation when VM not running." -msgstr "" +msgstr "VM wèi yùn xíng shí de duī fēn pèi." #: supervisor/shared/safe_mode.c msgid "" "Heap was corrupted because the stack was too small. Increase stack size." -msgstr "" +msgstr "duī yǐ sǔn huài, yīn wéi duī zhàn tài xiǎo. zēng jiā duī zhàn dà xiǎo." #: extmod/vfs_posix_file.c py/objstringio.c msgid "I/O operation on closed file" @@ -1237,12 +1265,14 @@ msgstr "Nèibù kān mén gǒu dìngshí qì chāoshí." #: supervisor/shared/safe_mode.c msgid "Interrupt error." -msgstr "" +msgstr "zhōng duàn cuò wù." #: py/argcheck.c shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/displayio/EPaperDisplay.c msgid "Invalid %q" msgstr "wú xiào %q" +#: ports/atmel-samd/common-hal/microcontroller/Pin.c #: shared-bindings/microcontroller/Pin.c msgid "Invalid %q pin" msgstr "Wúxiào de %q yǐn jiǎo" @@ -1264,8 +1294,7 @@ msgstr "Wúxiào de BSSID" msgid "Invalid MAC address" msgstr "wú xiào de MAC dì zhǐ" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c -#: py/moduerrno.c +#: ports/espressif/common-hal/espidf/__init__.c py/moduerrno.c msgid "Invalid argument" msgstr "Wúxiào de cānshù" @@ -1291,7 +1320,7 @@ msgstr "Géshì kuài dàxiǎo wúxiào" msgid "Invalid multicast MAC address" msgstr "wú xiào de duō bō MAC dì zhǐ" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" msgstr "dà xiǎo wú xiào" @@ -1300,7 +1329,7 @@ msgstr "dà xiǎo wú xiào" msgid "Invalid socket for TLS" msgstr "TLS de chā zuò wú xiào" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid state" msgstr "wú xiào zhuàng tài" @@ -1332,7 +1361,7 @@ msgstr "tú céng yǐ zài zǔ zhōng" msgid "Layer must be a Group or TileGrid subclass" msgstr "tú céng bìxū shì zǔ huò píng pū wǎng gé zi lèi" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC dì zhǐ wú xiào" @@ -1694,11 +1723,11 @@ msgstr "Yīcì zhǐ néng yǒuyī zhǒng yánsè shì tòumíng de" msgid "Operation not permitted" msgstr "bù yǔnxǔ cāozuò" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" msgstr "bù zhī chí cāo zuò huò gōng néng" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" msgstr "cāo zuò yǐ fēn shí" @@ -1706,7 +1735,7 @@ msgstr "cāo zuò yǐ fēn shí" msgid "Out of MDNS service slots" msgstr "chāo chū MDNS fú wù chā cáo" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" msgstr "nèi cún bù zú" @@ -1887,7 +1916,7 @@ msgstr "Zhǐ dú" msgid "Read-only filesystem" msgstr "Zhǐ dú wénjiàn xìtǒng" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" msgstr "shōu dào de xiǎng yìng wú xiào" @@ -1907,7 +1936,7 @@ msgstr "RemoteTransmissionRequests xiànzhì wèi 8 gè zì jié" msgid "Requested AES mode is unsupported" msgstr "Qǐngqiú de AES móshì bù shòu zhīchí" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" msgstr "wèi zhǎo dào qǐng qiú de zī yuán" @@ -2020,10 +2049,6 @@ msgstr "lì tǐ shēng yòu cè bì xū zài PWM tōng dào B shàng" msgid "Stopping AP is not supported." msgstr "bù zhī chí tíng zhǐ AP." -#: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c -msgid "Supply at least one UART pin" -msgstr "Dìngyì zhìshǎo yīgè UART yǐn jiǎo" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "tí gòng qí zhōng yī monotonic_time huò epoch_time" @@ -2038,7 +2063,7 @@ msgstr "Wēndù dòu qǔ chāoshí" #: supervisor/shared/safe_mode.c msgid "The `microcontroller` module was used to boot into safe mode." -msgstr "" +msgstr "`microcontroller` mó kuài yòng yú qǐ dòng dào ān quán mó shì." #: py/obj.c msgid "The above exception was the direct cause of the following exception:" @@ -2050,7 +2075,7 @@ msgstr "Rgb_pins de chángdù bìxū wèi 6,12,18,24 huò 30" #: supervisor/shared/safe_mode.c msgid "The power dipped. Make sure you are providing enough power." -msgstr "" +msgstr "lì liàng xià jiàng le. què bǎo nín tí gòng zú gòu de diàn lì." #: shared-module/audiomixer/MixerVoice.c msgid "The sample's bits_per_sample does not match the mixer's" @@ -2070,7 +2095,7 @@ msgstr "Yàngběn de qiānmíng yǔ hǔn yīn qì de qiānmíng bù pǐpèi" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." -msgstr "" +msgstr "dì sān fāng gù jiàn zhì mìng cuò wù." #: shared-module/imagecapture/ParallelImageCapture.c msgid "This microcontroller does not support continuous capture." @@ -2152,7 +2177,7 @@ msgstr "UART chūshǐhuà" #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" -msgstr "" +msgstr "UART wài shè shǐ yòng zhōng" #: ports/stm/common-hal/busio/UART.c msgid "UART re-init" @@ -2203,7 +2228,12 @@ msgstr "Wúfǎ fēnpèi huǎnchōng qū yòng yú qiānmíng zhuǎnhuàn" #: supervisor/shared/safe_mode.c msgid "Unable to allocate the heap." -msgstr "" +msgstr "wú fǎ fēn pèi duī." + +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to configure ADC DMA controller, ErrorCode:%d" +msgstr "wú fǎ pèi zhì ADC DMA kòng zhì qì, cuò wù dài mǎ:%d" #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" @@ -2223,10 +2253,20 @@ msgstr "Wúfǎ zhǎodào miǎnfèi de GCLK" msgid "Unable to init parser" msgstr "Wúfǎ chūshǐhuà jiěxī qì" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to initialize ADC DMA controller, ErrorCode:%d" +msgstr "wú fǎ chū shǐ huà ADC DMA kòng zhì qì, cuò wù dài mǎ:%d" + #: shared-module/displayio/OnDiskBitmap.c msgid "Unable to read color palette data" msgstr "Wúfǎ dúqǔ tiáosèbǎn shùjù" +#: ports/espressif/common-hal/analogbufio/BufferedIn.c +#, c-format +msgid "Unable to start ADC DMA controller, ErrorCode:%d" +msgstr "wú fǎ qǐ dòng ADC DMA kòng zhì qì, cuò wù dài mǎ:%d" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2351,7 +2391,7 @@ msgstr "Zhí chángdù != Suǒ xū de gùdìng chángdù" msgid "Value length > max_length" msgstr "Zhí chángdù > zuìdà chángdù" -#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c +#: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" msgstr "bǎn běn wú xiào" @@ -2423,44 +2463,52 @@ msgstr "Tèzhēng bù zhīchí xiě rù" #: 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 "nín zài qǐ dòng shí àn xià le liǎng gè àn niǔ." #: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h msgid "You pressed button A at start up." -msgstr "" +msgstr "nín zài qǐ dòng shí àn xià le àn niǔ A." #: supervisor/shared/safe_mode.c msgid "You pressed the BOOT button at start up" -msgstr "" +msgstr "nín zài qǐ dòng shí àn xià le qǐ dòng àn niǔ" + +#: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h +msgid "You pressed the GPIO0 button at start up." +msgstr "nín zài qǐ dòng shí àn xià le GPIO0 àn niǔ." + +#: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h +msgid "You pressed the Rec button at start up." +msgstr "nín zài qǐ dòng shí àn xià le lù zhì àn niǔ." #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." -msgstr "" +msgstr "nín zài qǐ dòng shí àn xià le SW38 àn niǔ." #: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h msgid "You pressed the VOLUME button at start up." -msgstr "" +msgstr "nín zài qǐ dòng shí àn xià le yīn liàng àn niǔ." #: 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 "nín zài qǐ dòng shí àn xià le zhōng yāng àn niǔ." #: ports/nrf/boards/aramcon2_badge/mpconfigboard.h msgid "You pressed the left button at start up." -msgstr "" +msgstr "nín zài qǐ dòng shí àn xià le zuǒ àn niǔ." #: supervisor/shared/safe_mode.c msgid "You pressed the reset button during boot." -msgstr "" +msgstr "nín zài qǐ dòng guò chéng zhōng àn xià le chóng zhì àn niǔ." #: supervisor/shared/micropython.c msgid "[truncated due to length]" -msgstr "" +msgstr "[yīn cháng dù ér jié duàn]" #: py/objtype.c msgid "__init__() should return None" @@ -2533,7 +2581,7 @@ msgstr "shùzǔ yǒu tài duō wéidù" #: extmod/ulab/code/ndarray.c msgid "array is too big" -msgstr "" +msgstr "zhèn liè tài dà" #: py/objarray.c shared-bindings/alarm/SleepMemory.c #: shared-bindings/memorymap/AddressRange.c shared-bindings/nvm/ByteArray.c @@ -3019,6 +3067,8 @@ msgid "" "espcamera.Camera requires reserved PSRAM to be configured. See the " "documentation for instructions." msgstr "" +"espcamera.Camera xū yào pèi zhì bǎo liú de PSRAM. yǒu guān shuō míng, qǐng " +"cān yuè wén dàng." #: py/runtime.c msgid "exceptions must derive from BaseException" @@ -3789,7 +3839,7 @@ msgstr "jǐn zhī chí dān shēng dào" #: extmod/ulab/code/numpy/create.c msgid "only ndarrays can be concatenated" -msgstr "" +msgstr "zhǐ néng lián jiē ndarray (shù zì)" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only oversample=64 is supported" @@ -4178,8 +4228,6 @@ msgstr "twai_driver_install fǎn huí esp-idf cuò wù #%d" msgid "twai_start returned esp-idf error #%d" msgstr "twai_start fǎn huí esp -idf cuò wù #%d" -#: ports/atmel-samd/common-hal/busio/UART.c -#: ports/espressif/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx hé rx bùnéng dōu shì wú" @@ -4401,6 +4449,12 @@ 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 "Supply at least one UART pin" +#~ msgstr "Dìngyì zhìshǎo yīgè UART yǐn jiǎo" + +#~ msgid "%q pin invalid" +#~ msgstr "%q yǐn jiǎo wúxiào" + #~ msgid "" #~ "\n" #~ "Please file an issue with the contents of your CIRCUITPY drive at \n" diff --git a/main.c b/main.c index ee08726425..002c97c167 100644 --- a/main.c +++ b/main.c @@ -122,8 +122,8 @@ uint8_t value_out = 0; #endif -#if MICROPY_ENABLE_PYSTACK -static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]); +#if MICROPY_ENABLE_PYSTACK && CIRCUITPY_OS_GETENV +#include "shared-module/os/__init__.h" #endif static void reset_devices(void) { @@ -132,7 +132,32 @@ static void reset_devices(void) { #endif } -STATIC void start_mp(supervisor_allocation *heap) { +#if MICROPY_ENABLE_PYSTACK +STATIC supervisor_allocation *allocate_pystack(safe_mode_t safe_mode) { + mp_int_t pystack_size = CIRCUITPY_PYSTACK_SIZE; + #if CIRCUITPY_OS_GETENV && CIRCUITPY_SETTABLE_PYSTACK + // Fetch value if exists from settings.toml + // Leaves size to build default on any failure + if (safe_mode == SAFE_MODE_NONE || safe_mode == SAFE_MODE_USER) { + (void)common_hal_os_getenv_int("CIRCUITPY_PYSTACK_SIZE", &pystack_size); + // Check if value is valid + pystack_size = pystack_size - pystack_size % sizeof(size_t); // Round down to multiple of 4. + if ((pystack_size < 384) || (pystack_size > 900000)) { + serial_write_compressed(translate("\nInvalid CIRCUITPY_PYSTACK_SIZE\n\n\r")); + pystack_size = CIRCUITPY_PYSTACK_SIZE; // Reset + } + } + #endif + supervisor_allocation *pystack = allocate_memory(pystack_size, false, false); + if (pystack == NULL) { + serial_write_compressed(translate("\nInvalid CIRCUITPY_PYSTACK_SIZE\n\n\r")); + pystack = allocate_memory(CIRCUITPY_PYSTACK_SIZE, false, false); + } + return pystack; +} +#endif + +STATIC void start_mp(supervisor_allocation *heap, supervisor_allocation *pystack) { supervisor_workflow_reset(); // Stack limit should be less than real stack size, so we have a chance @@ -160,7 +185,7 @@ STATIC void start_mp(supervisor_allocation *heap) { readline_init0(); #if MICROPY_ENABLE_PYSTACK - mp_pystack_init(_pystack, _pystack + (sizeof(_pystack) / sizeof(size_t))); + mp_pystack_init(pystack->ptr, pystack->ptr + get_allocation_length(pystack) / sizeof(size_t)); #endif #if MICROPY_ENABLE_GC @@ -264,7 +289,7 @@ STATIC void count_strn(void *data, const char *str, size_t len) { *(size_t *)data += len; } -STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) { +STATIC void cleanup_after_vm(supervisor_allocation *heap, supervisor_allocation *pystack, mp_obj_t exception) { // Get the traceback of any exception from this run off the heap. // MP_OBJ_SENTINEL means "this run does not contribute to traceback storage, don't touch it" // MP_OBJ_NULL (=0) means "this run completed successfully, clear any stored traceback" @@ -345,6 +370,9 @@ STATIC void cleanup_after_vm(supervisor_allocation *heap, mp_obj_t exception) { filesystem_flush(); stop_mp(); free_memory(heap); + #if MICROPY_ENABLE_PYSTACK + free_memory(pystack); + #endif supervisor_move_memory(); // Let the workflows know we've reset in case they want to restart. @@ -399,10 +427,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) { }; #endif + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - - // Prepare the VM state. - start_mp(heap); + start_mp(heap, pystack); #if CIRCUITPY_USB usb_setup_with_vm(); @@ -450,7 +480,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) { // Finished executing python code. Cleanup includes filesystem flush and a board reset. - cleanup_after_vm(heap, _exec_result.exception); + cleanup_after_vm(heap, pystack, _exec_result.exception); _exec_result.exception = NULL; // If a new next code file was set, that is a reason to keep it (obviously). Stuff this into @@ -739,8 +769,12 @@ STATIC void __attribute__ ((noinline)) run_safemode_py(safe_mode_t safe_mode) { return; } + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - start_mp(heap); + start_mp(heap, pystack); static const char *const safemode_py_filenames[] = {"safemode.py", "safemode.txt"}; maybe_run_list(safemode_py_filenames, MP_ARRAY_SIZE(safemode_py_filenames)); @@ -751,7 +785,7 @@ STATIC void __attribute__ ((noinline)) run_safemode_py(safe_mode_t safe_mode) { set_safe_mode(SAFE_MODE_SAFEMODE_PY_ERROR); } - cleanup_after_vm(heap, _exec_result.exception); + cleanup_after_vm(heap, pystack, _exec_result.exception); _exec_result.exception = NULL; } #endif @@ -772,9 +806,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { // Do USB setup even if boot.py is not run. + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - - start_mp(heap); + start_mp(heap, pystack); #if CIRCUITPY_USB // Set up default USB values after boot.py VM starts but before running boot.py. @@ -860,7 +897,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { port_post_boot_py(true); - cleanup_after_vm(heap, _exec_result.exception); + cleanup_after_vm(heap, pystack, _exec_result.exception); _exec_result.exception = NULL; port_post_boot_py(false); @@ -871,12 +908,16 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { #endif } -STATIC int run_repl(void) { +STATIC int run_repl(safe_mode_t safe_mode) { int exit_code = PYEXEC_FORCED_EXIT; stack_resize(); filesystem_flush(); + supervisor_allocation *pystack = NULL; + #if MICROPY_ENABLE_PYSTACK + pystack = allocate_pystack(safe_mode); + #endif supervisor_allocation *heap = allocate_remaining_memory(); - start_mp(heap); + start_mp(heap, pystack); #if CIRCUITPY_USB usb_setup_with_vm(); @@ -919,7 +960,7 @@ STATIC int run_repl(void) { exit_code = PYEXEC_DEEP_SLEEP; } #endif - cleanup_after_vm(heap, MP_OBJ_SENTINEL); + cleanup_after_vm(heap, pystack, MP_OBJ_SENTINEL); // Also reset bleio. The above call omits it in case workflows should continue. In this case, // we're switching straight to another VM so we want to reset. @@ -938,6 +979,7 @@ STATIC int run_repl(void) { } int __attribute__((used)) main(void) { + // initialise the cpu and peripherals set_safe_mode(port_init()); @@ -1038,13 +1080,14 @@ int __attribute__((used)) main(void) { bool simulate_reset = true; for (;;) { if (!skip_repl) { - exit_code = run_repl(); + exit_code = run_repl(get_safe_mode()); supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); } if (exit_code == PYEXEC_FORCED_EXIT) { if (!simulate_reset) { serial_write_compressed(translate("soft reboot\n")); } + simulate_reset = false; 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 diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 68beeaf129..0ac326d3cc 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -367,7 +367,7 @@ $(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE) $(STEPECHO) "LINK $@" $(Q)echo $(OBJ) > $(BUILD)/firmware.objs $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group - $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) + $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) $(BUILD) $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(STEPECHO) "Create $@" diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 9dcedf3f9b..6e1dc71d85 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -57,5 +57,8 @@ void port_finish_background_task(void) { } #endif +void port_background_tick(void) { +} + void port_background_task(void) { } diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk index 6017b551f1..1c032f02c0 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk @@ -12,6 +12,7 @@ LONGINT_IMPL = NONE # To keep the build small CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_BUSDEVICE = 1 # lis3dh needs it CIRCUITPY_KEYPAD = 0 # Include these Python libraries in firmware. diff --git a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk index 9bc50ab429..9ca9259747 100644 --- a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk +++ b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk @@ -20,11 +20,13 @@ CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_PIXELMAP = 0 CIRCUITPY_GETPASS = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_MSGPACK = 0 CIRCUITPY_PS2IO = 0 CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_RAINBOWIO = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_TOUCHIO = 0 CIRCUITPY_USB_HID = 0 diff --git a/ports/atmel-samd/boards/openbook_m4/board.c b/ports/atmel-samd/boards/openbook_m4/board.c index 30537dd3f4..ec1ba9f956 100644 --- a/ports/atmel-samd/boards/openbook_m4/board.c +++ b/ports/atmel-samd/boards/openbook_m4/board.c @@ -52,6 +52,10 @@ uint8_t stop_sequence[] = { 0x02, 0x80, 0xf0 // Power off }; +uint8_t refresh_sequence[] = { + 0x12, 0x00 +}; + void board_init(void) { busio_spi_obj_t *spi = &displays[0].fourwire_bus.inline_bus; common_hal_busio_spi_construct(spi, &pin_PB13, &pin_PB15, NULL, false); @@ -74,6 +78,7 @@ void board_init(void) { bus, start_sequence, sizeof(start_sequence), + 0, // start up time stop_sequence, sizeof(stop_sequence), 300, // width @@ -92,13 +97,15 @@ void board_init(void) { NO_COMMAND, // write_color_ram_command (can add this for grayscale eventually) false, // color_bits_inverted 0x000000, // highlight_color - 0x12, // refresh_display_command + 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 } diff --git a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk index 1e1bd31a24..f7e7be88d5 100644 --- a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk @@ -37,6 +37,7 @@ CIRCUITPY_USB_MIDI = 0 CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 CIRCUITPY_BITMAPTOOLS = 0 +CIRCUITPY_GIFIO = 0 CIRCUITPY_WATCHDOG = 0 CIRCUITPY_AUDIOIO = 1 diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index 3bb0cabf9e..02776928ca 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -268,7 +268,21 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, } int32_t status; if (len >= 16) { - status = sercom_dma_write(self->spi_desc.dev.prvt, data, len); + size_t bytes_remaining = len; + + // Maximum DMA transfer is 65535 + while (1) { + size_t to_send = (bytes_remaining > 65535) ? 65535 : bytes_remaining; + status = sercom_dma_write(self->spi_desc.dev.prvt, data + (len - bytes_remaining), to_send); + bytes_remaining -= to_send; + if (bytes_remaining > 0) { + // Multi-part transfer; let other things run before doing the next chunk. + RUN_BACKGROUND_TASKS; + } else { + // All done. + break; + } + } } else { struct io_descriptor *spi_io; spi_m_sync_get_io_descriptor(&self->spi_desc, &spi_io); diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c index 6027b6a5fa..280e8d10b6 100644 --- a/ports/atmel-samd/common-hal/busio/UART.c +++ b/ports/atmel-samd/common-hal/busio/UART.c @@ -58,6 +58,8 @@ static void usart_async_rxc_callback(const struct usart_async_descriptor *const // Nothing needs to be done by us. } +// shared-bindings validates that the tx and rx are not both missing, +// and that the pins are distinct. 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, @@ -92,10 +94,6 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, bool have_rts = rts != NULL; bool have_cts = cts != NULL; - if (!have_tx && !have_rx) { - mp_raise_ValueError(translate("tx and rx cannot both be None")); - } - if (have_rx && receiver_buffer_size > 0 && (receiver_buffer_size & (receiver_buffer_size - 1)) != 0) { mp_raise_ValueError_varg(translate("%q must be power of 2"), MP_QSTR_receiver_buffer_size); } @@ -107,6 +105,20 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // This assignment is only here because the usart_async routines take a *const argument. struct usart_async_descriptor *const usart_desc_p = (struct usart_async_descriptor *const)&self->usart_desc; + // Allowed pads for USART. See the SAMD21 and SAMx5x datasheets. + // TXPO: + // (both) 0x0: TX pad 0; no RTS/CTS + // (SAMD21) 0x1: TX pad 2; no RTS/CTS + // (SAMx5x) 0x1: reserved + // (both) 0x2: TX pad 0; RTS: pad 2, CTS: pad 3 + // (SAMD21) 0x3: reserved + // (SAMx5x) 0x3: TX pad 0; RTS: pad 2; no CTS + // RXPO: + // 0x0: RX pad 0 + // 0x1: RX pad 1 + // 0x2: RX pad 2 + // 0x3: RX pad 3 + for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { Sercom *potential_sercom = NULL; if (have_tx) { @@ -115,29 +127,71 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, continue; } potential_sercom = sercom_insts[sercom_index]; + + // SAMD21 and SAMx5x have different requirements. + #ifdef SAMD21 - if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 || - !(tx->sercom[i].pad == 0 || - tx->sercom[i].pad == 2)) { + if (potential_sercom->USART.CTRLA.bit.ENABLE != 0) { + // In use. continue; } + if (tx->sercom[i].pad != 0 && + tx->sercom[i].pad != 2) { + // TX must be on pad 0 or 2. + continue; + } + if (have_rts) { + if (rts->sercom[i].pad != 2 || + tx->sercom[i].pad == 2) { + // RTS pin must be on pad 2, so if TX is also on pad 2, not possible + continue; + } + } + if (have_cts) { + if (cts->sercom[i].pad != 3 || + (have_rx && rx->sercom[i].pad == 3)) { + // CTS pin must be on pad 3, so if RX is also on pad 3, not possible + continue; + } + } #endif + #ifdef SAM_D5X_E5X - if (potential_sercom->USART.CTRLA.bit.ENABLE != 0 || - !(tx->sercom[i].pad == 0)) { + if (potential_sercom->USART.CTRLA.bit.ENABLE != 0) { + // In use. continue; } + if (tx->sercom[i].pad != 0) { + // TX must be on pad 0 + continue; + } + + if (have_rts && rts->sercom[i].pad != 2) { + // RTS pin must be on pad 2 + continue; + } + if (have_cts) { + if (cts->sercom[i].pad != 3 || + (have_rx && rx->sercom[i].pad == 3)) { + // CTS pin must be on pad 3, so if RX is also on pad 3, not possible + continue; + } + } #endif + tx_pinmux = PINMUX(tx->number, (i == 0) ? MUX_C : MUX_D); tx_pad = tx->sercom[i].pad; if (have_rts) { rts_pinmux = PINMUX(rts->number, (i == 0) ? MUX_C : MUX_D); } - if (rx == NULL) { + if (!have_rx) { + // TX only, so don't need to look further. sercom = potential_sercom; break; } } + + // Have TX, now look for RX match. We know have_rx is true at this point. for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { if (((!have_tx && rx->sercom[j].index < SERCOM_INST_NUM && sercom_insts[rx->sercom[j].index]->USART.CTRLA.bit.ENABLE == 0) || @@ -160,20 +214,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if (sercom == NULL) { raise_ValueError_invalid_pins(); } - if (!have_tx) { - tx_pad = 0; - if (rx_pad == 0) { - tx_pad = 2; - } - } - if (!have_rx) { - rx_pad = (tx_pad + 1) % 4; - } - // Set up clocks on SERCOM. samd_peripherals_sercom_clock_init(sercom, sercom_index); - if (rx && receiver_buffer_size > 0) { + if (have_rx && receiver_buffer_size > 0) { self->buffer_length = receiver_buffer_size; if (NULL != receiver_buffer) { self->buffer = receiver_buffer; @@ -204,36 +248,41 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, // which don't necessarily match what we need. After calling it, set the values // specific to this instantiation of UART. - // Set pads computed for this SERCOM. Refer to the datasheet for details on pads. - // TXPO: - // 0x0: TX pad 0; no RTS/CTS - // 0x1: reserved - // 0x2: TX pad 0; RTS: pad 2, CTS: pad 3 - // 0x3: TX pad 0; RTS: pad 2; no CTS - // RXPO: - // 0x0: RX pad 0 - // 0x1: RX pad 1 - // 0x2: RX pad 2 - // 0x3: RX pad 3 + // See the TXPO/RXPO table above for how RXPO and TXPO are chosen below. - // Default to TXPO with no RTS/CTS - uint8_t computed_txpo = 0; - // If we have both CTS (with or without RTS), use second pinout - if (have_cts) { - computed_txpo = 2; - } - // If we have RTS only, use the third pinout - if (have_rts && !have_cts) { - computed_txpo = 3; + // rxpo maps directly to rx_pad. + // Set to 0x0 if no RX, but it doesn't matter because RX will not be enabled. + const uint8_t rxpo = have_rx ? rx_pad : 0x0; + + #ifdef SAMD21 + // SAMD21 has only one txpo value when using either CTS or RTS or both. + // TX is on pad 0 or 2, or there is no TX. + // 0x0 for pad 0, 0x1 for pad 2. + uint8_t txpo; + if (tx_pad == 2) { + txpo = 0x1; + } else { + txpo = (have_cts || have_rts) ? 0x2 : 0x0; } + #endif + + #ifdef SAM_D5X_E5X + // SAMx5x has two different possibilities, per the chart above. + // We already know TX is on pad 0, or there is no TX. + + // Without RTS or CTS, txpo can be 0x0. + // It's not clear if 0x2 would cover all our cases, but this is known to be safe. + uint8_t txpo = (have_rts || have_cts) ? 0x2: 0x0; + #endif // Doing a group mask and set of the registers saves 60 bytes over setting the bitfields individually. sercom->USART.CTRLA.reg &= ~(SERCOM_USART_CTRLA_TXPO_Msk | SERCOM_USART_CTRLA_RXPO_Msk | SERCOM_USART_CTRLA_FORM_Msk); - sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_TXPO(computed_txpo) | - SERCOM_USART_CTRLA_RXPO(rx_pad) | + // See chart above for TXPO values and RXPO values. + sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_TXPO(txpo) | + SERCOM_USART_CTRLA_RXPO(rxpo) | (parity == BUSIO_UART_PARITY_NONE ? 0 : SERCOM_USART_CTRLA_FORM(1)); // Enable tx and/or rx based on whether the pins were specified. diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c index b36286e5f2..d70de33618 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.c +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c @@ -211,5 +211,5 @@ mcu_pin_function_t *mcu_find_pin_function(mcu_pin_function_t *table, const mcu_p return table; } } - mp_raise_ValueError_varg(translate("%q pin invalid"), name); + mp_raise_ValueError_varg(translate("Invalid %q pin"), name); } diff --git a/ports/atmel-samd/common-hal/pwmio/PWMOut.c b/ports/atmel-samd/common-hal/pwmio/PWMOut.c index c6e9e07304..1bb955fce8 100644 --- a/ports/atmel-samd/common-hal/pwmio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pwmio/PWMOut.c @@ -67,10 +67,6 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { never_reset_pin_number(self->pin->number); } -void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { - timer_reset_ok(self->timer->index, self->timer->is_tc); -} - void pwmout_reset(void) { // Reset all timers for (int i = 0; i < TCC_INST_NUM; i++) { @@ -267,6 +263,7 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { if (common_hal_pwmio_pwmout_deinited(self)) { return; } + timer_reset_ok(self->timer->index, self->timer->is_tc); const pin_timer_t *t = self->timer; if (t->is_tc) { Tc *tc = tc_insts[t->index]; diff --git a/ports/broadcom/background.c b/ports/broadcom/background.c index 4b5190aa27..5d92f1b8bf 100644 --- a/ports/broadcom/background.c +++ b/ports/broadcom/background.c @@ -33,5 +33,8 @@ void port_start_background_task(void) { void port_finish_background_task(void) { } +void port_background_tick(void) { +} + void port_background_task(void) { } diff --git a/ports/broadcom/common-hal/busio/I2C.c b/ports/broadcom/common-hal/busio/I2C.c index 3142fda145..64187f434b 100644 --- a/ports/broadcom/common-hal/busio/I2C.c +++ b/ports/broadcom/common-hal/busio/I2C.c @@ -98,7 +98,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, self->sda_pin = sda; self->scl_pin = scl; - uint32_t source_clock = vcmailbox_get_clock_rate_measured(VCMAILBOX_CLOCK_CORE); + uint32_t source_clock = vcmailbox_get_clock_rate(VCMAILBOX_CLOCK_CORE); uint16_t clock_divider = source_clock / frequency; self->peripheral->DIV_b.CDIV = clock_divider; diff --git a/ports/broadcom/common-hal/busio/SPI.c b/ports/broadcom/common-hal/busio/SPI.c index 017674dfc0..5780ebe801 100644 --- a/ports/broadcom/common-hal/busio/SPI.c +++ b/ports/broadcom/common-hal/busio/SPI.c @@ -87,6 +87,8 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, mp_raise_NotImplementedError(translate("Half duplex SPI is not implemented")); } + // 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++) { if (spi_in_use[i]) { continue; @@ -157,6 +159,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { 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 || self->index == 2) { @@ -180,7 +183,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, if (self->index == 1 || self->index == 2) { SPI1_Type *p = aux_spi[self->index]; - uint32_t source_clock = vcmailbox_get_clock_rate_measured(VCMAILBOX_CLOCK_CORE); + uint32_t source_clock = vcmailbox_get_clock_rate(VCMAILBOX_CLOCK_CORE); uint16_t clock_divider = source_clock / baudrate; if (source_clock % baudrate > 0) { clock_divider += 2; @@ -198,7 +201,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, SPI0_Type *p = spi[self->index]; p->CS = polarity << SPI0_CS_CPOL_Pos | phase << SPI0_CS_CPHA_Pos; - uint32_t source_clock = vcmailbox_get_clock_rate_measured(VCMAILBOX_CLOCK_CORE); + uint32_t source_clock = vcmailbox_get_clock_rate(VCMAILBOX_CLOCK_CORE); uint16_t clock_divider = source_clock / baudrate; if (source_clock % baudrate > 0) { clock_divider += 2; diff --git a/ports/broadcom/common-hal/busio/UART.c b/ports/broadcom/common-hal/busio/UART.c index 9f51f15acb..5be098cf03 100644 --- a/ports/broadcom/common-hal/busio/UART.c +++ b/ports/broadcom/common-hal/busio/UART.c @@ -124,7 +124,7 @@ void pl011_IRQHandler(uint8_t index) { // Clear the interrupt in case we weren't able to clear it by emptying the // FIFO. (This won't clear the FIFO.) ARM_UART_PL011_Type *pl011 = uart[index]; - pl011->ICR = UART0_ICR_RXIC_Msk; + pl011->ICR = ARM_UART_PL011_ICR_RXIC_Msk; } void UART0_IRQHandler(void) { @@ -258,31 +258,31 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, common_hal_busio_uart_set_baudrate(self, baudrate); - uint32_t line_control = UART0_LCR_H_FEN_Msk; - line_control |= (bits - 5) << UART0_LCR_H_WLEN_Pos; + uint32_t line_control = ARM_UART_PL011_LCR_H_FEN_Msk; + line_control |= (bits - 5) << ARM_UART_PL011_LCR_H_WLEN_Pos; if (stop == 2) { - line_control |= UART0_LCR_H_STP2_Msk; + line_control |= ARM_UART_PL011_LCR_H_STP2_Msk; } if (parity != BUSIO_UART_PARITY_NONE) { - line_control |= UART0_LCR_H_PEN_Msk; + line_control |= ARM_UART_PL011_LCR_H_PEN_Msk; } if (parity == BUSIO_UART_PARITY_EVEN) { - line_control |= UART0_LCR_H_EPS_Msk; + line_control |= ARM_UART_PL011_LCR_H_EPS_Msk; } pl011->LCR_H = line_control; - uint32_t control = UART0_CR_UARTEN_Msk; + uint32_t control = ARM_UART_PL011_CR_UARTEN_Msk; if (tx != NULL) { - control |= UART0_CR_TXE_Msk; + control |= ARM_UART_PL011_CR_TXE_Msk; } if (rx != NULL) { - control |= UART0_CR_RXE_Msk; + control |= ARM_UART_PL011_CR_RXE_Msk; } if (cts != NULL) { - control |= UART0_CR_CTSEN_Msk; + control |= ARM_UART_PL011_CR_CTSEN_Msk; } if (rts != NULL) { - control |= UART0_CR_RTSEN_Msk; + control |= ARM_UART_PL011_CR_RTSEN_Msk; } pl011->CR = control; } @@ -460,7 +460,7 @@ uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { if (self->uart_id == 1) { - uint32_t source_clock = vcmailbox_get_clock_rate_measured(VCMAILBOX_CLOCK_CORE); + uint32_t source_clock = vcmailbox_get_clock_rate(VCMAILBOX_CLOCK_CORE); UART1->BAUD = ((source_clock / (baudrate * 8)) - 1); } else { ARM_UART_PL011_Type *pl011 = uart[self->uart_id]; diff --git a/ports/broadcom/common-hal/sdioio/SDCard.c b/ports/broadcom/common-hal/sdioio/SDCard.c index 27b36041de..cf8bfb1faa 100644 --- a/ports/broadcom/common-hal/sdioio/SDCard.c +++ b/ports/broadcom/common-hal/sdioio/SDCard.c @@ -122,27 +122,27 @@ STATIC sdmmc_err_t _do_transaction(int slot, sdmmc_command_t *cmdinfo) { if (EMMC->STATUS_b.DAT_INHIBIT) { return SDMMC_ERR_BUSY; } - cmd_flags = EMMC_CMDTM_TM_BLKCNT_EN_Msk | EMMC_CMDTM_CMD_ISDATA_Msk; + cmd_flags = Arasan_EMMC_Distributor_CMDTM_TM_BLKCNT_EN_Msk | Arasan_EMMC_Distributor_CMDTM_CMD_ISDATA_Msk; if (cmdinfo->datalen > cmdinfo->blklen) { - cmd_flags |= EMMC_CMDTM_TM_MULTI_BLOCK_Msk; + cmd_flags |= Arasan_EMMC_Distributor_CMDTM_TM_MULTI_BLOCK_Msk; if ((cmdinfo->flags & SCF_AUTO_STOP) != 0) { - cmd_flags |= 1 << EMMC_CMDTM_TM_AUTO_CMD_EN_Pos; + cmd_flags |= 1 << Arasan_EMMC_Distributor_CMDTM_TM_AUTO_CMD_EN_Pos; } } if (read) { - cmd_flags |= EMMC_CMDTM_TM_DAT_DIR_Msk; + cmd_flags |= Arasan_EMMC_Distributor_CMDTM_TM_DAT_DIR_Msk; } - EMMC->BLKSIZECNT = (cmdinfo->datalen / cmdinfo->blklen) << EMMC_BLKSIZECNT_BLKCNT_Pos | - cmdinfo->blklen << EMMC_BLKSIZECNT_BLKSIZE_Pos; + EMMC->BLKSIZECNT = (cmdinfo->datalen / cmdinfo->blklen) << Arasan_EMMC_Distributor_BLKSIZECNT_BLKCNT_Pos | + cmdinfo->blklen << Arasan_EMMC_Distributor_BLKSIZECNT_BLKSIZE_Pos; } uint32_t response_type = EMMC_CMDTM_CMD_RSPNS_TYPE_RESPONSE_48BITS; uint32_t crc = 0; if ((cmdinfo->flags & SCF_RSP_CRC) != 0) { - crc |= EMMC_CMDTM_CMD_CRCCHK_EN_Msk; + crc |= Arasan_EMMC_Distributor_CMDTM_CMD_CRCCHK_EN_Msk; } if ((cmdinfo->flags & SCF_RSP_IDX) != 0) { - crc |= EMMC_CMDTM_CMD_IXCHK_EN_Msk; + crc |= Arasan_EMMC_Distributor_CMDTM_CMD_IXCHK_EN_Msk; } if ((cmdinfo->flags & SCF_RSP_136) != 0) { response_type = EMMC_CMDTM_CMD_RSPNS_TYPE_RESPONSE_136BITS; @@ -152,8 +152,8 @@ STATIC sdmmc_err_t _do_transaction(int slot, sdmmc_command_t *cmdinfo) { response_type = EMMC_CMDTM_CMD_RSPNS_TYPE_RESPONSE_NONE; } uint32_t full_cmd = cmd_flags | crc | - cmdinfo->opcode << EMMC_CMDTM_CMD_INDEX_Pos | - response_type << EMMC_CMDTM_CMD_RSPNS_TYPE_Pos; + cmdinfo->opcode << Arasan_EMMC_Distributor_CMDTM_CMD_INDEX_Pos | + response_type << Arasan_EMMC_Distributor_CMDTM_CMD_RSPNS_TYPE_Pos; EMMC->CMDTM = full_cmd; // Wait for an interrupt to indicate completion of the command. @@ -170,7 +170,7 @@ STATIC sdmmc_err_t _do_transaction(int slot, sdmmc_command_t *cmdinfo) { } return SDMMC_ERR_TIMEOUT; } else { - EMMC->INTERRUPT = EMMC_INTERRUPT_CMD_DONE_Msk; + EMMC->INTERRUPT = Arasan_EMMC_Distributor_INTERRUPT_CMD_DONE_Msk; } // Transfer the data. @@ -197,7 +197,7 @@ STATIC sdmmc_err_t _do_transaction(int slot, sdmmc_command_t *cmdinfo) { EMMC->DATA = ((uint32_t *)cmdinfo->data)[i]; } } - uint32_t data_done_mask = EMMC_INTERRUPT_ERR_Msk | EMMC_INTERRUPT_DATA_DONE_Msk; + uint32_t data_done_mask = Arasan_EMMC_Distributor_INTERRUPT_ERR_Msk | Arasan_EMMC_Distributor_INTERRUPT_DATA_DONE_Msk; start_ticks = port_get_raw_ticks(NULL); while ((EMMC->INTERRUPT & data_done_mask) == 0 && (port_get_raw_ticks(NULL) - start_ticks) < (size_t)cmdinfo->timeout_ms) { } @@ -282,7 +282,7 @@ void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, } // Set max timeout - EMMC->CONTROL1 |= EMMC_CONTROL1_CLK_INTLEN_Msk | (0xe << EMMC_CONTROL1_DATA_TOUNIT_Pos); + EMMC->CONTROL1 |= Arasan_EMMC_Distributor_CONTROL1_CLK_INTLEN_Msk | (0xe << Arasan_EMMC_Distributor_CONTROL1_DATA_TOUNIT_Pos); EMMC->IRPT_MASK = 0xffffffff; diff --git a/ports/broadcom/peripherals b/ports/broadcom/peripherals index 0837008608..d3a6b50a21 160000 --- a/ports/broadcom/peripherals +++ b/ports/broadcom/peripherals @@ -1 +1 @@ -Subproject commit 08370086080759ed54ac1136d62d2ad24c6fa267 +Subproject commit d3a6b50a21e7dd49ba4bfa0374da3407594caa50 diff --git a/ports/cxd56/background.c b/ports/cxd56/background.c index 644a5d7b0b..da172cf5d7 100644 --- a/ports/cxd56/background.c +++ b/ports/cxd56/background.c @@ -30,6 +30,8 @@ #include "supervisor/filesystem.h" #include "supervisor/shared/stack.h" +void port_background_tick(void) { +} void port_background_task(void) { } void port_start_background_task(void) { diff --git a/ports/cxd56/common-hal/pwmio/PWMOut.c b/ports/cxd56/common-hal/pwmio/PWMOut.c index 7e27817aab..10689dc55a 100644 --- a/ports/cxd56/common-hal/pwmio/PWMOut.c +++ b/ports/cxd56/common-hal/pwmio/PWMOut.c @@ -90,6 +90,8 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { return; } + pwmout_dev[self->number].reset = true; + ioctl(pwmout_dev[self->number].fd, PWMIOC_STOP, 0); close(pwmout_dev[self->number].fd); pwmout_dev[self->number].fd = -1; @@ -134,10 +136,6 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { pwmout_dev[self->number].reset = false; } -void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { - pwmout_dev[self->number].reset = true; -} - void pwmout_reset(void) { for (int i = 0; i < MP_ARRAY_SIZE(pwmout_dev); i++) { if (pwmout_dev[i].fd >= 0 && pwmout_dev[i].reset) { diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 1c79691b33..2151c8e03c 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -126,9 +126,13 @@ ifeq ($(DEBUG), 1) # CFLAGS += -fno-inline -fno-ipa-sra else CFLAGS += -DNDEBUG -ggdb3 - OPTIMIZATION_FLAGS ?= -O2 # RISC-V is larger than xtensa # Use -Os for RISC-V when it overflows + ifeq ($(IDF_TARGET_ARCH),riscv) + OPTIMIZATION_FLAGS ?= -Os + else + OPTIMIZATION_FLAGS ?= -O2 + endif endif # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk @@ -214,7 +218,6 @@ endif SRC_C += \ background.c \ mphalport.c \ - bindings/espidf/__init__.c \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ shared/netutils/netutils.c \ @@ -248,8 +251,6 @@ ifneq ($(CIRCUITPY_BLEIO),0) SRC_C += common-hal/_bleio/ble_events.c endif -SRC_C += $(wildcard common-hal/espidf/*.c) - ifneq ($(CIRCUITPY_ESPCAMERA),0) SRC_CAMERA := \ $(wildcard common-hal/espcamera/*.c) \ @@ -259,6 +260,20 @@ CFLAGS += -isystem esp32-camera/driver/include CFLAGS += -isystem esp32-camera/conversions/include endif +ifneq ($(CIRCUITPY_ESPIDF),0) +SRC_ESPIDF := \ + $(wildcard common-hal/espidf/*.c) \ + $(wildcard bindings/espidf/*.c) +SRC_C += $(SRC_ESPIDF) +endif + +ifneq ($(CIRCUITPY_ESPNOW),0) +SRC_ESPNOW := \ + $(wildcard common-hal/espnow/*.c) \ + $(wildcard bindings/espnow/*.c) +SRC_C += $(SRC_ESPNOW) +endif + ifneq ($(CIRCUITPY_ESPULP),0) SRC_ULP := \ $(wildcard common-hal/espulp/*.c) \ @@ -434,7 +449,7 @@ $(BUILD)/firmware.elf: $(OBJ) | esp-idf-stamp $(BUILD)/circuitpython-firmware.bin: $(BUILD)/firmware.elf | tools/build_memory_info.py $(STEPECHO) "Create $@" $(Q)esptool.py --chip $(IDF_TARGET) elf2image $(FLASH_FLAGS) --elf-sha256-offset 0xb0 -o $@ $^ - $(Q)$(PYTHON) tools/build_memory_info.py $< $(BUILD)/esp-idf/sdkconfig $@ + $(Q)$(PYTHON) tools/build_memory_info.py $< $(BUILD)/esp-idf/sdkconfig $@ $(BUILD) $(BUILD)/firmware.bin: $(BUILD)/circuitpython-firmware.bin | esp-idf-stamp $(Q)$(PYTHON) ../../tools/join_bins.py $@ $(BOOTLOADER_OFFSET) $(BUILD)/esp-idf/bootloader/bootloader.bin $(PARTITION_TABLE_OFFSET) $(BUILD)/esp-idf/partition_table/partition-table.bin $(FIRMWARE_OFFSET) $(BUILD)/circuitpython-firmware.bin diff --git a/ports/espressif/background.c b/ports/espressif/background.c index 0b5bb96a3b..3fac768f3f 100644 --- a/ports/espressif/background.c +++ b/ports/espressif/background.c @@ -40,7 +40,7 @@ #include "common-hal/pulseio/PulseIn.h" #endif -void port_background_task(void) { +void port_background_tick(void) { // Zero delay in case FreeRTOS wants to switch to something else. vTaskDelay(0); #if CIRCUITPY_PULSEIO @@ -48,6 +48,9 @@ void port_background_task(void) { #endif } +void port_background_task(void) { +} + void port_start_background_task(void) { } diff --git a/ports/espressif/bindings/espnow/ESPNow.c b/ports/espressif/bindings/espnow/ESPNow.c new file mode 100644 index 0000000000..513966e1e8 --- /dev/null +++ b/ports/espressif/bindings/espnow/ESPNow.c @@ -0,0 +1,369 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017-2020 Nick Moore + * Copyright (c) 2018 shawwwn + * Copyright (c) 2020-2021 Glenn Moloney @glenn20 + * Copyright (c) 2023 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. + */ + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/stream.h" + +#include "shared-bindings/util.h" + +#include "bindings/espnow/ESPNow.h" +#include "bindings/espnow/Peer.h" + +#include "common-hal/espnow/__init__.h" +#include "common-hal/espnow/ESPNow.h" + +#include "esp_now.h" + +// Raise ValueError if the ESPNow object is deinited +static void espnow_check_for_deinit(espnow_obj_t *self) { + if (common_hal_espnow_deinited(self)) { + raise_deinited_error(); + } +} + +// --- Initialisation and Config functions --- + +//| class ESPNow: +//| """Provides access to the ESP-NOW protocol.""" +//| +//| def __init__(self, buffer_size: Optional[int], phy_rate: Optional[int]) -> None: +//| """Allocate and initialize `ESPNow` instance as a singleton. +//| +//| :param int buffer_size: The size of the internal ring buffer. Default: 526 bytes. +//| :param int phy_rate: The ESP-NOW physical layer rate. Default: 1 Mbps.""" +//| ... +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[] = { + { MP_QSTR_buffer_size, MP_ARG_INT, { .u_int = 526 } }, + { MP_QSTR_phy_rate, MP_ARG_INT, { .u_int = WIFI_PHY_RATE_1M_L } }, + }; + + 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); + + espnow_obj_t *self = MP_STATE_PORT(espnow_singleton); + + if (self != NULL) { + mp_raise_RuntimeError(translate("Already running")); + } + + // Allocate a new object + self = m_new_obj(espnow_obj_t); + self->base.type = &espnow_type; + + // Construct the object + common_hal_espnow_construct(self, args[ARG_buffer_size].u_int, args[ARG_phy_rate].u_int); + + // Set the global singleton pointer for the espnow protocol. + MP_STATE_PORT(espnow_singleton) = self; + return MP_OBJ_FROM_PTR(self); +} + +//| 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); + common_hal_espnow_deinit(self); + return mp_const_none; +} +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__); + +// --- Send and Read messages --- + +//| def send( +//| self, +//| message: ReadableBuffer, +//| peer: Optional[Peer] = None, +//| ) -> None: +//| """Send a message to the peer's mac address. +//| +//| This blocks until a timeout of ``2`` seconds if the ESP-NOW internal buffers are full. +//| +//| :param ReadableBuffer message: The message to send (length <= 250 bytes). +//| :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[] = { + { MP_QSTR_message, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_peer, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + + 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); + + espnow_obj_t *self = pos_args[0]; + espnow_check_for_deinit(self); + + // Get a pointer to the data buffer of the message + mp_buffer_info_t message; + mp_get_buffer_raise(args[ARG_message].u_obj, &message, MP_BUFFER_READ); + + const uint8_t *mac = NULL; + if (args[ARG_peer].u_obj != mp_const_none) { + const espnow_peer_obj_t *peer = MP_OBJ_FROM_PTR(mp_arg_validate_type_or_none(args[ARG_peer].u_obj, &espnow_peer_type, MP_QSTR_peer)); + mac = peer->peer_info.peer_addr; + } + + return common_hal_espnow_send(self, &message, mac); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espnow_send_obj, 2, espnow_send); + +//| def read(self) -> Optional[ESPNowPacket]: +//| """Read a packet from the receive buffer. +//| +//| This is non-blocking, the packet is received asynchronously from the peer(s). +//| +//| :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); + + return common_hal_espnow_read(self); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_read_obj, espnow_read); + +//| send_success: int +//| """The number of tx packets received by the peer(s) ``ESP_NOW_SEND_SUCCESS``. (read-only)""" +//| +STATIC mp_obj_t espnow_get_send_success(const mp_obj_t self_in) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(self->send_success); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_send_success_obj, espnow_get_send_success); + +MP_PROPERTY_GETTER(espnow_send_success_obj, + (mp_obj_t)&espnow_get_send_success_obj); + +//| send_failure: int +//| """The number of failed tx packets ``ESP_NOW_SEND_FAIL``. (read-only)""" +//| +STATIC mp_obj_t espnow_send_get_failure(const mp_obj_t self_in) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(self->send_failure); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_send_get_failure_obj, espnow_send_get_failure); + +MP_PROPERTY_GETTER(espnow_send_failure_obj, + (mp_obj_t)&espnow_send_get_failure_obj); + +//| read_success: int +//| """The number of rx packets captured in the buffer. (read-only)""" +//| +STATIC mp_obj_t espnow_get_read_success(const mp_obj_t self_in) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(self->read_success); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_read_success_obj, espnow_get_read_success); + +MP_PROPERTY_GETTER(espnow_read_success_obj, + (mp_obj_t)&espnow_get_read_success_obj); + +//| read_failure: int +//| """The number of dropped rx packets due to buffer overflow. (read-only)""" +//| +STATIC mp_obj_t espnow_read_get_failure(const mp_obj_t self_in) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(self->read_failure); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_read_get_failure_obj, espnow_read_get_failure); + +MP_PROPERTY_GETTER(espnow_read_failure_obj, + (mp_obj_t)&espnow_read_get_failure_obj); + +//| def set_pmk(self, pmk: ReadableBuffer) -> None: +//| """Set the ESP-NOW Primary Master Key (pmk) for encrypted communications. +//| +//| :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); + common_hal_espnow_set_pmk(self, common_hal_espnow_get_bytes_len(key, ESP_NOW_KEY_LEN)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_set_pmk_obj, espnow_set_pmk); + +//| buffer_size: int +//| """The size of the internal ring buffer. (read-only)""" +//| +STATIC mp_obj_t espnow_get_buffer_size(const mp_obj_t self_in) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int_from_uint(self->recv_buffer_size); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_buffer_size_obj, espnow_get_buffer_size); + +MP_PROPERTY_GETTER(espnow_buffer_size_obj, + (mp_obj_t)&espnow_get_buffer_size_obj); + +//| phy_rate: int +//| """The ESP-NOW physical layer rate.""" +//| +STATIC mp_obj_t espnow_get_phy_rate(const mp_obj_t self_in) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(self->phy_rate); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_phy_rate_obj, espnow_get_phy_rate); + +STATIC mp_obj_t espnow_set_phy_rate(const mp_obj_t self_in, const mp_obj_t value) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + espnow_check_for_deinit(self); + common_hal_espnow_set_phy_rate(self, mp_obj_get_int(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(espnow_set_phy_rate_obj, espnow_set_phy_rate); + +MP_PROPERTY_GETSET(espnow_phy_rate_obj, + (mp_obj_t)&espnow_get_phy_rate_obj, + (mp_obj_t)&espnow_set_phy_rate_obj); + +// --- Peer Related Properties --- + +//| peers: Peers +//| """The peer info records for all registered `ESPNow` peers. (read-only)""" +//| +STATIC mp_obj_t espnow_get_peers(mp_obj_t self_in) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_FROM_PTR(self->peers); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_peers_obj, espnow_get_peers); + +MP_PROPERTY_GETTER(espnow_peers_obj, + (mp_obj_t)&espnow_get_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) }, + + // Deinit the object + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espnow_deinit_obj) }, + + // Send messages + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&espnow_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_send_success),MP_ROM_PTR(&espnow_send_success_obj)}, + { MP_ROM_QSTR(MP_QSTR_send_failure),MP_ROM_PTR(&espnow_send_failure_obj)}, + + // Read messages + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&espnow_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_read_success),MP_ROM_PTR(&espnow_read_success_obj)}, + { MP_ROM_QSTR(MP_QSTR_read_failure),MP_ROM_PTR(&espnow_read_failure_obj)}, + + // Config parameters + { MP_ROM_QSTR(MP_QSTR_set_pmk), MP_ROM_PTR(&espnow_set_pmk_obj) }, + { MP_ROM_QSTR(MP_QSTR_buffer_size), MP_ROM_PTR(&espnow_buffer_size_obj) }, + { MP_ROM_QSTR(MP_QSTR_phy_rate), MP_ROM_PTR(&espnow_phy_rate_obj) }, + + // Peer related properties + { MP_ROM_QSTR(MP_QSTR_peers), MP_ROM_PTR(&espnow_peers_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(espnow_locals_dict, espnow_locals_dict_table); + +// --- Dummy Buffer Protocol support --- +// ...so asyncio can poll.ipoll() on this device + +// Support ioctl(MP_STREAM_POLL, ) for asyncio +STATIC mp_uint_t espnow_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); + espnow_check_for_deinit(self); + switch (request) { + case MP_STREAM_POLL: { + mp_uint_t flags = arg; + mp_uint_t ret = 0; + if ((flags & MP_STREAM_POLL_RD) && ringbuf_num_filled(self->recv_buffer) > 0) { + ret |= MP_STREAM_POLL_RD; + } + return ret; + } + default: + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } +} + +STATIC const mp_stream_p_t espnow_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) + .ioctl = espnow_stream_ioctl, +}; + +//| def __bool__(self) -> bool: +//| """``True`` if `len()` is greater than zero. +//| This is an easy way to check if the buffer is empty. +//| """ +//| ... +//| def __len__(self) -> int: +//| """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); + size_t len = ringbuf_num_filled(self->recv_buffer); + switch (op) { + case MP_UNARY_OP_BOOL: + return mp_obj_new_bool(len != 0); + case MP_UNARY_OP_LEN: + return mp_obj_new_int_from_uint(len); + default: + return MP_OBJ_NULL; // op not supported + } +} + +const mp_obj_type_t espnow_type = { + { &mp_type_type }, + .name = MP_QSTR_ESPNow, + .make_new = espnow_make_new, + .locals_dict = (mp_obj_t)&espnow_locals_dict, + .flags = MP_TYPE_FLAG_EXTENDED, + MP_TYPE_EXTENDED_FIELDS( + .protocol = &espnow_stream_p, + .unary_op = &espnow_unary_op + ), +}; diff --git a/ports/espressif/bindings/espnow/ESPNow.h b/ports/espressif/bindings/espnow/ESPNow.h new file mode 100644 index 0000000000..6aa011c501 --- /dev/null +++ b/ports/espressif/bindings/espnow/ESPNow.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Glenn Moloney @glenn20 + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "py/obj.h" +extern const mp_obj_type_t espnow_type; diff --git a/ports/espressif/bindings/espnow/ESPNowPacket.c b/ports/espressif/bindings/espnow/ESPNowPacket.c new file mode 100644 index 0000000000..f8bc8e8418 --- /dev/null +++ b/ports/espressif/bindings/espnow/ESPNowPacket.c @@ -0,0 +1,70 @@ +/* + * This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#include "bindings/espnow/ESPNowPacket.h" + +//| class ESPNowPacket: +//| """A packet retrieved from ESP-NOW communication protocol. A namedtuple.""" +//| +//| mac: ReadableBuffer +//| """The sender's mac address (length = 6 bytes).""" +//| +//| msg: ReadableBuffer +//| """The message sent by the peer (length <= 250 bytes).""" +//| +//| rssi: int +//| """The received signal strength indication (in dBm from -127 to 0).""" +//| +//| 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 = { + .base = { + .base = { + .type = &mp_type_type + }, + .flags = MP_TYPE_FLAG_EXTENDED, + .name = MP_QSTR_ESPNowPacket, + .print = namedtuple_print, + .parent = &mp_type_tuple, + .make_new = namedtuple_make_new, + .attr = namedtuple_attr, + MP_TYPE_EXTENDED_FIELDS( + .unary_op = mp_obj_tuple_unary_op, + .binary_op = mp_obj_tuple_binary_op, + .subscr = mp_obj_tuple_subscr, + .getiter = mp_obj_tuple_getiter, + ), + }, + .n_fields = 4, + .fields = { + MP_QSTR_mac, + MP_QSTR_msg, + MP_QSTR_rssi, + MP_QSTR_time, + }, +}; diff --git a/ports/espressif/bindings/espnow/ESPNowPacket.h b/ports/espressif/bindings/espnow/ESPNowPacket.h new file mode 100644 index 0000000000..87fc51ee92 --- /dev/null +++ b/ports/espressif/bindings/espnow/ESPNowPacket.h @@ -0,0 +1,30 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "py/objnamedtuple.h" +extern const mp_obj_namedtuple_type_t espnow_packet_type_obj; diff --git a/ports/espressif/bindings/espnow/Peer.c b/ports/espressif/bindings/espnow/Peer.c new file mode 100644 index 0000000000..7b6cc5f668 --- /dev/null +++ b/ports/espressif/bindings/espnow/Peer.c @@ -0,0 +1,240 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +#include "bindings/espnow/Peer.h" +#include "common-hal/espnow/__init__.h" + +// TODO: check peer already exist +// TODO: check peer dosen't exist + +//| class Peer: +//| """A data class to store parameters specific to a peer.""" +//| +//| def __init__( +//| self, +//| mac: bytes, +//| lmk: Optional[bytes], +//| channel: int = 0, +//| interface: int = 0, +//| encrypt: bool = False, +//| ) -> None: +//| """Construct a new peer object. +//| +//| :param bytes mac: The mac address of the peer. +//| :param bytes lmk: The Local Master Key (lmk) of the peer. +//| :param int channel: The peer's channel. Default: 0 ie. use the current channel. +//| :param int interface: The WiFi interface to use. Default: 0 ie. STA. +//| :param bool encrypt: 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_encrypt }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mac, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_lmk, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_channel, MP_ARG_INT, { .u_obj = mp_const_none } }, + { MP_QSTR_interface,MP_ARG_INT, { .u_obj = mp_const_none } }, + { MP_QSTR_encrypt, MP_ARG_BOOL,{ .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); + + espnow_peer_obj_t *self = m_new_obj(espnow_peer_obj_t); + self->base.type = &espnow_peer_type; + self->peer_info = (esp_now_peer_info_t) { + .channel = 0, + .ifidx = WIFI_IF_STA, + .encrypt = false + }; + + memcpy(self->peer_info.peer_addr, common_hal_espnow_get_bytes_len(args[ARG_mac].u_obj, ESP_NOW_ETH_ALEN), ESP_NOW_ETH_ALEN); + + const mp_obj_t channel = args[ARG_channel].u_obj; + if (channel != mp_const_none) { + self->peer_info.channel = mp_arg_validate_int_range(mp_obj_get_int(channel), 0, 14, MP_QSTR_channel); + } + + const mp_obj_t interface = args[ARG_interface].u_obj; + if (interface != mp_const_none) { + self->peer_info.ifidx = (wifi_interface_t)mp_arg_validate_int_range(mp_obj_get_int(interface), 0, 1, MP_QSTR_interface); + } + + const mp_obj_t encrypt = args[ARG_encrypt].u_obj; + if (encrypt != mp_const_none) { + self->peer_info.encrypt = mp_obj_is_true(encrypt); + } + + const mp_obj_t lmk = args[ARG_lmk].u_obj; + if (lmk != mp_const_none) { + memcpy(self->peer_info.lmk, common_hal_espnow_get_bytes_len(lmk, ESP_NOW_KEY_LEN), ESP_NOW_KEY_LEN); + } else if (self->peer_info.encrypt && !self->peer_info.lmk) { + mp_raise_ValueError_varg(translate("%q is %q"), MP_QSTR_lmk, MP_QSTR_None); + } + + return self; +} + +//| mac: ReadableBuffer +//| """The WiFi mac to use.""" +//| +STATIC mp_obj_t espnow_peer_get_mac(const mp_obj_t self_in) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bytes(self->peer_info.peer_addr, MP_ARRAY_SIZE(self->peer_info.peer_addr)); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_peer_get_mac_obj, espnow_peer_get_mac); + +STATIC mp_obj_t espnow_peer_set_mac(const mp_obj_t self_in, const mp_obj_t value) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + memcpy(self->peer_info.peer_addr, common_hal_espnow_get_bytes_len(value, ESP_NOW_ETH_ALEN), ESP_NOW_ETH_ALEN); + esp_now_mod_peer(&self->peer_info); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(espnow_peer_set_mac_obj, espnow_peer_set_mac); + +MP_PROPERTY_GETSET(espnow_peer_mac_obj, + (mp_obj_t)&espnow_peer_get_mac_obj, + (mp_obj_t)&espnow_peer_set_mac_obj); + +//| lmk: ReadableBuffer +//| """The WiFi lmk to use.""" +//| +STATIC mp_obj_t espnow_peer_get_lmk(const mp_obj_t self_in) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bytes(self->peer_info.lmk, MP_ARRAY_SIZE(self->peer_info.lmk)); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_peer_get_lmk_obj, espnow_peer_get_lmk); + +STATIC mp_obj_t espnow_peer_set_lmk(const mp_obj_t self_in, const mp_obj_t value) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + memcpy(self->peer_info.lmk, common_hal_espnow_get_bytes_len(value, ESP_NOW_KEY_LEN), ESP_NOW_KEY_LEN); + esp_now_mod_peer(&self->peer_info); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(espnow_peer_set_lmk_obj, espnow_peer_set_lmk); + +MP_PROPERTY_GETSET(espnow_peer_lmk_obj, + (mp_obj_t)&espnow_peer_get_lmk_obj, + (mp_obj_t)&espnow_peer_set_lmk_obj); + +//| channel: int +//| """The WiFi channel to use.""" +//| +STATIC mp_obj_t espnow_peer_get_channel(const mp_obj_t self_in) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(self->peer_info.channel); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_peer_get_channel_obj, espnow_peer_get_channel); + +STATIC mp_obj_t espnow_peer_set_channel(const mp_obj_t self_in, const mp_obj_t value) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->peer_info.channel = mp_arg_validate_int_range(mp_obj_get_int(value), 0, 14, MP_QSTR_channel); + esp_now_mod_peer(&self->peer_info); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(espnow_peer_set_channel_obj, espnow_peer_set_channel); + +MP_PROPERTY_GETSET(espnow_peer_channel_obj, + (mp_obj_t)&espnow_peer_get_channel_obj, + (mp_obj_t)&espnow_peer_set_channel_obj); + +//| interface: int +//| """The WiFi interface to use.""" +//| +STATIC mp_obj_t espnow_peer_get_interface(const mp_obj_t self_in) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(self->peer_info.ifidx); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_peer_get_interface_obj, espnow_peer_get_interface); + +STATIC mp_obj_t espnow_peer_set_interface(const mp_obj_t self_in, const mp_obj_t value) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->peer_info.ifidx = (wifi_interface_t)mp_arg_validate_int_range(mp_obj_get_int(value), 0, 1, MP_QSTR_interface); + esp_now_mod_peer(&self->peer_info); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(espnow_peer_set_interface_obj, espnow_peer_set_interface); + +MP_PROPERTY_GETSET(espnow_peer_interface_obj, + (mp_obj_t)&espnow_peer_get_interface_obj, + (mp_obj_t)&espnow_peer_set_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); +} +MP_DEFINE_CONST_FUN_OBJ_1(espnow_peer_get_encrypted_obj, espnow_peer_get_encrypted); + +STATIC mp_obj_t espnow_peer_set_encrypted(const mp_obj_t self_in, const mp_obj_t value) { + espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->peer_info.encrypt = mp_obj_is_true(value); + + if (!self->peer_info.lmk) { + mp_raise_ValueError_varg(translate("%q is %q"), MP_QSTR_lmk, MP_QSTR_None); + } + + esp_now_mod_peer(&self->peer_info); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(espnow_peer_set_encrypted_obj, espnow_peer_set_encrypted); + +MP_PROPERTY_GETSET(espnow_peer_encrypted_obj, + (mp_obj_t)&espnow_peer_get_encrypted_obj, + (mp_obj_t)&espnow_peer_set_encrypted_obj); + +STATIC const mp_rom_map_elem_t espnow_peer_locals_dict_table[] = { + // Peer parameters + { MP_ROM_QSTR(MP_QSTR_mac), MP_ROM_PTR(&espnow_peer_mac_obj) }, + { MP_ROM_QSTR(MP_QSTR_lmk), MP_ROM_PTR(&espnow_peer_lmk_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&espnow_peer_channel_obj) }, + { MP_ROM_QSTR(MP_QSTR_interface), MP_ROM_PTR(&espnow_peer_interface_obj) }, + { MP_ROM_QSTR(MP_QSTR_encrypted), MP_ROM_PTR(&espnow_peer_encrypted_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(espnow_peer_locals_dict, espnow_peer_locals_dict_table); + +const mp_obj_type_t espnow_peer_type = { + { &mp_type_type }, + .name = MP_QSTR_Peer, + .make_new = espnow_peer_make_new, + .locals_dict = (mp_obj_t)&espnow_peer_locals_dict, +}; diff --git a/ports/espressif/bindings/espnow/Peer.h b/ports/espressif/bindings/espnow/Peer.h new file mode 100644 index 0000000000..e4cb828472 --- /dev/null +++ b/ports/espressif/bindings/espnow/Peer.h @@ -0,0 +1,37 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "py/obj.h" +#include "esp_now.h" + +typedef struct { + mp_obj_base_t base; + esp_now_peer_info_t peer_info; +} espnow_peer_obj_t; + +const mp_obj_type_t espnow_peer_type; diff --git a/ports/espressif/bindings/espnow/Peers.c b/ports/espressif/bindings/espnow/Peers.c new file mode 100644 index 0000000000..15d07c09d0 --- /dev/null +++ b/ports/espressif/bindings/espnow/Peers.c @@ -0,0 +1,140 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#include "py/obj.h" +#include "py/objlist.h" +#include "py/runtime.h" + +#include "bindings/espidf/__init__.h" + +#include "bindings/espnow/Peer.h" +#include "bindings/espnow/Peers.h" + +#include "esp_now.h" + +// TODO: Check for deinit + +//| class Peers: +//| """Maintains a `list` of `Peer` internally and only exposes a subset of `list` methods.""" +//| +//| def __init__(self) -> None: +//| """You cannot create an instance of `Peers`.""" +//| ... + +//| def append(self, peer: Peer) -> None: +//| """Append peer. +//| +//| :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)); + espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_list_append(self->list, arg); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_peers_append_obj, espnow_peers_append); + +//| def remove(self, peer: Peer) -> None: +//| """Remove peer. +//| +//| :param Peer peer: The peer object to remove. +//| """ +//| ... +//| +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)); + espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_list_remove(self->list, arg); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_peers_remove_obj, espnow_peers_remove); + +STATIC const mp_rom_map_elem_t espnow_peers_locals_dict_table[] = { + // Peer management functions + { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&espnow_peers_append_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&espnow_peers_remove_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(espnow_peers_locals_dict, espnow_peers_locals_dict_table); + +/******************************************************************************/ +/* peers print */ + +STATIC void espnow_peers_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); + return list->base.type->print(print, self->list, kind); +} + +/******************************************************************************/ +/* peers unary_op */ + +STATIC mp_obj_t espnow_peers_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); + return list->base.type->ext->unary_op(op, self->list); +} + +/******************************************************************************/ +/* peers subscript */ + +STATIC mp_obj_t espnow_peers_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { + if (value != MP_OBJ_SENTINEL) { + return MP_OBJ_NULL; // op not supported + } + espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); + return list->base.type->ext->subscr(self->list, index, value); +} + +/******************************************************************************/ +/* peers iterator */ + +STATIC mp_obj_t espnow_peers_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { + espnow_peers_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); + return list->base.type->ext->getiter(self->list, iter_buf); +} + +espnow_peers_obj_t *espnow_peers_new(void) { + espnow_peers_obj_t *self = m_new_obj(espnow_peers_obj_t); + self->base.type = &espnow_peers_type; + self->list = mp_obj_new_list(0, NULL); + return self; +} + +const mp_obj_type_t espnow_peers_type = { + { &mp_type_type }, + .name = MP_QSTR_Peers, + .print = espnow_peers_print, + .locals_dict = (mp_obj_t)&espnow_peers_locals_dict, + .flags = MP_TYPE_FLAG_EXTENDED, + MP_TYPE_EXTENDED_FIELDS( + .unary_op = espnow_peers_unary_op, + .subscr = espnow_peers_subscr, + .getiter = espnow_peers_getiter, + ), +}; diff --git a/ports/espressif/bindings/espnow/Peers.h b/ports/espressif/bindings/espnow/Peers.h new file mode 100644 index 0000000000..e871ae86c0 --- /dev/null +++ b/ports/espressif/bindings/espnow/Peers.h @@ -0,0 +1,37 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t list; +} espnow_peers_obj_t; + +extern const mp_obj_type_t espnow_peers_type; +extern espnow_peers_obj_t *espnow_peers_new(void); diff --git a/ports/espressif/bindings/espnow/__init__.c b/ports/espressif/bindings/espnow/__init__.c new file mode 100644 index 0000000000..da15be49ea --- /dev/null +++ b/ports/espressif/bindings/espnow/__init__.c @@ -0,0 +1,95 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#include "bindings/espnow/__init__.h" +#include "bindings/espnow/ESPNow.h" +#include "bindings/espnow/ESPNowPacket.h" +#include "bindings/espnow/Peer.h" +#include "bindings/espnow/Peers.h" + +//| """ESP-NOW Module +//| +//| The `espnow` module provides an interface to the +//| `ESP-NOW `_ +//| protocol provided by Espressif on its SoCs +//| (`API docs `_). +//| +//| **Sender** +//| +//| .. code-block:: python +//| +//| import espnow +//| +//| e = espnow.ESPNow() +//| peer = espnow.Peer(mac=b'\xaa\xaa\xaa\xaa\xaa\xaa') +//| e.peers.append(peer) +//| +//| e.send("Starting...") +//| for i in range(10): +//| e.send(str(i)*20) +//| e.send(b'end') +//| +//| **Receiver** +//| +//| .. code-block:: python +//| +//| import espnow +//| +//| e = espnow.ESPNow() +//| packets = [] +//| +//| while True: +//| if e: +//| packet = e.read() +//| packets.append(packet) +//| if packet.msg == b'end': +//| break +//| +//| print("packets:", f"length={len(packets)}") +//| for packet in packets: +//| print(packet) +//| """ +//| ... +//| + +STATIC const mp_rom_map_elem_t espnow_module_globals_table[] = { + // module name + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espnow) }, + + // module classes + { MP_ROM_QSTR(MP_QSTR_ESPNow), MP_ROM_PTR(&espnow_type) }, + { MP_ROM_QSTR(MP_QSTR_ESPNowPacket),MP_ROM_PTR(&espnow_packet_type_obj) }, + { MP_ROM_QSTR(MP_QSTR_Peer), MP_ROM_PTR(&espnow_peer_type) }, + { MP_ROM_QSTR(MP_QSTR_Peers), MP_ROM_PTR(&espnow_peers_type) }, +}; +STATIC MP_DEFINE_CONST_DICT(espnow_module_globals, espnow_module_globals_table); + +const mp_obj_module_t espnow_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&espnow_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_espnow, espnow_module, CIRCUITPY_ESPNOW); diff --git a/ports/espressif/bindings/espnow/__init__.h b/ports/espressif/bindings/espnow/__init__.h new file mode 100644 index 0000000000..fb814a434f --- /dev/null +++ b/ports/espressif/bindings/espnow/__init__.h @@ -0,0 +1,29 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#pragma once + +void espnow_reset(void); 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 a8d02f082c..6d78999532 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk @@ -9,5 +9,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB -OPTIMIZATION_FLAGS = -Os CIRCUITPY_ESPCAMERA = 0 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 3fdb028f5e..d027443f56 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.mk @@ -9,3 +9,5 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk index 858d0b1859..d801afd493 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk @@ -10,5 +10,4 @@ CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB -OPTIMIZATION_FLAGS = -Os CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk index c314f90246..8fafc18373 100644 --- a/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk @@ -6,4 +6,5 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB + CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/adafruit_huzzah32_breakout/board.c b/ports/espressif/boards/adafruit_huzzah32_breakout/board.c new file mode 100644 index 0000000000..164430c88c --- /dev/null +++ b/ports/espressif/boards/adafruit_huzzah32_breakout/board.c @@ -0,0 +1,29 @@ +/* + * 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" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h b/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h new file mode 100644 index 0000000000..0c6132c7ff --- /dev/null +++ b/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Dan Halbert 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. + */ + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Adafruit HUZZAH32 Breakout" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO13) + +// For entering safe mode, use GPIO0 button +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +// Explanation of how a user got into safe mode +#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the GPIO0 button at start up.") + +// UART pins +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.mk b/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.mk new file mode 100644 index 0000000000..ecf07e8e70 --- /dev/null +++ b/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.mk @@ -0,0 +1,10 @@ +CIRCUITPY_CREATOR_ID = 0x0000239A +CIRCUITPY_CREATION_ID = 0x00320004 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 40m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/adafruit_huzzah32_breakout/pins.c b/ports/espressif/boards/adafruit_huzzah32_breakout/pins.c new file mode 100644 index 0000000000..f0d6f3118a --- /dev/null +++ b/ports/espressif/boards/adafruit_huzzah32_breakout/pins.c @@ -0,0 +1,49 @@ +#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_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_TX), 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_RX), 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_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LED), 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_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_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/adafruit_huzzah32_breakout/sdkconfig b/ports/espressif/boards/adafruit_huzzah32_breakout/sdkconfig new file mode 100644 index 0000000000..6c0168c829 --- /dev/null +++ b/ports/espressif/boards/adafruit_huzzah32_breakout/sdkconfig @@ -0,0 +1,20 @@ +CONFIG_ESP32_ECO3_CACHE_LOCK_FIX=y +CONFIG_ESP32_SPIRAM_SUPPORT=n + +# Uncomment (remove ###) to send ESP_LOG output to TX/RX pins +### # +### # ESP System Settings +### # +### CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y +### # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +### 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_CUSTOM_NUM_1 is not set +### CONFIG_ESP_CONSOLE_UART_NUM=0 +### CONFIG_ESP_CONSOLE_UART_TX_GPIO=17 +### CONFIG_ESP_CONSOLE_UART_RX_GPIO=16 +### CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +### # CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set +### # end of ESP System Settings 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 0c85922524..681efc1cea 100644 --- a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c +++ b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c @@ -109,6 +109,10 @@ const uint8_t display_stop_sequence[] = { 0x02, 0x00 // Power off }; +const uint8_t refresh_sequence[] = { + 0x12, 0x00 +}; + void board_init(void) { // Debug UART #ifdef DEBUG @@ -137,6 +141,7 @@ void board_init(void) { display, bus, display_start_sequence, sizeof(display_start_sequence), + 0, // start up time display_stop_sequence, sizeof(display_stop_sequence), 296, // width 128, // height @@ -154,13 +159,14 @@ void board_init(void) { 0x13, // write_color_ram_command false, // color_bits_inverted 0x000000, // highlight_color - 0x12, // refresh_display_command + 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 } diff --git a/ports/espressif/boards/brainboardz_neuron/mpconfigboard.h b/ports/espressif/boards/brainboardz_neuron/mpconfigboard.h index 9507917ead..72cda83c9b 100755 --- a/ports/espressif/boards/brainboardz_neuron/mpconfigboard.h +++ b/ports/espressif/boards/brainboardz_neuron/mpconfigboard.h @@ -31,3 +31,10 @@ #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_GPIO14) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO15) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO13) diff --git a/ports/espressif/boards/brainboardz_neuron/pins.c b/ports/espressif/boards/brainboardz_neuron/pins.c index b0cbb91563..5c198c20a7 100755 --- a/ports/espressif/boards/brainboardz_neuron/pins.c +++ b/ports/espressif/boards/brainboardz_neuron/pins.c @@ -25,13 +25,13 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { 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_SD_MISO), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO15) }, { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO16) }, @@ -64,5 +64,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { 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_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/espressif_esp32_lyrat/board.c b/ports/espressif/boards/espressif_esp32_lyrat/board.c new file mode 100644 index 0000000000..8c0c8b8b0b --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/board.c @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Radio Sound, Inc. + * + * 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/microcontroller/Pin.h" +#include "components/driver/include/driver/gpio.h" +#include "components/hal/include/hal/gpio_hal.h" +#include "common-hal/microcontroller/Pin.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h new file mode 100644 index 0000000000..7835e93f21 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Radio Sound, Inc. + * + * 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. + */ + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Espressif ESP32-LyraT" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO22) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO23, .sda = &pin_GPIO18}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO14, .mosi = &pin_GPIO13, .miso = &pin_GPIO12}} + +#define CIRCUITPY_BOARD_UART (0) + +// For entering safe mode, use Rec button +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO36) + +// Explanation of how a user got into safe mode +#define BOARD_USER_SAFE_MODE_ACTION translate("You pressed the Rec button 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/espressif_esp32_lyrat/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk new file mode 100644 index 0000000000..e9fcd24e61 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk @@ -0,0 +1,10 @@ +CIRCUITPY_CREATOR_ID = 0x000C303A +CIRCUITPY_CREATION_ID = 0x0032A000 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 40m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32_lyrat/pins.c b/ports/espressif/boards/espressif_esp32_lyrat/pins.c new file mode 100644 index 0000000000..afef90e480 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/pins.c @@ -0,0 +1,56 @@ +#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_CS0), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_REC), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_SW36), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_MODE), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SW39), MP_ROM_PTR(&pin_GPIO39) }, + + { 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/espressif_esp32_lyrat/sdkconfig b/ports/espressif/boards/espressif_esp32_lyrat/sdkconfig new file mode 100644 index 0000000000..4b2981ba62 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_lyrat/sdkconfig @@ -0,0 +1,37 @@ +CONFIG_ESP32_SPIRAM_SUPPORT=y +# SPI RAM config +# +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_SIZE=4194304 +CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +CONFIG_SPIRAM_CACHE_WORKAROUND=y + +# Uncomment (remove ###) to send ESP_LOG output to TX/RX pins +### # +### # ESP System Settings +### # +### CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y +### # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +### 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_CUSTOM_NUM_1 is not set +### CONFIG_ESP_CONSOLE_UART_NUM=0 +### CONFIG_ESP_CONSOLE_UART_TX_GPIO=8 +### CONFIG_ESP_CONSOLE_UART_RX_GPIO=7 +### CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +### # CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set +### # end of ESP System Settings diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/board.c b/ports/espressif/boards/lilygo_tembed_esp32s3/board.c new file mode 100644 index 0000000000..ed49eb504c --- /dev/null +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/board.c @@ -0,0 +1,99 @@ +/* + * 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/microcontroller/Pin.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/displayio/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +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 + 0x13, 0x80, 0x0A, // _NORON and Delay 10ms + 0x36, 0x01, 0xC8, // _MADCTL + 0x29, 0x80, 0xFF, // _DISPON and Delay 500ms +}; + +void board_init(void) { + busio_spi_obj_t *spi = &displays[0].fourwire_bus.inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO12, &pin_GPIO11, NULL, false); + common_hal_busio_spi_never_reset(spi); + + displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; + bus->base.type = &displayio_fourwire_type; + common_hal_displayio_fourwire_construct(bus, + spi, + &pin_GPIO13, // TFT_DC Command or data + &pin_GPIO10, // TFT_CS Chip select + &pin_GPIO9, // TFT_RST Reset + 60000000, // Baudrate + 0, // Polarity + 0); // Phase + + displayio_display_obj_t *display = &displays[0].display; + display->base.type = &displayio_display_type; + common_hal_displayio_display_construct(display, + bus, + 320, // Width + 170, // Height + 35, // column start + 0, // 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_GPIO15, // 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 + + // Debug UART + #ifdef DEBUG + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); + #endif +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.h b/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.h new file mode 100644 index 0000000000..307c103e33 --- /dev/null +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "LILYGO TEMBED ESP32S3" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO48) + +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO11) +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO12) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.mk b/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.mk new file mode 100644 index 0000000000..2b8f67b560 --- /dev/null +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x303A +USB_PID = 0x8151 +USB_PRODUCT = "TEMBED ESP32S3" +USB_MANUFACTURER = "LILYGO" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/pins.c b/ports/espressif/boards/lilygo_tembed_esp32s3/pins.c new file mode 100644 index 0000000000..94c57f162f --- /dev/null +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/pins.c @@ -0,0 +1,86 @@ +#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_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) }, + + // TFT control pins + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_LITE), MP_ROM_PTR(&pin_GPIO15) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + + // SD card control pins + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCLK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO38) }, + + // Microphone control pins + { MP_ROM_QSTR(MP_QSTR_ES_BCLK), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_ES_LRCK), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_ES_DIN), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_ES_MCLK), MP_ROM_PTR(&pin_GPIO48) }, + + // Speaker control pins + { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WCLK), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DOUT), MP_ROM_PTR(&pin_GPIO6) }, + + // Encoder control pins + { MP_ROM_QSTR(MP_QSTR_ENCODER_A), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_ENCODER_B), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_ENCODER_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + + // APA102 control pins (Leds) + { MP_ROM_QSTR(MP_QSTR_APA102_CLK), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_APA102_DI), MP_ROM_PTR(&pin_GPIO42) }, + + { 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_tembed_esp32s3/sdkconfig b/ports/espressif/boards/lilygo_tembed_esp32s3/sdkconfig new file mode 100644 index 0000000000..f508f4a67c --- /dev/null +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/sdkconfig @@ -0,0 +1,34 @@ +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +# +# SPI RAM config +# +# CONFIG_SPIRAM_MODE_QUAD is not set +CONFIG_SPIRAM_MODE_OCT=y +# CONFIG_SPIRAM_TYPE_AUTO is not set +CONFIG_SPIRAM_TYPE_ESPPSRAM64=y +CONFIG_SPIRAM_SIZE=8388608 +# end of SPI RAM config + +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +# +# PSRAM Clock and CS IO for ESP32S3 +# +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# end of PSRAM Clock and CS IO for ESP32S3 + +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" +# end of LWIP diff --git a/ports/espressif/boards/lolin_s3/mpconfigboard.mk b/ports/espressif/boards/lolin_s3/mpconfigboard.mk index c81e3e6fb9..56b42a419c 100644 --- a/ports/espressif/boards/lolin_s3/mpconfigboard.mk +++ b/ports/espressif/boards/lolin_s3/mpconfigboard.mk @@ -9,5 +9,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 16MB -OPTIMIZATION_FLAGS = -Os CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/waveshare_esp32s2_pico/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32s2_pico/mpconfigboard.h index 6a10db6061..bb8b00f327 100644 --- a/ports/espressif/boards/waveshare_esp32s2_pico/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32s2_pico/mpconfigboard.h @@ -30,3 +30,14 @@ #define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_LED_STATUS (&pin_GPIO9) +#define MICROPY_HW_LED_STATUS_INVERTED (1) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO41) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO40) + +#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_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig b/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig index 3a2989a41e..c81fbb4837 100644 --- a/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig @@ -5,8 +5,9 @@ CONFIG_ESP32S2_SPIRAM_SUPPORT=y CONFIG_DEFAULT_PSRAM_CLK_IO=30 CONFIG_DEFAULT_PSRAM_CS_IO=26 CONFIG_SPIRAM_TYPE_ESPPSRAM64=y +CONFIG_SPIRAM_MODE_QUAD=y CONFIG_SPIRAM_SIZE=8388608 -CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_SPEED_120M=y CONFIG_SPIRAM=y CONFIG_SPIRAM_BOOT_INIT=y CONFIG_SPIRAM_USE_MEMMAP=y diff --git a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c index 96de70bf84..cfc6018708 100644 --- a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c @@ -27,17 +27,20 @@ #include #include -#include "shared/runtime/interrupt_char.h" #include "py/ringbuf.h" #include "py/runtime.h" #include "py/stream.h" +#include "shared/runtime/interrupt_char.h" + #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Connection.h" -#include "supervisor/shared/tick.h" -#include "common-hal/_bleio/CharacteristicBuffer.h" #include "shared-bindings/_bleio/CharacteristicBuffer.h" +#include "supervisor/shared/tick.h" + +#include "common-hal/_bleio/ble_events.h" + STATIC int characteristic_buffer_on_ble_evt(struct ble_gap_event *event, void *param) { bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *)param; switch (event->type) { diff --git a/ports/espressif/common-hal/_bleio/Connection.c b/ports/espressif/common-hal/_bleio/Connection.c index 63c85099e6..75def8ad76 100644 --- a/ports/espressif/common-hal/_bleio/Connection.c +++ b/ports/espressif/common-hal/_bleio/Connection.c @@ -30,21 +30,24 @@ #include #include -#include "shared/runtime/interrupt_char.h" #include "py/gc.h" #include "py/objlist.h" #include "py/objstr.h" #include "py/qstr.h" #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/Attribute.h" #include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" + #include "supervisor/shared/tick.h" -// #include "common-hal/_bleio/bonding.h" +#include "common-hal/_bleio/ble_events.h" #include "host/ble_att.h" diff --git a/ports/espressif/common-hal/_bleio/PacketBuffer.c b/ports/espressif/common-hal/_bleio/PacketBuffer.c index 3b3e51df61..d1d8c24123 100644 --- a/ports/espressif/common-hal/_bleio/PacketBuffer.c +++ b/ports/espressif/common-hal/_bleio/PacketBuffer.c @@ -27,17 +27,20 @@ #include #include -#include "shared/runtime/interrupt_char.h" #include "py/runtime.h" #include "py/stream.h" +#include "shared/runtime/interrupt_char.h" + #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Connection.h" #include "shared-bindings/_bleio/PacketBuffer.h" -#include "supervisor/shared/tick.h" +#include "supervisor/shared/tick.h" #include "supervisor/shared/bluetooth/serial.h" +#include "common-hal/_bleio/ble_events.h" + #include "host/ble_att.h" STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, const struct os_mbuf *mbuf) { diff --git a/ports/espressif/common-hal/analogbufio/BufferedIn.c b/ports/espressif/common-hal/analogbufio/BufferedIn.c new file mode 100644 index 0000000000..f2ee8c19af --- /dev/null +++ b/ports/espressif/common-hal/analogbufio/BufferedIn.c @@ -0,0 +1,310 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * SPDX-FileCopyrightText: Copyright (c) 2023 Milind Movasha + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + * 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 "common-hal/analogbufio/BufferedIn.h" +#include "shared-bindings/analogbufio/BufferedIn.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared/runtime/interrupt_char.h" +#include "py/runtime.h" +#include +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "driver/adc.h" + +// #define DEBUG_ANALOGBUFIO + +#define NUM_SAMPLES_PER_INTERRUPT 256 +#define NUM_ADC_CHANNELS 1 +#define DMA_BUFFER_SIZE 1024 +#define ATTENUATION ADC_ATTEN_DB_0 +#define ADC_READ_TIMEOUT_MS 2000 + +#if defined(CONFIG_IDF_TARGET_ESP32) +#define ADC_RESULT_BYTE 2 +#define ADC_CONV_LIMIT_EN 1 // For ESP32, this should always be set to 1 +#elif defined(CONFIG_IDF_TARGET_ESP32S2) +#define ADC_RESULT_BYTE 2 +#define ADC_CONV_LIMIT_EN 0 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32H2) +#define ADC_RESULT_BYTE 4 +#define ADC_CONV_LIMIT_EN 0 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) +#define ADC_RESULT_BYTE 4 +#define ADC_CONV_LIMIT_EN 0 +#endif + +static void start_dma(analogbufio_bufferedin_obj_t *self, adc_digi_convert_mode_t *convert_mode, adc_digi_output_format_t *output_format); +static void stop_dma(analogbufio_bufferedin_obj_t *self); + +void common_hal_analogbufio_bufferedin_construct(analogbufio_bufferedin_obj_t *self, const mcu_pin_obj_t *pin, uint32_t sample_rate) { + self->pin = pin; + self->sample_rate = sample_rate; +} + +static void start_dma(analogbufio_bufferedin_obj_t *self, adc_digi_convert_mode_t *convert_mode, adc_digi_output_format_t *output_format) { + uint16_t adc1_chan_mask = 0; + uint16_t adc2_chan_mask = 0; + + const mcu_pin_obj_t *pin = self->pin; + uint32_t sample_rate = self->sample_rate; + + *output_format = ADC_DIGI_OUTPUT_FORMAT_TYPE1; + if (pin->adc_index == ADC_UNIT_1) { + *convert_mode = ADC_CONV_SINGLE_UNIT_1; + } else { + *convert_mode = ADC_CONV_SINGLE_UNIT_2; + } + + if (pin->adc_index == NO_ADC || pin->adc_channel == NO_ADC_CHANNEL) { + raise_ValueError_invalid_pin(); + } + + /* + * Chip version Conversion Mode Output Format Type + * ESP32 1 TYPE1 + * ESP32S2 1,2,BOTH,ALTER TYPE1, TYPE2 + * ESP32C3 ALTER TYPE2 + * ESP32S3 1,2,BOTH,ALTER TYPE2 + * ESP32H3 1,2,BOTH,ALTER TYPE2 + */ + + #if defined(CONFIG_IDF_TARGET_ESP32) + if (pin->adc_index != ADC_UNIT_1) { + /* + * ESP32 only supports ADC1 unit + * https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf + * Table 29-3 + */ + raise_ValueError_invalid_pin(); + } + #endif + + #if defined(CONFIG_IDF_TARGET_ESP32C3) + /* ESP32C3 only supports alter mode */ + *convert_mode = ADC_CONV_ALTER_UNIT; + #endif + + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32H2) + *output_format = ADC_DIGI_OUTPUT_FORMAT_TYPE2; + #endif + + common_hal_mcu_pin_claim(pin); + + if (pin->adc_index == ADC_UNIT_1) { + adc1_chan_mask = 1 << pin->adc_channel; + } else { + adc2_chan_mask = 1 << pin->adc_channel; + } + + adc_digi_init_config_t adc_dma_config = { + .max_store_buf_size = DMA_BUFFER_SIZE, + .conv_num_each_intr = NUM_SAMPLES_PER_INTERRUPT, + .adc1_chan_mask = adc1_chan_mask, + .adc2_chan_mask = adc2_chan_mask, + }; + + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"pin:%d, ADC channel:%d, ADC index:%d, adc1_chan_mask:0x%x, adc2_chan_mask:0x%x\n",pin->number,pin->adc_channel,pin->adc_index,adc1_chan_mask,adc2_chan_mask); + #endif // DEBUG_ANALOGBUFIO + esp_err_t err = adc_digi_initialize(&adc_dma_config); + if (ESP_OK != err) { + stop_dma(self); + common_hal_analogbufio_bufferedin_deinit(self); + mp_raise_ValueError_varg(translate("Unable to initialize ADC DMA controller, ErrorCode:%d"),err); + } + + adc_digi_configuration_t dig_cfg = { + .conv_limit_en = ADC_CONV_LIMIT_EN, + .conv_limit_num = 250, + .pattern_num = NUM_ADC_CHANNELS, + .sample_freq_hz = sample_rate, + .conv_mode = *convert_mode, + .format = *output_format, + }; + + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"conversion_mode:%d, format:%d, conv_limit_en:%d, sample_rate:%d\n",*convert_mode,*output_format,ADC_CONV_LIMIT_EN,sample_rate); + #endif // DEBUG_ANALOGBUFIO + + adc_digi_pattern_config_t adc_pattern[NUM_ADC_CHANNELS] = {0}; + adc_pattern[0].atten = ATTENUATION; + adc_pattern[0].channel = pin->adc_channel; + if (pin->adc_index == ADC_UNIT_1) { + adc_pattern[0].unit = 0; + } else { + adc_pattern[0].unit = 1; + } + adc_pattern[0].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH; + + dig_cfg.adc_pattern = adc_pattern; + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"adc_pattern[0].channel:%d, adc_pattern[0].unit:%d, adc_pattern[0].atten:%d\n",adc_pattern[0].channel,adc_pattern[0].unit,adc_pattern[0].atten); + #endif // DEBUG_ANALOGBUFIO + + err = adc_digi_controller_configure(&dig_cfg); + if (ESP_OK != err) { + stop_dma(self); + common_hal_analogbufio_bufferedin_deinit(self); + mp_raise_ValueError_varg(translate("Unable to configure ADC DMA controller, ErrorCode:%d"),err); + } + err = adc_digi_start(); + if (ESP_OK != err) { + stop_dma(self); + common_hal_analogbufio_bufferedin_deinit(self); + mp_raise_ValueError_varg(translate("Unable to start ADC DMA controller, ErrorCode:%d"),err); + } +} + +static void stop_dma(analogbufio_bufferedin_obj_t *self) { + adc_digi_stop(); + adc_digi_deinitialize(); + // Release ADC Pin + reset_pin_number(self->pin->number); +} + +bool common_hal_analogbufio_bufferedin_deinited(analogbufio_bufferedin_obj_t *self) { + return self->pin == NULL; +} + +void common_hal_analogbufio_bufferedin_deinit(analogbufio_bufferedin_obj_t *self) { + if (common_hal_analogbufio_bufferedin_deinited(self)) { + return; + } + self->pin = NULL; +} + +static bool check_valid_data(const adc_digi_output_data_t *data, const mcu_pin_obj_t *pin, adc_digi_convert_mode_t convert_mode, adc_digi_output_format_t output_format) { + unsigned int unit = data->type2.unit; + if (output_format == ADC_DIGI_OUTPUT_FORMAT_TYPE2) { + if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) { + return false; + } + if (pin->adc_channel != data->type2.channel) { + return false; + } + } else { + if (convert_mode == ADC_CONV_SINGLE_UNIT_1) { + unit = 0; + } else { + unit = 1; + } + #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) + if (data->type1.channel >= SOC_ADC_CHANNEL_NUM(unit)) { + return false; + } + if (pin->adc_channel != data->type1.channel) { + return false; + } + #endif + } + if (unit > 2) { + return false; + } + return true; +} + +uint32_t common_hal_analogbufio_bufferedin_readinto(analogbufio_bufferedin_obj_t *self, uint8_t *buffer, uint32_t len, uint8_t bytes_per_sample) { + uint8_t result[NUM_SAMPLES_PER_INTERRUPT] __attribute__ ((aligned(4))) = {0}; + uint32_t captured_samples = 0; + uint32_t captured_bytes = 0; + esp_err_t ret; + uint32_t ret_num = 0; + adc_digi_convert_mode_t convert_mode = ADC_CONV_SINGLE_UNIT_2; + adc_digi_output_format_t output_format = ADC_DIGI_OUTPUT_FORMAT_TYPE1; + + if (bytes_per_sample != 2) { + mp_raise_ValueError_varg(translate("%q must be array of type 'H'"), MP_QSTR_buffer); + } + + start_dma(self, &convert_mode, &output_format); + + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"Required bytes: %d\n",len); + #endif // DEBUG_ANALOGBUFIO + + while (captured_bytes < len) { + ret_num = 0; + ret = adc_digi_read_bytes(result, NUM_SAMPLES_PER_INTERRUPT, &ret_num, ADC_READ_TIMEOUT_MS); + + if (ret == ESP_OK) { + for (uint32_t i = 0; i < ret_num; i += ADC_RESULT_BYTE) { + adc_digi_output_data_t *pResult = (adc_digi_output_data_t *)(void *)&result[i]; + if (check_valid_data(pResult, self->pin, convert_mode, output_format)) { + if (captured_bytes < len) { + uint16_t *pBuffer = (uint16_t *)(void *)&buffer[captured_bytes]; + if (output_format == ADC_DIGI_OUTPUT_FORMAT_TYPE1) { + #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) + *pBuffer = pResult->type1.data; + #endif + } else { + *pBuffer = pResult->type2.data; + } + captured_bytes += sizeof(uint16_t); + captured_samples++; + } else { + stop_dma(self); + return captured_samples; + } + } else { + #if !defined(CONFIG_IDF_TARGET_ESP32C3) + // For all chips except for ESP32C3 we would receive samples only from one unit + // For ESP32C3 we may receive sample from alternating units and need to ignore them + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"Invalid sample received: 0x%x\n",pResult->val); + #endif // DEBUG_ANALOGBUFIO + stop_dma(self); + return captured_samples; + #endif + } + } + } else if (ret == ESP_ERR_TIMEOUT) { + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"ADC Timeout\n"); + #endif // DEBUG_ANALOGBUFIO + stop_dma(self); + return captured_samples; + } else { + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"adc_digi_read_bytes failed error code:%d\n",ret); + #endif // DEBUG_ANALOGBUFIO + stop_dma(self); + return captured_samples; + } + } + + stop_dma(self); + #if defined(DEBUG_ANALOGBUFIO) + mp_printf(&mp_plat_print,"Captured bytes: %d\n",captured_bytes); + #endif // DEBUG_ANALOGBUFIO + return captured_samples; +} diff --git a/ports/espressif/common-hal/analogbufio/BufferedIn.h b/ports/espressif/common-hal/analogbufio/BufferedIn.h new file mode 100644 index 0000000000..909455ca06 --- /dev/null +++ b/ports/espressif/common-hal/analogbufio/BufferedIn.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * SPDX-FileCopyrightText: Copyright (c) 2023 Milind Movasha + * + * SPDX-License-Identifier: BSD-3-Clause + * + * 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_ESP32_COMMON_HAL_ANALOGBUFIO_BUFFEREDIN_H +#define MICROPY_INCLUDED_ESP32_COMMON_HAL_ANALOGBUFIO_BUFFEREDIN_H + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +// This is the analogbufio object +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; + uint32_t sample_rate; +} analogbufio_bufferedin_obj_t; + +#endif // MICROPY_INCLUDED_ESP32_COMMON_HAL_ANALOGBUFIO_BUFFEREDIN_H diff --git a/ports/espressif/common-hal/analogbufio/__init__.c b/ports/espressif/common-hal/analogbufio/__init__.c new file mode 100644 index 0000000000..b6c74b985b --- /dev/null +++ b/ports/espressif/common-hal/analogbufio/__init__.c @@ -0,0 +1 @@ +// No analogbufio module functions. diff --git a/ports/espressif/common-hal/busio/SPI.c b/ports/espressif/common-hal/busio/SPI.c index 0b894fa215..da9170a5b0 100644 --- a/ports/espressif/common-hal/busio/SPI.c +++ b/ports/espressif/common-hal/busio/SPI.c @@ -33,6 +33,7 @@ #include "driver/spi_common_internal.h" #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]; @@ -59,7 +60,7 @@ static void set_spi_config(busio_spi_obj_t *self, .clock_speed_hz = baudrate, .mode = phase | (polarity << 1), .spics_io_num = -1, // No CS pin - .queue_size = 1, + .queue_size = MAX_SPI_TRANSACTIONS, .pre_cb = NULL }; esp_err_t result = spi_bus_add_device(self->host_id, &device_config, &spi_handle[self->host_id]); @@ -213,47 +214,61 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, mp_raise_ValueError(translate("No MISO Pin")); } - spi_transaction_t transaction = { 0 }; + spi_transaction_t transactions[MAX_SPI_TRANSACTIONS]; // Round to nearest whole set of bits int bits_to_send = len * 8 / self->bits * self->bits; if (len <= 4) { + memset(&transactions[0], 0, sizeof(spi_transaction_t)); if (data_out != NULL) { - memcpy(&transaction.tx_data, data_out, len); + memcpy(&transactions[0].tx_data, data_out, len); } - transaction.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; - transaction.length = bits_to_send; - spi_device_transmit(spi_handle[self->host_id], &transaction); + transactions[0].flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; + transactions[0].length = bits_to_send; + spi_device_transmit(spi_handle[self->host_id], &transactions[0]); if (data_in != NULL) { - memcpy(data_in, &transaction.rx_data, len); + memcpy(data_in, &transactions[0].rx_data, len); } } else { int offset = 0; int bits_remaining = bits_to_send; + int cur_trans = 0; while (bits_remaining && !mp_hal_is_interrupted()) { - memset(&transaction, 0, sizeof(transaction)); - transaction.length = - bits_remaining > SPI_MAX_DMA_BITS ? SPI_MAX_DMA_BITS : bits_remaining; + cur_trans = 0; + while (bits_remaining && (cur_trans != MAX_SPI_TRANSACTIONS)) { + memset(&transactions[cur_trans], 0, sizeof(spi_transaction_t)); - if (data_out != NULL) { - transaction.tx_buffer = data_out + offset; - } - if (data_in != NULL) { - transaction.rx_buffer = data_in + offset; + transactions[cur_trans].length = + bits_remaining > SPI_MAX_DMA_BITS ? SPI_MAX_DMA_BITS : bits_remaining; + + if (data_out != NULL) { + transactions[cur_trans].tx_buffer = data_out + offset; + } + if (data_in != NULL) { + transactions[cur_trans].rx_buffer = data_in + offset; + } + + bits_remaining -= transactions[cur_trans].length; + + // doesn't need ceil(); loop ends when bits_remaining is 0 + offset += transactions[cur_trans].length / 8; + cur_trans++; } - spi_device_transmit(spi_handle[self->host_id], &transaction); - bits_remaining -= transaction.length; + for (int i = 0; i < cur_trans; i++) { + spi_device_queue_trans(spi_handle[self->host_id], &transactions[i], portMAX_DELAY); + } - // doesn't need ceil(); loop ends when bits_remaining is 0 - offset += transaction.length / 8; - - RUN_BACKGROUND_TASKS; + spi_transaction_t *rtrans; + for (int x = 0; x < cur_trans; x++) { + RUN_BACKGROUND_TASKS; + spi_device_get_trans_result(spi_handle[self->host_id], &rtrans, portMAX_DELAY); + } } } return true; diff --git a/ports/espressif/common-hal/busio/UART.c b/ports/espressif/common-hal/busio/UART.c index f025c15b3e..c13bdedac0 100644 --- a/ports/espressif/common-hal/busio/UART.c +++ b/ports/espressif/common-hal/busio/UART.c @@ -112,9 +112,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, uart_config_t uart_config = {0}; bool have_rs485_dir = rs485_dir != NULL; - if (!have_tx && !have_rx) { - mp_raise_ValueError(translate("tx and rx cannot both be None")); - } + + // shared-bindings checks that TX and RX are not both None, so we don't need to check here. // Filter for sane settings for RS485 if (have_rs485_dir) { diff --git a/ports/espressif/common-hal/espidf/__init__.c b/ports/espressif/common-hal/espidf/__init__.c index 183ebb3817..d2d00ebc56 100644 --- a/ports/espressif/common-hal/espidf/__init__.c +++ b/ports/espressif/common-hal/espidf/__init__.c @@ -29,7 +29,9 @@ #include "supervisor/memory.h" #include "py/runtime.h" +#include "esp_now.h" #include "esp_log.h" + #define TAG "espidf" #ifdef CONFIG_SPIRAM @@ -180,14 +182,19 @@ void raise_esp_error(esp_err_t err) { // tests must be in descending order MP_STATIC_ASSERT(ESP_ERR_FLASH_BASE > ESP_ERR_MESH_BASE); - MP_STATIC_ASSERT(ESP_ERR_MESH_BASE > ESP_ERR_WIFI_BASE); + MP_STATIC_ASSERT(ESP_ERR_MESH_BASE > ESP_ERR_ESPNOW_BASE); + MP_STATIC_ASSERT(ESP_ERR_ESPNOW_BASE > ESP_ERR_WIFI_BASE); + if (err >= ESP_ERR_FLASH_BASE) { group = "Flash"; } else if (err >= ESP_ERR_MESH_BASE) { group = "Mesh"; + } else if (err >= ESP_ERR_ESPNOW_BASE) { + group = "ESP-NOW"; } else if (err >= ESP_ERR_WIFI_BASE) { group = "WiFi"; } + mp_raise_msg_varg(exception_type, translate("%s error 0x%x"), group, err); } diff --git a/ports/espressif/common-hal/espnow/ESPNow.c b/ports/espressif/common-hal/espnow/ESPNow.c new file mode 100644 index 0000000000..a048c7f9f1 --- /dev/null +++ b/ports/espressif/common-hal/espnow/ESPNow.c @@ -0,0 +1,240 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017-2020 Nick Moore + * Copyright (c) 2018 shawwwn + * Copyright (c) 2020-2021 Glenn Moloney @glenn20 + * Copyright (c) 2023 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. + */ + +#include "py/mperrno.h" +#include "py/runtime.h" + +#include "bindings/espidf/__init__.h" +#include "bindings/espnow/ESPNowPacket.h" + +#include "shared-bindings/wifi/__init__.h" + +#include "common-hal/espnow/ESPNow.h" + +#include "mphalport.h" + +#include "esp_now.h" + +#define ESPNOW_MAGIC 0x99 + +// TODO: deinit wifi? + +// The min/max length of an espnow packet (bytes) +#define MIN_PACKET_LEN (sizeof(espnow_packet_t)) +#define MAX_PACKET_LEN (sizeof(espnow_packet_t) + ESP_NOW_MAX_DATA_LEN) + +// Enough for 2 full-size packets: 2 * (6 + 7 + 250) = 526 bytes +// Will allocate an additional 7 bytes for buffer overhead +#define DEFAULT_RECV_BUFFER_SIZE (2 * MAX_PACKET_LEN) + +// Time to wait (millisec) for responses from sent packets: (2 seconds). +#define DEFAULT_SEND_TIMEOUT_MS (2000) + +// ESPNow packet format for the receive buffer. +// Use this for peeking at the header of the next packet in the buffer. +typedef struct { + uint8_t magic; // = ESPNOW_MAGIC + uint8_t msg_len; // Length of the message + uint32_t time_ms; // Timestamp (ms) when packet is received + int8_t rssi; // RSSI value (dBm) (-127 to 0) +} __attribute__((packed)) espnow_header_t; + +typedef struct { + espnow_header_t header; // The header + uint8_t peer[6]; // Peer address + uint8_t msg[0]; // Message is up to 250 bytes +} __attribute__((packed)) espnow_packet_t; + +// --- The ESP-NOW send and recv callback routines --- + +// 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) { + espnow_obj_t *self = MP_STATE_PORT(espnow_singleton); + if (status == ESP_NOW_SEND_SUCCESS) { + self->send_success++; + } else { + self->send_failure++; + } +} + +// Callback triggered when an ESP-NOW packet is received. +// Write the peer MAC address and the message into the recv_buffer as an ESPNow packet. +// If the buffer is full, drop the message and increment the dropped count. +static void recv_cb(const uint8_t *mac, const uint8_t *msg, int msg_len) { + espnow_obj_t *self = MP_STATE_PORT(espnow_singleton); + ringbuf_t *buf = self->recv_buffer; + + if (sizeof(espnow_packet_t) + msg_len > ringbuf_num_empty(buf)) { + self->read_failure++; + return; + } + + // Get the RSSI value from the wifi packet header + // Secret magic to get the rssi from the wifi packet header + // See espnow.c:espnow_recv_cb() at https://github.com/espressif/esp-now/ + // In the wifi packet the msg comes after a wifi_promiscuous_pkt_t + // and a espnow_frame_format_t. + // Backtrack to get a pointer to the wifi_promiscuous_pkt_t. + #define SIZEOF_ESPNOW_FRAME_FORMAT 39 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + wifi_promiscuous_pkt_t *wifi_packet = (wifi_promiscuous_pkt_t *)( + msg - SIZEOF_ESPNOW_FRAME_FORMAT - sizeof(wifi_promiscuous_pkt_t)); + #pragma GCC diagnostic pop + + espnow_header_t header; + header.magic = ESPNOW_MAGIC; + header.msg_len = msg_len; + header.rssi = wifi_packet->rx_ctrl.rssi; + header.time_ms = mp_hal_ticks_ms(); + + ringbuf_put_n(buf, (uint8_t *)&header, sizeof(header)); + ringbuf_put_n(buf, mac, ESP_NOW_ETH_ALEN); + ringbuf_put_n(buf, msg, msg_len); + + self->read_success++; +} + +bool common_hal_espnow_deinited(espnow_obj_t *self) { + return self == NULL || self->recv_buffer == NULL; +} + +// Construct the ESPNow object +void common_hal_espnow_construct(espnow_obj_t *self, mp_int_t buffer_size, mp_int_t phy_rate) { + common_hal_espnow_set_phy_rate(self, phy_rate); + self->recv_buffer_size = mp_arg_validate_int_min(buffer_size, MIN_PACKET_LEN, MP_QSTR_buffer_size); + self->peers = espnow_peers_new(); + common_hal_espnow_init(self); +} + +// Initialize the ESP-NOW software stack, +// register callbacks and allocate the recv data buffers. +void common_hal_espnow_init(espnow_obj_t *self) { + if (!common_hal_espnow_deinited(self)) { + return; + } + + self->recv_buffer = m_new_obj(ringbuf_t); + if (!ringbuf_alloc(self->recv_buffer, self->recv_buffer_size, true)) { + m_malloc_fail(self->recv_buffer_size); + } + + if (!common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) { + common_hal_wifi_init(false); + common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, true); + } + + CHECK_ESP_RESULT(esp_wifi_config_espnow_rate(ESP_IF_WIFI_STA, self->phy_rate)); + CHECK_ESP_RESULT(esp_wifi_config_espnow_rate(ESP_IF_WIFI_AP, self->phy_rate)); + + CHECK_ESP_RESULT(esp_now_init()); + CHECK_ESP_RESULT(esp_now_register_send_cb(send_cb)); + CHECK_ESP_RESULT(esp_now_register_recv_cb(recv_cb)); +} + +// De-initialize the ESP-NOW software stack, +// disable callbacks and deallocate the recv data buffer. +void common_hal_espnow_deinit(espnow_obj_t *self) { + if (common_hal_espnow_deinited(self)) { + return; + } + + CHECK_ESP_RESULT(esp_now_unregister_send_cb()); + CHECK_ESP_RESULT(esp_now_unregister_recv_cb()); + CHECK_ESP_RESULT(esp_now_deinit()); + + self->recv_buffer->buf = NULL; + self->recv_buffer = NULL; +} + +void espnow_reset(void) { + common_hal_espnow_deinit(MP_STATE_PORT(espnow_singleton)); + MP_STATE_PORT(espnow_singleton) = NULL; +} + +void common_hal_espnow_set_phy_rate(espnow_obj_t *self, mp_int_t value) { + self->phy_rate = mp_arg_validate_int_range(value, 0, WIFI_PHY_RATE_MAX - 1, MP_QSTR_phy_rate); +}; + +void common_hal_espnow_set_pmk(espnow_obj_t *self, const uint8_t *key) { + CHECK_ESP_RESULT(esp_now_set_pmk(key)); +} + +// --- Send and Receive ESP-NOW data --- + + +mp_obj_t common_hal_espnow_send(espnow_obj_t *self, const mp_buffer_info_t *message, const uint8_t *mac) { + // Send the packet - keep trying until timeout if the internal esp-now buffers are full. + esp_err_t err; + mp_uint_t start = mp_hal_ticks_ms(); + + while ((ESP_ERR_ESPNOW_NO_MEM == (err = esp_now_send(mac, message->buf, message->len))) && + (mp_hal_ticks_ms() - start) <= DEFAULT_SEND_TIMEOUT_MS) { + RUN_BACKGROUND_TASKS; + } + CHECK_ESP_RESULT(err); + + return mp_const_none; +} + +mp_obj_t common_hal_espnow_read(espnow_obj_t *self) { + if (!ringbuf_num_filled(self->recv_buffer)) { + return mp_const_none; + } + + // Read the packet header from the incoming buffer + espnow_header_t header; + if (ringbuf_get_n(self->recv_buffer, (uint8_t *)&header, sizeof(header)) != sizeof(header)) { + mp_arg_error_invalid(MP_QSTR_buffer); + } + + uint8_t msg_len = header.msg_len; + + uint8_t mac_buf[ESP_NOW_ETH_ALEN]; + uint8_t msg_buf[msg_len]; + + // Check the message packet header format and read the message data + if (header.magic != ESPNOW_MAGIC || + msg_len > ESP_NOW_MAX_DATA_LEN || + ringbuf_get_n(self->recv_buffer, mac_buf, ESP_NOW_ETH_ALEN) != ESP_NOW_ETH_ALEN || + ringbuf_get_n(self->recv_buffer, msg_buf, msg_len) != msg_len) { + mp_arg_error_invalid(MP_QSTR_buffer); + } + + mp_obj_t elems[4] = { + mp_obj_new_bytes(mac_buf, ESP_NOW_ETH_ALEN), + mp_obj_new_bytes(msg_buf, msg_len), + MP_OBJ_NEW_SMALL_INT(header.rssi), + mp_obj_new_int(header.time_ms), + }; + + return namedtuple_make_new((const mp_obj_type_t *)&espnow_packet_type_obj, 4, 0, elems); +} diff --git a/ports/espressif/common-hal/espnow/ESPNow.h b/ports/espressif/common-hal/espnow/ESPNow.h new file mode 100644 index 0000000000..6240788603 --- /dev/null +++ b/ports/espressif/common-hal/espnow/ESPNow.h @@ -0,0 +1,59 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "py/obj.h" +#include "py/ringbuf.h" + +#include "bindings/espnow/Peers.h" + +#include "esp_wifi.h" + +typedef struct _espnow_obj_t { + mp_obj_base_t base; + ringbuf_t *recv_buffer; + size_t recv_buffer_size; + wifi_phy_rate_t phy_rate; + espnow_peers_obj_t *peers; + volatile size_t send_success; + volatile size_t send_failure; + volatile size_t read_success; + volatile size_t read_failure; +} espnow_obj_t; + +extern void espnow_reset(void); + +extern void common_hal_espnow_construct(espnow_obj_t *self, mp_int_t buffer_size, mp_int_t phy_rate); +extern void common_hal_espnow_init(espnow_obj_t *self); +extern void common_hal_espnow_deinit(espnow_obj_t *self); +extern bool common_hal_espnow_deinited(espnow_obj_t *self); + +extern void common_hal_espnow_set_phy_rate(espnow_obj_t *self, mp_int_t value); +extern void common_hal_espnow_set_pmk(espnow_obj_t *self, const uint8_t *key); + +extern mp_obj_t common_hal_espnow_send(espnow_obj_t *self, const mp_buffer_info_t *message, const uint8_t *mac); +extern mp_obj_t common_hal_espnow_read(espnow_obj_t *self); diff --git a/ports/espressif/common-hal/espnow/__init__.c b/ports/espressif/common-hal/espnow/__init__.c new file mode 100644 index 0000000000..effc752f79 --- /dev/null +++ b/ports/espressif/common-hal/espnow/__init__.c @@ -0,0 +1,38 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#include "common-hal/espnow/__init__.h" + +#include "py/runtime.h" + +// Return C pointer to byte memory string/bytes/bytearray in obj. +// Raise ValueError if the length does not match expected len. +const uint8_t *common_hal_espnow_get_bytes_len(mp_obj_t obj, size_t len) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(bufinfo.len, len, MP_QSTR_buffer); + return (uint8_t *)bufinfo.buf; +} diff --git a/ports/espressif/common-hal/espnow/__init__.h b/ports/espressif/common-hal/espnow/__init__.h new file mode 100644 index 0000000000..bb1950d98c --- /dev/null +++ b/ports/espressif/common-hal/espnow/__init__.h @@ -0,0 +1,30 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include "py/obj.h" +extern const uint8_t *common_hal_espnow_get_bytes_len(mp_obj_t obj, size_t len); diff --git a/ports/espressif/common-hal/pwmio/PWMOut.c b/ports/espressif/common-hal/pwmio/PWMOut.c index 68518fbd25..2cb1e6254b 100644 --- a/ports/espressif/common-hal/pwmio/PWMOut.c +++ b/ports/espressif/common-hal/pwmio/PWMOut.c @@ -164,24 +164,6 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { never_reset_pin_number(self->pin->number); } -void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { - never_reset_tim[self->tim_handle.timer_num] = false; - // Search if any other channel is using the timer and is never reset. - // Otherwise, we clear never_reset for the timer as well. - bool other_never_reset = false; - for (size_t i = 0; i < LEDC_CHANNEL_MAX; i++) { - if (i != self->chan_handle.channel && - reserved_channels[i] == self->tim_handle.timer_num && - never_reset_chan[i]) { - other_never_reset = true; - break; - } - } - if (!other_never_reset) { - never_reset_chan[self->chan_handle.channel] = false; - } -} - bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t *self) { return self->deinited == true; } @@ -196,14 +178,21 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { } reserved_channels[self->chan_handle.channel] = INDEX_EMPTY; never_reset_chan[self->chan_handle.channel] = false; + // Search if any other channel is using the timer bool taken = false; + bool other_never_reset = false; for (size_t i = 0; i < LEDC_CHANNEL_MAX; i++) { if (reserved_channels[i] == self->tim_handle.timer_num) { taken = true; + other_never_reset = never_reset_chan[i]; break; } } + // Clear the timer's never reset if the other channel isn't never reset. + if (!other_never_reset) { + never_reset_tim[self->tim_handle.timer_num] = false; + } // Variable frequency means there's only one channel on the timer if (!taken || self->variable_frequency) { ledc_timer_rst(LEDC_LOW_SPEED_MODE, self->tim_handle.timer_num); diff --git a/ports/espressif/esp_error.c b/ports/espressif/esp_error.c deleted file mode 100644 index 4bc44674b7..0000000000 --- a/ports/espressif/esp_error.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Jeff Epler 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 "esp_error.h" -#include "py/runtime.h" - -#include "bindings/espidf/__init__.h" - -void raise_esp_error(esp_err_t err) { - const compressed_string_t *msg = NULL; - const mp_obj_type_t *exception_type = &mp_type_espidf_IDFError; - switch (err) { - case ESP_FAIL: - msg = translate("Generic Failure"); - break; - case ESP_ERR_NO_MEM: - exception_type = &mp_type_espidf_MemoryError; - msg = translate("Out of memory"); - break; - case ESP_ERR_INVALID_ARG: - msg = translate("Invalid argument"); - break; - case ESP_ERR_INVALID_STATE: - msg = translate("Invalid state"); - break; - case ESP_ERR_INVALID_SIZE: - msg = translate("Invalid size"); - break; - case ESP_ERR_NOT_FOUND: - msg = translate("Requested resource not found"); - break; - case ESP_ERR_NOT_SUPPORTED: - msg = translate("Operation or feature not supported"); - break; - case ESP_ERR_TIMEOUT: - msg = translate("Operation timed out"); - break; - case ESP_ERR_INVALID_RESPONSE: - msg = translate("Received response was invalid"); - break; - case ESP_ERR_INVALID_CRC: - msg = translate("CRC or checksum was invalid"); - break; - case ESP_ERR_INVALID_VERSION: - msg = translate("Version was invalid"); - break; - case ESP_ERR_INVALID_MAC: - msg = translate("MAC address was invalid"); - break; - } - if (msg) { - mp_raise_msg(exception_type, msg); - } - - const char *group = "ESP-IDF"; - - // tests must be in descending order - MP_STATIC_ASSERT(ESP_ERR_FLASH_BASE > ESP_ERR_MESH_BASE); - MP_STATIC_ASSERT(ESP_ERR_MESH_BASE > ESP_ERR_WIFI_BASE); - if (err >= ESP_ERR_FLASH_BASE) { - group = "Flash"; - } else if (err >= ESP_ERR_MESH_BASE) { - group = "Mesh"; - } else if (err >= ESP_ERR_WIFI_BASE) { - group = "WiFi"; - } - mp_raise_msg_varg(exception_type, translate("%s error 0x%x"), group, err); -} diff --git a/ports/espressif/mpconfigport.h b/ports/espressif/mpconfigport.h index c296be2024..e4733356bb 100644 --- a/ports/espressif/mpconfigport.h +++ b/ports/espressif/mpconfigport.h @@ -38,18 +38,22 @@ #include "py/circuitpy_mpconfig.h" #if CIRCUITPY_BLEIO -#include "common-hal/_bleio/ble_events.h" +#define BLEIO_ROOT_POINTERS struct ble_event_handler_entry *ble_event_handler_entries; +#else +#define BLEIO_ROOT_POINTERS #endif -#if CIRCUITPY_BLEIO -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS \ - ble_event_handler_entry_t *ble_event_handler_entries; +#if CIRCUITPY_ESPNOW +#define ESPNOW_ROOT_POINTERS struct _espnow_obj_t *espnow_singleton; #else -#define MICROPY_PORT_ROOT_POINTERS \ - CIRCUITPY_COMMON_ROOT_POINTERS +#define ESPNOW_ROOT_POINTERS #endif +#define MICROPY_PORT_ROOT_POINTERS \ + CIRCUITPY_COMMON_ROOT_POINTERS \ + BLEIO_ROOT_POINTERS \ + ESPNOW_ROOT_POINTERS + #define MICROPY_NLR_SETJMP (1) #define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index 460e651705..4637d971a4 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -12,6 +12,7 @@ CIRCUITPY_FULL_BUILD ?= 1 # These modules are implemented in ports//common-hal: CIRCUITPY_ALARM ?= 1 +CIRCUITPY_ANALOGBUFIO ?= 1 CIRCUITPY_AUDIOBUSIO ?= 1 CIRCUITPY_AUDIOBUSIO_I2SOUT ?= 1 CIRCUITPY_AUDIOBUSIO_PDMIN ?= 0 @@ -81,6 +82,7 @@ CIRCUITPY_DUALBANK = 0 endif # Modules dependent on other modules +CIRCUITPY_ESPNOW ?= $(CIRCUITPY_WIFI) CIRCUITPY_GIFIO ?= $(CIRCUITPY_ESPCAMERA) CIRCUITPY_QRIO ?= $(CIRCUITPY_ESPCAMERA) diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index a71825afa5..db4a436b13 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -37,6 +37,7 @@ #include "freertos/task.h" #include "bindings/espidf/__init__.h" +#include "bindings/espnow/__init__.h" #include "bindings/espulp/__init__.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/analogio/AnalogOut.h" @@ -369,6 +370,10 @@ void reset_port(void) { dualbank_reset(); #endif + #if CIRCUITPY_ESPNOW + espnow_reset(); + #endif + #if CIRCUITPY_ESPULP espulp_reset(); #endif diff --git a/ports/espressif/tools/build_memory_info.py b/ports/espressif/tools/build_memory_info.py index df9d6a801e..a11bef82bc 100644 --- a/ports/espressif/tools/build_memory_info.py +++ b/ports/espressif/tools/build_memory_info.py @@ -6,13 +6,12 @@ # SPDX-License-Identifier: MIT import csv +import json import os -import re import sys from elftools.elf.elffile import ELFFile -print() internal_memory = { "esp32": [ @@ -117,8 +116,12 @@ with open(sys.argv[1], "rb") as stream: # This file is the bin used_flash = os.stat(sys.argv[3]).st_size - free_flash = firmware_region - used_flash + +with open(f"{sys.argv[4]}/firmware.size.json", "w") as f: + json.dump({"used_flash": used_flash, "firmware_region": firmware_region}, f) + +print() print( "{:7} bytes used, {:7} bytes free in flash firmware space out of {} bytes ({}kB).".format( used_flash, free_flash, firmware_region, firmware_region / 1024 diff --git a/ports/litex/Makefile b/ports/litex/Makefile index efe99dc5b4..5556dea11d 100644 --- a/ports/litex/Makefile +++ b/ports/litex/Makefile @@ -136,7 +136,7 @@ all: $(BUILD)/firmware.bin $(BUILD)/firmware.dfu $(BUILD)/firmware.elf: $(OBJ) $(STEPECHO) "LINK $@" $(Q)$(CC) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group - $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) + $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) $(BUILD) $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(STEPECHO) "Create $@" diff --git a/ports/litex/background.c b/ports/litex/background.c index d2e94c5b8d..1329d5fd83 100644 --- a/ports/litex/background.c +++ b/ports/litex/background.c @@ -32,6 +32,8 @@ void port_background_task(void) { } +void port_background_tick(void) { +} void port_start_background_task(void) { } void port_finish_background_task(void) { diff --git a/ports/mimxrt10xx/background.c b/ports/mimxrt10xx/background.c index 9e531cea23..5815c222b4 100644 --- a/ports/mimxrt10xx/background.c +++ b/ports/mimxrt10xx/background.c @@ -28,10 +28,14 @@ #include "supervisor/port.h" void port_background_task(void) { +} + +void port_background_tick(void) { #if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO audio_dma_background(); #endif } + void port_start_background_task(void) { } void port_finish_background_task(void) { diff --git a/ports/mimxrt10xx/common-hal/busio/UART.c b/ports/mimxrt10xx/common-hal/busio/UART.c index 871d57648d..086b8dee87 100644 --- a/ports/mimxrt10xx/common-hal/busio/UART.c +++ b/ports/mimxrt10xx/common-hal/busio/UART.c @@ -179,7 +179,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, break; } } else { - mp_raise_ValueError(translate("Supply at least one UART pin")); + // TX and RX are both None. But this is already handled in shared-bindings, so + // we won't get here. } if (rx && !rx_config) { diff --git a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c index ded46b648e..5388f404de 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c +++ b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c @@ -39,8 +39,6 @@ #include "supervisor/shared/safe_mode.h" #include "supervisor/shared/translate/translate.h" -#define DBL_TAP_REG SNVS->LPGPR[3] - void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); } diff --git a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c index 97892b1095..c2afb38664 100644 --- a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c +++ b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.c @@ -38,9 +38,19 @@ #include "supervisor/shared/translate/translate.h" #include "periph.h" -// Debug print support set to zero to enable debug printing -#define ENABLE_DEBUG_PRINTING 0 +static PWM_Type *const _flexpwms[] = PWM_BASE_PTRS; +// 4 bits for each submodule in each FlexPWM. +static uint16_t _pwm_never_reset[MP_ARRAY_SIZE(_flexpwms)]; +// Bitmask of whether state machines are use for variable frequency. +static uint8_t _pwm_variable_frequency[MP_ARRAY_SIZE(_flexpwms)]; +// Configured frequency for each submodule. +static uint32_t _pwm_sm_frequencies[MP_ARRAY_SIZE(_flexpwms)][FSL_FEATURE_PWM_SUBMODULE_COUNT]; +// Channels use is tracked using the OUTEN register. + +// The SDK gives use clocks per submodule but they all share the same value! So, ignore the +// submodule and only turn off the clock when no other submodules are in use. +static const clock_ip_name_t _flexpwm_clocks[][FSL_FEATURE_PWM_SUBMODULE_COUNT] = PWM_CLOCKS; static void config_periph_pin(const mcu_pwm_obj_t *periph) { IOMUXC_SetPinMux( @@ -61,13 +71,59 @@ static void config_periph_pin(const mcu_pwm_obj_t *periph) { | IOMUXC_SW_PAD_CTL_PAD_SRE(0)); } +static uint16_t _outen_mask(pwm_submodule_t submodule, pwm_channels_t channel) { + uint16_t outen_mask = 0; + uint8_t sm_mask = 1 << submodule; + switch (channel) { + case kPWM_PwmX: + outen_mask |= PWM_OUTEN_PWMX_EN(sm_mask); + break; + case kPWM_PwmA: + outen_mask |= PWM_OUTEN_PWMA_EN(sm_mask); + break; + case kPWM_PwmB: + outen_mask |= PWM_OUTEN_PWMB_EN(sm_mask); + break; + } + return outen_mask; +} + void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { + common_hal_never_reset_pin(self->pin); + _pwm_never_reset[self->flexpwm_index] |= (1 << (self->pwm->submodule * 4 + self->pwm->channel)); } -void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { +STATIC void _maybe_disable_clock(uint8_t instance) { + if ((_flexpwms[instance]->MCTRL & PWM_MCTRL_RUN_MASK) == 0) { + CLOCK_DisableClock(_flexpwm_clocks[instance][0]); + } } -void pwmout_reset(void) { +void reset_all_flexpwm(void) { + for (size_t i = 1; i < MP_ARRAY_SIZE(_pwm_never_reset); i++) { + PWM_Type *flexpwm = _flexpwms[i]; + for (size_t submodule = 0; submodule < FSL_FEATURE_PWM_SUBMODULE_COUNT; submodule++) { + uint8_t sm_mask = 1 << submodule; + for (size_t channel = 0; channel < 3; channel++) { + uint16_t channel_mask = 0x1 << (submodule * 4 + channel); + if ((_pwm_never_reset[i] & channel_mask) != 0) { + continue; + } + + // Turn off the channel. + flexpwm->OUTEN &= ~_outen_mask(submodule, channel); + } + uint16_t submodule_mask = 0xf << (submodule * 4); + if ((_pwm_never_reset[i] & submodule_mask) != 0) { + // Leave the submodule on since a channel is marked for never_reset. + continue; + } + flexpwm->MCTRL &= ~(sm_mask << PWM_MCTRL_RUN_SHIFT); + _pwm_variable_frequency[i] &= ~sm_mask; + _pwm_sm_frequencies[i][submodule] = 0; + } + _maybe_disable_clock(i); + } } #define PWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_IpgClk) @@ -87,33 +143,6 @@ static int calculate_pulse_count(uint32_t frequency, uint8_t *prescaler) { return 0; } -// ========================================================== -// Debug code -// ========================================================== -#if ENABLE_DEBUG_PRINTING -#define DBGPrintf mp_printf -extern void debug_print_flexpwm_registers(PWM_Type *base); - -void debug_print_flexpwm_registers(PWM_Type *base) { - mp_printf(&mp_plat_print, - "\t\tPWM OUTEN:%x MASK:%x SWCOUT:%x DTSRCSEL:%x MCTRL:%x MCTRL2:%x FCTRL:%x FSTS:%x FFILT:%x FTST:%x FCTRL2:%x\n", - base->OUTEN, base->MASK, base->SWCOUT, base->DTSRCSEL, base->MCTRL, base->MCTRL2, base->FCTRL, - base->FSTS, base->FFILT, base->FTST, base->FCTRL2); - for (uint8_t i = 0; i < 4; i++) { - mp_printf(&mp_plat_print, - "\t\t(%u) INIT:%x CTRL2:%x CTRL:%x VAL0:%x VAL1:%x VAL2:%x VAL3:%x VAL4:%x VAL5:%x OCTRL:%x DTCNT0:%x DTCNT1:%x DISMAP: %x %x\n", i, - base->SM[i].INIT, base->SM[i].CTRL2, base->SM[i].CTRL, base->SM[i].VAL0, base->SM[i].VAL1, base->SM[i].VAL2, - base->SM[i].VAL3, base->SM[i].VAL4, base->SM[i].VAL5, base->SM[i].OCTRL, base->SM[i].DTCNT0, base->SM[i].DTCNT1, - base->SM[i].DISMAP[0], base->SM[i].DISMAP[1]); - } - -} -#else -#define DBGPrintf(p,...) -inline void debug_print_flexpwm_registers(PWM_Type *base) { -} -#endif - pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, const mcu_pin_obj_t *pin, uint16_t duty, @@ -122,12 +151,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, self->pin = pin; self->variable_frequency = variable_frequency; - const uint32_t pwm_count = sizeof(mcu_pwm_list) / sizeof(mcu_pwm_obj_t); - - DBGPrintf(&mp_plat_print, ">>> common_hal_pwmio_pwmout_construct called: pin: %p %u freq:%u duty:%u var:%u\n", - self->pin->gpio, self->pin->number, frequency, duty, variable_frequency); - - for (uint32_t i = 0; i < pwm_count; ++i) { + for (uint32_t i = 0; i < MP_ARRAY_SIZE(mcu_pwm_list); ++i) { if (mcu_pwm_list[i].pin != pin) { continue; } @@ -141,30 +165,20 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, return PWMOUT_INVALID_PIN; } - DBGPrintf(&mp_plat_print, "\tFound in PWM List\n"); + PWM_Type *flexpwm = self->pwm->pwm; + pwm_submodule_t submodule = self->pwm->submodule; + uint16_t sm_mask = 1 << submodule; + pwm_channels_t channel = self->pwm->channel; - config_periph_pin(self->pwm); + uint8_t flexpwm_index = 1; + for (; flexpwm_index < MP_ARRAY_SIZE(_flexpwms); flexpwm_index++) { + if (_flexpwms[flexpwm_index] == flexpwm) { + break; + } + } + self->flexpwm_index = flexpwm_index; - pwm_config_t pwmConfig; - - /* - * pwmConfig.enableDebugMode = false; - * pwmConfig.enableWait = false; - * pwmConfig.reloadSelect = kPWM_LocalReload; - * pwmConfig.faultFilterCount = 0; - * pwmConfig.faultFilterPeriod = 0; - * pwmConfig.clockSource = kPWM_BusClock; - * pwmConfig.prescale = kPWM_Prescale_Divide_1; - * pwmConfig.initializationControl = kPWM_Initialize_LocalSync; - * pwmConfig.forceTrigger = kPWM_Force_Local; - * pwmConfig.reloadFrequency = kPWM_LoadEveryOportunity; - * pwmConfig.reloadLogic = kPWM_ReloadImmediate; - * pwmConfig.pairOperation = kPWM_Independent; - */ - PWM_GetDefaultConfig(&pwmConfig); - - // pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; - pwmConfig.enableDebugMode = true; + uint16_t outen_mask = _outen_mask(submodule, channel); self->pulse_count = calculate_pulse_count(frequency, &self->prescaler); @@ -172,69 +186,92 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, return PWMOUT_INVALID_FREQUENCY; } - pwmConfig.prescale = self->prescaler; - - DBGPrintf(&mp_plat_print, "\tCall PWM_Init\n"); - if (PWM_Init(self->pwm->pwm, self->pwm->submodule, &pwmConfig) == kStatus_Fail) { - return PWMOUT_INVALID_PIN; - } - - // Disable all fault inputs - self->pwm->pwm->SM[self->pwm->submodule].DISMAP[0] = 0; - self->pwm->pwm->SM[self->pwm->submodule].DISMAP[1] = 0; - - DBGPrintf(&mp_plat_print, "\tCall PWM_SetupPwm %p %x %u\n", self->pwm->pwm, self->pwm->submodule); - // ======================================================================================================== - // Not calling the PWM_SetupPwm as it was setup to only work for PWM output on chan A and B but not X - // I have done some experimenting, probably could try others, but again they do not work with X. - // Most of the code checks to see if A if not, then it assume B. - // - // Instead I set it up to work similar to what the Teensy 4.x code does. - // - // That is we set the PWM_CTRL_FULL_MASK, which then uses base->SM[submodule].VAL1 to control - // when the timer is reset, so it sets up your cycle/frequency. But then this implies that X channel - // which uses 0, 1 has to be handled specially. So for the different channels: - // A - Uses VAL2 to turn on (0) and VAL3=duty to turn off - // B - Uses VAL4 to turn on (0) and VAL5 to turn off - // X - As mentioned above VAL1 turns off, but it's set to the timing for frequency. so - // VAL0 turns on, so we set it to VAL1 - duty - // - PWM_Type *base = self->pwm->pwm; - uint8_t submodule = self->pwm->submodule; - - uint32_t mask = 1 << submodule; - uint32_t olddiv = base->SM[submodule].VAL1 + 1; - if (self->pulse_count != olddiv) { - base->MCTRL |= PWM_MCTRL_CLDOK(mask); - base->SM[submodule].CTRL = PWM_CTRL_PRSC_MASK | PWM_CTRL_PRSC(self->prescaler); - base->SM[submodule].VAL1 = self->pulse_count - 1; - base->SM[submodule].CTRL2 = PWM_CTRL2_INDEP_MASK | PWM_CTRL2_WAITEN_MASK | PWM_CTRL2_DBGEN_MASK; - - if (olddiv == 1) { - base->SM[submodule].CTRL = PWM_CTRL_FULL_MASK; - base->SM[submodule].VAL0 = 0; - base->SM[submodule].VAL2 = 0; - base->SM[submodule].VAL3 = 0; - base->SM[submodule].VAL4 = 0; - base->SM[submodule].VAL5 = 0; - } else { - base->SM[submodule].VAL0 = (base->SM[submodule].VAL0 * self->pulse_count) / olddiv; - base->SM[submodule].VAL3 = (base->SM[submodule].VAL3 * self->pulse_count) / olddiv; - base->SM[submodule].VAL5 = (base->SM[submodule].VAL5 * self->pulse_count) / olddiv; + // The submodule is already running + if (((flexpwm->MCTRL >> PWM_MCTRL_RUN_SHIFT) & sm_mask) != 0) { + // Another output has claimed this submodule for variable frequency already. + if ((_pwm_variable_frequency[flexpwm_index] & sm_mask) != 0) { + return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; + } + + // We want variable frequency but another class has already claim a fixed frequency. + if (variable_frequency) { + return PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE; + } + + // Another pin is already using this output. + if ((flexpwm->OUTEN & outen_mask) != 0) { + return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; + } + + if (frequency != _pwm_sm_frequencies[flexpwm_index][submodule]) { + return PWMOUT_INVALID_FREQUENCY_ON_PIN; + } + + // Submodule is already running at our target frequency and the output + // is free. + } else { + pwm_config_t pwmConfig; + + /* + * pwmConfig.enableDebugMode = false; + * pwmConfig.enableWait = false; + * pwmConfig.reloadSelect = kPWM_LocalReload; + * pwmConfig.faultFilterCount = 0; + * pwmConfig.faultFilterPeriod = 0; + * pwmConfig.clockSource = kPWM_BusClock; + * pwmConfig.prescale = kPWM_Prescale_Divide_1; + * pwmConfig.initializationControl = kPWM_Initialize_LocalSync; + * pwmConfig.forceTrigger = kPWM_Force_Local; + * pwmConfig.reloadFrequency = kPWM_LoadEveryOportunity; + * pwmConfig.reloadLogic = kPWM_ReloadImmediate; + * pwmConfig.pairOperation = kPWM_Independent; + */ + PWM_GetDefaultConfig(&pwmConfig); + + pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; + pwmConfig.enableWait = true; + pwmConfig.enableDebugMode = true; + + pwmConfig.prescale = self->prescaler; + + if (PWM_Init(flexpwm, submodule, &pwmConfig) != kStatus_Success) { + return PWMOUT_INITIALIZATION_ERROR; + } + + // Disable all fault inputs + flexpwm->SM[submodule].DISMAP[0] = 0; + flexpwm->SM[submodule].DISMAP[1] = 0; + + PWM_SetPwmLdok(flexpwm, sm_mask, false); + flexpwm->SM[submodule].CTRL = PWM_CTRL_FULL_MASK | PWM_CTRL_PRSC(self->prescaler); + flexpwm->SM[submodule].CTRL2 = PWM_CTRL2_INDEP_MASK | PWM_CTRL2_WAITEN_MASK | PWM_CTRL2_DBGEN_MASK; + // Set the reload value to zero so we're in unsigned mode. + flexpwm->SM[submodule].INIT = 0; + // Set the top/reload value. + flexpwm->SM[submodule].VAL1 = self->pulse_count; + // Clear the other channels. + flexpwm->SM[submodule].VAL0 = 0; + flexpwm->SM[submodule].VAL2 = 0; + flexpwm->SM[submodule].VAL3 = 0; + flexpwm->SM[submodule].VAL4 = 0; + flexpwm->SM[submodule].VAL5 = 0; + PWM_SetPwmLdok(flexpwm, sm_mask, true); + + PWM_StartTimer(flexpwm, sm_mask); + _pwm_sm_frequencies[flexpwm_index][submodule] = frequency; + + if (variable_frequency) { + _pwm_variable_frequency[flexpwm_index] = sm_mask; } - base->MCTRL |= PWM_MCTRL_LDOK(mask); } - debug_print_flexpwm_registers(self->pwm->pwm); - PWM_SetPwmLdok(self->pwm->pwm, 1 << self->pwm->submodule, true); - - PWM_StartTimer(self->pwm->pwm, 1 << self->pwm->submodule); - - - DBGPrintf(&mp_plat_print, "\tCall common_hal_pwmio_pwmout_set_duty_cycle\n"); common_hal_pwmio_pwmout_set_duty_cycle(self, duty); - DBGPrintf(&mp_plat_print, "\tReturn OK\n"); + flexpwm->OUTEN |= outen_mask; + + // Configure the IOMUX once we know everything else is working. + config_periph_pin(self->pwm); + return PWMOUT_OK; } @@ -247,8 +284,29 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { return; } + _pwm_never_reset[self->flexpwm_index] &= ~(1 << (self->pwm->submodule * 4 + self->pwm->channel)); + + PWM_Type *flexpwm = self->pwm->pwm; + pwm_submodule_t submodule = self->pwm->submodule; + uint16_t sm_mask = 1 << submodule; + + // Reset the pin before we turn it off. common_hal_reset_pin(self->pin); self->pin = NULL; + + // Always disable the output. + flexpwm->OUTEN &= ~_outen_mask(submodule, self->pwm->channel); + + uint16_t all_sm_channels = _outen_mask(submodule, kPWM_PwmX) | _outen_mask(submodule, kPWM_PwmA) | _outen_mask(submodule, kPWM_PwmB); + + // Turn off the submodule if it doesn't have any outputs active. + if ((flexpwm->OUTEN & all_sm_channels) == 0) { + // Deinit ourselves because the SDK turns off the clock to the whole FlexPWM on deinit. + flexpwm->MCTRL &= ~(sm_mask << PWM_MCTRL_RUN_SHIFT); + _pwm_variable_frequency[self->flexpwm_index] &= ~sm_mask; + _pwm_sm_frequencies[self->flexpwm_index][submodule] = 0; + } + _maybe_disable_clock(self->flexpwm_index); } void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uint16_t duty) { @@ -261,39 +319,40 @@ void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uint16_t d // X - As mentioned above VAL1 turns off, but it's set to the timing for frequency. so // VAL0 turns on, so we set it to VAL1 - duty - DBGPrintf(&mp_plat_print, "common_hal_pwmio_pwmout_set_duty_cycle %u\n", duty); self->duty_cycle = duty; PWM_Type *base = self->pwm->pwm; - uint8_t mask = 1 << self->pwm->submodule; + uint8_t sm_mask = 1 << self->pwm->submodule; + uint16_t duty_scaled; if (duty == 65535) { - self->duty_scaled = self->pulse_count + 1; + // X channels can't do a full 100% duty cycle. + if (self->pwm->channel == kPWM_PwmX) { + mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_duty_cycle); + } + duty_scaled = self->pulse_count + 1; } else { - self->duty_scaled = ((uint32_t)duty * self->pulse_count + self->pulse_count / 2) / 65535; + duty_scaled = ((uint32_t)duty * self->pulse_count) / 65535; } + PWM_SetPwmLdok(self->pwm->pwm, sm_mask, false); switch (self->pwm->channel) { case kPWM_PwmX: - base->SM[self->pwm->submodule].VAL0 = self->pulse_count - self->duty_scaled; - base->OUTEN |= PWM_OUTEN_PWMX_EN(mask); + // PWM X Signals always having a falling edge at the reload value. (Otherwise we'd + // change the PWM frequency.) So, we adjust the rising edge to get the correct duty + // cycle. + base->SM[self->pwm->submodule].VAL0 = self->pulse_count - duty_scaled; break; case kPWM_PwmA: - base->SM[self->pwm->submodule].VAL3 = self->duty_scaled; - base->OUTEN |= PWM_OUTEN_PWMA_EN(mask); + // The other two channels always have their rising edge at 0 and vary their falling + // edge. + base->SM[self->pwm->submodule].VAL3 = duty_scaled; break; case kPWM_PwmB: - base->SM[self->pwm->submodule].VAL5 = self->duty_scaled; - base->OUTEN |= PWM_OUTEN_PWMB_EN(mask); + base->SM[self->pwm->submodule].VAL5 = duty_scaled; } - PWM_SetPwmLdok(self->pwm->pwm, 1 << self->pwm->submodule, true); - - debug_print_flexpwm_registers(self->pwm->pwm); - + PWM_SetPwmLdok(self->pwm->pwm, sm_mask, true); } uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t *self) { - if (self->duty_cycle == 65535) { - return 65535; - } - return ((uint32_t)self->duty_scaled * 65535 + 65535 / 2) / self->pulse_count; + return self->duty_cycle; } void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t *self, @@ -309,6 +368,8 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t *self, // a small glitch can occur when adjusting the prescaler, from the setting // of CTRL just below to the setting of the Ldok register in // set_duty_cycle. + // Clear LDOK so that we can update the values. + PWM_SetPwmLdok(self->pwm->pwm, 1 << self->pwm->submodule, false); uint32_t reg = self->pwm->pwm->SM[self->pwm->submodule].CTRL; reg &= ~(PWM_CTRL_PRSC_MASK); reg |= PWM_CTRL_PRSC(self->prescaler); diff --git a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.h b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.h index fa4ce46780..6542d67e1f 100644 --- a/ports/mimxrt10xx/common-hal/pwmio/PWMOut.h +++ b/ports/mimxrt10xx/common-hal/pwmio/PWMOut.h @@ -37,10 +37,12 @@ typedef struct { const mcu_pin_obj_t *pin; const mcu_pwm_obj_t *pwm; bool variable_frequency; + uint8_t flexpwm_index; uint8_t prescaler; - uint16_t duty_cycle, duty_scaled, pulse_count; + uint16_t duty_cycle; + uint16_t pulse_count; } pwmio_pwmout_obj_t; -void pwmout_reset(void); +void reset_all_flexpwm(void); #endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_PWMIO_PWMOUT_H diff --git a/ports/mimxrt10xx/reset.h b/ports/mimxrt10xx/reset.h index ea56df02a1..0d458a907d 100644 --- a/ports/mimxrt10xx/reset.h +++ b/ports/mimxrt10xx/reset.h @@ -33,6 +33,7 @@ #include "py/mpconfig.h" // Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21 +#define DBL_TAP_REG SNVS->LPGPR[3] #define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set #define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef diff --git a/ports/mimxrt10xx/supervisor/port.c b/ports/mimxrt10xx/supervisor/port.c index 2ac7995943..6997b4bae5 100644 --- a/ports/mimxrt10xx/supervisor/port.c +++ b/ports/mimxrt10xx/supervisor/port.c @@ -284,7 +284,7 @@ void reset_port(void) { // eic_reset(); #if CIRCUITPY_PWMIO - pwmout_reset(); + reset_all_flexpwm(); #endif #if CIRCUITPY_RTC @@ -301,7 +301,7 @@ void reset_port(void) { } void reset_to_bootloader(void) { - SNVS->LPGPR[0] = DBL_TAP_MAGIC; + DBL_TAP_REG = DBL_TAP_MAGIC; reset(); } diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index d1b71799bf..2267a582a4 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -212,7 +212,7 @@ $(BUILD)/firmware.elf: $(OBJ) $(GENERATED_LD_FILE) $(STEPECHO) "LINK $@" $(Q)echo $(OBJ) > $(BUILD)/firmware.objs $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group - $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) + $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(GENERATED_LD_FILE) $(BUILD) $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(STEPECHO) "Create $@" @@ -275,7 +275,8 @@ endif ##################### .phony: dfu-gen dfu-flash -NRFUTIL = adafruit-nrfutil +NRFUTIL = nrfutil +ADAFRUIT_NRFUTIL = adafruit-nrfutil ifeq ($(MCU_SUB_VARIANT),nrf52840) DFU_TOUCH = --touch 1200 @@ -293,14 +294,19 @@ __check_defined = \ ## Flash with DFU serial dfu-flash: $(BUILD)/dfu-package.zip @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyUSB0) - $(NRFUTIL) --verbose dfu serial --package $^ -p $(SERIAL) -b 115200 --singlebank $(DFU_TOUCH) + $(ADAFRUIT_NRFUTIL) --verbose dfu serial --package $^ -p $(SERIAL) -b 115200 --singlebank $(DFU_TOUCH) ## Create DFU package file dfu-gen: $(BUILD)/dfu-package.zip $(BUILD)/dfu-package.zip: $(BUILD)/firmware.hex - $(NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $^ $(BUILD)/dfu-package.zip + $(ADAFRUIT_NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $^ $(BUILD)/dfu-package.zip +# Espruino DFU +$(BUILD)/firmware.espruino.zip: $(BUILD)/firmware.hex + $(Q)$(NRFUTIL) pkg generate $(BUILD)/firmware.espruino.zip --application $^ --application-version 0xff --hw-version 52 --sd-req 0xa9,0xae,0xb6 --key-file espruino_dfu_private_key.pem + +espruino-dfu-gen: $(BUILD)/firmware.espruino.zip include $(TOP)/py/mkrules.mk diff --git a/ports/nrf/background.c b/ports/nrf/background.c index f0822de521..b8d4df6324 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -24,6 +24,8 @@ * THE SOFTWARE. */ +#include "background.h" + #include "py/runtime.h" #include "supervisor/filesystem.h" #include "supervisor/port.h" @@ -44,10 +46,11 @@ void port_start_background_task(void) { } + void port_finish_background_task(void) { } -void port_background_task(void) { +void port_background_tick(void) { #if CIRCUITPY_AUDIOPWMIO audiopwmout_background(); #endif @@ -55,3 +58,11 @@ void port_background_task(void) { i2s_background(); #endif } + +// Allow boards to override this. +MP_WEAK void board_background_task(void) { +} + +void port_background_task(void) { + board_background_task(); +} diff --git a/ports/nrf/background.h b/ports/nrf/background.h index 64a768cf9b..4fba46d031 100644 --- a/ports/nrf/background.h +++ b/ports/nrf/background.h @@ -27,4 +27,6 @@ #ifndef MICROPY_INCLUDED_NRF_BACKGROUND_H #define MICROPY_INCLUDED_NRF_BACKGROUND_H +void board_background_task(void); + #endif // MICROPY_INCLUDED_NRF_BACKGROUND_H diff --git a/ports/nrf/boards/espruino_banglejs2/board.c b/ports/nrf/boards/espruino_banglejs2/board.c new file mode 100644 index 0000000000..49a37b7db5 --- /dev/null +++ b/ports/nrf/boards/espruino_banglejs2/board.c @@ -0,0 +1,97 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 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 "background.h" +#include "mpconfigboard.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/displayio/FourWire.h" +#include "shared-bindings/framebufferio/FramebufferDisplay.h" +#include "shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h" +#include "shared-module/displayio/__init__.h" + +digitalio_digitalinout_obj_t extcomin; +digitalio_digitalinout_obj_t display_on; + +uint32_t last_down_ticks_ms; + +void board_init(void) { + common_hal_digitalio_digitalinout_construct(&extcomin, &pin_P0_06); + common_hal_digitalio_digitalinout_switch_to_output(&extcomin, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_never_reset(&extcomin); + + common_hal_digitalio_digitalinout_construct(&display_on, &pin_P0_07); + common_hal_digitalio_digitalinout_switch_to_output(&display_on, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_never_reset(&display_on); + + sharpdisplay_framebuffer_obj_t *fb = &allocate_display_bus()->sharpdisplay; + fb->base.type = &sharpdisplay_framebuffer_type; + + busio_spi_obj_t *spi = &fb->inline_bus; + common_hal_busio_spi_construct(spi, &pin_P0_26, &pin_P0_27, NULL, false); + common_hal_busio_spi_never_reset(spi); + + common_hal_sharpdisplay_framebuffer_construct(fb, spi, &pin_P0_05, 500000, 176, 176, true); + + primary_display_t *display = allocate_display(); + framebufferio_framebufferdisplay_obj_t *self = &display->framebuffer_display; + self->base.type = &framebufferio_framebufferdisplay_type; + common_hal_framebufferio_framebufferdisplay_construct(self, fb, 0, true); +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + nrf_gpio_cfg_input(17, NRF_GPIO_PIN_PULLUP); +} + +void board_deinit(void) { + // common_hal_displayio_release_displays(); +} + +void board_background_task(void) { + if (!nrf_gpio_pin_read(17)) { + if (last_down_ticks_ms == 0) { + last_down_ticks_ms = supervisor_ticks_ms32(); + } + } else { + last_down_ticks_ms = 0; + } + // If the button isn't pressed, then feed the watchdog. + if (last_down_ticks_ms == 0) { + NRF_WDT->RR[0] = 0x6E524635; + return; + } + // if the button has been pressed less than 5 seconds, then feed the watchdog. + uint32_t now = supervisor_ticks_ms32(); + if (now - last_down_ticks_ms < 5000) { + NRF_WDT->RR[0] = 0x6E524635; + } + // Don't feed the watchdog so that it'll expire and kick us to the bootloader. +} diff --git a/ports/nrf/boards/espruino_banglejs2/mpconfigboard.h b/ports/nrf/boards/espruino_banglejs2/mpconfigboard.h new file mode 100644 index 0000000000..6057cd56e7 --- /dev/null +++ b/ports/nrf/boards/espruino_banglejs2/mpconfigboard.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Dan Halbert 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 "nrfx/hal/nrf_gpio.h" + +#define MICROPY_HW_BOARD_NAME "Espruino Bangle.js 2" +#define MICROPY_HW_MCU_NAME "nRF52840" + +#define MICROPY_HW_LED_STATUS (&pin_P0_19) + +#if SPI_FLASH_FILESYSTEM +#define SPI_FLASH_MOSI_PIN &pin_P0_15 +#define SPI_FLASH_MISO_PIN &pin_P0_13 +#define SPI_FLASH_SCK_PIN &pin_P0_16 +#define SPI_FLASH_CS_PIN &pin_P0_14 +#endif + +#define CIRCUITPY_BOOT_BUTTON (&pin_P0_17) + +#define BOARD_HAS_32KHZ_XTAL (1) diff --git a/ports/nrf/boards/espruino_banglejs2/mpconfigboard.mk b/ports/nrf/boards/espruino_banglejs2/mpconfigboard.mk new file mode 100644 index 0000000000..106b85cd75 --- /dev/null +++ b/ports/nrf/boards/espruino_banglejs2/mpconfigboard.mk @@ -0,0 +1,25 @@ +CIRCUITPY_CREATOR_ID = 0xBA000000 +CIRCUITPY_CREATION_ID = 0x0BA20001 +MCU_CHIP = nrf52840 + +SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICES = "XT25F64B,GD25Q64C" + +CIRCUITPY_FULL_BUILD = 1 + +# Modules that aren't useful on the board. +CIRCUITPY_AESIO = 0 +CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOCORE = 0 +CIRCUITPY_AUDIOMIXER = 0 +CIRCUITPY_AUDIOPWMIO = 0 +CIRCUITPY_COUNTIO = 0 +CIRCUITPY_NEOPIXEL_WRITE = 0 +CIRCUITPY_ONEWIREIO = 0 +CIRCUITPY_RAINBOWIO = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_ROTARYIO = 0 +CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_USB = 0 + +CIRCUITPY_BUILD_EXTENSIONS = espruino.zip diff --git a/ports/nrf/boards/espruino_banglejs2/pins.c b/ports/nrf/boards/espruino_banglejs2/pins.c new file mode 100644 index 0000000000..b114c2f130 --- /dev/null +++ b/ports/nrf/boards/espruino_banglejs2/pins.c @@ -0,0 +1,41 @@ +#include "shared-bindings/board/__init__.h" + +#include "supervisor/board.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_PRESSURE_SCL), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_P0_03) }, + { MP_ROM_QSTR(MP_QSTR_MEMLCD_CS), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_MEMLCD_EXTCOMIN), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_MEMLCD_DISP), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_BACKLIGHT), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_P0_17) }, + { MP_ROM_QSTR(MP_QSTR_VIBRATE), MP_ROM_PTR(&pin_P0_19) }, + { MP_ROM_QSTR(MP_QSTR_HRM_POWER), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_HRM_INT), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_CHARGE_PORT), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_HRM_SDA), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_CHARGE_COMPLETE), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_MEMLCD_SCK), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_MEMLCD_MOSI), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_GPS_POWER), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_GPS_TX), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_GPS_RX), MP_ROM_PTR(&pin_P0_31) }, + { MP_ROM_QSTR(MP_QSTR_HRM_SCL), MP_ROM_PTR(&pin_P1_00) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_SDA), MP_ROM_PTR(&pin_P1_01) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_SCL), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_INT), MP_ROM_PTR(&pin_P1_03) }, + { MP_ROM_QSTR(MP_QSTR_ACCEL_SDA), MP_ROM_PTR(&pin_P1_04) }, + { MP_ROM_QSTR(MP_QSTR_ACCEL_SCL), MP_ROM_PTR(&pin_P1_05) }, + { MP_ROM_QSTR(MP_QSTR_COMPASS_SDA), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_COMPASS_SCL), MP_ROM_PTR(&pin_P1_11) }, + { MP_ROM_QSTR(MP_QSTR_PRESSURE_SDA), MP_ROM_PTR(&pin_P1_13) }, + + + { 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/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index df4a485999..10a34e09df 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -183,9 +183,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, mp_raise_ValueError(translate("All UART peripherals are in use")); } - if ((tx == NULL) && (rx == NULL)) { - mp_raise_ValueError(translate("tx and rx cannot both be None")); - } + // shared-bindings checks that TX and RX are not both None, so we don't need to check here. mp_arg_validate_int_min(receiver_buffer_size, 1, MP_QSTR_receiver_buffer_size); diff --git a/ports/nrf/common-hal/pwmio/PWMOut.c b/ports/nrf/common-hal/pwmio/PWMOut.c index 1bd38e7a6e..f73e3d3952 100644 --- a/ports/nrf/common-hal/pwmio/PWMOut.c +++ b/ports/nrf/common-hal/pwmio/PWMOut.c @@ -67,25 +67,11 @@ STATIC int pwm_idx(NRF_PWM_Type *pwm) { } void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { - for (size_t i = 0; i < MP_ARRAY_SIZE(pwms); i++) { - NRF_PWM_Type *pwm = pwms[i]; - if (pwm == self->pwm) { - never_reset_pwm[i] += 1; - } - } + never_reset_pwm[pwm_idx(self->pwm)] |= 1 << self->channel; common_hal_never_reset_pin(self->pin); } -void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { - for (size_t i = 0; i < MP_ARRAY_SIZE(pwms); i++) { - NRF_PWM_Type *pwm = pwms[i]; - if (pwm == self->pwm) { - never_reset_pwm[i] -= 1; - } - } -} - STATIC void reset_single_pwmout(uint8_t i) { NRF_PWM_Type *pwm = pwms[i]; @@ -114,7 +100,13 @@ STATIC void reset_single_pwmout(uint8_t i) { void pwmout_reset(void) { for (size_t i = 0; i < MP_ARRAY_SIZE(pwms); i++) { - if (never_reset_pwm[i] > 0) { + for (size_t c = 0; c < CHANNELS_PER_PWM; c++) { + if ((never_reset_pwm[i] & (1 << c)) != 0) { + continue; + } + pwms[i]->PSEL.OUT[c] = 0xFFFFFFFF; + } + if (never_reset_pwm[i] != 0) { continue; } reset_single_pwmout(i); @@ -270,6 +262,8 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { nrf_gpio_cfg_default(self->pin->number); + never_reset_pwm[pwm_idx(self->pwm)] &= ~(1 << self->channel); + NRF_PWM_Type *pwm = self->pwm; self->pwm = NULL; diff --git a/ports/nrf/espruino_dfu_private_key.pem b/ports/nrf/espruino_dfu_private_key.pem new file mode 100644 index 0000000000..79c70f76ee --- /dev/null +++ b/ports/nrf/espruino_dfu_private_key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIK5uG3MovsdlHdw0xKzHsiv7hCRlFFQbwF30wW2KT4YJoAoGCCqGSM49 +AwEHoUQDQgAElQMkm+myar6SNwygD8seLeccsydVakcn3kHvxVK5AUnTCcYEFKPY +B9RfTIE/mwpHoaXs8e4swKX9nPBeC2mTZQ== +-----END EC PRIVATE KEY----- diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index ee0356b852..fafc817ca2 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -33,17 +33,23 @@ INC_CYW43 := \ -isystem lib/cyw43-driver/firmware \ -isystem lib/cyw43-driver/src \ -isystem lib/lwip/src/include \ + -isystem sdk/src/rp2_common/pico_async_context/include/ \ -isystem sdk/src/rp2_common/pico_cyw43_arch/include/ \ + -isystem sdk/src/rp2_common/pico_cyw43_driver/include/ \ -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_NETUTILS=1 SRC_SDK_CYW43 := \ src/common/pico_sync/sem.c \ - src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.c \ + src/rp2_common/pico_async_context/async_context_base.c \ + src/rp2_common/pico_async_context/async_context_threadsafe_background.c \ src/rp2_common/pico_cyw43_arch/cyw43_arch.c \ src/rp2_common/pico_cyw43_arch/cyw43_arch_threadsafe_background.c \ - src/rp2_common/pico_lwip/nosys.c \ - src/rp2_common/pico_lwip/random.c \ + src/rp2_common/pico_cyw43_driver/cyw43_driver.c \ + src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c \ + src/rp2_common/pico_lwip/lwip_nosys.c \ + src/rp2_common/pico_rand/rand.c \ SRC_LWIP := \ shared/netutils/netutils.c \ @@ -69,27 +75,15 @@ $(PIOASM): $(Q)cmake -S pioasm -B $(BUILD)/pioasm $(Q)$(MAKE) -C $(BUILD)/pioasm PioasmBuild -$(BUILD)/cyw43_bus_pio_spi.pio.h: sdk/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.pio $(PIOASM) +$(BUILD)/cyw43_bus_pio_spi.pio.h: sdk/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.pio $(PIOASM) $(Q)$(PIOASM) -o c-sdk $< $@ -$(BUILD)/sdk/src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.o: $(BUILD)/cyw43_bus_pio_spi.pio.h +$(BUILD)/sdk/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.o: $(BUILD)/cyw43_bus_pio_spi.pio.h -CYW43_FIRMWARE_BIN = 43439A0-7.95.49.00.combined - -$(BUILD)/cyw43_resource.o: lib/cyw43-driver/firmware/$(CYW43_FIRMWARE_BIN) - $(Q)$(OBJCOPY) -I binary -O elf32-littlearm -B arm \ - --readonly-text \ - --rename-section .data=.big_const,contents,alloc,load,readonly,data \ - --redefine-sym _binary_lib_cyw43_driver_firmware_43439A0_7_95_49_00_combined_start=fw_43439A0_7_95_49_00_start \ - --redefine-sym _binary_lib_cyw43_driver_firmware_43439A0_7_95_49_00_combined_size=fw_43439A0_7_95_49_00_size \ - --redefine-sym _binary_lib_cyw43_driver_firmware_43439A0_7_95_49_00_combined_end=fw_43439A0_7_95_49_00_end \ - $< $@ -OBJ_CYW43 := $(BUILD)/cyw43_resource.o else INC_CYW43 := CFLAGS_CYW43 := SRC_SDK_CYW43 := SRC_CYW43 := -OBJ_CYW43 := SRC_LWIP := endif @@ -377,7 +371,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/boot2_padded_checksummed.o -OBJ += $(OBJ_CYW43) $(OBJ_MBEDTLS) +OBJ += $(OBJ_MBEDTLS) $(BUILD)/%.o: $(BUILD)/%.S $(STEPECHO) "CC $<" @@ -417,7 +411,7 @@ $(BUILD)/firmware.elf: $(OBJ) $(LINK_LD) $(Q)echo $(OBJ) > $(BUILD)/firmware.objs $(Q)echo $(PICO_LDFLAGS) > $(BUILD)/firmware.ldflags $(Q)$(CC) -o $@ $(CFLAGS) @$(BUILD)/firmware.ldflags -Wl,-T,$(LINK_LD) -Wl,-Map=$@.map -Wl,-cref -Wl,--gc-sections @$(BUILD)/firmware.objs -Wl,-lc - $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LINK_LD) + $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LINK_LD) $(BUILD) $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(STEPECHO) "Create $@" diff --git a/ports/raspberrypi/background.c b/ports/raspberrypi/background.c index 4b5190aa27..8e5e3fcd91 100644 --- a/ports/raspberrypi/background.c +++ b/ports/raspberrypi/background.c @@ -30,8 +30,12 @@ void port_start_background_task(void) { } + void port_finish_background_task(void) { } +void port_background_tick(void) { +} + void port_background_task(void) { } diff --git a/ports/raspberrypi/boards/cosmo_pico/board.c b/ports/raspberrypi/boards/cosmo_pico/board.c new file mode 100644 index 0000000000..331653173e --- /dev/null +++ b/ports/raspberrypi/boards/cosmo_pico/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/cosmo_pico/mpconfigboard.h b/ports/raspberrypi/boards/cosmo_pico/mpconfigboard.h new file mode 100644 index 0000000000..d313e6097f --- /dev/null +++ b/ports/raspberrypi/boards/cosmo_pico/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "COSMO-Pico" +#define MICROPY_HW_MCU_NAME "rp2040" diff --git a/ports/raspberrypi/boards/cosmo_pico/mpconfigboard.mk b/ports/raspberrypi/boards/cosmo_pico/mpconfigboard.mk new file mode 100644 index 0000000000..f4278e0c1b --- /dev/null +++ b/ports/raspberrypi/boards/cosmo_pico/mpconfigboard.mk @@ -0,0 +1,11 @@ +USB_VID = 0x2E8A +USB_PID = 0x104C +USB_PRODUCT = "COSMO-Pico" +USB_MANUFACTURER = "Raspberry Pi" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/cosmo_pico/pico-sdk-configboard.h b/ports/raspberrypi/boards/cosmo_pico/pico-sdk-configboard.h new file mode 100644 index 0000000000..36da55d457 --- /dev/null +++ b/ports/raspberrypi/boards/cosmo_pico/pico-sdk-configboard.h @@ -0,0 +1 @@ +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/cosmo_pico/pins.c b/ports/raspberrypi/boards/cosmo_pico/pins.c new file mode 100644 index 0000000000..f2c094cb4d --- /dev/null +++ b/ports/raspberrypi/boards/cosmo_pico/pins.c @@ -0,0 +1,44 @@ +#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_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/pimoroni_badger2040/board.c b/ports/raspberrypi/boards/pimoroni_badger2040/board.c index 48ae66e7cb..9eea472925 100644 --- a/ports/raspberrypi/boards/pimoroni_badger2040/board.c +++ b/ports/raspberrypi/boards/pimoroni_badger2040/board.c @@ -260,6 +260,10 @@ const uint8_t display_stop_sequence[] = { POF, 0x00 // Power off }; +const uint8_t refresh_sequence[] = { + DRF, 0x00 +}; + void board_init(void) { // Drive the EN_3V3 pin high so the board stays awake on battery power enable_pin_obj.base.type = &digitalio_digitalinout_type; @@ -293,6 +297,7 @@ void board_init(void) { display, bus, display_start_sequence, sizeof(display_start_sequence), + 0, // start up time display_stop_sequence, sizeof(display_stop_sequence), 296, // width 128, // height @@ -310,13 +315,14 @@ void board_init(void) { DTM1, // write_color_ram_command false, // color_bits_inverted 0x000000, // highlight_color - DRF, // refresh_display_command + 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 } diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c index f75c4b3451..7925a734fb 100644 --- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c +++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c @@ -89,20 +89,12 @@ void pwmout_never_reset(uint8_t slice, uint8_t ab_channel) { never_reset_channel |= _mask(slice, ab_channel); } -void pwmout_reset_ok(uint8_t slice, uint8_t ab_channel) { - never_reset_channel &= ~_mask(slice, ab_channel); -} - void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { pwmout_never_reset(self->slice, self->ab_channel); never_reset_pin_number(self->pin->number); } -void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { - pwmout_reset_ok(self->slice, self->ab_channel); -} - void pwmout_reset(void) { // Reset all slices for (size_t slice = 0; slice < NUM_PWM_SLICES; slice++) { diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.c b/ports/raspberrypi/common-hal/socketpool/Socket.c index fe12f461fb..e2b82264ba 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.c +++ b/ports/raspberrypi/common-hal/socketpool/Socket.c @@ -1109,7 +1109,7 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *socket, break; } if (ret == (unsigned)-1) { - return -_errno; + mp_raise_OSError(_errno); } return ret; } diff --git a/ports/raspberrypi/common-hal/ssl/SSLSocket.c b/ports/raspberrypi/common-hal/ssl/SSLSocket.c index 21e2a95c90..67508f16c8 100644 --- a/ports/raspberrypi/common-hal/ssl/SSLSocket.c +++ b/ports/raspberrypi/common-hal/ssl/SSLSocket.c @@ -260,8 +260,8 @@ mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t *self, uint8_t // renegotation. ret = MP_EWOULDBLOCK; } - DEBUG("returning [error case] %d\n", -ret); - return -ret; + DEBUG("raising errno [error case] %d\n", ret); + mp_raise_OSError(ret); } mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t *self, const uint8_t *buf, uint32_t len) { @@ -279,8 +279,8 @@ mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t *self, const uint8_t // renegotation. ret = MP_EWOULDBLOCK; } - DEBUG("returning [error case] %d\n", -ret); - return -ret; + DEBUG("raising errno [error case] %d\n", ret); + mp_raise_OSError(ret); } bool common_hal_ssl_sslsocket_bind(ssl_sslsocket_obj_t *self, const char *host, size_t hostlen, uint32_t port) { diff --git a/ports/raspberrypi/lib/cyw43-driver b/ports/raspberrypi/lib/cyw43-driver index 2cf328d9e4..e52dd14a15 160000 --- a/ports/raspberrypi/lib/cyw43-driver +++ b/ports/raspberrypi/lib/cyw43-driver @@ -1 +1 @@ -Subproject commit 2cf328d9e41603405a037a29e081a7d30dd519e6 +Subproject commit e52dd14a15e6a53e6263840704470246aa77c5ce diff --git a/ports/raspberrypi/lwip_inc/lwipopts.h b/ports/raspberrypi/lwip_inc/lwipopts.h index 6d116e89b6..06df7f1318 100644 --- a/ports/raspberrypi/lwip_inc/lwipopts.h +++ b/ports/raspberrypi/lwip_inc/lwipopts.h @@ -60,6 +60,7 @@ #define LWIP_NUM_NETIF_CLIENT_DATA 1 #define LWIP_NETIF_EXT_STATUS_CALLBACK 1 #define MDNS_MAX_SECONDARY_HOSTNAMES 1 +#define MEMP_NUM_SYS_TIMEOUT (8 + 3 * (LWIP_IPV4 + LWIP_IPV6)) #endif #ifndef NDEBUG diff --git a/ports/raspberrypi/sdk b/ports/raspberrypi/sdk index 2e6142b15b..2ccab115de 160000 --- a/ports/raspberrypi/sdk +++ b/ports/raspberrypi/sdk @@ -1 +1 @@ -Subproject commit 2e6142b15b8a75c1227dd3edbe839193b2bf9041 +Subproject commit 2ccab115de0d42d31d6611cca19ef0cd0d2ccaa7 diff --git a/ports/stm/Makefile b/ports/stm/Makefile index 094bee7aef..325b13b1bc 100755 --- a/ports/stm/Makefile +++ b/ports/stm/Makefile @@ -268,7 +268,7 @@ $(BUILD)/firmware.elf: $(OBJ) $(STEPECHO) "LINK $@" $(Q)echo $^ > $(BUILD)/firmware.objs $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--start-group $(LIBS) -Wl,--end-group - $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) + $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LD_FILE) $(BUILD) $(BUILD)/firmware.bin: $(BUILD)/firmware.elf $(STEPECHO) "Create $@" diff --git a/ports/stm/background.c b/ports/stm/background.c index dbf5ccee2b..68703a5233 100644 --- a/ports/stm/background.c +++ b/ports/stm/background.c @@ -35,6 +35,8 @@ void port_background_task(void) { } +void port_background_tick(void) { +} void port_start_background_task(void) { } void port_finish_background_task(void) { diff --git a/ports/stm/boards/swan_r5/mpconfigboard.h b/ports/stm/boards/swan_r5/mpconfigboard.h index 94cc58ff9d..8c6949201e 100644 --- a/ports/stm/boards/swan_r5/mpconfigboard.h +++ b/ports/stm/boards/swan_r5/mpconfigboard.h @@ -45,6 +45,9 @@ #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 diff --git a/ports/stm/common-hal/busio/UART.c b/ports/stm/common-hal/busio/UART.c index 48894db5f9..cdace31639 100644 --- a/ports/stm/common-hal/busio/UART.c +++ b/ports/stm/common-hal/busio/UART.c @@ -85,7 +85,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, bool sigint_enabled) { // match pins to UART objects - USART_TypeDef *USARTx; + USART_TypeDef *USARTx = NULL; uint8_t tx_len = MP_ARRAY_SIZE(mcu_uart_tx_list); uint8_t rx_len = MP_ARRAY_SIZE(mcu_uart_rx_list); @@ -159,8 +159,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, USARTx = assign_uart_or_throw(self, (self->tx != NULL), periph_index, uart_taken); } else { - // both pins cannot be empty - mp_raise_ValueError(translate("Supply at least one UART pin")); + // TX and RX are both None. But this is already handled in shared-bindings, so + // we won't get here. } // Other errors diff --git a/ports/stm/common-hal/pwmio/PWMOut.c b/ports/stm/common-hal/pwmio/PWMOut.c index cc712497d2..a983718ff2 100644 --- a/ports/stm/common-hal/pwmio/PWMOut.c +++ b/ports/stm/common-hal/pwmio/PWMOut.c @@ -40,7 +40,8 @@ STATIC uint8_t tim_channels_taken[TIM_BANK_ARRAY_LEN]; // Initial frequency timer is set to. STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN]; -STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN]; +STATIC uint8_t never_reset_tim[TIM_BANK_ARRAY_LEN]; +STATIC TIM_HandleTypeDef *active_handles[TIM_BANK_ARRAY_LEN]; STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) { // duty cycle is duty/0xFFFF fraction x (number of pulses per period) @@ -64,10 +65,25 @@ STATIC bool timer_get_optimal_divisors(uint32_t *period, uint32_t *prescaler, void pwmout_reset(void) { for (int i = 0; i < TIM_BANK_ARRAY_LEN; i++) { - if (!never_reset_tim[i]) { - tim_channels_taken[i] = 0x00; - tim_frequencies[i] = 0; + if (active_handles[i] == NULL) { + continue; } + for (int c = 0; c < 8; c++) { + if ((never_reset_tim[i] & (1 << c)) != 0 || + (tim_channels_taken[i] & (1 << c)) == 0) { + continue; + } + HAL_TIM_PWM_Stop(active_handles[i], c); + } + // TODO: Actually shut down individual channels and PWM. + if (never_reset_tim[i] != 0) { + continue; + } + tim_channels_taken[i] = 0x00; + tim_frequencies[i] = 0; + stm_peripherals_timer_free(mcu_tim_banks[i]); + HAL_TIM_PWM_DeInit(active_handles[i]); + active_handles[i] = NULL; } } @@ -176,6 +192,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self, if (HAL_TIM_PWM_Init(&self->handle) != HAL_OK) { return PWMOUT_INITIALIZATION_ERROR; } + active_handles[tim_index] = &self->handle; } // Channel/PWM init @@ -208,15 +225,6 @@ void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) { } } -void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) { - for (size_t i = 0; i < TIM_BANK_ARRAY_LEN; i++) { - if (mcu_tim_banks[i] == self->handle.Instance) { - never_reset_tim[i] = false; - break; - } - } -} - bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t *self) { return self->tim == NULL; } @@ -234,9 +242,13 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) { } common_hal_reset_pin(self->pin); + never_reset_tim[self->tim->tim_index] &= ~(1 << self->tim->channel_index); + // if reserved timer has no active channels, we can disable it if (tim_channels_taken[self->tim->tim_index] == 0) { tim_frequencies[self->tim->tim_index] = 0x00; + HAL_TIM_PWM_DeInit(&self->handle); + active_handles[self->tim->tim_index] = NULL; stm_peripherals_timer_free(self->handle.Instance); } diff --git a/ports/stm/peripherals/stm32l4/clocks.c b/ports/stm/peripherals/stm32l4/clocks.c index 4419f751d4..5724a74ae2 100644 --- a/ports/stm/peripherals/stm32l4/clocks.c +++ b/ports/stm/peripherals/stm32l4/clocks.c @@ -39,6 +39,8 @@ #error HSE support needs to be added for the L4 family. #elif !BOARD_HAS_LOW_SPEED_CRYSTAL #error LSE clock source required +#elif !defined(BOARD_LSE_DRIVE_LEVEL) + #error BOARD_LSE_DRIVE_LEVEL is not defined for this board. The board should define the 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. #endif void Error_Handler(void) { @@ -57,7 +59,7 @@ void stm32_peripherals_clocks_init(void) { // Configure LSE Drive HAL_PWR_EnableBkUpAccess(); - __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + __HAL_RCC_LSEDRIVE_CONFIG(BOARD_LSE_DRIVE_LEVEL); __HAL_RCC_PWR_CLK_ENABLE(); /** Configure the main internal regulator output voltage diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index c54fede813..c94845229c 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -178,6 +178,9 @@ #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ +#define MICROPY_FATFS_LFN_UNICODE (2) + +#define FF_FS_CASE_INSENSITIVE_COMPARISON_ASCII_ONLY (1) // Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. // names in exception messages (may require more RAM). diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index e351fc0836..fd12bbd8b5 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -26,7 +26,6 @@ CFLAGS += -DCIRCUITPY_QRIO=1 $(BUILD)/lib/quirc/lib/%.o: CFLAGS += -Wno-shadow -Wno-sign-compare -include shared-module/qrio/quirc_alloc.h SRC_BITMAP := \ - $(patsubst ../../%,%,$(wildcard ../../shared-bindings/gifio/*.c ../../shared-module/gifio/*.c)) \ shared/runtime/context_manager_helpers.c \ displayio_min.c \ shared-bindings/aesio/aes.c \ diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 9de0e5a804..79769e000e 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -597,6 +597,7 @@ SRC_SHARED_MODULE_ALL = \ getpass/__init__.c \ gifio/__init__.c \ gifio/GifWriter.c \ + gifio/OnDiskGif.c \ imagecapture/ParallelImageCapture.c \ ipaddress/IPv4Address.c \ ipaddress/__init__.c \ @@ -702,6 +703,13 @@ SRC_MOD += $(addprefix lib/protomatter/src/, \ $(BUILD)/lib/protomatter/src/core.o: CFLAGS += -include "shared-module/rgbmatrix/allocator.h" -DCIRCUITPY -Wno-missing-braces -Wno-missing-prototypes endif +ifeq ($(CIRCUITPY_GIFIO),1) +SRC_MOD += $(addprefix lib/AnimatedGIF/, \ + gif.c \ +) +$(BUILD)/lib/AnimatedGIF/gif.o: CFLAGS += -DCIRCUITPY +endif + ifeq ($(CIRCUITPY_ZLIB),1) SRC_MOD += $(addprefix lib/uzlib/, \ tinflate.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 8bfb69297a..a514b6a160 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -145,6 +145,7 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_ENABLE_PYSTACK (1) +#define CIRCUITPY_SETTABLE_PYSTACK (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_STREAMS_NON_BLOCK (1) #ifndef MICROPY_USE_INTERNAL_PRINTF @@ -594,6 +595,8 @@ void supervisor_run_background_tasks_if_tick(void); #define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (0) #endif +#define FF_FS_CASE_INSENSITIVE_COMPARISON_ASCII_ONLY (1) + #define FF_FS_MAKE_VOLID (1) #define MICROPY_PY_OPTIMIZE_PROPERTY_FLASH_SIZE (CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE) diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 4ea6ead794..c849a12851 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -226,6 +226,9 @@ CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO) CIRCUITPY_ESPIDF ?= 0 CFLAGS += -DCIRCUITPY_ESPIDF=$(CIRCUITPY_ESPIDF) +CIRCUITPY_ESPNOW ?= 0 +CFLAGS += -DCIRCUITPY_ESPNOW=$(CIRCUITPY_ESPNOW) + CIRCUITPY_ESPULP ?= 0 CFLAGS += -DCIRCUITPY_ESPULP=$(CIRCUITPY_ESPULP) @@ -248,7 +251,8 @@ CIRCUITPY_GETPASS ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_GETPASS=$(CIRCUITPY_GETPASS) ifeq ($(CIRCUITPY_DISPLAYIO),1) -CIRCUITPY_GIFIO ?= $(CIRCUITPY_CAMERA) +#CIRCUITPY_GIFIO ?= $(CIRCUITPY_CAMERA) +CIRCUITPY_GIFIO ?= 1 else CIRCUITPY_GIFIO ?= 0 endif diff --git a/py/obj.h b/py/obj.h index b7e76a1106..86fbe5155f 100644 --- a/py/obj.h +++ b/py/obj.h @@ -419,7 +419,7 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; // Declare a module as a builtin, processed by makemoduledefs.py // param module_name: MP_QSTR_ // param obj_module: mp_obj_module_t instance -// prarm enabled_define: used as `#if (enabled_define) around entry` +// param enabled_define: used as `#if (enabled_define) around entry` #define MP_REGISTER_MODULE(module_name, obj_module, enabled_define) diff --git a/py/objmodule.c b/py/objmodule.c index a9d20c7ee5..8f04a44597 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -218,9 +218,6 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = { #if MICROPY_PY_UJSON && !CIRCUITPY { MP_ROM_QSTR(MP_QSTR_ujson), MP_ROM_PTR(&mp_module_ujson) }, #endif - #if CIRCUITPY_ULAB - { MP_ROM_QSTR(MP_QSTR_ulab), MP_ROM_PTR(&ulab_user_cmodule) }, - #endif #if MICROPY_PY_URE && !CIRCUITPY { MP_ROM_QSTR(MP_QSTR_ure), MP_ROM_PTR(&mp_module_ure) }, #endif diff --git a/py/objtuple.h b/py/objtuple.h index 7bfb447fa4..ded265b47e 100644 --- a/py/objtuple.h +++ b/py/objtuple.h @@ -50,6 +50,9 @@ mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf); extern const mp_obj_type_t mp_type_attrtuple; +// Relies on gcc Variadic Macros and Statement Expressions +#define MP_OBJ_NEW_TUPLE(...) ({mp_obj_t _z[] = {__VA_ARGS__}; mp_obj_new_tuple(MP_ARRAY_SIZE(_z), _z);}) + #define MP_DEFINE_ATTRTUPLE(tuple_obj_name, fields, nitems, ...) \ const mp_rom_obj_tuple_t tuple_obj_name = { \ .base = {&mp_type_attrtuple}, \ diff --git a/py/ringbuf.c b/py/ringbuf.c index 8a4cb33cbc..5936b64230 100644 --- a/py/ringbuf.c +++ b/py/ringbuf.c @@ -72,7 +72,6 @@ int ringbuf_get16(ringbuf_t *r) { if (r->used < 2) { return -1; } - int high_byte = ringbuf_get(r); int low_byte = ringbuf_get(r); return (high_byte << 8) | low_byte; @@ -92,6 +91,15 @@ int ringbuf_put(ringbuf_t *r, uint8_t v) { return 0; } +int ringbuf_put16(ringbuf_t *r, uint16_t v) { + if (r->size - r->used < 2) { + return -1; + } + ringbuf_put(r, (v >> 8) & 0xff); + ringbuf_put(r, v & 0xff); + return 0; +} + void ringbuf_clear(ringbuf_t *r) { r->next_write = 0; r->next_read = 0; @@ -132,13 +140,3 @@ size_t ringbuf_get_n(ringbuf_t *r, uint8_t *buf, size_t bufsize) { } return bufsize; } - -int ringbuf_put16(ringbuf_t *r, uint16_t v) { - if (r->size - r->used < 2) { - return -1; - } - - ringbuf_put(r, (v >> 8) & 0xff); - ringbuf_put(r, v & 0xff); - return 0; -} diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c index 218d72bdbb..1efb992c72 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.c +++ b/shared-bindings/_bleio/CharacteristicBuffer.c @@ -159,7 +159,12 @@ STATIC mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t r 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); - return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_buffer_rx_characters_available(self)); + uint32_t available = common_hal_bleio_characteristic_buffer_rx_characters_available(self); + if (available == 0) { + // Only check if connected when none available, otherwise, allow code to continue. + raise_error_if_not_connected(self); + } + return MP_OBJ_NEW_SMALL_INT(available); } MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_buffer_get_in_waiting_obj, bleio_characteristic_buffer_obj_get_in_waiting); diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c index 50e07a5b61..c5c50515ea 100644 --- a/shared-bindings/aesio/aes.c +++ b/shared-bindings/aesio/aes.c @@ -20,7 +20,7 @@ //| self, //| key: ReadableBuffer, //| mode: int = 0, -//| iv: Optional[ReadableBuffer] = None, +//| IV: Optional[ReadableBuffer] = None, //| segment_size: int = 8, //| ) -> None: //| """Create a new AES state with the given key. @@ -28,7 +28,7 @@ //| :param ~circuitpython_typing.ReadableBuffer key: A 16-, 24-, or 32-byte key //| :param int mode: AES mode to use. One of: `MODE_ECB`, `MODE_CBC`, or //| `MODE_CTR` -//| :param ~circuitpython_typing.ReadableBuffer iv: Initialization vector to use for CBC or CTR mode +//| :param ~circuitpython_typing.ReadableBuffer IV: Initialization vector to use for CBC or CTR mode //| //| Additional arguments are supported for legacy reasons. //| @@ -98,33 +98,49 @@ STATIC mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t aesio_aes_rekey(size_t n_args, const mp_obj_t *pos_args) { +//| def rekey( +//| self, +//| key: ReadableBuffer, +//| IV: Optional[ReadableBuffer] = None, +//| ) -> None: +//| """Update the AES state with the given key. +//| +//| :param ~circuitpython_typing.ReadableBuffer key: A 16-, 24-, or 32-byte key +//| :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 }; + static const mp_arg_t allowed_args[] = { + {MP_QSTR_key, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, + {MP_QSTR_IV, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + 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 bufinfo; - mp_get_buffer_raise(pos_args[1], &bufinfo, MP_BUFFER_READ); + + mp_get_buffer_raise(args[ARG_key].u_obj, &bufinfo, MP_BUFFER_READ); const uint8_t *key = bufinfo.buf; size_t key_length = bufinfo.len; - if (key == NULL) { - mp_raise_ValueError(translate("No key was specified")); - } + if ((key_length != 16) && (key_length != 24) && (key_length != 32)) { mp_raise_ValueError(translate("Key must be 16, 24, or 32 bytes long")); } const uint8_t *iv = NULL; - if (n_args > 2) { - mp_get_buffer_raise(pos_args[2], &bufinfo, MP_BUFFER_READ); - size_t iv_length = bufinfo.len; - iv = (const uint8_t *)bufinfo.buf; - (void)mp_arg_validate_length(iv_length, AES_BLOCKLEN, MP_QSTR_IV); + if (args[ARG_IV].u_obj != NULL && + mp_get_buffer(args[ARG_IV].u_obj, &bufinfo, MP_BUFFER_READ)) { + (void)mp_arg_validate_length(bufinfo.len, AES_BLOCKLEN, MP_QSTR_IV); + + iv = bufinfo.buf; } common_hal_aesio_aes_rekey(self, key, key_length, iv); return mp_const_none; } - -MP_DEFINE_CONST_FUN_OBJ_VAR(aesio_aes_rekey_obj, 2, aesio_aes_rekey); +MP_DEFINE_CONST_FUN_OBJ_KW(aesio_aes_rekey_obj, 1, aesio_aes_rekey); STATIC void validate_length(aesio_aes_obj_t *self, size_t src_length, size_t dest_length) { diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 493ff93b09..1195e1811d 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -523,6 +523,101 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line); // requires all 6 arguments +//| def draw_polygon( +//| dest_bitmap: displayio.Bitmap, +//| xs: ReadableBuffer, +//| ys: ReadableBuffer, +//| value: int, +//| close: Optional[bool] = True, +//| ) -> None: +//| """Draw a polygon conecting points on provided bitmap with provided value +//| +//| :param bitmap dest_bitmap: Destination bitmap that will be written into +//| :param ReadableBuffer xs: x-pixel position of the polygon's vertices +//| :param ReadableBuffer ys: y-pixel position of the polygon's vertices +//| :param int value: Bitmap palette index that will be written into the +//| line in the destination bitmap +//| :param bool close: (Optional) Wether to connect first and last point. (True) +//| +//| .. code-block:: Python +//| +//| import board +//| import displayio +//| import bitmaptools +//| +//| display = board.DISPLAY +//| main_group = displayio.Group() +//| display.root_group = main_group +//| +//| palette = displayio.Palette(3) +//| palette[0] = 0xffffff +//| palette[1] = 0x0000ff +//| palette[2] = 0xff0000 +//| +//| bmp = displayio.Bitmap(128,128, 3) +//| bmp.fill(0) +//| +//| xs = bytes([4, 101, 101, 19]) +//| ys = bytes([4, 19, 121, 101]) +//| bitmaptools.draw_polygon(bmp, xs, ys, 1) +//| +//| xs = bytes([14, 60, 110]) +//| ys = bytes([14, 24, 90]) +//| bitmaptools.draw_polygon(bmp, xs, ys, 2) +//| +//| tilegrid = displayio.TileGrid(bitmap=bmp, pixel_shader=palette) +//| main_group.append(tilegrid) +//| +//| while True: +//| pass +//| """ +//| ... +//| +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_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 + + mp_buffer_info_t xs_buf, ys_buf; + mp_get_buffer_raise(args[ARG_xs].u_obj, &xs_buf, MP_BUFFER_READ); + mp_get_buffer_raise(args[ARG_ys].u_obj, &ys_buf, MP_BUFFER_READ); + size_t xs_size = mp_binary_get_size('@', xs_buf.typecode, NULL); + size_t ys_size = mp_binary_get_size('@', ys_buf.typecode, NULL); + size_t xs_len = xs_buf.len / xs_size; + size_t ys_len = ys_buf.len / ys_size; + if (xs_size != ys_size) { + mp_raise_ValueError(translate("Coordinate arrays types have different sizes")); + } + if (xs_len != ys_len) { + mp_raise_ValueError(translate("Coordinate arrays have different lengths")); + } + + uint32_t value, color_depth; + value = args[ARG_value].u_int; + color_depth = (1 << destination->bits_per_value); + if (color_depth <= value) { + mp_raise_ValueError(translate("out of range of target")); + } + + bool close = args[ARG_close].u_bool; + + common_hal_bitmaptools_draw_polygon(destination, xs_buf.buf, ys_buf.buf, xs_len, xs_size, value, close); + + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_polygon_obj, 0, bitmaptools_obj_draw_polygon); + //| def arrayblit( //| bitmap: displayio.Bitmap, //| data: ReadableBuffer, @@ -784,6 +879,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = { { 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) }, + { MP_ROM_QSTR(MP_QSTR_draw_polygon), MP_ROM_PTR(&bitmaptools_draw_polygon_obj) }, { MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&bitmaptools_dither_obj) }, { MP_ROM_QSTR(MP_QSTR_DitherAlgorithm), MP_ROM_PTR(&bitmaptools_dither_algorithm_type) }, }; diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h index fb5c78911f..db72410cf6 100644 --- a/shared-bindings/bitmaptools/__init__.h +++ b/shared-bindings/bitmaptools/__init__.h @@ -64,6 +64,7 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, int16_t x1, int16_t y1, uint32_t value); +void common_hal_bitmaptools_draw_polygon(displayio_bitmap_t *destination, void *xs, void *ys, size_t points_len, int point_size, uint32_t value, bool close); void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, mp_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes, bool reverse_rows); void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_index); void common_hal_bitmaptools_dither(displayio_bitmap_t *dest_bitmap, displayio_bitmap_t *source_bitmap, displayio_colorspace_t colorspace, bitmaptools_dither_algorithm_t algorithm); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index aada49a051..77d7036c2e 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -48,9 +48,13 @@ //| //| def __init__( //| self, -//| tx: microcontroller.Pin, -//| rx: microcontroller.Pin, +//| tx: Optional[microcontroller.Pin] = None, +//| rx: Optional[microcontroller.Pin] = None, //| *, +//| rts: Optional[microcontroller.Pin] = None, +//| cts: Optional[microcontroller.Pin] = None, +//| rs485_dir: Optional[microcontroller.Pin] = None, +//| rs485_invert: bool = False, //| baudrate: int = 9600, //| bits: int = 8, //| parity: Optional[Parity] = None, @@ -74,11 +78,13 @@ //| :param float timeout: the timeout in seconds to wait for the first character and between subsequent characters when reading. Raises ``ValueError`` if timeout >100 seconds. //| :param int receiver_buffer_size: the character length of the read buffer (0 to disable). (When a character is 9 bits the buffer will be 2 * receiver_buffer_size bytes.) //| +//| ``tx`` and ``rx`` cannot both be ``None``. +//| //| *New in CircuitPython 4.0:* ``timeout`` has incompatibly changed units from milliseconds to seconds. //| The new upper limit on ``timeout`` is meant to catch mistaken use of milliseconds. //| //| **Limitations:** RS485 is not supported on SAMD, nRF, Broadcom, Spresense, or STM. -//| On i.MX and Raspberry Pi RP2040 support is implemented in software: +//| On i.MX and Raspberry Pi RP2040, RS485 support is implemented in software: //| The timing for the ``rs485_dir`` pin signal is done on a best-effort basis, and may not meet //| RS485 specifications intermittently. //| """ @@ -118,11 +124,21 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, si const mcu_pin_obj_t *rx = validate_obj_is_free_pin_or_none(args[ARG_rx].u_obj, MP_QSTR_rx); const mcu_pin_obj_t *tx = validate_obj_is_free_pin_or_none(args[ARG_tx].u_obj, MP_QSTR_tx); - + const mcu_pin_obj_t *rts = validate_obj_is_free_pin_or_none(args[ARG_rts].u_obj, MP_QSTR_rts); + const mcu_pin_obj_t *cts = validate_obj_is_free_pin_or_none(args[ARG_cts].u_obj, MP_QSTR_cts); + const mcu_pin_obj_t *rs485_dir = validate_obj_is_free_pin_or_none(args[ARG_rs485_dir].u_obj, MP_QSTR_rs485_dir); if ((tx == NULL) && (rx == NULL)) { mp_raise_ValueError(translate("tx and rx cannot both be None")); } + // Pins must be distinct. + if ((tx != NULL && (tx == rx || tx == rts || tx == cts || tx == rs485_dir)) || + (rx != NULL && (rx == rts || rx == cts || rx == rs485_dir)) || + (rts != NULL && (rts == cts || rts == rs485_dir)) || + (cts != NULL && (cts == rs485_dir))) { + raise_ValueError_invalid_pins(); + } + uint8_t bits = (uint8_t)mp_arg_validate_int_range(args[ARG_bits].u_int, 5, 9, MP_QSTR_bits); busio_uart_parity_t parity = BUSIO_UART_PARITY_NONE; @@ -137,10 +153,6 @@ STATIC mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, si mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); validate_timeout(timeout); - const mcu_pin_obj_t *rts = validate_obj_is_free_pin_or_none(args[ARG_rts].u_obj, MP_QSTR_rts); - const mcu_pin_obj_t *cts = validate_obj_is_free_pin_or_none(args[ARG_cts].u_obj, MP_QSTR_cts); - const mcu_pin_obj_t *rs485_dir = validate_obj_is_free_pin_or_none(args[ARG_rs485_dir].u_obj, MP_QSTR_rs485_dir); - const bool rs485_invert = args[ARG_rs485_invert].u_bool; // Always initially allocate the UART object within the long-lived heap. diff --git a/shared-bindings/displayio/ColorConverter.c b/shared-bindings/displayio/ColorConverter.c index 9c3d297fdc..06de5a4b09 100644 --- a/shared-bindings/displayio/ColorConverter.c +++ b/shared-bindings/displayio/ColorConverter.c @@ -73,10 +73,8 @@ STATIC mp_obj_t displayio_colorconverter_obj_convert(mp_obj_t self_in, mp_obj_t displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t color = mp_arg_validate_type_int(color_obj, MP_QSTR_color); - _displayio_colorspace_t colorspace; - colorspace.depth = 16; uint32_t output_color; - common_hal_displayio_colorconverter_convert(self, &colorspace, color, &output_color); + common_hal_displayio_colorconverter_convert(self, &self->output_colorspace, color, &output_color); return MP_OBJ_NEW_SMALL_INT(output_color); } MP_DEFINE_CONST_FUN_OBJ_2(displayio_colorconverter_convert_obj, displayio_colorconverter_obj_convert); diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c index 47b1de8914..49194ebd1e 100644 --- a/shared-bindings/displayio/Display.c +++ b/shared-bindings/displayio/Display.c @@ -240,10 +240,16 @@ static displayio_display_obj_t *native_display(mp_obj_t display_obj) { } //| def show(self, group: Group) -> None: -//| """Switches to displaying the given group of layers. When group is None, the default +//| """ +//| .. note:: `show()` is deprecated and will be removed in CircuitPython 9.0.0. +//| Use ``.root_group = group`` instead. +//| +//| Switches to displaying the given group of layers. When group is None, the default //| CircuitPython terminal will be shown. //| -//| :param Group group: The group to show.""" +//| :param Group group: The group to show. +//| +//| """ //| ... STATIC mp_obj_t displayio_display_obj_show(mp_obj_t self_in, mp_obj_t group_in) { displayio_display_obj_t *self = native_display(self_in); @@ -419,7 +425,9 @@ MP_PROPERTY_GETTER(displayio_display_bus_obj, (mp_obj_t)&displayio_display_get_bus_obj); //| root_group: Group -//| """The root group on the display.""" +//| """The root group on the display. +//| If the root group is set to ``None``, the default CircuitPython terminal will be shown. +//| """ STATIC mp_obj_t displayio_display_obj_get_root_group(mp_obj_t self_in) { displayio_display_obj_t *self = native_display(self_in); return common_hal_displayio_display_get_root_group(self); diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c index 4745223ad3..93d91110a2 100644 --- a/shared-bindings/displayio/EPaperDisplay.c +++ b/shared-bindings/displayio/EPaperDisplay.c @@ -71,14 +71,16 @@ //| write_color_ram_command: Optional[int] = None, //| color_bits_inverted: bool = False, //| highlight_color: int = 0x000000, -//| refresh_display_command: int, +//| refresh_display_command: Union[int, circuitpython_typing.ReadableBuffer], //| refresh_time: float = 40, //| busy_pin: Optional[microcontroller.Pin] = None, //| busy_state: bool = True, //| seconds_per_frame: float = 180, //| always_toggle_chip_select: bool = False, //| grayscale: bool = False, -//| two_byte_sequence_length: bool = False +//| advanced_color_epaper: bool = False, +//| two_byte_sequence_length: bool = False, +//| start_up_time: float = 0 //| ) -> None: //| """Create a EPaperDisplay object on the given display bus (`displayio.FourWire` or `paralleldisplay.ParallelBus`). //| @@ -92,8 +94,8 @@ //| //| :param display_bus: The bus that the display is connected to //| :type _DisplayBus: displayio.FourWire or paralleldisplay.ParallelBus -//| :param ~circuitpython_typing.ReadableBuffer start_sequence: Byte-packed initialization sequence. -//| :param ~circuitpython_typing.ReadableBuffer stop_sequence: Byte-packed initialization sequence. +//| :param ~circuitpython_typing.ReadableBuffer start_sequence: Byte-packed command sequence. +//| :param ~circuitpython_typing.ReadableBuffer stop_sequence: Byte-packed command sequence. //| :param int width: Width in pixels //| :param int height: Height in pixels //| :param int ram_width: RAM width in pixels @@ -110,14 +112,16 @@ //| :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 refresh_display_command: Command used to start a display refresh +//| :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 //| :param bool busy_state: State of the busy pin when the display is busy //| :param float seconds_per_frame: Minimum number of seconds between screen refreshes //| :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 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 //| """ //| ... STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { @@ -127,7 +131,8 @@ STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size 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_refresh_display_command, ARG_refresh_time, ARG_busy_pin, ARG_busy_state, - ARG_seconds_per_frame, ARG_always_toggle_chip_select, ARG_grayscale, ARG_two_byte_sequence_length }; + ARG_seconds_per_frame, ARG_always_toggle_chip_select, ARG_grayscale, ARG_advanced_color_epaper, + ARG_two_byte_sequence_length, ARG_start_up_time }; static const mp_arg_t allowed_args[] = { { MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_start_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -148,14 +153,16 @@ STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size { 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_refresh_display_command, MP_ARG_INT | MP_ARG_REQUIRED }, + { 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} }, { MP_QSTR_busy_state, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, { MP_QSTR_seconds_per_frame, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(180)} }, { 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_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_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); @@ -177,10 +184,10 @@ STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size primary_display_t *disp = allocate_display_or_raise(); displayio_epaperdisplay_obj_t *self = &disp->epaper_display; - ; mp_float_t refresh_time = mp_obj_get_float(args[ARG_refresh_time].u_obj); mp_float_t seconds_per_frame = mp_obj_get_float(args[ARG_seconds_per_frame].u_obj); + mp_float_t start_up_time = mp_obj_get_float(args[ARG_start_up_time].u_obj); mp_int_t write_color_ram_command = NO_COMMAND; mp_int_t highlight_color = args[ARG_highlight_color].u_int; @@ -188,19 +195,40 @@ STATIC mp_obj_t displayio_epaperdisplay_make_new(const mp_obj_type_t *type, size write_color_ram_command = mp_obj_get_int(args[ARG_write_color_ram_command].u_obj); } + bool two_byte_sequence_length = args[ARG_two_byte_sequence_length].u_bool; + + mp_obj_t refresh_obj = args[ARG_refresh_display_command].u_obj; + const uint8_t *refresh_buf; + mp_buffer_info_t refresh_bufinfo; + 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, true); + command_buf[0] = refresh_command; + command_buf[1] = 0; + command_buf[2] = 0; + refresh_buf = command_buf; + refresh_buf_len = two_byte_sequence_length? 3: 2; + } else if (mp_get_buffer(refresh_obj, &refresh_bufinfo, MP_BUFFER_READ)) { + refresh_buf = refresh_bufinfo.buf; + refresh_buf_len = refresh_bufinfo.len; + } else { + mp_raise_ValueError_varg(translate("Invalid %q"), MP_QSTR_refresh_display_command); + } + self->base.type = &displayio_epaperdisplay_type; common_hal_displayio_epaperdisplay_construct( self, display_bus, - start_bufinfo.buf, start_bufinfo.len, stop_bufinfo.buf, stop_bufinfo.len, + 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, args[ARG_refresh_display_command].u_int, refresh_time, + 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_two_byte_sequence_length].u_bool + args[ARG_always_toggle_chip_select].u_bool, args[ARG_grayscale].u_bool, args[ARG_advanced_color_epaper].u_bool, two_byte_sequence_length ); return self; @@ -214,7 +242,11 @@ static displayio_epaperdisplay_obj_t *native_display(mp_obj_t display_obj) { } //| def show(self, group: Group) -> None: -//| """Switches to displaying the given group of layers. When group is None, the default +//| """ +//| .. note:: `show()` is deprecated and will be removed in CircuitPython 9.0.0. +//| Use ``.root_group = group`` instead. +//| +//| Switches to displaying the given group of layers. When group is None, the default //| CircuitPython terminal will be shown. //| //| :param Group group: The group to show.""" @@ -351,7 +383,9 @@ MP_PROPERTY_GETTER(displayio_epaperdisplay_bus_obj, (mp_obj_t)&displayio_epaperdisplay_get_bus_obj); //| root_group: Group -//| """The root group on the epaper display.""" +//| """The root group on the epaper display. +//| If the root group is set to ``None``, the default CircuitPython terminal will be shown. +//| """ //| STATIC mp_obj_t displayio_epaperdisplay_obj_get_root_group(mp_obj_t self_in) { displayio_epaperdisplay_obj_t *self = native_display(self_in); diff --git a/shared-bindings/displayio/EPaperDisplay.h b/shared-bindings/displayio/EPaperDisplay.h index 13fd51d132..1ef2ed4b4b 100644 --- a/shared-bindings/displayio/EPaperDisplay.h +++ b/shared-bindings/displayio/EPaperDisplay.h @@ -37,12 +37,12 @@ extern const mp_obj_type_t displayio_epaperdisplay_type; #define NO_COMMAND 0x100 void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t *self, - mp_obj_t bus, const uint8_t *start_sequence, uint16_t start_sequence_len, const uint8_t *stop_sequence, uint16_t stop_sequence_len, + 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, uint16_t refresh_display_command, 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 two_byte_sequence_length); + 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 common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t *self); diff --git a/shared-bindings/displayio/Palette.c b/shared-bindings/displayio/Palette.c index aa24dc262f..50deff5748 100644 --- a/shared-bindings/displayio/Palette.c +++ b/shared-bindings/displayio/Palette.c @@ -40,29 +40,54 @@ //| """Map a pixel palette_index to a full color. Colors are transformed to the display's format internally to //| save memory.""" //| -//| def __init__(self, color_count: int) -> None: +//| def __init__(self, color_count: int, *, dither: bool = False) -> None: //| """Create a Palette object to store a set number of colors. //| -//| :param int color_count: The number of colors in the Palette""" +//| :param int color_count: The number of colors in the Palette +//| :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. //| STATIC mp_obj_t displayio_palette_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_color_count }; + enum { ARG_color_count, ARG_dither }; static const mp_arg_t allowed_args[] = { { MP_QSTR_color_count, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_dither, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.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); displayio_palette_t *self = m_new_obj(displayio_palette_t); self->base.type = &displayio_palette_type; - common_hal_displayio_palette_construct(self, args[ARG_color_count].u_int); + common_hal_displayio_palette_construct(self, args[ARG_color_count].u_int, args[ARG_dither].u_bool); return MP_OBJ_FROM_PTR(self); } +//| 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)); +} +MP_DEFINE_CONST_FUN_OBJ_1(displayio_palette_get_dither_obj, displayio_palette_obj_get_dither); + +STATIC mp_obj_t displayio_palette_obj_set_dither(mp_obj_t self_in, mp_obj_t dither) { + displayio_palette_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_displayio_palette_set_dither(self, mp_obj_is_true(dither)); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(displayio_palette_set_dither_obj, displayio_palette_obj_set_dither); + +MP_PROPERTY_GETSET(displayio_palette_dither_obj, + (mp_obj_t)&displayio_palette_get_dither_obj, + (mp_obj_t)&displayio_palette_set_dither_obj); + //| def __bool__(self) -> bool: ... //| def __len__(self) -> int: //| """Returns the number of colors in a Palette""" @@ -185,6 +210,7 @@ STATIC mp_obj_t displayio_palette_obj_is_transparent(mp_obj_t self_in, mp_obj_t MP_DEFINE_CONST_FUN_OBJ_2(displayio_palette_is_transparent_obj, displayio_palette_obj_is_transparent); STATIC const mp_rom_map_elem_t displayio_palette_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&displayio_palette_dither_obj) }, { MP_ROM_QSTR(MP_QSTR_make_transparent), MP_ROM_PTR(&displayio_palette_make_transparent_obj) }, { MP_ROM_QSTR(MP_QSTR_make_opaque), MP_ROM_PTR(&displayio_palette_make_opaque_obj) }, { MP_ROM_QSTR(MP_QSTR_is_transparent), MP_ROM_PTR(&displayio_palette_is_transparent_obj) }, diff --git a/shared-bindings/displayio/Palette.h b/shared-bindings/displayio/Palette.h index d9a798016c..2cc7417fe3 100644 --- a/shared-bindings/displayio/Palette.h +++ b/shared-bindings/displayio/Palette.h @@ -31,11 +31,14 @@ extern const mp_obj_type_t displayio_palette_type; -void common_hal_displayio_palette_construct(displayio_palette_t *self, uint16_t color_count); +void common_hal_displayio_palette_construct(displayio_palette_t *self, uint16_t color_count, bool dither); void common_hal_displayio_palette_set_color(displayio_palette_t *self, uint32_t palette_index, uint32_t color); uint32_t common_hal_displayio_palette_get_color(displayio_palette_t *self, uint32_t palette_index); uint32_t common_hal_displayio_palette_get_len(displayio_palette_t *self); +void common_hal_displayio_palette_set_dither(displayio_palette_t *self, bool dither); +bool common_hal_displayio_palette_get_dither(displayio_palette_t *self); + void common_hal_displayio_palette_make_opaque(displayio_palette_t *self, uint32_t palette_index); void common_hal_displayio_palette_make_transparent(displayio_palette_t *self, uint32_t palette_index); bool common_hal_displayio_palette_is_transparent(displayio_palette_t *self, uint32_t palette_index); diff --git a/shared-bindings/gifio/OnDiskGif.c b/shared-bindings/gifio/OnDiskGif.c new file mode 100644 index 0000000000..7fb3fcf2bd --- /dev/null +++ b/shared-bindings/gifio/OnDiskGif.c @@ -0,0 +1,247 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Mark Komus + * + * 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/gifio/OnDiskGif.h" + +#include + +#include "py/runtime.h" +#include "py/objproperty.h" +#include "supervisor/shared/translate/translate.h" +#include "shared-bindings/gifio/OnDiskGif.h" + +//| class OnDiskGif: +//| """Loads one frame of a GIF into memory at a time. +//| +//| The code can be used in cooperation with displayio but this mode is relatively slow: +//| +//| .. code-block:: Python +//| +//| import board +//| import gifio +//| import displayio +//| import time +//| +//| display = board.DISPLAY +//| splash = displayio.Group() +//| display.root_group = splash +//| +//| odg = gifio.OnDiskGif('/sample.gif') +//| +//| start = time.monotonic() +//| odg.next_frame() # Load the first frame +//| end = time.monotonic() +//| overhead = end - start +//| +//| face = displayio.TileGrid( +//| odg.bitmap, +//| pixel_shader=displayio.ColorConverter( +//| input_colorspace=displayio.Colorspace.RGB565_SWAPPED +//| ), +//| ) +//| splash.append(face) +//| board.DISPLAY.refresh() +//| +//| # Display repeatedly. +//| while True: +//| # Sleep for the frame delay specified by the GIF, +//| # minus the overhead measured to advance between frames. +//| time.sleep(max(0, next_delay - overhead)) +//| next_delay = odg.next_frame() +//| +//| The displayio Group and TileGrid layers can be bypassed and the image can +//| be directly blitted to the full screen. This can give a speed-up of ~4x to +//| ~6x depending on the GIF and display. This requires an LCD that uses +//| standard codes to set the update area, and which accepts RGB565_SWAPPED +//| pixel data directly: +//| +//| .. code-block:: Python +//| +//| # Initial set-up the same as above +//| +//| # Take over display to drive directly +//| display.auto_refresh = False +//| display_bus = display.bus +//| +//| # Display repeatedly & directly. +//| while True: +//| # Sleep for the frame delay specified by the GIF, +//| # minus the overhead measured to advance between frames. +//| time.sleep(max(0, next_delay - overhead)) +//| next_delay = odg.next_frame() +//| +//| display_bus.send(42, struct.pack(">hh", 0, odg.bitmap.width - 1)) +//| display_bus.send(43, struct.pack(">hh", 0, odg.bitmap.height - 1)) +//| display_bus.send(44, d.bitmap) +//| """ +//| +//| def __init__(self, file: str) -> None: +//| """Create an `OnDiskGif` object with the given file. +//| The GIF frames are decoded into RGB565 big-endian format. +//| `displayio` expects little-endian, so the example above uses `Colorspace.RGB565_SWAPPED`. +//| +//| :param file file: The name of the GIF file. +//| """ +//| ... +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) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + mp_obj_t arg = all_args[0]; + + if (mp_obj_is_str(arg)) { + arg = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), arg, MP_ROM_QSTR(MP_QSTR_rb)); + } + + if (!mp_obj_is_type(arg, &mp_type_fileio)) { + mp_raise_TypeError(translate("file must be a file opened in byte mode")); + } + + gifio_ondiskgif_t *self = m_new_obj(gifio_ondiskgif_t); + self->base.type = &gifio_ondiskgif_type; + common_hal_gifio_ondiskgif_construct(self, MP_OBJ_TO_PTR(arg)); + + return MP_OBJ_FROM_PTR(self); +} + +//| width: int +//| """Width of the gif. (read only)""" +STATIC mp_obj_t gifio_ondiskgif_obj_get_width(mp_obj_t self_in) { + gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); + + return MP_OBJ_NEW_SMALL_INT(common_hal_gifio_ondiskgif_get_width(self)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_width_obj, gifio_ondiskgif_obj_get_width); + +MP_PROPERTY_GETTER(gifio_ondiskgif_width_obj, + (mp_obj_t)&gifio_ondiskgif_get_width_obj); + +//| height: int +//| """Height of the gif. (read only)""" +STATIC mp_obj_t gifio_ondiskgif_obj_get_height(mp_obj_t self_in) { + gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); + + return MP_OBJ_NEW_SMALL_INT(common_hal_gifio_ondiskgif_get_height(self)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_height_obj, gifio_ondiskgif_obj_get_height); + +MP_PROPERTY_GETTER(gifio_ondiskgif_height_obj, + (mp_obj_t)&gifio_ondiskgif_get_height_obj); + +//| bitmap: displayio.Bitmap +//| """The bitmap used to hold the current frame.""" +STATIC mp_obj_t gifio_ondiskgif_obj_get_bitmap(mp_obj_t self_in) { + gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_gifio_ondiskgif_get_bitmap(self); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_bitmap_obj, gifio_ondiskgif_obj_get_bitmap); + +MP_PROPERTY_GETTER(gifio_ondiskgif_bitmap_obj, + (mp_obj_t)&gifio_ondiskgif_get_bitmap_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); + + return mp_obj_new_float((float)common_hal_gifio_ondiskgif_next_frame(self, true) / 1000); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_next_frame_obj, gifio_ondiskgif_obj_next_frame); + + +//| duration: float +//| """Returns the total duration of the GIF in seconds. (read only)""" +STATIC mp_obj_t gifio_ondiskgif_obj_get_duration(mp_obj_t self_in) { + gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_float((float)common_hal_gifio_ondiskgif_get_duration(self) / 1000); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_duration_obj, gifio_ondiskgif_obj_get_duration); + +MP_PROPERTY_GETTER(gifio_ondiskgif_duration_obj, + (mp_obj_t)&gifio_ondiskgif_get_duration_obj); + +//| frame_count: int +//| """Returns the number of frames in the GIF. (read only)""" +STATIC mp_obj_t gifio_ondiskgif_obj_get_frame_count(mp_obj_t self_in) { + gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); + + return MP_OBJ_NEW_SMALL_INT(common_hal_gifio_ondiskgif_get_frame_count(self)); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_frame_count_obj, gifio_ondiskgif_obj_get_frame_count); + +MP_PROPERTY_GETTER(gifio_ondiskgif_frame_count_obj, + (mp_obj_t)&gifio_ondiskgif_get_frame_count_obj); + +//| min_delay: float +//| """The minimum delay found between frames. (read only)""" +STATIC mp_obj_t gifio_ondiskgif_obj_get_min_delay(mp_obj_t self_in) { + gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_float((float)common_hal_gifio_ondiskgif_get_min_delay(self) / 1000); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_min_delay_obj, gifio_ondiskgif_obj_get_min_delay); + +MP_PROPERTY_GETTER(gifio_ondiskgif_min_delay_obj, + (mp_obj_t)&gifio_ondiskgif_get_min_delay_obj); + +//| max_delay: float +//| """The maximum delay found between frames. (read only)""" +//| +STATIC mp_obj_t gifio_ondiskgif_obj_get_max_delay(mp_obj_t self_in) { + gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_float((float)common_hal_gifio_ondiskgif_get_max_delay(self) / 1000); +} + +MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_max_delay_obj, gifio_ondiskgif_obj_get_max_delay); + +MP_PROPERTY_GETTER(gifio_ondiskgif_max_delay_obj, + (mp_obj_t)&gifio_ondiskgif_get_max_delay_obj); + +STATIC const mp_rom_map_elem_t gifio_ondiskgif_locals_dict_table[] = { + { 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_width), MP_ROM_PTR(&gifio_ondiskgif_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_next_frame), MP_ROM_PTR(&gifio_ondiskgif_next_frame_obj) }, + { MP_ROM_QSTR(MP_QSTR_duration), MP_ROM_PTR(&gifio_ondiskgif_duration_obj) }, + { MP_ROM_QSTR(MP_QSTR_frame_count), MP_ROM_PTR(&gifio_ondiskgif_frame_count_obj) }, + { MP_ROM_QSTR(MP_QSTR_min_delay), MP_ROM_PTR(&gifio_ondiskgif_min_delay_obj) }, + { MP_ROM_QSTR(MP_QSTR_max_delay), MP_ROM_PTR(&gifio_ondiskgif_max_delay_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(gifio_ondiskgif_locals_dict, gifio_ondiskgif_locals_dict_table); + +const mp_obj_type_t gifio_ondiskgif_type = { + { &mp_type_type }, + .name = MP_QSTR_OnDiskGif, + .make_new = gifio_ondiskgif_make_new, + .locals_dict = (mp_obj_dict_t *)&gifio_ondiskgif_locals_dict, +}; diff --git a/shared-bindings/gifio/OnDiskGif.h b/shared-bindings/gifio/OnDiskGif.h new file mode 100644 index 0000000000..4ecbfca495 --- /dev/null +++ b/shared-bindings/gifio/OnDiskGif.h @@ -0,0 +1,48 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Mark Komus + * + * 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_BINDINGS_DISPLAYIO_ONDISKGIF_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_ONDISKGIF_H + +#include "shared-module/gifio/OnDiskGif.h" +#include "extmod/vfs_fat.h" + +extern const mp_obj_type_t gifio_ondiskgif_type; + +void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_t *file); + +uint32_t common_hal_gifio_ondiskgif_get_pixel(gifio_ondiskgif_t *bitmap, + int16_t x, int16_t y); + +uint16_t common_hal_gifio_ondiskgif_get_height(gifio_ondiskgif_t *self); +mp_obj_t common_hal_gifio_ondiskgif_get_bitmap(gifio_ondiskgif_t *self); +uint16_t common_hal_gifio_ondiskgif_get_width(gifio_ondiskgif_t *self); +uint32_t common_hal_gifio_ondiskgif_next_frame(gifio_ondiskgif_t *self, bool setDirty); +int32_t common_hal_gifio_ondiskgif_get_duration(gifio_ondiskgif_t *self); +int32_t common_hal_gifio_ondiskgif_get_frame_count(gifio_ondiskgif_t *self); +int32_t common_hal_gifio_ondiskgif_get_min_delay(gifio_ondiskgif_t *self); +int32_t common_hal_gifio_ondiskgif_get_max_delay(gifio_ondiskgif_t *self); +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_ONDISKGIF_H diff --git a/shared-bindings/gifio/__init__.c b/shared-bindings/gifio/__init__.c index 6bd5765966..bfc87f0d99 100644 --- a/shared-bindings/gifio/__init__.c +++ b/shared-bindings/gifio/__init__.c @@ -27,6 +27,7 @@ #include "py/runtime.h" #include "py/mphal.h" #include "shared-bindings/gifio/GifWriter.h" +#include "shared-bindings/gifio/OnDiskGif.h" #include "shared-bindings/util.h" //| """Access GIF-format images @@ -34,6 +35,7 @@ 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_OnDiskGif), MP_ROM_PTR(&gifio_ondiskgif_type) }, }; STATIC MP_DEFINE_CONST_DICT(gifio_module_globals, gifio_module_globals_table); diff --git a/shared-bindings/pwmio/PWMOut.c b/shared-bindings/pwmio/PWMOut.c index 1fd69272da..24c0097c0c 100644 --- a/shared-bindings/pwmio/PWMOut.c +++ b/shared-bindings/pwmio/PWMOut.c @@ -69,7 +69,27 @@ void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) { } //| class PWMOut: -//| """Output a Pulse Width Modulated signal on a given pin.""" +//| """Output a Pulse Width Modulated signal on a given pin. +//| +//| .. note:: The exact frequencies possible depend on the specific microcontroller. +//| If the requested frequency is within the available range, one of the two +//| nearest possible frequencies to the requested one is selected. +//| +//| If the requested frequency is outside the range, either (A) a ValueError +//| may be raised or (B) the highest or lowest frequency is selected. This +//| behavior is microcontroller-dependent, and may depend on whether it's the +//| upper or lower bound that is exceeded. +//| +//| In any case, the actual frequency (rounded to 1Hz) is available in the +//| ``frequency`` property after construction. +//| +//| .. note:: The frequency is calculated based on a nominal CPU frequency. +//| However, depending on the board, the error between the nominal and +//| actual CPU frequency can be large (several hundred PPM in the case of +//| crystal oscillators and up to ten percent in the case of RC +//| oscillators) +//| +//| """ //| //| def __init__( //| self, @@ -134,7 +154,9 @@ void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) { //| pwm = pwmio.PWMOut(board.D13, duty_cycle=2 ** 15, frequency=440, variable_frequency=True) //| time.sleep(0.2) //| pwm.frequency = 880 -//| time.sleep(0.1)""" +//| time.sleep(0.1) +//| +//| """ //| ... 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 }; @@ -234,7 +256,8 @@ MP_PROPERTY_GETSET(pwmio_pwmout_duty_cycle_obj, //| for the PWM's duty cycle may need to be recalculated when the frequency //| changes. In these cases, the duty cycle is automatically recalculated //| from the original duty cycle value. This should happen without any need -//| to manually re-set the duty cycle.""" +//| 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); diff --git a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c index b0f68333e6..d9643495ba 100644 --- a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c @@ -33,14 +33,42 @@ #include "shared-module/displayio/__init__.h" #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" +//| class SharpMemoryFramebuffer: +//| """A framebuffer for a memory-in-pixel display. Sharp makes monochrome displays and JDI used +//| to make 8-color displays. +//| +//| This initializes a display and connects it into CircuitPython. Unlike other +//| objects in CircuitPython, Display objects live until `displayio.release_displays()` +//| is called. This is done so that CircuitPython can use the display itself.""" +//| +//| def __init__( +//| self, +//| spi_bus: busio.SPI, +//| chip_select: microcontroller.Pin, +//| width: int, +//| height: int, +//| baudrate: int = 2000000, +//| jdi_display: bool = False, +//| ) -> None: +//| """Create a framebuffer for the memory-in-pixel display. +//| +//| :param busio.SPI spi_bus: The SPI bus that the display is connected to +//| :param microcontroller.Pin chip_select: The pin connect to the display's chip select line +//| :param int width: The width of the display in pixels +//| :param int height: The height of the display in pixels +//| :param int baudrate: The baudrate to communicate with the screen at +//| :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, NUM_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[] = { { MP_QSTR_spi_bus, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_chip_select, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} }, { MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 2000000} }, + { MP_QSTR_jdi_display, MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; MP_STATIC_ASSERT(MP_ARRAY_SIZE(allowed_args) == NUM_ARGS); @@ -53,7 +81,7 @@ STATIC mp_obj_t sharpdisplay_framebuffer_make_new(const mp_obj_type_t *type, siz sharpdisplay_framebuffer_obj_t *self = &allocate_display_bus_or_raise()->sharpdisplay; self->base.type = &sharpdisplay_framebuffer_type; - common_hal_sharpdisplay_framebuffer_construct(self, spi, chip_select, args[ARG_baudrate].u_int, args[ARG_width].u_int, args[ARG_height].u_int); + common_hal_sharpdisplay_framebuffer_construct(self, spi, chip_select, args[ARG_baudrate].u_int, args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_jdi_display].u_bool); return MP_OBJ_FROM_PTR(self); } @@ -69,6 +97,12 @@ STATIC mp_int_t sharpdisplay_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer_ return 0; } +//| def deinit(self) -> None: +//| """Free the resources (pins, timers, etc.) associated with this +//| SharpMemoryFramebuffer instance. After deinitialization, no further operations +//| 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/sharpdisplay/SharpMemoryFramebuffer.h b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h index 30f1b867b1..b2c15ac499 100644 --- a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h +++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.h @@ -26,9 +26,18 @@ #pragma once -// #include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" -// #include "shared-module/framebufferio/FramebufferDisplay.h" - #include "py/objtype.h" +#include "shared-module/sharpdisplay/SharpMemoryFramebuffer.h" + extern const mp_obj_type_t sharpdisplay_framebuffer_type; + +void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *chip_select, int baudrate, int width, int height, bool jdi_display); +void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask); +void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self); +void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo); +int common_hal_sharpdisplay_framebuffer_get_height(sharpdisplay_framebuffer_obj_t *self); +int common_hal_sharpdisplay_framebuffer_get_width(sharpdisplay_framebuffer_obj_t *self); +void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask); +void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self); +void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self); diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index dbf5a9ef96..6818316768 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -384,37 +384,11 @@ void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination, } -void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, +STATIC void draw_line(displayio_bitmap_t *destination, int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint32_t value) { - // - // adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line - // - - // update the dirty rectangle - int16_t xbb0, xbb1, ybb0, ybb1; - if (x0 < x1) { - xbb0 = x0; - xbb1 = x1 + 1; - } else { - xbb0 = x1; - xbb1 = x0 + 1; - } - if (y0 < y1) { - ybb0 = y0; - ybb1 = y1 + 1; - } else { - ybb0 = y1; - ybb1 = y0 + 1; - } - displayio_area_t area = { xbb0, ybb0, xbb1, ybb1, NULL }; - displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL }; - displayio_area_compute_overlap(&area, &bitmap_area, &area); - - displayio_bitmap_set_dirty_area(destination, &area); - int16_t temp, x, y; if (x0 == x1) { // vertical line @@ -488,6 +462,84 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, } } +void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, + int16_t x0, int16_t y0, + int16_t x1, int16_t y1, + uint32_t value) { + + // + // adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line + // + + // update the dirty rectangle + int16_t xbb0, xbb1, ybb0, ybb1; + if (x0 < x1) { + xbb0 = x0; + xbb1 = x1 + 1; + } else { + xbb0 = x1; + xbb1 = x0 + 1; + } + if (y0 < y1) { + ybb0 = y0; + ybb1 = y1 + 1; + } else { + ybb0 = y1; + ybb1 = y0 + 1; + } + displayio_area_t area = { xbb0, ybb0, xbb1, ybb1, NULL }; + displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL }; + displayio_area_compute_overlap(&area, &bitmap_area, &area); + + displayio_bitmap_set_dirty_area(destination, &area); + + draw_line(destination, x0, y0, x1, y1, value); +} + +STATIC int32_t ith(void *data, size_t i, int element_size) { + switch (element_size) { + default: + case 1: + return *((int8_t *)data + i); + case 2: + return *((int16_t *)data + i); + case 4: + return *((int32_t *)data + i); + } +} + +void common_hal_bitmaptools_draw_polygon(displayio_bitmap_t *destination, void *xs, void *ys, size_t points_len, int point_size, uint32_t value, bool close) { + int16_t x0, y0, xmin, xmax, ymin, ymax, xprev, yprev, x, y; + x0 = ith(xs, 0, point_size); + xmin = x0; + xmax = x0; + xprev = x0; + y0 = ith(ys, 0, point_size); + ymin = y0; + ymax = y0; + yprev = y0; + + for (size_t i = 1; i < points_len; i++) { + x = ith(xs, i, point_size); + y = ith(ys, i, point_size); + draw_line(destination, xprev, yprev, x, y, value); + xprev = x; + yprev = y; + xmin = MIN(xmin, x); + xmax = MAX(xmax, x); + ymin = MIN(ymin, y); + ymax = MAX(ymax, y); + } + if (close) { + draw_line(destination, xprev, yprev, x0, y0, value); + } + + displayio_area_t area = { xmin, ymin, xmax, ymax, NULL }; + displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL }; + displayio_area_compute_overlap(&area, &bitmap_area, &area); + displayio_bitmap_set_dirty_area(destination, &area); +} + void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_value) { uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1; diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c index 707601a3e7..7064569e2d 100644 --- a/shared-module/displayio/ColorConverter.c +++ b/shared-module/displayio/ColorConverter.c @@ -45,6 +45,7 @@ void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *s self->dither = dither; self->transparent_color = NO_TRANSPARENT_COLOR; self->input_colorspace = input_colorspace; + self->output_colorspace.depth = 16; } uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888) { @@ -54,6 +55,13 @@ uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888) { return r5 << 11 | g6 << 5 | b5; } +uint8_t displayio_colorconverter_compute_rgbd(uint32_t color_rgb888) { + uint32_t r1 = (color_rgb888 >> 23) & 0x1; + uint32_t g1 = (color_rgb888 >> 15) & 0x1; + uint32_t b1 = (color_rgb888 >> 7) & 0x1; + return r1 << 3 | g1 << 2 | b1 << 1 /* | dummy */; +} + uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888) { uint32_t r8 = (color_rgb888 >> 16); uint32_t g8 = (color_rgb888 >> 8) & 0xff; @@ -96,6 +104,44 @@ uint8_t displayio_colorconverter_compute_hue(uint32_t color_rgb888) { return hue; } +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); + if (chroma >= 64) { + uint8_t hue = displayio_colorconverter_compute_hue(color_rgb888); + // Red 0 + if (hue < 10) { + return 0x4; + } + // Orange 21 + if (hue < 21 + 10) { + return 0x6; + } + // Yellow 42 + if (hue < 42 + 21) { + return 0x5; + } + // Green 85 + if (hue < 85 + 42) { + return 0x2; + } + // Blue 170 + if (hue < 170 + 42) { + return 0x3; + } + + // The rest is red to 255 + return 0x4; + } else { + uint8_t luma = displayio_colorconverter_compute_luma(color_rgb888); + if (luma >= 128) { + return 0x1; // White + } else { + return 0x0; // Black + } + } +} + void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_hue, uint32_t *color) { int16_t hue_diff = colorspace->tricolor_hue - pixel_hue; @@ -207,18 +253,9 @@ uint32_t displayio_colorconverter_convert_pixel(displayio_colorspace_t colorspac return pixel; } -void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t *colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) { +void displayio_convert_color(const _displayio_colorspace_t *colorspace, bool dither, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) { uint32_t pixel = input_pixel->pixel; - - if (self->transparent_color == pixel) { - output_color->opaque = false; - return; - } - - pixel = displayio_colorconverter_convert_pixel(self->input_colorspace, pixel); - - - if (self->dither) { + if (dither) { uint8_t randr = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y)); uint8_t randg = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x + 33,input_pixel->tile_y)); uint8_t randb = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y + 33)); @@ -272,10 +309,44 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d output_color->pixel = pixel; output_color->opaque = true; return; + } else if (colorspace->depth == 4) { + uint8_t packed; + if (colorspace->sevencolor) { + packed = displayio_colorconverter_compute_sevencolor(pixel); + } else { + packed = displayio_colorconverter_compute_rgbd(pixel); + } + output_color->pixel = packed; + output_color->opaque = true; + return; } output_color->opaque = false; } +void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t *colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) { + uint32_t pixel = input_pixel->pixel; + + if (self->transparent_color == pixel) { + output_color->opaque = false; + return; + } + + if (!self->dither && self->cached_colorspace == colorspace && self->cached_input_pixel == input_pixel->pixel) { + output_color->pixel = self->cached_output_color; + return; + } + + displayio_input_pixel_t rgb888_pixel = *input_pixel; + rgb888_pixel.pixel = displayio_colorconverter_convert_pixel(self->input_colorspace, input_pixel->pixel); + displayio_convert_color(colorspace, self->dither, &rgb888_pixel, output_color); + + if (!self->dither) { + self->cached_colorspace = colorspace; + self->cached_input_pixel = input_pixel->pixel; + self->cached_output_color = output_color->pixel; + } +} + // Currently no refresh logic is needed for a ColorConverter. diff --git a/shared-module/displayio/ColorConverter.h b/shared-module/displayio/ColorConverter.h index 7e4e9819ac..c1e46035ca 100644 --- a/shared-module/displayio/ColorConverter.h +++ b/shared-module/displayio/ColorConverter.h @@ -37,7 +37,13 @@ typedef struct displayio_colorconverter { mp_obj_base_t base; bool dither; uint8_t input_colorspace; + _displayio_colorspace_t output_colorspace; uint32_t transparent_color; + + // Cache the last computed color in case the are the same. + const _displayio_colorspace_t *cached_colorspace; + uint32_t cached_input_pixel; + uint32_t cached_output_color; } displayio_colorconverter_t; bool displayio_colorconverter_needs_refresh(displayio_colorconverter_t *self); @@ -47,10 +53,15 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d uint32_t displayio_colorconverter_dither_noise_1(uint32_t n); uint32_t displayio_colorconverter_dither_noise_2(uint32_t x, uint32_t y); +// Convert version that doesn't require a colorconverter object. +void displayio_convert_color(const _displayio_colorspace_t *colorspace, bool dither, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color); + uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888); +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_sevencolor(uint32_t color_rgb888); void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_hue, uint32_t *color); #endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_COLORCONVERTER_H diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c index 8367e23b59..5af97a4144 100644 --- a/shared-module/displayio/Display.c +++ b/shared-module/displayio/Display.c @@ -423,7 +423,6 @@ void release_display(displayio_display_obj_t *self) { release_display_core(&self->core); #if (CIRCUITPY_PWMIO) if (self->backlight_pwm.base.type == &pwmio_pwmout_type) { - common_hal_pwmio_pwmout_reset_ok(&self->backlight_pwm); common_hal_pwmio_pwmout_deinit(&self->backlight_pwm); } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) { common_hal_digitalio_digitalinout_deinit(&self->backlight_inout); diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index d876599650..289fc47a68 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -28,6 +28,7 @@ #include "py/gc.h" #include "py/runtime.h" +#include "shared/runtime/interrupt_char.h" #include "shared-bindings/displayio/ColorConverter.h" #include "shared-bindings/displayio/FourWire.h" #include "shared-bindings/displayio/I2CDisplay.h" @@ -47,21 +48,31 @@ #define DELAY 0x80 void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t *self, - mp_obj_t bus, const uint8_t *start_sequence, uint16_t start_sequence_len, + 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, uint16_t refresh_display_command, 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 two_byte_sequence_length) { + 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) { + uint16_t color_depth = 1; if (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); } + if (acep) { + self->core.colorspace.sevencolor = true; + color_depth = 4; // bits. 7 colors + clean + self->acep = acep; + grayscale = false; + } - displayio_display_core_construct(&self->core, bus, width, height, ram_width, ram_height, colstart, rowstart, rotation, 1, true, true, 1, true, true); + displayio_display_core_construct(&self->core, bus, width, height, ram_width, ram_height, colstart, rowstart, rotation, color_depth, grayscale, true, 1, true, true); self->set_column_window_command = set_column_window_command; self->set_row_window_command = set_row_window_command; @@ -71,7 +82,6 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t 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_display_command = refresh_display_command; self->refresh_time = refresh_time * 1000; self->busy_state = busy_state; self->refreshing = false; @@ -81,8 +91,11 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t 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->busy.base.type = &mp_type_NoneType; self->two_byte_sequence_length = two_byte_sequence_length; @@ -193,6 +206,8 @@ STATIC void displayio_epaperdisplay_start_refresh(displayio_epaperdisplay_obj_t // run start sequence self->core.bus_reset(self->core.bus); + common_hal_time_delay_ms(self->start_up_time_ms); + send_command_sequence(self, true, self->start_sequence, self->start_sequence_len); displayio_display_core_start_refresh(&self->core); } @@ -211,9 +226,8 @@ uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaper STATIC void displayio_epaperdisplay_finish_refresh(displayio_epaperdisplay_obj_t *self) { // Actually refresh the display now that all pixel RAM has been updated. - displayio_display_core_begin_transaction(&self->core); - self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, &self->refresh_display_command, 1); - displayio_display_core_end_transaction(&self->core); + send_command_sequence(self, false, self->refresh_sequence, self->refresh_sequence_len); + supervisor_enable_tick(); self->refreshing = true; @@ -326,8 +340,10 @@ STATIC bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t * memset(mask, 0, mask_length * sizeof(mask[0])); memset(buffer, 0, buffer_size * sizeof(buffer[0])); - self->core.colorspace.grayscale = true; - self->core.colorspace.grayscale_bit = 7; + if (self->grayscale) { + self->core.colorspace.grayscale = true; + self->core.colorspace.grayscale_bit = 7; + } if (pass == 1) { if (self->grayscale) { // 4-color grayscale self->core.colorspace.grayscale_bit = 6; @@ -335,6 +351,8 @@ STATIC bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t * } 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) { + displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); } } else { displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); @@ -366,6 +384,36 @@ STATIC bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t * return true; } +STATIC bool _clean_area(displayio_epaperdisplay_obj_t *self) { + uint16_t width = displayio_display_core_get_width(&self->core); + uint16_t height = displayio_display_core_get_height(&self->core); + + uint8_t buffer[width / 2]; + memset(buffer, 0x77, width / 2); + + uint8_t write_command = self->write_black_ram_command; + displayio_display_core_begin_transaction(&self->core); + self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1); + displayio_display_core_end_transaction(&self->core); + + for (uint16_t j = 0; j < height; j++) { + if (!displayio_display_core_begin_transaction(&self->core)) { + // Can't acquire display bus; skip the rest of the data. Try next display. + return false; + } + self->core.send(self->core.bus, DISPLAY_DATA, self->chip_select, buffer, width / 2); + displayio_display_core_end_transaction(&self->core); + + // TODO(tannewt): Make refresh displays faster so we don't starve other + // background tasks. + #if CIRCUITPY_USB + usb_background(); + #endif + } + + return true; +} + bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t *self) { if (self->refreshing && self->busy.base.type == &digitalio_digitalinout_type) { @@ -393,6 +441,18 @@ bool common_hal_displayio_epaperdisplay_refresh(displayio_epaperdisplay_obj_t *s if (current_area == NULL) { return true; } + if (self->acep) { + displayio_epaperdisplay_start_refresh(self); + _clean_area(self); + displayio_epaperdisplay_finish_refresh(self); + while (self->refreshing && !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + } + } + if (mp_hal_is_interrupted()) { + return false; + } + displayio_epaperdisplay_start_refresh(self); while (current_area != NULL) { displayio_epaperdisplay_refresh_area(self, current_area); diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h index 55feaf964b..f2398398ea 100644 --- a/shared-module/displayio/EPaperDisplay.h +++ b/shared-module/displayio/EPaperDisplay.h @@ -39,9 +39,12 @@ typedef struct { digitalio_digitalinout_obj_t busy; uint32_t milliseconds_per_frame; const uint8_t *start_sequence; - uint32_t start_sequence_len; const uint8_t *stop_sequence; - uint32_t stop_sequence_len; + const uint8_t *refresh_sequence; + uint16_t start_sequence_len; + uint16_t stop_sequence_len; + uint16_t refresh_sequence_len; + uint16_t start_up_time_ms; uint16_t refresh_time; uint16_t set_column_window_command; uint16_t set_row_window_command; @@ -49,15 +52,15 @@ typedef struct { uint16_t set_current_row_command; uint16_t write_black_ram_command; uint16_t write_color_ram_command; - uint8_t refresh_display_command; uint8_t hue; bool busy_state; bool black_bits_inverted; bool color_bits_inverted; bool refreshing; bool grayscale; - display_chip_select_behavior_t chip_select; + bool acep; bool two_byte_sequence_length; + display_chip_select_behavior_t chip_select; } displayio_epaperdisplay_obj_t; void displayio_epaperdisplay_change_refresh_mode_parameters(displayio_epaperdisplay_obj_t *self, diff --git a/shared-module/displayio/OnDiskBitmap.c b/shared-module/displayio/OnDiskBitmap.c index 2863dffb19..c9a9d7d9f2 100644 --- a/shared-module/displayio/OnDiskBitmap.c +++ b/shared-module/displayio/OnDiskBitmap.c @@ -90,7 +90,7 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, displayio_palette_t *palette = m_new_obj(displayio_palette_t); palette->base.type = &displayio_palette_type; - common_hal_displayio_palette_construct(palette, number_of_colors); + common_hal_displayio_palette_construct(palette, number_of_colors, false); if (number_of_colors > 1) { uint16_t palette_size = number_of_colors * sizeof(uint32_t); diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c index 1bd168b354..a2ddc285fd 100644 --- a/shared-module/displayio/Palette.c +++ b/shared-module/displayio/Palette.c @@ -28,9 +28,18 @@ #include "shared-module/displayio/ColorConverter.h" -void common_hal_displayio_palette_construct(displayio_palette_t *self, uint16_t color_count) { +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), false); + self->dither = dither; +} + +void common_hal_displayio_palette_set_dither(displayio_palette_t *self, bool dither) { + self->dither = dither; +} + +bool common_hal_displayio_palette_get_dither(displayio_palette_t *self) { + return self->dither; } void common_hal_displayio_palette_make_opaque(displayio_palette_t *self, uint32_t palette_index) { @@ -56,12 +65,7 @@ void common_hal_displayio_palette_set_color(displayio_palette_t *self, uint32_t return; } self->colors[palette_index].rgb888 = color; - self->colors[palette_index].luma = displayio_colorconverter_compute_luma(color); - self->colors[palette_index].rgb565 = displayio_colorconverter_compute_rgb565(color); - - uint8_t chroma = displayio_colorconverter_compute_chroma(color); - self->colors[palette_index].chroma = chroma; - self->colors[palette_index].hue = displayio_colorconverter_compute_hue(color); + self->colors[palette_index].cached_colorspace = NULL; self->needs_refresh = true; } @@ -69,40 +73,26 @@ uint32_t common_hal_displayio_palette_get_color(displayio_palette_t *self, uint3 return self->colors[palette_index].rgb888; } -bool displayio_palette_get_color(displayio_palette_t *self, const _displayio_colorspace_t *colorspace, uint32_t palette_index, uint32_t *color) { +void displayio_palette_get_color(displayio_palette_t *self, const _displayio_colorspace_t *colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color) { + uint32_t palette_index = input_pixel->pixel; if (palette_index > self->color_count || self->colors[palette_index].transparent) { - return false; // returns transparent + output_color->opaque = false; + return; } - if (colorspace->tricolor) { - uint8_t luma = self->colors[palette_index].luma; - *color = luma >> (8 - colorspace->depth); - // Chroma 0 means the color is a gray and has no hue so never color based on it. - if (self->colors[palette_index].chroma <= 16) { - if (!colorspace->grayscale) { - *color = 0; - } - return true; - } - uint8_t pixel_hue = self->colors[palette_index].hue; - displayio_colorconverter_compute_tricolor(colorspace, pixel_hue, color); - } else if (colorspace->grayscale) { - size_t bitmask = (1 << colorspace->depth) - 1; - *color = (self->colors[palette_index].luma >> colorspace->grayscale_bit) & bitmask; - } else if (colorspace->depth == 16) { - uint16_t packed = self->colors[palette_index].rgb565; - if (colorspace->reverse_bytes_in_word) { - // swap bytes - packed = __builtin_bswap16(packed); - } - *color = packed; - } else if (colorspace->depth == 32) { - *color = self->colors[palette_index].rgb888; - } else { - return false; + // Cache results when not dithering. + if (!self->dither && self->colors[palette_index].cached_colorspace == colorspace) { + output_color->pixel = self->colors[palette_index].cached_color; + return; } - return true; + displayio_input_pixel_t rgb888_pixel = *input_pixel; + rgb888_pixel.pixel = self->colors[palette_index].rgb888; + displayio_convert_color(colorspace, self->dither, &rgb888_pixel, output_color); + if (!self->dither) { + self->colors[palette_index].cached_colorspace = colorspace; + self->colors[palette_index].cached_color = output_color->pixel; + } } bool displayio_palette_needs_refresh(displayio_palette_t *self) { diff --git a/shared-module/displayio/Palette.h b/shared-module/displayio/Palette.h index 49f03b56c7..e9b449c4e7 100644 --- a/shared-module/displayio/Palette.h +++ b/shared-module/displayio/Palette.h @@ -40,6 +40,7 @@ typedef struct { uint8_t grayscale_bit; // The lowest grayscale bit. Normally 8 - depth. bool grayscale; bool tricolor; + bool sevencolor; // Acep e-ink screens. bool pixels_in_byte_share_row; bool reverse_pixels_in_byte; bool reverse_bytes_in_word; @@ -48,10 +49,8 @@ typedef struct { typedef struct { uint32_t rgb888; - uint16_t rgb565; - uint8_t luma; - uint8_t hue; - uint8_t chroma; + const _displayio_colorspace_t *cached_colorspace; + uint32_t cached_color; bool transparent; // This may have additional bits added later for blending. } _displayio_color_t; @@ -74,11 +73,12 @@ typedef struct displayio_palette { _displayio_color_t *colors; uint32_t color_count; bool needs_refresh; + bool dither; } displayio_palette_t; -// Returns false if color fetch did not succeed (out of range or transparent). -// Returns true if color is opaque, and sets color. -bool displayio_palette_get_color(displayio_palette_t *palette, const _displayio_colorspace_t *colorspace, uint32_t palette_index, uint32_t *color); + +void displayio_palette_get_color(displayio_palette_t *palette, const _displayio_colorspace_t *colorspace, const displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color); +; bool displayio_palette_needs_refresh(displayio_palette_t *self); void displayio_palette_finish_refresh(displayio_palette_t *self); diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c index 769c334ac6..e5573ac34c 100644 --- a/shared-module/displayio/TileGrid.c +++ b/shared-module/displayio/TileGrid.c @@ -507,7 +507,7 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, 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)) { - output_pixel.opaque = displayio_palette_get_color(self->pixel_shader, colorspace, input_pixel.pixel, &output_pixel.pixel); + displayio_palette_get_color(self->pixel_shader, colorspace, &input_pixel, &output_pixel); } else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) { displayio_colorconverter_convert(self->pixel_shader, colorspace, &input_pixel, &output_pixel); } diff --git a/shared-module/framebufferio/FramebufferDisplay.h b/shared-module/framebufferio/FramebufferDisplay.h index b53461aad5..47f31d794f 100644 --- a/shared-module/framebufferio/FramebufferDisplay.h +++ b/shared-module/framebufferio/FramebufferDisplay.h @@ -66,7 +66,7 @@ typedef bool (*framebuffer_set_brightness_fun)(mp_obj_t, mp_float_t); typedef int (*framebuffer_get_bytes_per_cell_fun)(mp_obj_t); typedef int (*framebuffer_get_color_depth_fun)(mp_obj_t); typedef int (*framebuffer_get_first_pixel_offset_fun)(mp_obj_t); -typedef int (*framebuffer_get_grayscale_fun)(mp_obj_t); +typedef bool (*framebuffer_get_grayscale_fun)(mp_obj_t); typedef int (*framebuffer_get_height_fun)(mp_obj_t); typedef int (*framebuffer_get_native_frames_per_second_fun)(mp_obj_t); typedef bool (*framebuffer_get_pixels_in_byte_share_row_fun)(mp_obj_t); diff --git a/shared-module/gifio/OnDiskGif.c b/shared-module/gifio/OnDiskGif.c new file mode 100644 index 0000000000..234b7f8198 --- /dev/null +++ b/shared-module/gifio/OnDiskGif.c @@ -0,0 +1,204 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Mark Komus + * + * 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/gifio/OnDiskGif.h" +#include "shared-bindings/displayio/Bitmap.h" + +#include + +#include "py/mperrno.h" +#include "py/runtime.h" + +static int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) { + // mp_printf(&mp_plat_print, "GifReadFile len %d ", iLen); + uint32_t iBytesRead; + iBytesRead = iLen; + pyb_file_obj_t *f = pFile->fHandle; + // Note: If you read a file all the way to the last byte, seek() stops working + if ((pFile->iSize - pFile->iPos) < iLen) { + iBytesRead = pFile->iSize - pFile->iPos - 1; // <-- ugly work-around + } + if (iBytesRead <= 0) { + return 0; + } + UINT bytes_read; + if (f_read(&f->fp, pBuf, iBytesRead, &bytes_read) != FR_OK) { + mp_raise_OSError(MP_EIO); + } + pFile->iPos = f->fp.fptr; + // mp_printf(&mp_plat_print, " now at %d\n", pFile->iPos); + + return bytes_read; +} /* GIFReadFile() */ + +static int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition) { + // mp_printf(&mp_plat_print, "GifSeekFile %d ", iPosition); + pyb_file_obj_t *f = pFile->fHandle; + + f_lseek(&f->fp, iPosition); + pFile->iPos = f->fp.fptr; + // mp_printf(&mp_plat_print, " now at %d\n", pFile->iPos); + return pFile->iPos; +} /* GIFSeekFile() */ + +static void GIFDraw(GIFDRAW *pDraw) { + // Called for every scan line of the image as it decodes + // The pixels delivered are the 8-bit native GIF output + // The palette is either RGB565 or the original 24-bit RGB values + // depending on the pixel type selected with gif.begin() + + displayio_bitmap_t *bitmap = (displayio_bitmap_t *)pDraw->pUser; + + uint8_t *s; + uint16_t *d; + + int iWidth = pDraw->iWidth; + if (iWidth + pDraw->iX > bitmap->width) { + iWidth = bitmap->width - pDraw->iX; + } + + if (pDraw->iY + pDraw->y >= bitmap->height || pDraw->iX >= bitmap->width || iWidth < 1) { + return; + } + + int32_t row_start = (pDraw->y + pDraw->iY) * bitmap->stride; + uint32_t *row = bitmap->data + row_start; + s = pDraw->pPixels; + d = (uint16_t *)row; + + uint16_t *pPal; + pPal = (uint16_t *)pDraw->pPalette; + + if (pDraw->ucDisposalMethod == 2) { // restore to background color + // Not supported currently. Need to reset the area the previous frame occupied + // to the background color before the previous frame was drawn + // See: https://github.com/bitbank2/AnimatedGIF/issues/3 + + // To workaround clear the gif.bitmap object yourself as required. + } + + uint8_t c, ucTransparent = pDraw->ucTransparent; + d += pDraw->iX; + if (pDraw->ucHasTransparency == 1) { + for (int x = 0; x < iWidth; x++) + { + c = *s++; + if (c != ucTransparent) { + *d = pPal[c]; + } + d++; + } + } else { + for (int x = 0; x < iWidth; x++) + { + c = *s++; + *d++ = pPal[c]; + } + } +} + +void common_hal_gifio_ondiskgif_construct(gifio_ondiskgif_t *self, pyb_file_obj_t *file) { + // mp_printf(&mp_plat_print, "Begin OnDiskGif\n"); + self->file = file; + + GIF_begin(&self->gif, GIF_PALETTE_RGB565_BE); + + self->gif.iError = GIF_SUCCESS; + self->gif.pfnRead = GIFReadFile; + self->gif.pfnSeek = GIFSeekFile; + self->gif.pfnDraw = GIFDraw; + self->gif.pfnClose = NULL; + self->gif.pfnOpen = NULL; + self->gif.GIFFile.fHandle = self->file; + + f_rewind(&self->file->fp); + self->gif.GIFFile.iSize = (int32_t)f_size(&self->file->fp); + + int result = GIF_init(&self->gif); + if (result != 1) { + mp_arg_error_invalid(MP_QSTR_file); + } + + displayio_bitmap_t *bitmap = m_new_obj(displayio_bitmap_t); + bitmap->base.type = &displayio_bitmap_type; + common_hal_displayio_bitmap_construct(bitmap, self->gif.iCanvasWidth, self->gif.iCanvasHeight, 16); + self->bitmap = bitmap; + + GIFINFO info; + GIF_getInfo(&self->gif, &info); + self->duration = info.iDuration; + self->frame_count = info.iFrameCount; + self->min_delay = info.iMinDelay; + self->max_delay = info.iMaxDelay; + + // mp_printf(&mp_plat_print, "GIF_init returned %d %x\n", result, bitmap->data); +} + +uint16_t common_hal_gifio_ondiskgif_get_height(gifio_ondiskgif_t *self) { + return (uint16_t)self->gif.iCanvasHeight; +} + +uint16_t common_hal_gifio_ondiskgif_get_width(gifio_ondiskgif_t *self) { + return (uint16_t)self->gif.iCanvasWidth; +} + +mp_obj_t common_hal_gifio_ondiskgif_get_bitmap(gifio_ondiskgif_t *self) { + return MP_OBJ_FROM_PTR(self->bitmap); +} + +int32_t common_hal_gifio_ondiskgif_get_duration(gifio_ondiskgif_t *self) { + return self->duration; +} + +int32_t common_hal_gifio_ondiskgif_get_frame_count(gifio_ondiskgif_t *self) { + return self->frame_count; +} + +int32_t common_hal_gifio_ondiskgif_get_min_delay(gifio_ondiskgif_t *self) { + return self->min_delay; +} + +int32_t common_hal_gifio_ondiskgif_get_max_delay(gifio_ondiskgif_t *self) { + return self->max_delay; +} + +uint32_t common_hal_gifio_ondiskgif_next_frame(gifio_ondiskgif_t *self, bool setDirty) { + int nextDelay = 0; + int result = GIF_playFrame(&self->gif, &nextDelay, self->bitmap); + + if ((result >= 0) && (setDirty)) { + displayio_area_t dirty_area = { + .x1 = 0, + .y1 = 0, + .x2 = self->bitmap->width, + .y2 = self->bitmap->height, + }; + + displayio_bitmap_set_dirty_area(self->bitmap, &dirty_area); + } + + return nextDelay; +} diff --git a/shared-module/gifio/OnDiskGif.h b/shared-module/gifio/OnDiskGif.h new file mode 100644 index 0000000000..c40781ef1f --- /dev/null +++ b/shared-module/gifio/OnDiskGif.h @@ -0,0 +1,51 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Mark Komus + * + * 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_MODULE_DISPLAYIO_ONDISKGIF_H +#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_ONDISKGIF_H + +#include +#include + +#include "py/obj.h" + +#include "lib/AnimatedGIF/AnimatedGIF_circuitpy.h" +#include "shared-module/displayio/Bitmap.h" + +#include "extmod/vfs_fat.h" + +typedef struct { + mp_obj_base_t base; + GIFIMAGE gif; + pyb_file_obj_t *file; + displayio_bitmap_t *bitmap; + int32_t duration; + int32_t frame_count; + int32_t min_delay; + int32_t max_delay; +} gifio_ondiskgif_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_ONDISKGIF_H diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c index 285abb1dbe..3bb7f00e1b 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c @@ -36,6 +36,7 @@ #include "supervisor/memory.h" #define SHARPMEM_BIT_WRITECMD_LSB (0x80) +#define JDI_BIT_WRITECMD_LSB (0x90) #define SHARPMEM_BIT_VCOM_LSB (0x40) STATIC uint8_t bitrev(uint8_t n) { @@ -54,7 +55,11 @@ int common_hal_sharpdisplay_framebuffer_get_height(sharpdisplay_framebuffer_obj_ } STATIC int common_hal_sharpdisplay_framebuffer_get_row_stride(sharpdisplay_framebuffer_obj_t *self) { - return (self->width + 7) / 8 + 2; + if (self->jdi_display) { + return (self->width + 1) / 2 + 2; + } else { + return (self->width + 7) / 8 + 2; + } } STATIC int common_hal_sharpdisplay_framebuffer_get_first_pixel_offset(sharpdisplay_framebuffer_obj_t *self) { @@ -99,10 +104,18 @@ void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_ob memset(alloc->ptr, 0, self->bufinfo.len); uint8_t *data = self->bufinfo.buf; - *data++ = SHARPMEM_BIT_WRITECMD_LSB; + if (self->jdi_display) { + *data++ = JDI_BIT_WRITECMD_LSB; + } else { + *data++ = SHARPMEM_BIT_WRITECMD_LSB; + } for (int y = 0; y < height; y++) { - *data = bitrev(y + 1); + if (self->jdi_display) { + *data = y + 1; + } else { + *data = bitrev(y + 1); + } data += row_stride; } self->full_refresh = true; @@ -128,7 +141,14 @@ void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t * memset(self, 0, sizeof(*self)); } -void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *chip_select, int baudrate, int width, int height) { +void common_hal_sharpdisplay_framebuffer_construct( + sharpdisplay_framebuffer_obj_t *self, + busio_spi_obj_t *spi, + const mcu_pin_obj_t *chip_select, + int baudrate, + int width, + int height, + bool jdi_display) { 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); common_hal_never_reset_pin(chip_select); @@ -139,6 +159,7 @@ void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_ self->width = width; self->height = height; self->baudrate = baudrate; + self->jdi_display = jdi_display; common_hal_sharpdisplay_framebuffer_get_bufinfo(self, NULL); } @@ -169,7 +190,8 @@ STATIC void common_hal_sharpdisplay_framebuffer_swapbuffers(sharpdisplay_framebu } // output a trailing zero - common_hal_busio_spi_write(self->bus, data, 1); + uint8_t zero[2] = {0, 0}; + common_hal_busio_spi_write(self->bus, zero, self->jdi_display ? 2 : 1); // set chip select low common_hal_digitalio_digitalinout_set_value(&self->chip_select, false); @@ -191,7 +213,13 @@ STATIC void sharpdisplay_framebuffer_get_bufinfo(mp_obj_t self_in, mp_buffer_inf } STATIC int sharpdisplay_framebuffer_get_color_depth(mp_obj_t self_in) { - return 1; + sharpdisplay_framebuffer_obj_t *self = MP_OBJ_TO_PTR(self_in); + return self->jdi_display ? 4 : 1; +} + +STATIC bool sharpdisplay_framebuffer_get_grayscale(mp_obj_t self_in) { + sharpdisplay_framebuffer_obj_t *self = MP_OBJ_TO_PTR(self_in); + return !self->jdi_display; } STATIC int sharpdisplay_framebuffer_get_height(mp_obj_t self_in) { @@ -234,6 +262,7 @@ const framebuffer_p_t sharpdisplay_framebuffer_proto = { .deinit = sharpdisplay_framebuffer_deinit, .get_bufinfo = sharpdisplay_framebuffer_get_bufinfo, .get_color_depth = sharpdisplay_framebuffer_get_color_depth, + .get_grayscale = sharpdisplay_framebuffer_get_grayscale, .get_height = sharpdisplay_framebuffer_get_height, .get_width = sharpdisplay_framebuffer_get_width, .swapbuffers = sharpdisplay_framebuffer_swapbuffers, diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h index abc951baf5..75abb2ff10 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.h +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.h @@ -41,19 +41,10 @@ typedef struct { uint16_t width, height; uint32_t baudrate; - bool full_refresh : 1; + bool full_refresh; + bool jdi_display; } sharpdisplay_framebuffer_obj_t; -void common_hal_sharpdisplay_framebuffer_construct(sharpdisplay_framebuffer_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *chip_select, int baudrate, int width, int height); -void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask); -void common_hal_sharpdisplay_framebuffer_deinit(sharpdisplay_framebuffer_obj_t *self); -void common_hal_sharpdisplay_framebuffer_get_bufinfo(sharpdisplay_framebuffer_obj_t *self, mp_buffer_info_t *bufinfo); -int common_hal_sharpdisplay_framebuffer_get_height(sharpdisplay_framebuffer_obj_t *self); -int common_hal_sharpdisplay_framebuffer_get_width(sharpdisplay_framebuffer_obj_t *self); -void common_hal_sharpdisplay_framebuffer_swap_buffers(sharpdisplay_framebuffer_obj_t *self, uint8_t *dirty_row_bitmask); -void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self); -void common_hal_sharpdisplay_framebuffer_reconstruct(sharpdisplay_framebuffer_obj_t *self); - extern const framebuffer_p_t sharpdisplay_framebuffer_proto; void common_hal_sharpdisplay_framebuffer_collect_ptrs(sharpdisplay_framebuffer_obj_t *); diff --git a/shared-module/vectorio/VectorShape.c b/shared-module/vectorio/VectorShape.c index 20e1405d9a..35131faa4f 100644 --- a/shared-module/vectorio/VectorShape.c +++ b/shared-module/vectorio/VectorShape.c @@ -406,7 +406,7 @@ bool vectorio_vector_shape_fill_area(vectorio_vector_shape_t *self, const _displ 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)) { - output_pixel.opaque = displayio_palette_get_color(self->pixel_shader, colorspace, input_pixel.pixel, &output_pixel.pixel); + displayio_palette_get_color(self->pixel_shader, colorspace, &input_pixel, &output_pixel); } else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) { displayio_colorconverter_convert(self->pixel_shader, colorspace, &input_pixel, &output_pixel); } diff --git a/supervisor/port.h b/supervisor/port.h index 2fb24385c1..70bdcb0170 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -90,7 +90,11 @@ void port_interrupt_after_ticks(uint32_t ticks); // may not be a system level sleep. void port_idle_until_interrupt(void); -// Execute port specific actions during background tasks. +// Execute port specific actions during background tick. Only if ticks are enabled. +void port_background_tick(void); + +// Execute port specific actions during background tasks. This is before the +// background callback system. void port_background_task(void); // Take port specific actions at the beginning and end of background tasks. diff --git a/supervisor/shared/background_callback.c b/supervisor/shared/background_callback.c index 88ffc15911..db6d62f8e7 100644 --- a/supervisor/shared/background_callback.c +++ b/supervisor/shared/background_callback.c @@ -74,6 +74,7 @@ bool PLACE_IN_ITCM(background_callback_pending)(void) { static bool in_background_callback; void PLACE_IN_ITCM(background_callback_run_all)() { + port_background_task(); if (!background_callback_pending()) { return; } diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c index 6fe5d570b8..bb44ab0f00 100644 --- a/supervisor/shared/bluetooth/bluetooth.c +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -158,7 +158,7 @@ STATIC void supervisor_bluetooth_start_advertising(void) { _private_advertising = true; // Advertise with less power when doing so publicly to reduce who can hear us. This will make it // harder for someone with bad intentions to pair from a distance. - if (!bonded) { + if (!bonded || boot_in_discovery_mode) { tx_power = -20; adv = public_advertising_data; adv_len = sizeof(public_advertising_data); @@ -179,7 +179,7 @@ STATIC void supervisor_bluetooth_start_advertising(void) { } uint32_t status = _common_hal_bleio_adapter_start_advertising(&common_hal_bleio_adapter_obj, true, - bonded, // Advertise anonymously if we are bonded + _private_advertising, // Advertise anonymously if we are privately advertising timeout, interval, adv, diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index 0a066e8016..26585c54d5 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -159,6 +159,14 @@ void supervisor_stop_terminal(void) { #endif } +bool supervisor_terminal_started(void) { + #if CIRCUITPY_TERMINALIO + return tilegrid_tiles != NULL; + #else + return false; + #endif +} + void supervisor_display_move_memory(void) { #if CIRCUITPY_TERMINALIO displayio_tilegrid_t *scroll_area = &supervisor_terminal_scroll_area_text_grid; diff --git a/supervisor/shared/display.h b/supervisor/shared/display.h index fcaab10818..0eb9bc507f 100644 --- a/supervisor/shared/display.h +++ b/supervisor/shared/display.h @@ -54,6 +54,7 @@ extern displayio_tilegrid_t supervisor_blinka_sprite; void supervisor_start_terminal(uint16_t width_px, uint16_t height_px); void supervisor_stop_terminal(void); +bool supervisor_terminal_started(void); void supervisor_display_move_memory(void); diff --git a/supervisor/shared/serial.c b/supervisor/shared/serial.c index 5680d8afe0..e683e8eb7c 100644 --- a/supervisor/shared/serial.c +++ b/supervisor/shared/serial.c @@ -192,6 +192,12 @@ bool serial_connected(void) { } #endif + #if CIRCUITPY_TERMINALIO + if (supervisor_terminal_started()) { + return true; + } + #endif + if (port_serial_connected()) { return true; diff --git a/supervisor/shared/web_workflow/websocket.c b/supervisor/shared/web_workflow/websocket.c index 7612066fa6..e55e09b3e7 100644 --- a/supervisor/shared/web_workflow/websocket.c +++ b/supervisor/shared/web_workflow/websocket.c @@ -52,6 +52,8 @@ typedef struct { // interrupt character. STATIC ringbuf_t _incoming_ringbuf; STATIC uint8_t _buf[16]; +// make sure background is not called recursively +STATIC bool in_web_background = false; static _websocket cp_serial; @@ -244,6 +246,10 @@ void websocket_background(void) { if (!websocket_connected()) { return; } + if (in_web_background) { + return; + } + in_web_background = true; uint8_t c; while (ringbuf_num_empty(&_incoming_ringbuf) > 0 && _read_next_payload_byte(&c)) { @@ -253,4 +259,5 @@ void websocket_background(void) { } ringbuf_put(&_incoming_ringbuf, c); } + in_web_background = false; } diff --git a/tests/extmod/vfs_fat_case.py b/tests/extmod/vfs_fat_case.py new file mode 100644 index 0000000000..40d67da9b8 --- /dev/null +++ b/tests/extmod/vfs_fat_case.py @@ -0,0 +1,81 @@ +try: + import uerrno + import uos +except ImportError: + print("missing u") + print("SKIP") + raise SystemExit + +try: + uos.VfsFat +except AttributeError: + print("missing VfsFat") + print("SKIP") + raise SystemExit + + +class RAMFS: + SEC_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.SEC_SIZE) + + def readblocks(self, n, buf): + # print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) + for i in range(len(buf)): + buf[i] = self.data[n * self.SEC_SIZE + i] + return 0 + + def writeblocks(self, n, buf): + # print("writeblocks(%s, %x)" % (n, id(buf))) + for i in range(len(buf)): + self.data[n * self.SEC_SIZE + i] = buf[i] + return 0 + + def ioctl(self, op, arg): + # print("ioctl(%d, %r)" % (op, arg)) + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT + return len(self.data) // self.SEC_SIZE + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE + return self.SEC_SIZE + + +try: + bdev = RAMFS(50) +except MemoryError: + print("SKIP") + raise SystemExit + +uos.VfsFat.mkfs(bdev) +vfs = uos.VfsFat(bdev) +uos.mount(vfs, "/ramdisk") +uos.chdir("/ramdisk") + +vfs.label = "labelæ" +# This label would normally be LABELÆ but our limited upper casing does "LABELæ" +print(vfs.label) + +# Check ASCII case-insensitivity +vfs.mkdir("fooaz") +print(uos.listdir("")) +vfs.rmdir("fOOAZ") + +# Check ASCII case-insensitivity for long names (8+ characters) +vfs.mkdir("123456789fooaz") +print(uos.listdir("")) +vfs.rmdir("123456789fOOAZ") + +# Characters outside of a-z are case sensitive. +vfs.mkdir("extended_æ") +print(uos.listdir("")) +# Normally this would work ok. With our limited uppercasing, it won't. +try: + vfs.rmdir("extended_Æ") +except OSError as e: + print(e.errno == uerrno.ENOENT) + +vfs.rmdir("extended_æ") + +# Emoji test for fun. +vfs.mkdir("emoji_😀") +vfs.rmdir("emoji_😀") diff --git a/tests/extmod/vfs_fat_case.py.exp b/tests/extmod/vfs_fat_case.py.exp new file mode 100644 index 0000000000..64b5e7b27a --- /dev/null +++ b/tests/extmod/vfs_fat_case.py.exp @@ -0,0 +1,5 @@ +LABELæ +['fooaz'] +['123456789fooaz'] +['extended_æ'] +True diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 582d90e1bc..65f67f0727 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -33,17 +33,17 @@ builtins micropython _asyncio _thread _uasyncio aesio array binascii bitmaptools btree cexample cmath collections cppexample displayio errno -ffi framebuf gc gifio -hashlib json math qrio -rainbowio re sys termios -traceback ubinascii uctypes uerrno -uheapq uio ujson ulab -ulab.numpy ulab.numpy.fft ulab.numpy.linalg -ulab.scipy ulab.scipy.linalg -ulab.scipy.optimize ulab.scipy.signal -ulab.scipy.special ulab.utils uos -urandom ure uselect ustruct -utime utimeq uzlib zlib +ffi framebuf gc hashlib +json math qrio rainbowio +re sys termios traceback +ubinascii uctypes uerrno uheapq +uio ujson ulab ulab.numpy +ulab.numpy.fft ulab.numpy.linalg ulab.scipy +ulab.scipy.linalg ulab.scipy.optimize +ulab.scipy.signal ulab.scipy.special +ulab.utils uos urandom ure +uselect ustruct utime utimeq +uzlib zlib ime utime utimeq diff --git a/tools/build_memory_info.py b/tools/build_memory_info.py index 722c548a1c..09d2e72a64 100755 --- a/tools/build_memory_info.py +++ b/tools/build_memory_info.py @@ -7,6 +7,8 @@ import re import sys +import json + # Handle size constants with K or M suffixes (allowed in .ld but not in Python). K_PATTERN = re.compile(r"([0-9]+)[kK]") @@ -15,11 +17,10 @@ K_REPLACE = r"(\1*1024)" M_PATTERN = re.compile(r"([0-9]+)[mM]") M_REPLACE = r"(\1*1024*1024)" -print() - text = 0 data = 0 bss = 0 + # stdin is the linker output. for line in sys.stdin: # Uncomment to see linker output. @@ -29,6 +30,7 @@ for line in sys.stdin: text, data, bss = map(int, line.split()[:3]) regions = {} + # This file is the linker script. with open(sys.argv[1], "r") as f: for line in f: @@ -51,6 +53,11 @@ used_flash = data + text free_flash = firmware_region - used_flash used_ram = data + bss free_ram = ram_region - used_ram + +with open(f"{sys.argv[2]}/firmware.size.json", "w") as f: + json.dump({"used_flash": used_flash, "firmware_region": firmware_region}, f) + +print() print( "{} bytes used, {} bytes free in flash firmware space out of {} bytes ({}kB).".format( used_flash, free_flash, firmware_region, firmware_region / 1024 diff --git a/tools/build_release_files.py b/tools/build_release_files.py index 309d91c368..341ae2d67f 100755 --- a/tools/build_release_files.py +++ b/tools/build_release_files.py @@ -11,6 +11,7 @@ import subprocess import shutil import build_board_info as build_info import time +import json sys.path.append("../docs") from shared_bindings_matrix import get_settings_from_makefile @@ -18,7 +19,7 @@ from shared_bindings_matrix import get_settings_from_makefile for port in build_info.SUPPORTED_PORTS: result = subprocess.run("rm -rf ../ports/{port}/build*".format(port=port), shell=True) -PARALLEL = "-j 5" +PARALLEL = "-j 4" if "GITHUB_ACTION" in os.environ: PARALLEL = "-j 2" @@ -29,6 +30,11 @@ if "BOARDS" in os.environ: sha, version = build_info.get_version_info() +build_all = os.environ.get("GITHUB_EVENT_NAME") != "pull_request" + +LANGUAGE_FIRST = "en_US" +LANGUAGE_THRESHOLD = 10 * 1024 + languages = build_info.get_languages() all_languages = build_info.get_languages(list_all=True) @@ -44,6 +50,9 @@ for board in build_boards: board_info = all_boards[board] board_settings = get_settings_from_makefile("../ports/" + board_info["port"], board) + languages.remove(LANGUAGE_FIRST) + languages.insert(0, LANGUAGE_FIRST) + for language in languages: bin_directory = "../bin/{board}/{language}".format(board=board, language=language) os.makedirs(bin_directory, exist_ok=True) @@ -66,13 +75,20 @@ for board in build_boards: if clean_build: build_dir += "-{language}".format(language=language) + extensions = [ + extension.strip() + for extension in board_settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",") + ] + + artifacts = [os.path.join(build_dir, "firmware." + extension) for extension in extensions] make_result = subprocess.run( - "make -C ../ports/{port} TRANSLATION={language} BOARD={board} BUILD={build} -j {cores}".format( + "make -C ../ports/{port} TRANSLATION={language} BOARD={board} BUILD={build} -j {cores} {artifacts}".format( port=board_info["port"], language=language, board=board, build=build_dir, cores=cores, + artifacts=" ".join(artifacts), ), shell=True, stdout=subprocess.PIPE, @@ -86,10 +102,6 @@ for board in build_boards: success = "\033[31mfailed\033[0m" other_output = "" - extensions = [ - extension.strip() - for extension in board_settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",") - ] for extension in extensions: temp_filename = "../ports/{port}/{build}/firmware.{extension}".format( @@ -127,4 +139,16 @@ for board in build_boards: # Flush so we will see something before 10 minutes has passed. print(flush=True) + if (not build_all) and (language is LANGUAGE_FIRST) and (exit_status is 0): + try: + with open( + f"../ports/{board_info['port']}/{build_dir}/firmware.size.json", "r" + ) as f: + firmware = json.load(f) + if firmware["used_flash"] + LANGUAGE_THRESHOLD < firmware["firmware_region"]: + print("Skipping languages") + break + except FileNotFoundError: + pass + sys.exit(exit_status) diff --git a/tools/ci_changes_per_commit.py b/tools/ci_changes_per_commit.py index 4d71f8e38c..58e86148ed 100644 --- a/tools/ci_changes_per_commit.py +++ b/tools/ci_changes_per_commit.py @@ -166,25 +166,12 @@ def get_commit_depth_and_check_suite(query_commits): return [None, None] -def append_runs_to_list(runs, bad_runs_by_matrix): - regex_matrix = re.compile("^build-[^ ]+") - regex_board = re.compile("\([^ ]+\)$") - for run in runs["nodes"]: - name = run["name"] - res_matrix = regex_matrix.search(name) - if res_matrix: - matrix = res_matrix.group() - if matrix not in bad_runs_by_matrix: - bad_runs_by_matrix[matrix] = [] - res_board = regex_board.search(name) - if res_board: - bad_runs_by_matrix[matrix].append(res_board.group()[1:-1]) - - def get_bad_check_runs(query_check_runs): + bad_runs = {} more_pages = True - bad_runs_by_matrix = {} + run_types = ["failed", "incomplete"] + have_dependent_jobs = ["scheduler", "mpy-cross", "tests"] while more_pages: check_runs = query_check_runs.fetch()["data"]["node"] @@ -194,7 +181,17 @@ def get_bad_check_runs(query_check_runs): run_type_camel = run_type.capitalize() + "Run" run_type = run_type + "Runs" - append_runs_to_list(check_runs[run_type], bad_runs_by_matrix) + for check_run in check_runs[run_type]["nodes"]: + name = check_run["name"] + + if any([name.startswith(job) for job in have_dependent_jobs]): + return {} + + if name.startswith("ports"): + matrix_job = name.rsplit(" (", 1)[1][:-1] + bad_runs.setdefault("ports", []).append(matrix_job) + else: + bad_runs[name] = True if query_check_runs.paginate( check_runs[run_type]["pageInfo"], "after" + run_type_camel @@ -202,7 +199,7 @@ def get_bad_check_runs(query_check_runs): query_check_runs.variables["include" + run_type_camel] = True more_pages = True - return bad_runs_by_matrix + return bad_runs def set_commit(commit): diff --git a/tools/ci_fetch_deps.py b/tools/ci_fetch_deps.py index bdf2967af8..1b292b9d73 100644 --- a/tools/ci_fetch_deps.py +++ b/tools/ci_fetch_deps.py @@ -78,16 +78,18 @@ def main(): submodules = ["extmod/ulab", "lib/", "tools/"] elif TARGET == "tests": submodules = ["extmod/ulab", "lib/", "tools/"] - elif TARGET == "build-doc": + elif TARGET == "docs": # used in .readthedocs.yml to generate RTD - submodules = ["extmod/ulab", "frozen/"] + submodules = ["extmod/ulab"] + submodules_tags = ["frozen/"] elif TARGET == "mpy-cross" or TARGET == "mpy-cross-mac": submodules = ["tools/"] # for huffman elif TARGET == "windows": # This builds one board from a number of ports so fill out a bunch of submodules submodules = ["extmod/ulab", "lib/", "tools/", "ports/", "data/nvm.toml"] elif TARGET == "website": - submodules = ["tools/adabot/", "frozen/"] + submodules = ["tools/adabot/"] + submodules_tags = ["frozen/"] elif TARGET == "pre-commit": submodules = ["extmod/ulab"] else: diff --git a/tools/ci_set_matrix.py b/tools/ci_set_matrix.py index 6e7a4f1229..b5618aec2f 100755 --- a/tools/ci_set_matrix.py +++ b/tools/ci_set_matrix.py @@ -42,18 +42,6 @@ from shared_bindings_matrix import ( all_ports_all_boards, ) -PORT_TO_ARCH = { - "atmel-samd": "arm", - "broadcom": "aarch", - "cxd56": "arm", - "espressif": "esp", - "litex": "riscv", - "mimxrt10xx": "arm", - "nrf": "arm", - "raspberrypi": "rpi", - "stm": "arm", -} - IGNORE = [ "tools/ci_set_matrix.py", "tools/ci_check_duplicate_usb_vid_pid.py", @@ -62,6 +50,24 @@ IGNORE = [ # Files in these directories never influence board builds IGNORE_DIRS = ["tests", "docs", ".devcontainer"] +PATTERN_DOCS = ( + r"^(?:\.github|docs|extmod\/ulab)|" + r"^(?:(?:ports\/\w+\/bindings|shared-bindings)\S+\.c|tools\/extract_pyi\.py|conf\.py|requirements-doc\.txt)$|" + r"(?:-stubs|\.(?:md|MD|rst|RST))$" +) + +PATTERN_WINDOWS = [ + ".github/", + "extmod/", + "lib/", + "mpy-cross/", + "ports/unix/", + "ports/windows/", + "py/", + "requirements", + "tools/", +] + if len(sys.argv) > 1: print("Using files list on commandline") changed_files = sys.argv[1:] @@ -91,7 +97,7 @@ def set_output(name: str, value): print(f"Would set GitHub actions output {name} to '{value}'") -def set_boards_to_build(build_all: bool): +def set_boards(build_all: bool): # Get boards in json format boards_info_json = build_board_info.get_board_mapping() all_board_ids = set() @@ -203,56 +209,49 @@ def set_boards_to_build(build_all: bool): boards_to_build = all_board_ids break - # Split boards by architecture. - arch_to_boards = {"aarch": [], "arm": [], "esp": [], "riscv": [], "rpi": []} - # Append previously failed boards - for arch in arch_to_boards: - arch_to_job = f"build-{arch}" - if arch_to_job in last_failed_jobs: - for board in last_failed_jobs[arch_to_job]: - if not board in boards_to_build: - boards_to_build.append(board) + boards_to_build.update(last_failed_jobs.get("ports") or []) - build_boards = bool(boards_to_build) - print("Building boards:", build_boards) - set_output("build-boards", build_boards) + print("Building boards:", bool(boards_to_build)) - # Append boards according to arch + # Split boards by port + port_to_boards_to_build = {} + + # Append boards according to job for board in sorted(boards_to_build): port = board_to_port.get(board) # A board can appear due to its _deletion_ (rare) # if this happens it's not in `board_to_port`. if not port: continue - arch_to_boards[PORT_TO_ARCH[port]].append(board) + port_to_boards_to_build.setdefault(port, []).append(board) print(" ", board) - # Set the step outputs for each architecture - for arch in arch_to_boards: - set_output(f"boards-{arch}", json.dumps(arch_to_boards[arch])) + if port_to_boards_to_build: + port_to_boards_to_build["ports"] = sorted(list(port_to_boards_to_build.keys())) + + # Set the step outputs + set_output("ports", json.dumps(port_to_boards_to_build)) -def set_docs_to_build(build_doc: bool): +def set_docs(build_doc: bool): if not build_doc: - if "build-doc" in last_failed_jobs: + if last_failed_jobs.get("docs"): build_doc = True else: - doc_pattern = re.compile( - r"^(?:\.github\/workflows\/|docs|extmod\/ulab|(?:(?:ports\/\w+\/bindings|shared-bindings)\S+\.c|conf\.py|tools\/extract_pyi\.py|requirements-doc\.txt)$)|(?:-stubs|\.(?:md|MD|rst|RST))$" - ) + doc_pattern = re.compile(PATTERN_DOCS) github_workspace = os.environ.get("GITHUB_WORKSPACE") or "" github_workspace = github_workspace and github_workspace + "/" - for p in changed_files: - if doc_pattern.search(p) and ( + for file in changed_files: + if doc_pattern.search(file) and ( ( subprocess.run( - f"git diff -U0 $BASE_SHA...$HEAD_SHA {github_workspace + p} | grep -o -m 1 '^[+-]\/\/|'", + f"git diff -U0 $BASE_SHA...$HEAD_SHA {github_workspace + file} | grep -o -m 1 '^[+-]\/\/|'", capture_output=True, shell=True, ).stdout ) - if p.endswith(".c") + if file.endswith(".c") else True ): build_doc = True @@ -260,22 +259,41 @@ def set_docs_to_build(build_doc: bool): # Set the step outputs print("Building docs:", build_doc) - set_output("build-doc", build_doc) + set_output("docs", build_doc) -def check_changed_files(): - if not changed_files: - print("Building all docs/boards") - return True - else: - print("Adding docs/boards to build based on changed files") - return False +def set_windows(build_windows: bool): + if not build_windows: + if last_failed_jobs.get("windows"): + build_windows = True + else: + for file in changed_files: + for pattern in PATTERN_WINDOWS: + if file.startswith(pattern): + build_windows = True + break + else: + continue + break + + # Set the step outputs + print("Building windows:", build_windows) + set_output("windows", build_windows) def main(): - build_all = check_changed_files() - set_docs_to_build(build_all) - set_boards_to_build(build_all) + # Build all if no changed files + build_all = not changed_files + print( + "Building all docs/boards" + if build_all + else "Adding docs/boards to build based on changed files" + ) + + # Set jobs + set_docs(build_all) + set_windows(build_all) + set_boards(build_all) if __name__ == "__main__": diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py index e5ce775e4a..7165db84cc 100644 --- a/tools/gen_display_resources.py +++ b/tools/gen_display_resources.py @@ -180,51 +180,25 @@ displayio_bitmap_t blinka_bitmap = {{ _displayio_color_t blinka_colors[7] = {{ {{ .rgb888 = 0x000000, - .rgb565 = 0x0000, - .luma = 0x00, - .chroma = 0, .transparent = true }}, - {{ - .rgb888 = 0x8428bc, - .rgb565 = 0x8978, - .luma = 0xff, // We cheat the luma here. It is actually 0x60 - .hue = 184, - .chroma = 148 + {{ // Purple + .rgb888 = 0x8428bc }}, - {{ - .rgb888 = 0xff89bc, - .rgb565 = 0xFCB8, - .luma = 0xb5, - .hue = 222, - .chroma = 118 + {{ // Pink + .rgb888 = 0xff89bc }}, - {{ - .rgb888 = 0x7beffe, - .rgb565 = 0x869F, - .luma = 0xe0, - .hue = 124, - .chroma = 131 + {{ // Light blue + .rgb888 = 0x7beffe }}, - {{ - .rgb888 = 0x51395f, - .rgb565 = 0x5A0D, - .luma = 0x47, - .hue = 185, - .chroma = 38 + {{ // Dark purple + .rgb888 = 0x51395f }}, - {{ - .rgb888 = 0xffffff, - .rgb565 = 0xffff, - .luma = 0xff, - .chroma = 0 + {{ // White + .rgb888 = 0xffffff }}, - {{ - .rgb888 = 0x0736a0, - .rgb565 = 0x01f5, - .luma = 0x44, - .hue = 147, - .chroma = 153 + {{ // Dark Blue + .rgb888 = 0x0736a0 }}, }}; @@ -270,16 +244,10 @@ c_file.write( #if CIRCUITPY_TERMINALIO _displayio_color_t terminal_colors[2] = { { - .rgb888 = 0x000000, - .rgb565 = 0x0000, - .luma = 0x00, - .chroma = 0 + .rgb888 = 0x000000 }, { - .rgb888 = 0xffffff, - .rgb565 = 0xffff, - .luma = 0xff, - .chroma = 0 + .rgb888 = 0xffffff }, };