Merge remote-tracking branch 'origin/main' into q-and-d-uvc

This commit is contained in:
Jeff Epler 2024-01-31 08:27:13 -06:00
commit 1c95a85ceb
115 changed files with 1989 additions and 695 deletions

View file

@ -16,7 +16,7 @@ runs:
tar -xaf dosfstools-4.2.tar.gz
cd dosfstools-4.2
./configure
make -j 2
make -j4
cd src
echo >> $GITHUB_PATH $(pwd)
shell: bash

View file

@ -18,7 +18,7 @@ runs:
shell: bash
- name: Cache IDF submodules
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
.git/modules/ports/espressif/esp-idf
@ -26,7 +26,7 @@ runs:
key: submodules-idf-${{ steps.idf-commit.outputs.commit }}
- name: Cache IDF tools
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ env.IDF_TOOLS_PATH }}
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-idf-${{ steps.idf-commit.outputs.commit }}

View file

@ -16,7 +16,7 @@ runs:
- name: Cache python dependencies
id: cache-python-deps
if: inputs.action == 'cache'
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: .cp_tools
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }}
@ -24,7 +24,7 @@ runs:
- name: Restore python dependencies
id: restore-python-deps
if: inputs.action == 'restore'
uses: actions/cache/restore@v3
uses: actions/cache/restore@v4
with:
path: .cp_tools
key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }}

View file

@ -48,7 +48,7 @@ runs:
- name: Cache submodules
if: ${{ inputs.action == 'cache' }}
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}"
key: submodules-common-${{ hashFiles('submodule_status') }}
@ -56,7 +56,7 @@ runs:
- name: Restore submodules
if: ${{ inputs.action == 'restore' }}
uses: actions/cache/restore@v3
uses: actions/cache/restore@v4
with:
path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}"
key: submodules-common-${{ hashFiles('submodule_status') }}

View file

@ -16,7 +16,7 @@ runs:
id: download-mpy-cross
if: inputs.download == 'true'
continue-on-error: true
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: mpy-cross
path: mpy-cross/build
@ -28,7 +28,7 @@ runs:
- name: Build mpy-cross
if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure'
run: make -C mpy-cross -j2
run: make -C mpy-cross -j4
shell: bash
env:
CP_VERSION: ${{ inputs.cp-version }}
@ -36,7 +36,7 @@ runs:
- name: Upload mpy-cross
if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure'
continue-on-error: true
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: mpy-cross
path: mpy-cross/build/mpy-cross

View file

@ -26,12 +26,13 @@ jobs:
board: ${{ fromJSON(inputs.boards) }}
steps:
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up port
@ -75,7 +76,7 @@ jobs:
PULL: ${{ github.event.number }}
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.board }}
path: bin/${{ matrix.board }}

View file

@ -28,12 +28,13 @@ jobs:
OS_static-raspbian: linux-raspbian
steps:
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up submodules
@ -53,7 +54,7 @@ jobs:
sudo apt-get install -y mingw-w64
- name: Build mpy-cross.${{ matrix.mpy-cross }}
run: make -C mpy-cross -j2 -f Makefile.${{ matrix.mpy-cross }}
run: make -C mpy-cross -j4 -f Makefile.${{ matrix.mpy-cross }}
- name: Set output
run: |
@ -61,7 +62,7 @@ jobs:
echo >> $GITHUB_ENV "OS=${{ env[format('OS_{0}', matrix.mpy-cross)] }}"
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: mpy-cross.${{ env.EX }}
path: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }}

View file

@ -28,12 +28,13 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Duplicate USB VID/PID check
@ -108,12 +109,13 @@ jobs:
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
steps:
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up submodules
@ -124,21 +126,21 @@ jobs:
python3 --version
msgfmt --version
- name: Build mpy-cross
run: make -C mpy-cross -j2
- uses: actions/upload-artifact@v3
run: make -C mpy-cross -j4
- uses: actions/upload-artifact@v4
with:
name: mpy-cross-macos-11-x64
path: mpy-cross/build/mpy-cross
- name: Build mpy-cross (arm64)
run: make -C mpy-cross -j2 -f Makefile.m1 V=2
- uses: actions/upload-artifact@v3
run: make -C mpy-cross -j4 -f Makefile.m1 V=2
- uses: actions/upload-artifact@v4
with:
name: mpy-cross-macos-11-arm64
path: mpy-cross/build-arm64/mpy-cross-arm64
- name: Make universal binary
run: lipo -create -output mpy-cross-macos-universal mpy-cross/build/mpy-cross mpy-cross/build-arm64/mpy-cross-arm64
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: mpy-cross-macos-11-universal
path: mpy-cross-macos-universal
@ -163,12 +165,13 @@ jobs:
CP_VERSION: ${{ needs.scheduler.outputs.cp-version }}
steps:
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up submodules
@ -179,23 +182,23 @@ jobs:
sudo apt-get install -y latexmk librsvg2-bin texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra
pip install -r requirements-doc.txt
- name: Build and Validate Stubs
run: make check-stubs -j2
- uses: actions/upload-artifact@v3
run: make check-stubs -j4
- uses: actions/upload-artifact@v4
with:
name: stubs
path: circuitpython-stubs/dist/*
- name: Test Documentation Build (HTML)
run: sphinx-build -E -W -b html -D version=${{ env.CP_VERSION }} -D release=${{ env.CP_VERSION }} . _build/html
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: docs
name: docs-html
path: _build/html
- name: Test Documentation Build (LaTeX/PDF)
run: |
make latexpdf
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: docs
name: docs-latexpdf
path: _build/latex
- name: Upload to S3
uses: ./.github/actions/upload_aws
@ -260,24 +263,25 @@ jobs:
which python; python --version; python -c "import cascadetoml"
which python3; python3 --version; python3 -c "import cascadetoml"
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up submodules
uses: ./.github/actions/deps/submodules
- name: build mpy-cross
run: make -j2 -C mpy-cross
run: make -j4 -C mpy-cross
- name: build rp2040
run: make -j2 -C ports/raspberrypi BOARD=adafruit_feather_rp2040 TRANSLATION=de_DE
run: make -j4 -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
run: make -j4 -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
run: make -j4 -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
run: make -j4 -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
run: make -j4 -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

View file

@ -17,12 +17,13 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up submodules

View file

@ -42,7 +42,7 @@ jobs:
run: |
> custom-build && git add custom-build
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up port
@ -81,10 +81,10 @@ jobs:
riscv64-unknown-elf-gcc --version || true
mkfs.fat --version || true
- name: Build board
run: make -j2 ${{ inputs.flags }} BOARD=${{ inputs.board }} DEBUG=${{ inputs.debug && '1' || '0' }} TRANSLATION=${{ inputs.language }}
run: make -j4 ${{ inputs.flags }} BOARD=${{ inputs.board }} DEBUG=${{ inputs.debug && '1' || '0' }} TRANSLATION=${{ inputs.language }}
working-directory: ports/${{ steps.set-up-port.outputs.port }}
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }}
path: ports/${{ steps.set-up-port.outputs.port }}/build-${{ inputs.board }}/firmware.*

View file

@ -17,12 +17,13 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up submodules
@ -40,7 +41,7 @@ jobs:
run: git diff > ~/pre-commit.patch
- name: Upload patch
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: patch
path: ~/pre-commit.patch

View file

@ -24,12 +24,13 @@ jobs:
TEST_native_mpy: --via-mpy --emit native -d basics float micropython
steps:
- name: Set up repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: false
show-progress: false
fetch-depth: 1
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Set up submodules
@ -44,12 +45,12 @@ jobs:
with:
cp-version: ${{ inputs.cp-version }}
- name: Build unix port
run: make -C ports/unix VARIANT=coverage -j2
run: make -C ports/unix VARIANT=coverage -j4
- name: Run tests
run: ./run-tests.py -j2 ${{ env[format('TEST_{0}', matrix.test)] }}
run: ./run-tests.py -j4 ${{ env[format('TEST_{0}', matrix.test)] }}
working-directory: tests
- name: Print failure info
run: ./run-tests.py -j2 --print-failures
run: ./run-tests.py -j4 --print-failures
if: failure()
working-directory: tests
- name: Build native modules

View file

@ -52,27 +52,9 @@ SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) $(STM_SRC_C)
The `Makefile` defines the modules to build and adds the sources to include the `shared-bindings` version and the `common-hal` version within the port specific directory. You may comment out certain subfolders to reduce the number of modules to add but don't comment out individual classes. It won't compile then.
### Hooking the modules in
Built in modules are typically defined in `mpconfigport.h`. To add support you should have something like:
```
extern const struct _mp_obj_module_t microcontroller_module;
extern const struct _mp_obj_module_t analogio_module;
extern const struct _mp_obj_module_t digitalio_module;
extern const struct _mp_obj_module_t pulseio_module;
extern const struct _mp_obj_module_t busio_module;
extern const struct _mp_obj_module_t board_module;
extern const struct _mp_obj_module_t time_module;
extern const struct _mp_obj_module_t neopixel_write_module;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)&microcontroller_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module } \
Modules are registered by the macro `MP_REGISTER_MODULE` from `py/obj.h`. The macro takes two arguments: the module name as a QSTR and the module object itself. The `board` module is registered like so:
```py
MP_REGISTER_MODULE(MP_QSTR_board, board_module);
```
### Implementing the Common HAL

View file

@ -173,6 +173,11 @@ def get_settings_from_makefile(port_dir, board_name):
This list must explicitly include any setting queried by tools/ci_set_matrix.py.
"""
if os.getenv('NO_BINDINGS_MATRIX'):
return {
'CIRCUITPY_BUILD_EXTENSIONS': '.bin'
}
contents = subprocess.run(
["make", "-C", port_dir, "-f", "Makefile", f"BOARD={board_name}", "print-CFLAGS", "print-CIRCUITPY_BUILD_EXTENSIONS", "print-FROZEN_MPY_DIRS", "print-SRC_PATTERNS", "print-SRC_SUPERVISOR"],
encoding="utf-8",

View file

@ -165,6 +165,13 @@ Returns a JSON representation of the directory.
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
* `404 Not Found` - Missing directory
Returns directory information:
* `free`: Count of free blocks on the disk holding this directory.
* `total`: Total blocks that make up the disk holding this directory.
* `block_size`: Size of a block in bytes.
* `writable`: True when CircuitPython and the web workflow can write to the disk. USB may claim a disk instead.
* `files`: Array of objects. One for each file.
Returns information about each file in the directory:
* `name` - File name. No trailing `/` on directory names
@ -179,14 +186,20 @@ curl -v -u :passw0rd -H "Accept: application/json" -L --location-trusted http://
```
```json
[
{
"free": 451623,
"total": 973344,
"block_size": 32768,
"writable": true,
"files": [
{
"name": "world.txt",
"directory": false,
"modified_ns": 946934328000000000,
"file_size": 12
}
]
]
}
```
##### PUT
@ -196,7 +209,7 @@ time resolution) used for the directories modification time. The RTC time will u
Returns:
* `204 No Content` - Directory exists
* `204 No Content` - Directory or file exists
* `201 Created` - Directory created
* `401 Unauthorized` - Incorrect password
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
@ -373,10 +386,10 @@ curl -v -L http://circuitpython.local/cp/devices.json
Returns information about the attached disk(s). A list of objects, one per disk.
* `root`: Filesystem path to the root of the disk.
* `free`: Count of free bytes on the disk.
* `free`: Count of free blocks on the disk.
* `total`: Total blocks that make up the disk.
* `block_size`: Size of a block in bytes.
* `writable`: True when CircuitPython and the web workflow can write to the disk. USB may claim a disk instead.
* `total`: Total bytes that make up the disk.
Example:
```sh
@ -405,7 +418,7 @@ This is an authenticated endpoint in both modes.
Returns information about the device.
* `web_api_version`: Between `1` and `3`. This versions the rest of the API and new versions may not be backwards compatible. See below for more info.
* `web_api_version`: Between `1` and `4`. This versions the rest of the API and new versions may not be backwards compatible. See below for more info.
* `version`: CircuitPython build version.
* `build_date`: CircuitPython build date.
* `board_name`: Human readable name of the board.
@ -467,3 +480,5 @@ Only one WebSocket at a time is supported.
* `1` - Initial version.
* `2` - Added `/cp/diskinfo.json`.
* `3` - Changed `/cp/diskinfo.json` to return a list in preparation for multi-disk support.
* `4` - Changed directory json to an object with additional data. File list is under `files` and is
the same as the old format.

View file

@ -48,6 +48,8 @@
#define MP_BLOCKDEV_FLAG_USB_WRITABLE (0x0010)
// Bit set when the above flag is checked before opening a file for write.
#define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020)
// Bit set when something has claimed the right to mutate the blockdev.
#define MP_BLOCKDEV_FLAG_LOCKED (0x0040)
// constants for block protocol ioctl
#define MP_BLOCKDEV_IOCTL_INIT (1)

View file

@ -30,12 +30,41 @@
#include "py/mperrno.h"
#include "extmod/vfs.h"
#if CIRCUITPY_SDCARDIO
#include "shared-bindings/sdcardio/SDCard.h"
#endif
#if CIRCUITPY_SDIOIO
#include "shared-bindings/sdioio/SDCard.h"
#endif
#if MICROPY_VFS
void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks);
mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks);
mp_load_method_maybe(bdev, MP_QSTR_ioctl, self->u.ioctl);
// CIRCUITPY-CHANGE: Support native SD cards.
#if CIRCUITPY_SDCARDIO
if (mp_obj_get_type(bdev) == &sdcardio_SDCard_type) {
self->flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL;
self->readblocks[0] = mp_const_none;
self->readblocks[1] = bdev;
self->readblocks[2] = (mp_obj_t)sdcardio_sdcard_readblocks; // native version
self->writeblocks[0] = mp_const_none;
self->writeblocks[1] = bdev;
self->writeblocks[2] = (mp_obj_t)sdcardio_sdcard_writeblocks; // native version
self->u.ioctl[0] = mp_const_none;
self->u.ioctl[1] = bdev;
self->u.ioctl[2] = (mp_obj_t)sdcardio_sdcard_ioctl; // native version
}
#endif
#if CIRCUITPY_SDIOIO
if (mp_obj_get_type(bdev) == &sdioio_SDCard_type) {
// TODO: Enable native blockdev for SDIO too.
}
#endif
if (self->u.ioctl[0] != MP_OBJ_NULL) {
// Device supports new block protocol, so indicate it
self->flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL;
@ -48,8 +77,10 @@ void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) {
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
mp_uint_t (*f)(uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
return f(buf, block_num, num_blocks);
// CIRCUITPY-CHANGE: Pass the blockdev object into native readblocks so
// it has the corresponding state.
mp_uint_t (*f)(mp_obj_t self, uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
return f(self->readblocks[1], buf, block_num, num_blocks);
} else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, buf};
self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
@ -80,8 +111,10 @@ int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_
}
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
return f(buf, block_num, num_blocks);
// CIRCUITPY-CHANGE: Pass the blockdev object into native readblocks so
// it has the corresponding state.
mp_uint_t (*f)(mp_obj_t self, const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
return f(self->writeblocks[1], buf, block_num, num_blocks);
} else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, (void *)buf};
self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
@ -112,6 +145,16 @@ int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t
mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) {
if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) {
// CIRCUITPY-CHANGE: Support native IOCTL so it can run outside of the VM.
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
size_t out_value;
bool (*f)(mp_obj_t self, uint32_t, uint32_t, size_t *) = (void *)(uintptr_t)self->u.ioctl[2];
bool b = f(self->u.ioctl[1], cmd, arg, &out_value);
if (!b) {
return mp_const_none;
}
return MP_OBJ_NEW_SMALL_INT(out_value);
}
// New protocol with ioctl
self->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(cmd);
self->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(arg);

View file

@ -34,6 +34,10 @@ typedef struct _fs_user_mount_t {
mp_obj_base_t base;
mp_vfs_blockdev_t blockdev;
FATFS fatfs;
// CIRCUITPY-CHANGE: Count the users that are manipulating the blockdev via
// native fatfs so we can lock and unlock the blockdev.
int8_t lock_count;
} fs_user_mount_t;
extern const byte fresult_to_errno_table[20];

@ -1 +1 @@
Subproject commit 267219f161d002e7a724859e01d000a88dc08683
Subproject commit 76dd808fa4a8bc5c20fa2660d3b45ce9b33e2be6

@ -1 +1 @@
Subproject commit f975229b3f0182e7ea857446ca610dee6e54cc95
Subproject commit f90a7cbccfd698f6c2fb36bf787295bcf9ddb910

@ -1 +1 @@
Subproject commit 1f35b4a552045bd1a216507b17833960364dce2c
Subproject commit 0adb75b898a133d929eb14baa2e54b7e9e23899c

@ -1 +1 @@
Subproject commit 4754bf3e5fdb559be9ea085bfb65bd435039e887
Subproject commit 178dbc30ff660fb93dc8fd8d1c193a00067398e4

@ -1 +1 @@
Subproject commit 8efd9f76ceaeae0fc43892108ff71335b8da1888
Subproject commit 5417f6225fb0573853972852ebdfa3aa080fed93

@ -1 +1 @@
Subproject commit 3203fbaea4f6ebc97ff7c3a1dc8dfaa899ff6216
Subproject commit b9c8eedd7b2c7e657ebb8195dde7a6190ae9b866

@ -1 +1 @@
Subproject commit db3b03c4c68a4d4d32a3d145f6fad8935a89a345
Subproject commit 7469b5fd5e24b856f01d59a03eed1c8e7049f0d9

View file

@ -207,7 +207,8 @@ msgid "%q must be multiple of 8."
msgstr ""
#: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c
#: shared-bindings/canio/CAN.c shared-bindings/digitalio/Pull.c
#: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c
#: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c
#: shared-module/synthio/Synthesizer.c
msgid "%q must be of type %q or %q, not %q"
msgstr ""
@ -216,7 +217,7 @@ msgstr ""
msgid "%q must be of type %q, %q, or %q, not %q"
msgstr ""
#: py/argcheck.c shared-bindings/bitmapfilter/__init__.c
#: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c
#: shared-module/synthio/__init__.c
msgid "%q must be of type %q, not %q"
msgstr ""
@ -234,7 +235,7 @@ msgstr ""
#: ports/nrf/common-hal/pulseio/PulseIn.c
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c
#: shared-bindings/canio/Match.c
#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c
msgid "%q out of range"
msgstr ""
@ -498,7 +499,6 @@ msgstr ""
#: 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 ""
@ -521,13 +521,11 @@ msgid "All sync event channels in use"
msgstr ""
#: ports/raspberrypi/common-hal/picodvi/Framebuffer.c
#: shared-bindings/pwmio/PWMOut.c
msgid "All timers for this pin are in use"
msgstr ""
#: ports/atmel-samd/common-hal/_pew/PewPew.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
#: ports/cxd56/common-hal/pulseio/PulseOut.c
@ -538,7 +536,7 @@ msgstr ""
#: ports/nrf/common-hal/audiopwmio/PWMAudioOut.c
#: ports/nrf/common-hal/pulseio/PulseIn.c ports/nrf/peripherals/nrf/timers.c
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
#: ports/stm/peripherals/timers.c shared-bindings/pwmio/PWMOut.c
#: ports/stm/peripherals/timers.c
msgid "All timers in use"
msgstr ""
@ -778,12 +776,6 @@ msgstr ""
msgid "Cannot remount '/' when visible via USB."
msgstr ""
#: ports/atmel-samd/common-hal/microcontroller/__init__.c
#: ports/cxd56/common-hal/microcontroller/__init__.c
#: ports/mimxrt10xx/common-hal/microcontroller/__init__.c
msgid "Cannot reset into bootloader because no bootloader is present"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
msgid "Cannot set socket options"
msgstr ""
@ -801,10 +793,6 @@ msgstr ""
msgid "Cannot subclass slice"
msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid "Cannot vary frequency on a timer that is already in use"
msgstr ""
#: ports/nrf/common-hal/alarm/pin/PinAlarm.c
msgid "Cannot wake on pin edge, only level"
msgstr ""
@ -847,10 +835,6 @@ msgstr ""
msgid "Could not set address"
msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid "Could not start PWM"
msgstr ""
#: ports/stm/common-hal/busio/UART.c
msgid "Could not start interrupt, RX busy"
msgstr ""
@ -942,16 +926,6 @@ msgstr ""
msgid "ESP-IDF memory allocation failed"
msgstr ""
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
#: ports/atmel-samd/common-hal/countio/Counter.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
#: ports/cxd56/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr ""
#: extmod/modre.c
msgid "Error in regex"
msgstr ""
@ -1084,10 +1058,6 @@ msgid ""
"Frequency must be 24, 150, 396, 450, 528, 600, 720, 816, 912, 960 or 1008 Mhz"
msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid "Frequency must match existing PWMOut using this timer"
msgstr ""
#: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c
#: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c
msgid "Function requires lock"
@ -1122,11 +1092,6 @@ msgstr ""
msgid "Heap allocation when VM not running."
msgstr ""
#: supervisor/shared/safe_mode.c
msgid ""
"Heap was corrupted because the stack was too small. Increase stack size."
msgstr ""
#: extmod/vfs_posix_file.c py/objstringio.c
msgid "I/O operation on closed file"
msgstr ""
@ -1202,7 +1167,7 @@ msgid "Internal define error"
msgstr ""
#: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c
#: shared-module/os/getenv.c
#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c
msgid "Internal error"
msgstr ""
@ -1211,6 +1176,16 @@ msgstr ""
msgid "Internal error #%d"
msgstr ""
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
#: ports/atmel-samd/common-hal/countio/Counter.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
#: ports/cxd56/common-hal/pulseio/PulseIn.c shared-bindings/pwmio/PWMOut.c
msgid "Internal resource(s) in use"
msgstr ""
#: supervisor/shared/safe_mode.c
msgid "Internal watchdog timer expired."
msgstr ""
@ -1228,7 +1203,7 @@ msgstr ""
#: ports/raspberrypi/bindings/picodvi/Framebuffer.c
#: ports/raspberrypi/common-hal/picodvi/Framebuffer.c py/argcheck.c
#: shared-bindings/digitalio/DigitalInOut.c
#: shared-bindings/epaperdisplay/EPaperDisplay.c
#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c
msgid "Invalid %q"
msgstr ""
@ -1376,6 +1351,10 @@ msgstr ""
msgid "Missing jmp_pin. %q[%u] jumps on pin"
msgstr ""
#: shared-module/storage/__init__.c
msgid "Mount point directory missing"
msgstr ""
#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c
msgid "Must be a %q subclass."
msgstr ""
@ -1460,8 +1439,10 @@ msgstr ""
msgid "No IP"
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
msgid "No available clocks"
#: ports/atmel-samd/common-hal/microcontroller/__init__.c
#: ports/cxd56/common-hal/microcontroller/__init__.c
#: ports/mimxrt10xx/common-hal/microcontroller/__init__.c
msgid "No bootloader present"
msgstr ""
#: ports/espressif/common-hal/imagecapture/ParallelImageCapture.c
@ -1480,15 +1461,12 @@ msgstr ""
msgid "No default %q bus"
msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
#: ports/atmel-samd/common-hal/touchio/TouchIn.c
msgid "No free GCLKs"
msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "No free GLCKs"
msgstr ""
#: shared-bindings/os/__init__.c
msgid "No hardware random available"
msgstr ""
@ -1687,11 +1665,6 @@ msgstr ""
msgid "Out-buffer elements must be <= 4 bytes long"
msgstr ""
#: shared-bindings/pwmio/PWMOut.c
msgid ""
"PWM frequency not writable when variable_frequency is False on construction."
msgstr ""
#: ports/stm/common-hal/pwmio/PWMOut.c
msgid "PWM restart"
msgstr ""
@ -1737,11 +1710,6 @@ msgstr ""
msgid "Pin must be on PWM Channel B"
msgstr ""
#: ports/atmel-samd/common-hal/countio/Counter.c
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
msgid "Pin must support hardware interrupts"
msgstr ""
#: shared-bindings/rgbmatrix/RGBMatrix.c
#, c-format
msgid ""
@ -1972,6 +1940,10 @@ msgstr ""
msgid "Specify exactly one of data0 or data_pins"
msgstr ""
#: supervisor/shared/safe_mode.c
msgid "Stack overflow. Increase stack size."
msgstr ""
#: shared-bindings/alarm/time/TimeAlarm.c
msgid "Supply one of monotonic_time or epoch_time"
msgstr ""
@ -2078,10 +2050,6 @@ msgstr ""
msgid "Traceback (most recent call last):\n"
msgstr ""
#: shared-bindings/time/__init__.c
msgid "Tuple or struct_time argument required"
msgstr ""
#: ports/stm/common-hal/busio/UART.c
msgid "UART de-init"
msgstr ""
@ -2435,10 +2403,6 @@ msgstr ""
msgid "argsort is not implemented for flattened arrays"
msgstr ""
#: py/runtime.c shared-bindings/supervisor/__init__.c
msgid "argument has wrong type"
msgstr ""
#: py/compile.c
msgid "argument name reused"
msgstr ""
@ -2448,10 +2412,6 @@ msgstr ""
msgid "argument num/types mismatch"
msgstr ""
#: py/runtime.c
msgid "argument should be a '%q' not a '%q'"
msgstr ""
#: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/numpy/transform.c
msgid "arguments must be ndarrays"
msgstr ""
@ -2636,7 +2596,7 @@ msgstr ""
msgid "can't convert %s to float"
msgstr ""
#: py/runtime.c
#: py/objint.c py/runtime.c
#, c-format
msgid "can't convert %s to int"
msgstr ""
@ -2645,18 +2605,10 @@ msgstr ""
msgid "can't convert '%q' object to %q implicitly"
msgstr ""
#: py/objint.c
msgid "can't convert NaN to int"
msgstr ""
#: extmod/ulab/code/numpy/vector.c
msgid "can't convert complex to float"
msgstr ""
#: py/objint.c
msgid "can't convert inf to int"
msgstr ""
#: py/obj.c
msgid "can't convert to complex"
msgstr ""
@ -3144,10 +3096,6 @@ msgstr ""
msgid "function takes %d positional arguments but %d were given"
msgstr ""
#: shared-bindings/time/__init__.c
msgid "function takes exactly 9 arguments"
msgstr ""
#: py/objgenerator.c
msgid "generator already executing"
msgstr ""
@ -3998,10 +3946,6 @@ msgstr ""
msgid "size is defined for ndarrays only"
msgstr ""
#: shared-bindings/time/__init__.c
msgid "sleep length must be non-negative"
msgstr ""
#: py/nativeglue.c
msgid "slice unsupported"
msgstr ""

2
main.c
View file

@ -1099,7 +1099,7 @@ int __attribute__((used)) main(void) {
exit_code = run_repl(get_safe_mode());
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
}
if (exit_code == PYEXEC_FORCED_EXIT) {
if (exit_code & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) {
if (!simulate_reset) {
serial_write_compressed(MP_ERROR_TEXT("soft reboot\n"));
}

View file

@ -235,7 +235,7 @@ static void pinalarm_set_alarms_light(size_t n_alarms, const mp_obj_t *alarms) {
case PINALARM_ERR_NOEXTINT:
raise_ValueError_invalid_pin();
case PINALARM_ERR_NOCHANNEL:
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
default:
mp_raise_RuntimeError(MP_ERROR_TEXT("Unknown reason."));
}

View file

@ -243,7 +243,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
// Find a free GCLK to generate the MCLK signal.
uint8_t gclk = find_free_gclk(divisor);
if (gclk > GCLK_GEN_NUM) {
mp_raise_RuntimeError(MP_ERROR_TEXT("No free GLCKs"));
mp_raise_RuntimeError(MP_ERROR_TEXT("No free GCLKs"));
}
self->gclk = gclk;

View file

@ -1,6 +1,7 @@
#include "common-hal/countio/Counter.h"
#include "shared-bindings/countio/Counter.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "atmel_start_pins.h"
@ -11,13 +12,13 @@
void common_hal_countio_counter_construct(countio_counter_obj_t *self,
const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) {
if (!pin->has_extint) {
mp_raise_RuntimeError(MP_ERROR_TEXT("Pin must support hardware interrupts"));
raise_ValueError_invalid_pin();
}
if (eic_get_enable()) {
if (!eic_channel_free(pin->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
} else {
turn_on_external_interrupt_controller();

View file

@ -295,12 +295,12 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t*
#ifdef SAM_D5X_E5X
((EIC->INTENSET.bit.EXTINT & mask) != 0 || (EIC->EVCTRL.bit.EXTINTEO & mask) != 0)) {
#endif
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
uint8_t timer_index = find_free_timer();
if (timer_index == 0xff) {
mp_raise_RuntimeError(MP_ERROR_TEXT("All timers in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
Tc *tc = tc_insts[timer_index];
@ -329,7 +329,7 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t*
frequencyin_samd51_start_dpll();
if (dpll_gclk == 0xff && !clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
common_hal_frequencyio_frequencyin_deinit(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("No available clocks"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
set_timer_handler(timer_index, dpll_gclk, TC_HANDLER_NO_INTERRUPT);
turn_on_clocks(true, timer_index, dpll_gclk);
@ -399,7 +399,7 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t*
reference_tc = find_free_timer();
if (reference_tc == 0xff) {
common_hal_frequencyio_frequencyin_deinit(self);
mp_raise_RuntimeError(MP_ERROR_TEXT("All timers in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
frequencyin_reference_tc_init();
}

View file

@ -64,7 +64,7 @@ void common_hal_mcu_enable_interrupts(void) {
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if ((runmode == RUNMODE_BOOTLOADER) || (runmode == RUNMODE_UF2)) {
if (!bootloader_available()) {
mp_raise_ValueError(MP_ERROR_TEXT("Cannot reset into bootloader because no bootloader is present"));
mp_raise_ValueError(MP_ERROR_TEXT("No bootloader present"));
}
// Pretend to be the first of the two reset presses needed to enter the
// bootloader. That way one reset will end in the bootloader.

View file

@ -248,7 +248,7 @@ void common_hal_ps2io_ps2_construct(ps2io_ps2_obj_t *self,
mp_arg_error_invalid(MP_QSTR_clock_pin);
}
if (eic_get_enable() && !eic_channel_free(clock_pin->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
clk_hi(self);

View file

@ -155,7 +155,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
raise_ValueError_invalid_pin();
}
if (eic_get_enable() && !eic_channel_free(pin->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t));

View file

@ -150,7 +150,6 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
// one output so we start with the TCs to see if they work.
int8_t direction = -1;
uint8_t start = NUM_TIMERS_PER_PIN - 1;
bool found = false;
if (variable_frequency) {
direction = 1;
start = 0;
@ -162,7 +161,6 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
continue;
}
if (t->is_tc) {
found = true;
Tc *tc = tc_insts[t->index];
if (tc->COUNT16.CTRLA.bit.ENABLE == 0 && t->wave_output == 1) {
timer = t;
@ -178,10 +176,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
}
if (timer == NULL) {
if (found) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
return PWMOUT_ALL_TIMERS_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
uint8_t resolution = 0;

View file

@ -25,6 +25,7 @@
*/
#include "common-hal/rotaryio/IncrementalEncoder.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/rotaryio/IncrementalEncoder.h"
#include "shared-module/rotaryio/IncrementalEncoder.h"
@ -36,8 +37,11 @@
void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self,
const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) {
if (!pin_a->has_extint || !pin_b->has_extint) {
mp_raise_RuntimeError(MP_ERROR_TEXT("Pin must support hardware interrupts"));
if (!pin_a->has_extint) {
raise_ValueError_invalid_pin_name(MP_QSTR_pin_a);
}
if (!pin_b->has_extint) {
raise_ValueError_invalid_pin_name(MP_QSTR_pin_b);
}
// TODO: The SAMD51 has a peripheral dedicated to quadrature encoder debugging. Use it instead
@ -45,7 +49,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
if (eic_get_enable()) {
if (!eic_channel_free(pin_a->extint_channel) || !eic_channel_free(pin_b->extint_channel)) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
}
} else {
turn_on_external_interrupt_controller();

View file

@ -72,7 +72,7 @@ void common_hal_mcu_enable_interrupts(void) {
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if (runmode == RUNMODE_BOOTLOADER) {
mp_raise_ValueError(MP_ERROR_TEXT("Cannot reset into bootloader because no bootloader is present"));
mp_raise_ValueError(MP_ERROR_TEXT("No bootloader present"));
} else if (runmode == RUNMODE_SAFE_MODE) {
safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC);
}

View file

@ -100,7 +100,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
int irq = pulsein_set_config(self, true);
if (irq < 0) {
mp_raise_RuntimeError(MP_ERROR_TEXT("EXTINT channel already in use"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
} else {
pulsein_objects[irq - CXD56_IRQ_EXDEVICE_0] = self;
}

View file

@ -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.

View file

@ -0,0 +1,43 @@
/*
* 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 "Espressif ESP32 DevKitc V4 WROOM-32E"
#define MICROPY_HW_MCU_NAME "ESP32"
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO23}}
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO5, .mosi = &pin_GPIO18, .miso = &pin_GPIO19}}
#define CIRCUITPY_BOARD_UART (1)
#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO17, .rx = &pin_GPIO16}}
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View file

@ -0,0 +1,10 @@
CIRCUITPY_CREATOR_ID = 0x000C303A
CIRCUITPY_CREATION_ID = 0x0032C002
IDF_TARGET = esp32
CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 4MB
CIRCUITPY_ESPCAMERA = 0

View file

@ -0,0 +1,70 @@
#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
// Left Side
// Pins dedicated to SPI flash
{ MP_ROM_QSTR(MP_QSTR_CLK), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
{ 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_IO5), MP_ROM_PTR(&pin_GPIO5) },
{ 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) },
// UART on silkscreen
{ 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_IO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) },
// Right side
// Pins dedicated to SPI flash
{ MP_ROM_QSTR(MP_QSTR_CMD), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) },
// Input-only pins, VP/VN on silkscreen
{ MP_ROM_QSTR(MP_QSTR_I35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_I34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_I39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_VN), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_I36), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_VP), MP_ROM_PTR(&pin_GPIO36) },
// Button
{ MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -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.

View file

@ -0,0 +1,43 @@
/*
* 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 "Espressif ESP32 DevKitc V4 WROVER"
#define MICROPY_HW_MCU_NAME "ESP32"
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO23}}
#define CIRCUITPY_BOARD_SPI (1)
#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO5, .mosi = &pin_GPIO18, .miso = &pin_GPIO19}}
#define CIRCUITPY_BOARD_UART (1)
#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO17, .rx = &pin_GPIO16}}
// UART pins attached to the USB-serial converter chip
#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1)
#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3)

View file

@ -0,0 +1,14 @@
CIRCUITPY_CREATOR_ID = 0x000C303A
CIRCUITPY_CREATION_ID = 0x0032C003
IDF_TARGET = esp32
CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 40m
CIRCUITPY_ESP_FLASH_SIZE = 8MB
CIRCUITPY_ESPCAMERA = 0
CIRCUITPY_ESP_PSRAM_SIZE = 8MB
CIRCUITPY_ESP_PSRAM_MODE = qio
CIRCUITPY_ESP_PSRAM_FREQ = 40m

View file

@ -0,0 +1,70 @@
#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
// Left Side
// Pins dedicated to SPI flash & mem
{ MP_ROM_QSTR(MP_QSTR_CLK), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) },
{ 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_IO5), MP_ROM_PTR(&pin_GPIO5) },
{ 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) },
// UART on silkscreen
{ 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_IO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) },
// Right side
// Pins dedicated to SPI flash & mem
{ MP_ROM_QSTR(MP_QSTR_CMD), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) },
// Normal pins
{ MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) },
// Input-only pins, VP/VN on silkscreen
{ MP_ROM_QSTR(MP_QSTR_I35), MP_ROM_PTR(&pin_GPIO35) },
{ MP_ROM_QSTR(MP_QSTR_I34), MP_ROM_PTR(&pin_GPIO34) },
{ MP_ROM_QSTR(MP_QSTR_I39), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_VN), MP_ROM_PTR(&pin_GPIO39) },
{ MP_ROM_QSTR(MP_QSTR_I36), MP_ROM_PTR(&pin_GPIO36) },
{ MP_ROM_QSTR(MP_QSTR_VP), MP_ROM_PTR(&pin_GPIO36) },
// Button
{ MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -27,9 +27,8 @@
#define MICROPY_HW_BOARD_NAME "DFRobot FireBeetle 2 ESP32-S3"
#define MICROPY_HW_MCU_NAME "ESP32S3"
#define CIRCUITPY_BOARD_I2C (2)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO2, .sda = &pin_GPIO3}, \
{.scl = &pin_GPIO2, .sda = &pin_GPIO1}}
#define CIRCUITPY_BOARD_I2C (1)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO2, .sda = &pin_GPIO1}}
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO17)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO15)

View file

@ -2,8 +2,6 @@
#include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h"
CIRCUITPY_BOARD_BUS_SINGLETON(cam_i2c, i2c, 1) // Camera sensor
STATIC const mp_rom_obj_tuple_t camera_data_tuple = {
// The order matters.
// They must be ordered from low to high (Y2, Y3 .. Y9).
@ -43,9 +41,8 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO1) },
// I2C cannot be used when CAM_I2C is in use.
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) },
@ -118,7 +115,5 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_CAM_HREF), MP_ROM_PTR(&pin_GPIO42)},
{ MP_ROM_QSTR(MP_QSTR_CAM_PCLK), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_CAM_XCLK), MP_ROM_PTR(&pin_GPIO45)},
{ MP_ROM_QSTR(MP_QSTR_CAM_I2C), MP_ROM_PTR(&board_cam_i2c_obj)},
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -73,6 +73,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}
// TODO: Uncomment once the display initialization code is added.
// { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -36,7 +36,8 @@
void board_init(void) {
mp_import_stat_t stat_b = mp_import_stat("boot.py");
if (stat_b != MP_IMPORT_STAT_FILE) {
FATFS *fatfs = filesystem_circuitpy();
fs_user_mount_t *fs_mount = filesystem_circuitpy();
FATFS *fatfs = &fs_mount->fatfs;
FIL fs;
UINT char_written = 0;
const byte buffer[] = "#Serial port upload mode\nimport storage\nstorage.remount(\"/\", False)\nstorage.disable_usb_drive()\n";
@ -44,7 +45,7 @@ void board_init(void) {
f_open(fatfs, &fs, "/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
f_write(&fs, buffer, sizeof(buffer) - 1, &char_written);
f_close(&fs);
// Delete code.Py, use main.py
// Delete code.py, use main.py
mp_import_stat_t stat_c = mp_import_stat("code.py");
if (stat_c == MP_IMPORT_STAT_FILE) {
f_unlink(fatfs, "/code.py");

View file

@ -37,16 +37,16 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_SEL), MP_ROM_PTR(&pin_GPIO39) },
// I2S Amplifier MAX98357A
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_LRCLK), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_BCLK), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_DATA), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_I2S_MIC_SD), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_I2S_AMP_LRCLK), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_I2S_AMP_BCLK), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_I2S_AMP_DATA), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_I2S_AMP_SD), MP_ROM_PTR(&pin_GPIO4) },
// RTC Interrupt Pin
{ MP_ROM_QSTR(MP_QSTR_RTC_INT), MP_ROM_PTR(&pin_GPIO7) },
// LED Matrix
{ MP_ROM_QSTR(MP_QSTR_MATRIX_POWER), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_MATRIX_POWER), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_MATRIX_DATA), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },

View file

@ -103,7 +103,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
}
if (timer_index == INDEX_EMPTY) {
// Running out of timers isn't pin related on ESP32S2.
return PWMOUT_ALL_TIMERS_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
// Find a viable channel
@ -114,7 +114,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
}
}
if (channel_index == INDEX_EMPTY) {
return PWMOUT_ALL_CHANNELS_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
// Run configuration

View file

@ -60,7 +60,8 @@ STATIC uint32_t _cache_lba = 0xffffffff;
#define SECSIZE(fs) ((fs)->ssize)
#endif // FF_MAX_SS == FF_MIN_SS
STATIC DWORD fatfs_bytes(void) {
FATFS *fatfs = filesystem_circuitpy();
fs_user_mount_t *fs_mount = filesystem_circuitpy();
FATFS *fatfs = &fs_mount->fatfs;
return (fatfs->csize * SECSIZE(fatfs)) * (fatfs->n_fatent - 2);
}
STATIC bool storage_extended = true;

View file

@ -107,9 +107,6 @@
#include "esp_log.h"
#define TAG "port"
uint32_t *heap;
uint32_t heap_size;
STATIC esp_timer_handle_t _tick_timer;
STATIC esp_timer_handle_t _sleep_timer;
@ -255,9 +252,6 @@ safe_mode_t port_init(void) {
esp_rom_install_uart_printf();
#endif
heap = NULL;
heap_size = 0;
#define pin_GPIOn(n) pin_GPIO##n
#define pin_GPIOn_EXPAND(x) pin_GPIOn(x)
@ -329,7 +323,16 @@ void *port_malloc(size_t size, bool dma_capable) {
if (dma_capable) {
caps |= MALLOC_CAP_DMA;
}
return heap_caps_malloc(size, caps);
void *ptr = NULL;
// Try SPIRAM first when available.
#ifdef CONFIG_SPIRAM
ptr = heap_caps_malloc(size, caps | MALLOC_CAP_SPIRAM);
#endif
if (ptr == NULL) {
ptr = heap_caps_malloc(size, caps);
}
return ptr;
}
void port_free(void *ptr) {
@ -341,7 +344,7 @@ void *port_realloc(void *ptr, size_t size) {
}
size_t port_heap_get_largest_free_size(void) {
size_t free_size = heap_caps_get_largest_free_block(0);
size_t free_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
return free_size;
}

View file

@ -67,7 +67,7 @@ void PLACE_IN_ITCM(common_hal_mcu_enable_interrupts)(void) {
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
if (runmode == RUNMODE_BOOTLOADER) {
if (!bootloader_available()) {
mp_raise_ValueError(MP_ERROR_TEXT("Cannot reset into bootloader because no bootloader is present"));
mp_raise_ValueError(MP_ERROR_TEXT("No bootloader present"));
}
// Pretend to be the first of the two reset presses needed to enter the
// bootloader. That way one reset will end in the bootloader.

View file

@ -189,7 +189,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
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;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
// We want variable frequency but another class has already claim a fixed frequency.
@ -199,7 +199,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
// Another pin is already using this output.
if ((flexpwm->OUTEN & outen_mask) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
if (frequency != _pwm_sm_frequencies[flexpwm_index][submodule]) {

View file

@ -30,6 +30,7 @@
#include "shared-bindings/busio/I2C.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/tick.h"
#include "py/mperrno.h"
#include "py/runtime.h"
@ -39,18 +40,23 @@
// all TWI instances have the same max size
// 16 bits for 840, 10 bits for 810, 8 bits for 832
#define I2C_MAX_XFER_LEN ((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1)
#define I2C_MAX_XFER_LEN MIN(((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1), 1024)
#define I2C_TIMEOUT 1000 // 1 second timeout
STATIC twim_peripheral_t twim_peripherals[] = {
#if NRFX_CHECK(NRFX_TWIM0_ENABLED)
// SPIM0 and TWIM0 share an address.
{ .twim = NRFX_TWIM_INSTANCE(0),
.in_use = false},
.in_use = false,
.transferring = false,
.last_event_type = NRFX_TWIM_EVT_DONE},
#endif
#if NRFX_CHECK(NRFX_TWIM1_ENABLED)
// SPIM1 and TWIM1 share an address.
{ .twim = NRFX_TWIM_INSTANCE(1),
.in_use = false},
.in_use = false,
.transferring = false,
.last_event_type = NRFX_TWIM_EVT_DONE},
#endif
};
@ -84,9 +90,12 @@ static uint8_t twi_error_to_mp(const nrfx_err_t err) {
return MP_ENODEV;
case NRFX_ERROR_BUSY:
return MP_EBUSY;
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
case NRFX_ERROR_INVALID_ADDR:
case NRFX_ERROR_DRV_TWI_ERR_DNACK:
case NRFX_ERROR_DRV_TWI_ERR_OVERRUN:
return MP_EIO;
case NRFX_ERROR_TIMEOUT:
return MP_ETIMEDOUT;
default:
break;
}
@ -94,6 +103,13 @@ static uint8_t twi_error_to_mp(const nrfx_err_t err) {
return 0;
}
static void twim_event_handler(nrfx_twim_evt_t const *p_event, void *p_context) {
// this is the callback handler - sets transferring to false and records the most recent event.
twim_peripheral_t *peripheral = (twim_peripheral_t *)p_context;
peripheral->last_event_type = p_event->type;
peripheral->transferring = false;
}
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) {
if (scl->number == sda->number) {
raise_ValueError_invalid_pins();
@ -155,7 +171,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *
// About to init. If we fail after this point, common_hal_busio_i2c_deinit() will set in_use to false.
self->twim_peripheral->in_use = true;
nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL);
nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, twim_event_handler, self->twim_peripheral);
if (err != NRFX_SUCCESS) {
common_hal_busio_i2c_deinit(self);
mp_raise_OSError(MP_EIO);
@ -238,6 +254,37 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
self->has_lock = false;
}
STATIC nrfx_err_t _twim_xfer_with_timeout(busio_i2c_obj_t *self, nrfx_twim_xfer_desc_t const *p_xfer_desc, uint32_t flags) {
// does non-blocking transfer and raises and exception if it takes longer than I2C_TIMEOUT ms to complete
uint64_t deadline = supervisor_ticks_ms64() + I2C_TIMEOUT;
nrfx_err_t err = NRFX_SUCCESS;
self->twim_peripheral->transferring = true;
err = nrfx_twim_xfer(&self->twim_peripheral->twim, p_xfer_desc, flags);
if (err != NRFX_SUCCESS) {
self->twim_peripheral->transferring = false;
return err;
}
while (self->twim_peripheral->transferring) {
if (supervisor_ticks_ms64() > deadline) {
self->twim_peripheral->transferring = false;
return NRFX_ERROR_TIMEOUT;
}
}
switch (self->twim_peripheral->last_event_type) {
case NRFX_TWIM_EVT_DONE: ///< Transfer completed event.
return NRFX_SUCCESS;
case NRFX_TWIM_EVT_ADDRESS_NACK: ///< Error event: NACK received after sending the address.
return NRFX_ERROR_DRV_TWI_ERR_ANACK;
case NRFX_TWIM_EVT_BUS_ERROR: ///< Error event: An unexpected transition occurred on the bus.
case NRFX_TWIM_EVT_DATA_NACK: ///< Error event: NACK received after sending a data byte.
return NRFX_ERROR_DRV_TWI_ERR_DNACK;
case NRFX_TWIM_EVT_OVERRUN: ///< Error event: The unread data is replaced by new data.
return NRFX_ERROR_DRV_TWI_ERR_OVERRUN;
default: /// unknown error...
return NRFX_ERROR_INTERNAL;
}
}
STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool stopBit) {
if (len == 0) {
return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV;
@ -253,7 +300,7 @@ STATIC uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_TX(addr, (uint8_t *)data, xact_len);
uint32_t const flags = (stopBit ? 0 : NRFX_TWIM_FLAG_TX_NO_STOP);
if (NRFX_SUCCESS != (err = nrfx_twim_xfer(&self->twim_peripheral->twim, &xfer_desc, flags))) {
if (NRFX_SUCCESS != (err = _twim_xfer_with_timeout(self, &xfer_desc, flags))) {
break;
}
@ -284,7 +331,7 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t
const size_t xact_len = MIN(len, I2C_MAX_XFER_LEN);
nrfx_twim_xfer_desc_t xfer_desc = NRFX_TWIM_XFER_DESC_RX(addr, data, xact_len);
if (NRFX_SUCCESS != (err = nrfx_twim_xfer(&self->twim_peripheral->twim, &xfer_desc, 0))) {
if (NRFX_SUCCESS != (err = _twim_xfer_with_timeout(self, &xfer_desc, 0))) {
break;
}

View file

@ -34,6 +34,9 @@
typedef struct {
nrfx_twim_t twim;
bool in_use;
volatile bool transferring;
nrfx_twim_evt_type_t last_event_type;
uint32_t timeout;
} twim_peripheral_t;
typedef struct {

View file

@ -220,7 +220,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
&channel, &pwm_already_in_use, NULL);
if (self->pwm == NULL) {
return PWMOUT_ALL_TIMERS_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
self->channel = channel;

@ -1 +1 @@
Subproject commit 3f55e49eb11e6db0da1da09e189bb094222702c9
Subproject commit ab21106ea57b63d97b757a9f17201ddf298ffab0

View file

@ -0,0 +1,114 @@
/*
* 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"
#include "mpconfigboard.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/fourwire/FourWire.h"
#include "shared-module/displayio/__init__.h"
#include "shared-module/displayio/mipi_constants.h"
#include "supervisor/shared/board.h"
fourwire_fourwire_obj_t board_display_obj;
#define DELAY 0x80
uint8_t display_init_sequence[] = {
0x01, 0 | DELAY, 150, // SWRESET
0x36, 1, 0x04, // MADCTL
0x35, 1, 0x00, // TEON
0xB2, 5, 0x0c, 0x0c, 0x00, 0x33, 0x33, // FRMCTR2
0x3A, 1, 0x05, // COLMOD
0xB7, 1, 0x14, // GCTRL
0xBB, 1, 0x37, // VCOMS
0xC0, 1, 0x2c, // LCMCTRL
0xC2, 1, 0x01, // VDVVRHEN
0xC3, 1, 0x12, // VRHS
0xC4, 1, 0x20, // VDVS
0xD0, 2, 0xa4, 0xa1, // PWRCTRL1
0xC6, 1, 0x0f, // FRCTRL2
0xE0, 14, 0xd0, 0x04, 0x0d, 0x11, 0x13, 0x2b, 0x3f, 0x54, 0x4c, 0x18, 0x0d, 0x0b, 0x1f, 0x23, // GMCTRP1
0xE1, 14, 0xd0, 0x04, 0x0c, 0x11, 0x13, 0x2c, 0x3f, 0x44, 0x51, 0x2f, 0x1f, 0x1f, 0x20, 0x23, // GMCTRN1
0x21, 0, // INVON
0x11, 0 | DELAY, 255, // SLPOUT
0x29, 0 | DELAY, 100, // DISPON
0x2a, 4, 0x00, 0, 0x00, 0xfe, // CASET
0x2b, 4, 0x00, 0, 0x00, 0xfe, // RASET
0x2c, 0, // RAMWR
};
void board_init(void) {
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
busio_spi_obj_t *spi = &bus->inline_bus;
common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, NULL, false);
common_hal_busio_spi_never_reset(spi);
bus->base.type = &fourwire_fourwire_type;
common_hal_fourwire_fourwire_construct(bus,
spi,
&pin_GPIO16, // TFT_DC Command or data
&pin_GPIO17, // TFT_CS Chip select
NULL, // TFT_RST Reset
62500000, // Baudrate
0, // Polarity
0); // Phase
busdisplay_busdisplay_obj_t *display = &allocate_display()->display;
display->base.type = &busdisplay_busdisplay_type;
common_hal_busdisplay_busdisplay_construct(display,
bus,
240, // Width
280, // Height
0, // column start
20, // row start
0, // rotation
16, // Color depth
false, // Grayscale
false, // pixels in a byte share a row. Only valid for depths < 8
1, // bytes per cell. Only valid for depths < 8
false, // reverse_pixels_in_byte. Only valid for depths < 8
true, // reverse_bytes_in_word
MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
display_init_sequence,
sizeof(display_init_sequence),
NULL, // no backlight pin
NO_BRIGHTNESS_COMMAND,
1.0f, // brightness
false, // single_byte_bounds
false, // data_as_commands
true, // auto_refresh
60, // native_frames_per_second
true, // backlight_on_high
false, // SH1107_addressing
0); // backlight pwm frequency
}
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.

View file

@ -0,0 +1,12 @@
#define MICROPY_HW_BOARD_NAME "HEIA-FR Picomo V2"
#define MICROPY_HW_MCU_NAME "rp2040"
#define CIRCUITPY_RGB_STATUS_R (&pin_GPIO10)
#define CIRCUITPY_RGB_STATUS_G (&pin_GPIO9)
#define CIRCUITPY_RGB_STATUS_B (&pin_GPIO8)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20)
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18)
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19)

View file

@ -0,0 +1,18 @@
USB_VID = 0x2E8A
USB_PID = 0x107D
USB_PRODUCT = "Picomo V2"
USB_MANUFACTURER = "HEIA-FR"
CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2
EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ"
CIRCUITPY__EVE = 1
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ST7789
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ProgressBar

View file

@ -0,0 +1 @@
// Put board-specific pico-sdk definitions here. This file must exist.

View file

@ -0,0 +1,99 @@
#include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h"
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
{ MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) },
{ MP_ROM_QSTR(MP_QSTR_SW_UP), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_S1), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) },
{ MP_ROM_QSTR(MP_QSTR_SW_MID), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_S5), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_SW_DOWN), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_S2), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_SW_TOPR), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_BOOTSEL), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_S7), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_SW_RIGHT), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_S4), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) },
{ MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) },
{ MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_BUZZER), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_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_DISP_DC), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_DISP_CS), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) },
{ MP_ROM_QSTR(MP_QSTR_DISP_SCL), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) },
{ MP_ROM_QSTR(MP_QSTR_DISP_SDA), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_TEMP_SDA), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) },
{ MP_ROM_QSTR(MP_QSTR_TEMP_SCL), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_SW_LEFT), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_S3), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) },
{ MP_ROM_QSTR(MP_QSTR_SW_TOPL), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_S6), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) },
{ MP_ROM_QSTR(MP_QSTR_USB_OVCUR), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) },
{ MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) },
{ MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) },
{ MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) },
{ MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)},
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View file

@ -119,21 +119,21 @@ pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t ab_channel, bool variable
// Check the channel first.
if ((channel_use & channel_use_mask) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
// Now check if the slice is in use and if we can share with it.
if (target_slice_frequencies[slice] > 0) {
// If we want to change frequency then we can't share.
if (variable_frequency) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
return PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE;
}
// If the other user wants a variable frequency then we can't share either.
if ((slice_variable_frequency & (1 << slice)) != 0) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
// If we're both fixed frequency but we don't match target frequencies then we can't share.
if (target_slice_frequencies[slice] != frequency) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
return PWMOUT_INVALID_FREQUENCY_ON_PIN;
}
}

View file

@ -83,7 +83,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
}
if (self->tim == NULL) {
return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
return PWMOUT_INTERNAL_RESOURCES_IN_USE;
}
self->duty_cycle = duty;

View file

@ -26,3 +26,9 @@ MCU_PACKAGE = UFQFPN48
LD_COMMON = boards/common_nvm.ld
LD_FILE = boards/STM32F411_nvm_nofs.ld
# Disable TERMINALIO on translations with missing characters.
ifneq (,$(filter $(TRANSLATION),ja ko ru))
CIRCUITPY_TERMINALIO = 0
RELEASE_NEEDS_CLEAN_BUILD = $(CIRCUITPY_DISPLAYIO)
endif

View file

@ -110,12 +110,12 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
if (tim_index < TIM_BANK_ARRAY_LEN && tim_channels_taken[tim_index] != 0) {
// Timer has already been reserved by an internal module
if (stm_peripherals_timer_is_reserved(mcu_tim_banks[tim_index])) {
last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
last_failure = PWMOUT_INTERNAL_RESOURCES_IN_USE;
continue; // keep looking
}
// is it the same channel? (or all channels reserved by a var-freq)
if (tim_channels_taken[tim_index] & (1 << tim_channel_index)) {
last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
last_failure = PWMOUT_INTERNAL_RESOURCES_IN_USE;
continue; // keep looking, might be another viable option
}
// If the frequencies are the same it's ok

View file

@ -87,7 +87,7 @@ extern void common_hal_mcu_enable_interrupts(void);
#define MICROPY_TRACKED_ALLOC (CIRCUITPY_SSL_MBEDTLS)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_EPOCH_IS_1970 (1)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
#define MICROPY_ERROR_REPORTING (CIRCUITPY_FULL_BUILD ? MICROPY_ERROR_REPORTING_NORMAL : MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_GC_ALLOC_THRESHOLD (0)

View file

@ -49,6 +49,22 @@ const mp_obj_dict_t mp_const_empty_dict_obj = {
}
};
// CIRCUITPY-CHANGE: Native methods are passed the subclass instance so they can
// refer to subclass members. Dict only cares about the native struct so this
// function gets it.
STATIC mp_obj_dict_t *native_dict(mp_obj_t self_in) {
// Check for OrderedDict first because it is marked as a subclass of dict. However, it doesn't
// store its state in subobj like python types to native types do.
mp_obj_t native_instance = MP_OBJ_NULL;
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
native_instance = mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_ordereddict));
#endif
if (native_instance == MP_OBJ_NULL) {
native_instance = mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_dict));
}
return MP_OBJ_TO_PTR(native_instance);
}
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
// This is a helper function to iterate through a dictionary. The state of
@ -71,7 +87,7 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) {
}
STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
bool first = true;
const char *item_separator = ", ";
const char *key_separator = ": ";
@ -144,7 +160,7 @@ mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
}
STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
switch (op) {
case MP_UNARY_OP_BOOL:
return mp_obj_new_bool(self->map.used != 0);
@ -162,7 +178,7 @@ STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in);
mp_obj_dict_t *o = native_dict(lhs_in);
switch (op) {
case MP_BINARY_OP_CONTAINS: {
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
@ -223,7 +239,7 @@ STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_
// Note: Make sure this is inlined in load part of dict_subscr() below.
mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
if (elem == NULL) {
mp_raise_type_arg(&mp_type_KeyError, index);
@ -239,7 +255,7 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return mp_const_none;
} else if (value == MP_OBJ_SENTINEL) {
// load
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
if (elem == NULL) {
mp_raise_type_arg(&mp_type_KeyError, index);
@ -264,7 +280,7 @@ STATIC void PLACE_IN_ITCM(mp_ensure_not_fixed)(const mp_obj_dict_t * dict) {
STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
mp_ensure_not_fixed(self);
mp_map_clear(&self->map);
@ -275,9 +291,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
mp_obj_t mp_obj_dict_copy(mp_obj_t self_in) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
mp_obj_t other_out = mp_obj_new_dict(self->map.alloc);
mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out);
mp_obj_dict_t *other = native_dict(other_out);
other->base.type = self->base.type;
other->map.used = self->map.used;
other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs;
@ -324,7 +340,7 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromk
STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) {
mp_check_self(mp_obj_is_dict_or_ordereddict(args[0]));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_dict_t *self = native_dict(args[0]);
if (lookup_kind != MP_MAP_LOOKUP) {
mp_ensure_not_fixed(self);
}
@ -369,7 +385,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde
STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
mp_ensure_not_fixed(self);
if (self->map.used == 0) {
mp_raise_msg_varg(&mp_type_KeyError, MP_ERROR_TEXT("pop from empty %q"), MP_QSTR_dict);
@ -394,7 +410,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
mp_check_self(mp_obj_is_dict_or_ordereddict(args[0]));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_dict_t *self = native_dict(args[0]);
mp_ensure_not_fixed(self);
mp_arg_check_num(n_args, kwargs->used, 1, 2, true);
@ -520,7 +536,7 @@ typedef struct _mp_obj_dict_view_t {
STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view_it));
mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);
mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);
mp_map_elem_t *next = dict_iter_next(native_dict(self->dict), &self->cur);
if (next == NULL) {
return MP_OBJ_STOP_ITERATION;
@ -726,7 +742,7 @@ size_t mp_obj_dict_len(mp_obj_t self_in) {
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_dict_t *self = native_dict(self_in);
mp_ensure_not_fixed(self);
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
return self_in;

View file

@ -140,9 +140,9 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {
// ...then number is Inf (positive or negative) if fraction is 0, else NaN.
if (u.p.frc == 0) {
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"));
mp_raise_msg_varg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert %s to int"), "inf");
} else {
mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int"));
mp_raise_ValueError_varg(MP_ERROR_TEXT("can't convert %s to int"), "NaN");
}
} else {
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);

View file

@ -27,22 +27,26 @@
#include "py/obj.h"
#include "py/builtin.h"
// CIRCUITPY-CHANGE: These three functions are used by dict only. In CP, we hard
// code the type to dict so that subclassed types still use the native dict
// subscr. MP doesn't have this problem because it passes the native instance
// in. CP passes the subclass instance.
STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) {
const mp_obj_type_t *type = mp_obj_get_type(self_in);
const mp_obj_type_t *type = &mp_type_dict;
// Note: assumes type must have subscr (only used by dict).
return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_SENTINEL);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem);
STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) {
const mp_obj_type_t *type = mp_obj_get_type(self_in);
const mp_obj_type_t *type = &mp_type_dict;
// Note: assumes type must have subscr (only used by dict).
return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, value_in);
}
MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem);
STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) {
const mp_obj_type_t *type = mp_obj_get_type(self_in);
const mp_obj_type_t *type = &mp_type_dict;
// Note: assumes type must have subscr (only used by dict).
return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_NULL);
}

View file

@ -1095,12 +1095,7 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
if (n_args > 0) {
const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]);
if (arg0_type != self->type) {
#if MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED
mp_raise_TypeError(MP_ERROR_TEXT("argument has wrong type"));
#else
mp_raise_msg_varg(&mp_type_TypeError,
MP_ERROR_TEXT("argument should be a '%q' not a '%q'"), self->type->name, arg0_type->name);
#endif
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_self, self->type->name, arg0_type->name);
}
}
return mp_call_function_n_kw(self->fun, n_args, n_kw, args);

View file

@ -134,7 +134,7 @@ STATIC mp_obj_t bitmapfilter_morph(size_t n_args, const mp_obj_t *pos_args, mp_m
mp_obj_t weights = args[ARG_weights].u_obj;
mp_obj_t obj_len = mp_obj_len(weights);
if (obj_len == MP_OBJ_NULL || !mp_obj_is_small_int(obj_len)) {
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_weights, MP_QSTR_Sequence, mp_obj_get_type(weights)->name);
mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be of type %q, not %q"), MP_QSTR_weights, MP_QSTR_Sequence, mp_obj_get_type_qstr(weights));
}
size_t n_weights = MP_OBJ_SMALL_INT_VALUE(obj_len);
@ -608,8 +608,131 @@ STATIC mp_obj_t bitmapfilter_false_color(size_t n_args, const mp_obj_t *pos_args
shared_module_bitmapfilter_false_color(bitmap, mask, palette->colors);
return args[ARG_bitmap].u_obj;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_false_color_obj, 0, bitmapfilter_false_color);
#define BLEND_TABLE_SIZE (4096)
STATIC uint8_t *get_blend_table(mp_obj_t lookup, int mode) {
mp_buffer_info_t lookup_buf;
if (!mp_get_buffer(lookup, &lookup_buf, mode) || lookup_buf.len != BLEND_TABLE_SIZE) {
return NULL;
}
return lookup_buf.buf;
}
//|
//| BlendFunction = Callable[[float, float], float]
//| """A function used to blend two images"""
//|
//| BlendTable = bytearray
//| """A precomputed blend table
//|
//| There is not actually a BlendTable type. The real type is actually any
//| buffer 4096 bytes in length."""
//|
//| def blend_precompute(lookup: BlendFunction, table: BlendTable | None = None) -> BlendTable:
//| """Precompute a BlendTable from a BlendFunction
//|
//| If the optional ``table`` argument is provided, an existing `BlendTable` is updated
//| with the new function values.
//|
//| The function's two arguments will range from 0 to 1. The returned value should also range from 0 to 1.
//|
//| A function to do a 33% blend of each source image could look like this:
//|
//| .. code-block:: python
//|
//| def blend_one_third(a, b):
//| return a * .33 + b * .67
//| """
//|
STATIC mp_obj_t blend_precompute(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_lookup, ARG_table };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_lookup, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_table, MP_ARG_OBJ, { .u_obj = MP_ROM_NONE } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_obj_t table = args[ARG_table].u_obj;
if (table == mp_const_none) {
table = mp_obj_new_bytearray_of_zeros(BLEND_TABLE_SIZE);
}
uint8_t *buf = get_blend_table(table, MP_BUFFER_WRITE);
if (!buf) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"),
MP_QSTR_table, MP_QSTR_NoneType, MP_QSTR_WritableBuffer,
mp_obj_get_type_qstr(table));
}
shared_module_bitmapfilter_blend_precompute(args[ARG_lookup].u_obj, buf);
return table;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_precompute_obj, 0, blend_precompute);
//|
//| def blend(
//| dest: displayio.Bitmap,
//| src1: displayio.Bitmap,
//| src2: displayio.Bitmap,
//| lookup: BlendFunction | BlendTable,
//| mask: displayio.Bitmap | None = None,
//| ) -> displayio.Bitmap:
//| """Blend the 'src1' and 'src2' images according to lookup function or table 'lookup'
//|
//| If ``lookup`` is a function, it is converted to a `BlendTable` by
//| internally calling blend_precompute. If a blend function is used repeatedly
//| it can be more efficient to compute it once with `blend_precompute`.
//|
//| If the mask is supplied, pixels from ``src1`` are taken unchanged in masked areas.
//|
//| The source and destination bitmaps may be the same bitmap.
//|
//| The destination bitmap is returned.
//| """
//|
STATIC mp_obj_t bitmapfilter_blend(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_dest, ARG_src1, ARG_src2, ARG_lookup, ARG_mask };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_dest, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_src1, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_src2, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_lookup, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } },
{ MP_QSTR_mask, MP_ARG_OBJ, { .u_obj = MP_ROM_NONE } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_arg_validate_type(args[ARG_dest].u_obj, &displayio_bitmap_type, MP_QSTR_dest);
displayio_bitmap_t *dest = MP_OBJ_TO_PTR(args[ARG_dest].u_obj);
mp_arg_validate_type(args[ARG_src1].u_obj, &displayio_bitmap_type, MP_QSTR_src1);
displayio_bitmap_t *src1 = MP_OBJ_TO_PTR(args[ARG_src1].u_obj);
mp_arg_validate_type(args[ARG_src2].u_obj, &displayio_bitmap_type, MP_QSTR_src2);
displayio_bitmap_t *src2 = MP_OBJ_TO_PTR(args[ARG_src2].u_obj);
mp_obj_t lookup = args[ARG_lookup].u_obj;
if (mp_obj_is_callable(lookup)) {
lookup = mp_call_function_1(MP_OBJ_FROM_PTR(&bitmapfilter_blend_precompute_obj), lookup);
}
uint8_t *lookup_buf = get_blend_table(lookup, MP_BUFFER_READ);
if (!lookup_buf) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"),
MP_QSTR_lookup, MP_QSTR_callable, MP_QSTR_ReadableBuffer,
mp_obj_get_type_qstr(lookup));
}
displayio_bitmap_t *mask = NULL;
if (args[ARG_mask].u_obj != mp_const_none) {
mp_arg_validate_type(args[ARG_mask].u_obj, &displayio_bitmap_type, MP_QSTR_mask);
mask = MP_OBJ_TO_PTR(args[ARG_mask].u_obj);
}
shared_module_bitmapfilter_blend(dest, src1, src2, mask, lookup_buf);
return args[ARG_dest].u_obj;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_obj, 0, bitmapfilter_blend);
STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmapfilter) },
{ MP_ROM_QSTR(MP_QSTR_morph), MP_ROM_PTR(&bitmapfilter_morph_obj) },
@ -621,6 +744,8 @@ STATIC const mp_rom_map_elem_t bitmapfilter_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ChannelScaleOffset), MP_ROM_PTR(&bitmapfilter_channel_scale_offset_type) },
{ MP_ROM_QSTR(MP_QSTR_ChannelMixer), MP_ROM_PTR(&bitmapfilter_channel_mixer_type) },
{ MP_ROM_QSTR(MP_QSTR_ChannelMixerOffset), MP_ROM_PTR(&bitmapfilter_channel_mixer_offset_type) },
{ MP_ROM_QSTR(MP_QSTR_blend), MP_ROM_PTR(&bitmapfilter_blend_obj) },
{ MP_ROM_QSTR(MP_QSTR_blend_precompute), MP_ROM_PTR(&bitmapfilter_blend_precompute_obj) },
};
STATIC MP_DEFINE_CONST_DICT(bitmapfilter_module_globals, bitmapfilter_module_globals_table);

View file

@ -73,3 +73,12 @@ void shared_module_bitmapfilter_false_color(
displayio_bitmap_t *bitmap,
displayio_bitmap_t *mask,
_displayio_color_t palette[256]);
void shared_module_bitmapfilter_blend_precompute(mp_obj_t fun, uint8_t lookup[4096]);
void shared_module_bitmapfilter_blend(
displayio_bitmap_t *dest,
displayio_bitmap_t *src1,
displayio_bitmap_t *src2,
displayio_bitmap_t *mask,
const uint8_t lookup[4096]);

View file

@ -1063,10 +1063,10 @@ STATIC mp_obj_t bitmaptools_obj_blit(size_t n_args, const mp_obj_t *pos_args, mp
uint16_t x = mp_arg_validate_int_range(args[ARG_x].u_int, 0, destination->width, MP_QSTR_x);
uint16_t y = mp_arg_validate_int_range(args[ARG_y].u_int, 0, destination->height, MP_QSTR_y);
bitmaptools_rect_t lim = bitmaptools_validate_coord_range_pair(&args[ARG_x1], destination->width, destination->height);
displayio_bitmap_t *source = mp_arg_validate_type(args[ARG_source].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap);
bitmaptools_rect_t lim = bitmaptools_validate_coord_range_pair(&args[ARG_x1], source->width, source->height);
// ensure that the target bitmap (self) has at least as many `bits_per_value` as the source
if (destination->bits_per_value < source->bits_per_value) {

View file

@ -46,23 +46,17 @@ void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) {
mp_arg_error_invalid(MP_QSTR_frequency);
break;
case PWMOUT_INVALID_FREQUENCY_ON_PIN:
mp_raise_ValueError(MP_ERROR_TEXT("Frequency must match existing PWMOut using this timer"));
mp_arg_error_invalid(MP_QSTR_frequency);
break;
case PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE:
mp_raise_ValueError(MP_ERROR_TEXT("Cannot vary frequency on a timer that is already in use"));
mp_arg_error_invalid(MP_QSTR_variable_frequency);
break;
case PWMOUT_ALL_TIMERS_ON_PIN_IN_USE:
mp_raise_ValueError(MP_ERROR_TEXT("All timers for this pin are in use"));
break;
case PWMOUT_ALL_TIMERS_IN_USE:
mp_raise_RuntimeError(MP_ERROR_TEXT("All timers in use"));
break;
case PWMOUT_ALL_CHANNELS_IN_USE:
mp_raise_RuntimeError(MP_ERROR_TEXT("All channels in use"));
case PWMOUT_INTERNAL_RESOURCES_IN_USE:
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use"));
break;
default:
case PWMOUT_INITIALIZATION_ERROR:
mp_raise_RuntimeError(MP_ERROR_TEXT("Could not start PWM"));
mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error"));
break;
}
}
@ -268,8 +262,7 @@ STATIC mp_obj_t pwmio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t freque
pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
if (!common_hal_pwmio_pwmout_get_variable_frequency(self)) {
mp_raise_AttributeError(MP_ERROR_TEXT(
"PWM frequency not writable when variable_frequency is False on construction."));
mp_raise_msg_varg(&mp_type_AttributeError, MP_ERROR_TEXT("Invalid %q"), MP_QSTR_variable_frequency);
}
mp_int_t freq = mp_obj_get_int(frequency);
if (freq == 0) {

View file

@ -38,9 +38,7 @@ typedef enum pwmout_result_t {
PWMOUT_INVALID_FREQUENCY,
PWMOUT_INVALID_FREQUENCY_ON_PIN,
PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE,
PWMOUT_ALL_TIMERS_ON_PIN_IN_USE,
PWMOUT_ALL_TIMERS_IN_USE,
PWMOUT_ALL_CHANNELS_IN_USE,
PWMOUT_INTERNAL_RESOURCES_IN_USE,
PWMOUT_INITIALIZATION_ERROR,
} pwmout_result_t;

View file

@ -131,7 +131,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit);
//|
//| :return: None"""
STATIC mp_obj_t sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
STATIC mp_obj_t _sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
@ -143,7 +143,7 @@ STATIC mp_obj_t sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_bloc
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, sdcardio_sdcard_readblocks);
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, _sdcardio_sdcard_readblocks);
//| def sync(self) -> None:
//| """Ensure all blocks written are actually committed to the SD card
@ -171,7 +171,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_sync_obj, sdcardio_sdcard_sync);
//| :return: None"""
//|
STATIC mp_obj_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
STATIC mp_obj_t _sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
@ -182,7 +182,7 @@ STATIC mp_obj_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_blo
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, sdcardio_sdcard_writeblocks);
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, _sdcardio_sdcard_writeblocks);
STATIC const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) },

View file

@ -27,4 +27,19 @@
#pragma once
#include "shared-module/sdcardio/SDCard.h"
extern const mp_obj_type_t sdcardio_SDCard_type;
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate);
void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self);
void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
// Used by native vfs blockdev.
mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen);
mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen);
bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value);

View file

@ -164,7 +164,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_count_obj, sdioio_sdcard_count);
//| :param ~circuitpython_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512.
//|
//| :return: None"""
STATIC mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
STATIC mp_obj_t _sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
@ -176,7 +176,7 @@ STATIC mp_obj_t sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, sdioio_sdcard_readblocks);
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, _sdioio_sdcard_readblocks);
//| def writeblocks(self, start_block: int, buf: ReadableBuffer) -> None:
//| """Write one or more blocks to the card
@ -185,7 +185,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, sdioio_sdcard_readblocks
//| :param ~circuitpython_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512.
//|
//| :return: None"""
STATIC mp_obj_t sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
STATIC mp_obj_t _sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
uint32_t start_block = mp_obj_get_int(start_block_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
@ -197,7 +197,7 @@ STATIC mp_obj_t sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_writeblocks_obj, sdioio_sdcard_writeblocks);
MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_writeblocks_obj, _sdioio_sdcard_writeblocks);
//| frequency: int
//| """The actual SDIO bus frequency. This may not match the frequency

View file

@ -130,11 +130,12 @@ STATIC mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
mp_arg_val_t sticky_on_reload;
} args;
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
if (!mp_obj_is_str_or_bytes(args.filename.u_obj) && args.filename.u_obj != mp_const_none) {
mp_raise_TypeError(MP_ERROR_TEXT("argument has wrong type"));
mp_obj_t filename_obj = args.filename.u_obj;
if (!mp_obj_is_str_or_bytes(filename_obj) && filename_obj != mp_const_none) {
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_filename, MP_QSTR_str, MP_QSTR_None, mp_obj_get_type(filename_obj)->name);
}
if (args.filename.u_obj == mp_const_none) {
args.filename.u_obj = mp_const_empty_bytes;
if (filename_obj == mp_const_none) {
filename_obj = mp_const_empty_bytes;
}
uint8_t options = 0;
if (args.reload_on_success.u_bool) {
@ -153,7 +154,7 @@ STATIC mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
options |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD;
}
size_t len;
const char *filename = mp_obj_str_get_data(args.filename.u_obj, &len);
const char *filename = mp_obj_str_get_data(filename_obj, &len);
if (next_code_configuration != NULL) {
port_free(next_code_configuration);
next_code_configuration = NULL;

View file

@ -83,9 +83,7 @@ STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
mp_int_t seconds = mp_obj_get_int(seconds_o);
mp_int_t msecs = 1000 * seconds;
#endif
if (seconds < 0) {
mp_raise_ValueError(MP_ERROR_TEXT("sleep length must be non-negative"));
}
mp_arg_validate_int_min(msecs, 0, MP_QSTR_seconds);
common_hal_time_delay_ms(msecs);
return mp_const_none;
}
@ -161,13 +159,13 @@ void struct_time_to_tm(mp_obj_t t, timeutils_struct_time_t *tm) {
mp_obj_t *elems;
size_t len;
if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, (mp_obj_type_t *)&struct_time_type_obj.base)) {
mp_raise_TypeError(MP_ERROR_TEXT("Tuple or struct_time argument required"));
if (!mp_obj_is_type(t, &mp_type_tuple)) {
mp_arg_validate_type(t, (mp_obj_type_t *)&struct_time_type_obj.base, MP_QSTR_value);
}
mp_obj_tuple_get(t, &len, &elems);
if (len != 9) {
mp_raise_TypeError(MP_ERROR_TEXT("function takes exactly 9 arguments"));
mp_raise_TypeError_varg(MP_ERROR_TEXT("function takes %d positional arguments but %d were given"), 9, len);
}
tm->tm_year = mp_obj_get_int(elems[0]);
@ -277,8 +275,8 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
mp_obj_t *elem;
size_t len;
if (!mp_obj_is_type(t, &mp_type_tuple) && !mp_obj_is_type(t, (mp_obj_type_t *)&struct_time_type_obj.base)) {
mp_raise_TypeError(MP_ERROR_TEXT("Tuple or struct_time argument required"));
if (!mp_obj_is_type(t, &mp_type_tuple)) {
mp_arg_validate_type(t, (mp_obj_type_t *)&struct_time_type_obj.base, MP_QSTR_value);
}
mp_obj_tuple_get(t, &len, &elem);
@ -287,7 +285,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
}
if (mp_obj_get_int(elem[0]) < 2000) {
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("timestamp out of range for platform time_t"));
mp_raise_msg_varg(&mp_type_OverflowError, MP_ERROR_TEXT("%q out of range"), MP_QSTR_tm_year);
}
mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),

View file

@ -72,6 +72,9 @@
//| in_report_lengths=(5, 2),
//| out_report_lengths=(6, 0),
//| )
//|
//| The HID device is able to wake up a suspended (sleeping) host computer.
//| See `send_report()` for details.
//| """
//| ...
//| KEYBOARD: Device
@ -166,6 +169,16 @@ STATIC mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args
//| """Send an HID report. If the device descriptor specifies zero or one report id's,
//| you can supply `None` (the default) as the value of ``report_id``.
//| Otherwise you must specify which report id to use when sending the report.
//|
//| If the USB host is suspended (sleeping), then `send_report()` will request that the host wake up.
//| The ``report`` itself will be discarded, to prevent unwanted extraneous characters,
//| mouse clicks, etc.
//|
//| Note: Host operating systems allow enabling and disabling specific devices
//| and kinds of devices to do wakeup.
//| The defaults are different for different operating systems.
//| For instance, on Linux, only the primary keyboard may be enabled.
//| In addition, there may be USB wakeup settings in the host computer BIOS/UEFI.
//| """
//| ...
STATIC mp_obj_t usb_hid_device_send_report(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {

View file

@ -31,7 +31,7 @@
#pragma GCC diagnostic ignored "-Wshadow"
static void check_matching_details(displayio_bitmap_t *b1, displayio_bitmap_t *b2) {
if (b1->width != b2->width || b1->height != b2->height) {
if (b1->width != b2->width || b1->height != b2->height || b1->bits_per_value != b2->bits_per_value) {
mp_raise_ValueError(MP_ERROR_TEXT("bitmap size and depth must match"));
}
}
@ -105,8 +105,6 @@ void shared_module_bitmapfilter_morph(
const int32_t m_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * m);
const int32_t b_int = (int32_t)MICROPY_FLOAT_C_FUN(round)(65536 * COLOR_G6_MAX * b);
check_matching_details(bitmap, bitmap);
switch (bitmap->bits_per_value) {
default:
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
@ -220,8 +218,6 @@ void shared_module_bitmapfilter_mix(
wt[i] = (int32_t)MICROPY_FLOAT_C_FUN(round)(scale * weights[i]);
}
check_matching_details(bitmap, bitmap);
switch (bitmap->bits_per_value) {
default:
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
@ -368,3 +364,64 @@ void shared_module_bitmapfilter_false_color(
}
}
}
void shared_module_bitmapfilter_blend_precompute(mp_obj_t fun, uint8_t lookup[4096]) {
uint8_t *ptr = lookup;
for (int i = 0; i < 64; i++) {
mp_obj_t fi = mp_obj_new_float(i * (1 / MICROPY_FLOAT_CONST(63.)));
for (int j = 0; j < 64; j++) {
mp_obj_t fj = mp_obj_new_float(j * (1 / MICROPY_FLOAT_CONST(63.)));
mp_float_t res = mp_obj_get_float(mp_call_function_2(fun, fi, fj));
*ptr++ = res < 0 ? 0 : res > 1 ? 1 : (uint8_t)MICROPY_FLOAT_C_FUN(round)(63 * res);
}
}
}
#define FIVE_TO_SIX(x) ({ int tmp = (x); (tmp << 1) | (tmp & 1); })
#define SIX_TO_FIVE(x) ((x) >> 1)
void shared_module_bitmapfilter_blend(
displayio_bitmap_t *bitmap,
displayio_bitmap_t *src1,
displayio_bitmap_t *src2,
displayio_bitmap_t *mask,
const uint8_t lookup[4096]) {
check_matching_details(bitmap, src1);
check_matching_details(bitmap, src2);
switch (bitmap->bits_per_value) {
default:
mp_raise_ValueError(MP_ERROR_TEXT("unsupported bitmap depth"));
case 16: {
for (int y = 0, yy = bitmap->height; y < yy; y++) {
uint16_t *dest_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(bitmap, y);
uint16_t *src1_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src1, y);
uint16_t *src2_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src2, y);
for (int x = 0, xx = bitmap->width; x < xx; x++) {
int pixel1 = IMAGE_GET_RGB565_PIXEL_FAST(src1_ptr, x);
if (mask && common_hal_displayio_bitmap_get_pixel(mask, x, y)) {
IMAGE_PUT_RGB565_PIXEL_FAST(dest_ptr, x, pixel1);
continue; // Short circuit.
}
int pixel2 = IMAGE_GET_RGB565_PIXEL_FAST(src2_ptr, x);
int r1 = FIVE_TO_SIX(COLOR_RGB565_TO_R5(pixel1));
int r2 = FIVE_TO_SIX(COLOR_RGB565_TO_R5(pixel2));
int r = SIX_TO_FIVE(lookup[r1 * 64 + r2]);
int g1 = COLOR_RGB565_TO_G6(pixel1);
int g2 = COLOR_RGB565_TO_G6(pixel2);
int g = lookup[g1 * 64 + g2];
int b1 = FIVE_TO_SIX(COLOR_RGB565_TO_B5(pixel1));
int b2 = FIVE_TO_SIX(COLOR_RGB565_TO_B5(pixel2));
int b = SIX_TO_FIVE(lookup[b1 * 64 + b2]);
int pixel = COLOR_R5_G6_B5_TO_RGB565(r, g, b);
IMAGE_PUT_RGB565_PIXEL_FAST(dest_ptr, x, pixel);
}
}
}
}
}

View file

@ -507,6 +507,7 @@ void epaperdisplay_epaperdisplay_collect_ptrs(epaperdisplay_epaperdisplay_obj_t
displayio_display_bus_collect_ptrs(&self->bus);
gc_collect_ptr((void *)self->start_sequence);
gc_collect_ptr((void *)self->stop_sequence);
gc_collect_ptr((void *)self->refresh_sequence);
}
size_t maybe_refresh_epaperdisplay(void) {

View file

@ -62,8 +62,12 @@ STATIC bool open_file(const char *name, file_arg *active_file) {
return false;
}
#else
FATFS *fs = filesystem_circuitpy();
FRESULT result = f_open(fs, active_file, name, FA_READ);
fs_user_mount_t *fs_mount = filesystem_circuitpy();
if (fs_mount == NULL) {
return false;
}
FATFS *fatfs = &fs_mount->fatfs;
FRESULT result = f_open(fatfs, active_file, name, FA_READ);
return result == FR_OK;
#endif
}

View file

@ -26,6 +26,8 @@
// This implementation largely follows the structure of adafruit_sdcard.py
#include "extmod/vfs.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/sdcardio/SDCard.h"
@ -358,23 +360,24 @@ STATIC int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) {
return 0;
}
STATIC int readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
uint32_t nblocks = buf->len / 512;
mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) {
sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (!lock_and_configure_bus(self)) {
return MP_EAGAIN;
}
int r = 0;
size_t buflen = 512 * nblocks;
if (nblocks == 1) {
// Use CMD17 to read a single block
return block_cmd(self, 17, start_block, buf->buf, buf->len, true, true);
r = block_cmd(self, 17, start_block, buf, buflen, true, true);
} else {
// Use CMD18 to read multiple blocks
int r = block_cmd(self, 18, start_block, NULL, 0, true, true);
if (r < 0) {
return r;
}
uint8_t *ptr = buf->buf;
while (nblocks--) {
r = block_cmd(self, 18, start_block, NULL, 0, true, true);
uint8_t *ptr = buf;
while (nblocks-- && r >= 0) {
r = readinto(self, ptr, 512);
if (r < 0) {
return r;
if (r != 0) {
break;
}
ptr += 512;
}
@ -387,12 +390,13 @@ STATIC int readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buff
uint8_t single_byte;
common_hal_busio_spi_read(self->bus, &single_byte, 1, 0xff);
if (single_byte & 0x80) {
return r;
break;
}
r = single_byte;
}
}
return 0;
extraclock_and_unlock_bus(self);
return r;
}
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
@ -401,10 +405,7 @@ int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t
mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512"));
}
lock_and_configure_bus(self);
int r = readblocks(self, start_block, buf);
extraclock_and_unlock_bus(self);
return r;
return sdcardio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512);
}
STATIC int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) {
@ -452,17 +453,20 @@ STATIC int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t
return 0;
}
STATIC int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) {
mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) {
sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_sdcardio_check_for_deinit(self);
uint32_t nblocks = buf->len / 512;
DEBUG_PRINT("cmd25? %d next_block %d start_block %d\n", self->in_cmd25, self->next_block, start_block);
if (!lock_and_configure_bus(self)) {
return MP_EAGAIN;
}
if (!self->in_cmd25 || start_block != self->next_block) {
DEBUG_PRINT("entering CMD25 at %d\n", (int)start_block);
// Use CMD25 to write multiple block
int r = block_cmd(self, 25, start_block, NULL, 0, true, true);
if (r < 0) {
extraclock_and_unlock_bus(self);
return r;
}
self->in_cmd25 = true;
@ -470,17 +474,19 @@ STATIC int writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buf
self->next_block = start_block;
uint8_t *ptr = buf->buf;
uint8_t *ptr = buf;
while (nblocks--) {
int r = _write(self, TOKEN_CMD25, ptr, 512);
if (r < 0) {
self->in_cmd25 = false;
extraclock_and_unlock_bus(self);
return r;
}
self->next_block++;
ptr += 512;
}
extraclock_and_unlock_bus(self);
return 0;
}
@ -498,7 +504,29 @@ int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t
mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512"));
}
lock_and_configure_bus(self);
int r = writeblocks(self, start_block, buf);
int r = sdcardio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512);
extraclock_and_unlock_bus(self);
return r;
}
bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) {
sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
*out_value = 0;
switch (cmd) {
case MP_BLOCKDEV_IOCTL_DEINIT:
common_hal_sdcardio_sdcard_sync(self);
break; // TODO properly
case MP_BLOCKDEV_IOCTL_SYNC:
common_hal_sdcardio_sdcard_sync(self);
break;
case MP_BLOCKDEV_IOCTL_BLOCK_COUNT:
*out_value = common_hal_sdcardio_sdcard_get_blockcount(self);
break;
case MP_BLOCKDEV_IOCTL_BLOCK_SIZE:
*out_value = 512;
break;
default:
return false;
}
return true;
}

View file

@ -44,11 +44,3 @@ typedef struct {
uint32_t next_block;
bool in_cmd25;
} sdcardio_sdcard_obj_t;
void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate);
void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self);
void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);
int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self);
int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf);

View file

@ -177,15 +177,20 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool rea
args[0] = readonly ? mp_const_true : mp_const_false;
args[1] = mp_const_false; // Don't make the file system automatically when mounting.
// Check that there's no file or directory with the same name as the mount point.
// Check that there is a directory with the same name as the mount point.
// But it's ok to mount '/' in any case.
if (strcmp(vfs->str, "/") != 0) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
common_hal_os_stat(mount_path);
mp_obj_t mount_point_stat = common_hal_os_stat(mount_path);
nlr_pop();
// Something with the same name exists.
mp_raise_OSError(MP_EEXIST);
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mount_point_stat);
if ((MP_OBJ_SMALL_INT_VALUE(t->items[0]) & MP_S_IFDIR) == 0) {
mp_raise_RuntimeError(MP_ERROR_TEXT("Mount point directory missing"));
}
} else {
// Something with the same name doesn't exist.
mp_raise_RuntimeError(MP_ERROR_TEXT("Mount point directory missing"));
}
}

View file

@ -229,6 +229,7 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t *
RUN_BACKGROUND_TASKS;
}
if (!tud_suspended()) {
if (!tud_hid_ready()) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB busy"));
}
@ -236,6 +237,9 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t *
if (!tud_hid_report(report_id, report, len)) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("USB error"));
}
} else {
tud_remote_wakeup();
}
}
mp_obj_t common_hal_usb_hid_device_get_last_received_report(usb_hid_device_obj_t *self, uint8_t report_id) {

View file

@ -602,7 +602,7 @@ raw_repl_reset:
}
int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
if (ret & PYEXEC_FORCED_EXIT) {
if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) {
return ret;
}
}
@ -739,7 +739,7 @@ friendly_repl_reset:
}
ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
if (ret & PYEXEC_FORCED_EXIT) {
if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) {
return ret;
}
}

View file

@ -24,8 +24,7 @@
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H
#define MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H
#pragma once
#include <stdbool.h>
@ -45,6 +44,16 @@ void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concu
bool filesystem_is_writable_by_python(fs_user_mount_t *vfs);
bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs);
FATFS *filesystem_circuitpy(void);
fs_user_mount_t *filesystem_circuitpy(void);
fs_user_mount_t *filesystem_for_path(const char *path_in, const char **path_under_mount);
bool filesystem_native_fatfs(fs_user_mount_t *fs_mount);
#endif // MICROPY_INCLUDED_SUPERVISOR_FILESYSTEM_H
// We have two levels of locking. filesystem_* calls grab a shared blockdev lock to allow
// CircuitPython's fatfs code edit the blocks. blockdev_* class grab a lock to mutate blocks
// directly, excluding any filesystem_* locks.
bool filesystem_lock(fs_user_mount_t *fs_mount);
void filesystem_unlock(fs_user_mount_t *fs_mount);
bool blockdev_lock(fs_user_mount_t *fs_mount);
void blockdev_unlock(fs_user_mount_t *fs_mount);

View file

@ -126,13 +126,21 @@ void background_callback_reset() {
background_callback_t *cb = (background_callback_t *)callback_head;
while (cb) {
background_callback_t *next = cb->next;
if (gc_ptr_on_heap((void *)cb)) {
*previous_next = cb;
previous_next = &cb->next;
cb->next = NULL;
new_tail = cb;
// Unlink any callbacks that are allocated on the python heap or if they
// reference data on the python heap. The python heap will be disappear
// soon after this.
if (gc_ptr_on_heap((void *)cb) || gc_ptr_on_heap(cb->data)) {
cb->prev = NULL; // Used to indicate a callback isn't queued.
} else {
memset(cb, 0, sizeof(*cb));
// Set .next of the previous callback.
*previous_next = cb;
// Set our .next for the next callback.
previous_next = &cb->next;
// Set our prev to the last callback.
cb->prev = new_tail;
// Now we're the tail of the list.
new_tail = cb;
}
cb = next;
}

View file

@ -151,6 +151,7 @@ STATIC uint64_t truncate_time(uint64_t input_time, DWORD *fattime) {
// Used by read and write.
STATIC FIL active_file;
STATIC fs_user_mount_t *active_mount;
STATIC uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) {
struct read_command *command = (struct read_command *)raw_buf;
size_t header_size = sizeof(struct read_command);
@ -170,11 +171,19 @@ STATIC uint8_t _process_read(const uint8_t *raw_buf, size_t command_len) {
return THIS_COMMAND;
}
char *path = (char *)((uint8_t *)command) + header_size;
path[command->path_length] = '\0';
char *full_path = (char *)((uint8_t *)command) + header_size;
full_path[command->path_length] = '\0';
FATFS *fs = filesystem_circuitpy();
FRESULT result = f_open(fs, &active_file, path, FA_READ);
const char *mount_path;
active_mount = filesystem_for_path(full_path, &mount_path);
if (active_mount == NULL || !filesystem_native_fatfs(active_mount)) {
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, response_size, NULL, 0);
return ANY_COMMAND;
}
FATFS *fs = &active_mount->fatfs;
FRESULT result = f_open(fs, &active_file, mount_path, FA_READ);
if (result != FR_OK) {
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, response_size, NULL, 0);
@ -250,22 +259,6 @@ STATIC uint8_t _process_read_pacing(const uint8_t *raw_buf, size_t command_len)
STATIC size_t total_write_length;
STATIC uint64_t _truncated_time;
// Returns true if usb is active and replies with an error if so. If not, it grabs
// the USB mass storage lock and returns false. Make sure to release the lock with
// usb_msc_unlock() when the transaction is complete.
STATIC bool _usb_active(void *response, size_t response_size) {
// Check to see if USB has already been mounted. If not, then we "eject" from USB until we're done.
#if CIRCUITPY_USB && CIRCUITPY_USB_MSC
if (storage_usb_enabled() && !usb_msc_lock()) {
// Status is always the second byte of the response.
((uint8_t *)response)[1] = STATUS_ERROR_READONLY;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)response, response_size, NULL, 0);
return true;
}
#endif
return false;
}
STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
struct write_command *command = (struct write_command *)raw_buf;
size_t header_size = sizeof(struct write_command);
@ -284,23 +277,31 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
}
total_write_length = command->total_length;
char *path = (char *)command->path;
path[command->path_length] = '\0';
if (_usb_active(&response, sizeof(struct write_pacing))) {
char *full_path = (char *)command->path;
full_path[command->path_length] = '\0';
const char *mount_path;
active_mount = filesystem_for_path(full_path, &mount_path);
if (active_mount == NULL || !filesystem_native_fatfs(active_mount)) {
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
return ANY_COMMAND;
}
if (!filesystem_lock(active_mount)) {
response.status = STATUS_ERROR_READONLY;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
return ANY_COMMAND;
}
FATFS *fs = filesystem_circuitpy();
FATFS *fs = &active_mount->fatfs;
DWORD fattime;
_truncated_time = truncate_time(command->modification_time, &fattime);
override_fattime(fattime);
FRESULT result = f_open(fs, &active_file, path, FA_WRITE | FA_OPEN_ALWAYS);
FRESULT result = f_open(fs, &active_file, mount_path, FA_WRITE | FA_OPEN_ALWAYS);
if (result != FR_OK) {
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
filesystem_unlock(active_mount);
override_fattime(0);
return ANY_COMMAND;
}
@ -315,9 +316,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
f_truncate(&active_file);
f_close(&active_file);
override_fattime(0);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
filesystem_unlock(active_mount);
}
response.offset = offset;
response.free_space = chunk_size;
@ -342,9 +341,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
// TODO: throw away any more packets of path.
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
filesystem_unlock(active_mount);
override_fattime(0);
return ANY_COMMAND;
}
@ -360,9 +357,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
// TODO: throw away any more packets of path.
response.status = STATUS_ERROR;
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct write_pacing), NULL, 0);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
filesystem_unlock(active_mount);
override_fattime(0);
return ANY_COMMAND;
}
@ -377,9 +372,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
f_truncate(&active_file);
f_close(&active_file);
override_fattime(0);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
filesystem_unlock(active_mount);
// Don't reload until everything is written out of the packet buffer.
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
return ANY_COMMAND;
@ -399,29 +392,19 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct delete_status), NULL, 0);
return ANY_COMMAND;
}
if (_usb_active(&response, sizeof(struct delete_status))) {
return ANY_COMMAND;
}
// We need to receive another packet to have the full path.
if (command_len < header_size + command->path_length) {
return THIS_COMMAND;
}
FATFS *fs = filesystem_circuitpy();
char *path = (char *)((uint8_t *)command) + header_size;
path[command->path_length] = '\0';
FILINFO file;
FRESULT result = f_stat(fs, path, &file);
if (result == FR_OK) {
if ((file.fattrib & AM_DIR) != 0) {
result = supervisor_workflow_delete_directory_contents(fs, path);
char *full_path = (char *)((uint8_t *)command) + header_size;
full_path[command->path_length] = '\0';
FRESULT result = supervisor_workflow_delete_recursive(full_path);
if (result == FR_WRITE_PROTECTED) {
response.status = STATUS_ERROR_READONLY;
}
if (result == FR_OK) {
result = f_unlink(fs, path);
}
}
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
if (result != FR_OK) {
response.status = STATUS_ERROR;
}
@ -456,25 +439,16 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct mkdir_status), NULL, 0);
return ANY_COMMAND;
}
if (_usb_active(&response, sizeof(struct mkdir_status))) {
return ANY_COMMAND;
}
// We need to receive another packet to have the full path.
if (command_len < header_size + command->path_length) {
return THIS_COMMAND;
}
FATFS *fs = filesystem_circuitpy();
char *path = (char *)command->path;
_terminate_path(path, command->path_length);
char *full_path = (char *)command->path;
_terminate_path(full_path, command->path_length);
DWORD fattime;
response.truncated_time = truncate_time(command->modification_time, &fattime);
override_fattime(fattime);
FRESULT result = supervisor_workflow_mkdir_parents(fs, path);
override_fattime(0);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
FRESULT result = supervisor_workflow_mkdir(fattime, full_path);
if (result != FR_OK) {
response.status = STATUS_ERROR;
}
@ -520,12 +494,21 @@ STATIC uint8_t _process_listdir(uint8_t *raw_buf, size_t command_len) {
return THIS_COMMAND;
}
FATFS *fs = filesystem_circuitpy();
char *path = (char *)&command->path;
_terminate_path(path, command->path_length);
// mp_printf(&mp_plat_print, "list %s\n", path);
char *full_path = (char *)&command->path;
_terminate_path(full_path, command->path_length);
const char *mount_path;
active_mount = filesystem_for_path(full_path, &mount_path);
if (active_mount == NULL || !filesystem_native_fatfs(active_mount)) {
entry->command = LISTDIR_ENTRY;
entry->status = STATUS_ERROR_NO_FILE;
send_listdir_entry_header(entry, max_packet_size);
return ANY_COMMAND;
}
FATFS *fs = &active_mount->fatfs;
FF_DIR dir;
FRESULT res = f_opendir(fs, &dir, path);
FRESULT res = f_opendir(fs, &dir, mount_path);
entry->command = LISTDIR_ENTRY;
entry->status = STATUS_OK;
@ -601,27 +584,21 @@ STATIC uint8_t _process_move(const uint8_t *raw_buf, size_t command_len) {
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0);
return ANY_COMMAND;
}
if (_usb_active(&response, sizeof(struct move_status))) {
return ANY_COMMAND;
}
// We need to receive another packet to have the full path.
if (command_len < header_size + total_path_length) {
return THIS_COMMAND;
}
FATFS *fs = filesystem_circuitpy();
char *old_path = (char *)command->paths;
old_path[command->old_path_length] = '\0';
char *new_path = old_path + command->old_path_length + 1;
new_path[command->new_path_length] = '\0';
// mp_printf(&mp_plat_print, "move %s to %s\n", old_path, new_path);
FRESULT result = f_rename(fs, old_path, new_path);
#if CIRCUITPY_USB_MSC
usb_msc_unlock();
#endif
if (result != FR_OK) {
FRESULT result = supervisor_workflow_move(old_path, new_path);
if (result == FR_WRITE_PROTECTED) {
response.status = STATUS_ERROR_READONLY;
} else if (result != FR_OK) {
response.status = STATUS_ERROR;
}
common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, (const uint8_t *)&response, sizeof(struct move_status), NULL, 0);

View file

@ -221,9 +221,56 @@ bool filesystem_present(void) {
return _mp_vfs.len > 0;
}
FATFS *filesystem_circuitpy(void) {
fs_user_mount_t *filesystem_circuitpy(void) {
if (!filesystem_present()) {
return NULL;
}
return &_internal_vfs.fatfs;
return &_internal_vfs;
}
fs_user_mount_t *filesystem_for_path(const char *path_in, const char **path_under_mount) {
mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path_in, path_under_mount);
if (vfs == MP_VFS_NONE) {
return NULL;
}
fs_user_mount_t *fs_mount;
*path_under_mount = path_in;
if (vfs == MP_VFS_ROOT) {
fs_mount = filesystem_circuitpy();
} else {
fs_mount = MP_OBJ_TO_PTR(vfs->obj);
*path_under_mount += strlen(vfs->str);
}
return fs_mount;
}
bool filesystem_native_fatfs(fs_user_mount_t *fs_mount) {
return fs_mount->base.type == &mp_fat_vfs_type && (fs_mount->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) != 0;
}
bool filesystem_lock(fs_user_mount_t *fs_mount) {
if (fs_mount->lock_count == 0 && !blockdev_lock(fs_mount)) {
return false;
}
fs_mount->lock_count += 1;
return true;
}
void filesystem_unlock(fs_user_mount_t *fs_mount) {
fs_mount->lock_count -= 1;
if (fs_mount->lock_count == 0) {
blockdev_unlock(fs_mount);
}
}
bool blockdev_lock(fs_user_mount_t *fs_mount) {
if ((fs_mount->blockdev.flags & MP_BLOCKDEV_FLAG_LOCKED) != 0) {
return false;
}
fs_mount->blockdev.flags |= MP_BLOCKDEV_FLAG_LOCKED;
return true;
}
void blockdev_unlock(fs_user_mount_t *fs_mount) {
fs_mount->blockdev.flags &= ~MP_BLOCKDEV_FLAG_LOCKED;
}

View file

@ -87,7 +87,7 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo
buf[15] = num_blocks >> 24;
}
static mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
static mp_uint_t flash_read_blocks(mp_obj_t self, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
if (block_num == 0) {
// fake the MBR so we can decide on our own partition table
@ -117,7 +117,7 @@ static mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t n
static volatile bool filesystem_dirty = false;
static mp_uint_t flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
static mp_uint_t flash_write_blocks(mp_obj_t self, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
if (block_num == 0) {
if (num_blocks > 1) {
return 1; // error
@ -150,7 +150,7 @@ void PLACE_IN_ITCM(supervisor_flash_flush)(void) {
STATIC mp_obj_t supervisor_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
mp_uint_t ret = flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE);
mp_uint_t ret = flash_read_blocks(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_readblocks_obj, supervisor_flash_obj_readblocks);
@ -158,13 +158,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_readblocks_obj, supervisor
STATIC mp_obj_t supervisor_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
mp_uint_t ret = flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE);
mp_uint_t ret = flash_write_blocks(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE);
return MP_OBJ_NEW_SMALL_INT(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_writeblocks_obj, supervisor_flash_obj_writeblocks);
static bool flash_ioctl(size_t cmd, mp_int_t *out_value) {
STATIC bool flash_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) {
if (out_value != NULL) {
*out_value = 0;
}
switch (cmd) {
case MP_BLOCKDEV_IOCTL_INIT:
supervisor_flash_init();
@ -189,8 +191,9 @@ static bool flash_ioctl(size_t cmd, mp_int_t *out_value) {
STATIC mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
mp_int_t cmd = mp_obj_get_int(cmd_in);
mp_int_t arg = mp_obj_get_int(arg_in);
mp_int_t out_value;
if (flash_ioctl(cmd, &out_value)) {
if (flash_ioctl(self, cmd, arg, &out_value)) {
return MP_OBJ_NEW_SMALL_INT(out_value);
}
return mp_const_none;

Some files were not shown because too many files have changed in this diff Show more