From 5ac3aeaac72ad0624d78900a5a70a45035ab7880 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:47 -0500 Subject: [PATCH 01/30] Remove unused header --- shared-bindings/floppyio/__init__.c | 1 - 1 file changed, 1 deletion(-) diff --git a/shared-bindings/floppyio/__init__.c b/shared-bindings/floppyio/__init__.c index 3ef58b2f66..a6b041c4a0 100644 --- a/shared-bindings/floppyio/__init__.c +++ b/shared-bindings/floppyio/__init__.c @@ -31,7 +31,6 @@ #include #include "py/binary.h" -#include "py/enum.h" #include "py/obj.h" #include "py/runtime.h" From 8e08cc38f852111d8b9870a84de1c548ad753cb4 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:48 -0500 Subject: [PATCH 02/30] Add default I2C bus to Kaluga --- ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h | 3 +++ ports/espressif/boards/espressif_kaluga_1.3/pins.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h b/ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h index 8f89bfcbc4..459a5b3289 100644 --- a/ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h +++ b/ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h @@ -30,3 +30,6 @@ #define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_NEOPIXEL (&pin_GPIO45) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO7) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) diff --git a/ports/espressif/boards/espressif_kaluga_1.3/pins.c b/ports/espressif/boards/espressif_kaluga_1.3/pins.c index dff98ceeb9..caa7ecd064 100644 --- a/ports/espressif/boards/espressif_kaluga_1.3/pins.c +++ b/ports/espressif/boards/espressif_kaluga_1.3/pins.c @@ -140,5 +140,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S1_LRCK_DAC1), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_AUDIO_I2S1_BCLK_DAC2), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); From 07afb3eab81463e588c05bf2183568728d0887e8 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:49 -0500 Subject: [PATCH 03/30] Fix typo --- shared-bindings/countio/Edge.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/countio/Edge.h b/shared-bindings/countio/Edge.h index ca4cddbef3..86112fb4a3 100644 --- a/shared-bindings/countio/Edge.h +++ b/shared-bindings/countio/Edge.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2021 an Halbertfor Adafruit Industries + * Copyright (c) 2021 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 From 5db6db01287079b0314a5356cd9b5c40886e4d23 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:50 -0500 Subject: [PATCH 04/30] add esp32-camera This uses the esp32-camera code instead of our own homebrewed camera code. In theory it supports esp32, esp32-s2 and esp32-s3, as long as they have PSRAM. This is very basic and doesn't support changing any camera parameters, including switching resolution or pixelformat. This is tested on the Kaluga (ESP32-S2) and ESP32-S3-Eye boards. First, reserve some PSRAM by putting this line in `CIRCUITPY/_env`: ``` CIRCUITPY_RESERVED_PSRAM=524288 ``` and hard-reset the board for it to take effect. Now, the following script will take a very low-resolution jpeg file and print it in the REPL in escape coded form: ```python import board import esp32_camera c = esp32_camera.Camera( data_pins=board.CAMERA_DATA, external_clock_pin=board.CAMERA_XCLK, pixel_clock_pin=board.CAMERA_PCLK, vsync_pin=board.CAMERA_VSYNC, href_pin=board.CAMERA_HREF, pixel_format=esp32_camera.PixelFormat.JPEG, i2c=board.I2C(), external_clock_frequency=20_000_000) m = c.take() if m is not None: print(bytes(m)) ``` Then on desktop open a python repl and run something like ```python >>> with open("my.jpg", "wb") as f: f.write() ``` and open my.jpg in a viewer. --- .gitmodules | 3 + ports/espressif/CMakeLists.txt | 7 + ports/espressif/Makefile | 28 +- .../espressif/bindings/esp32_camera/Camera.c | 232 +++++++++++++++++ .../espressif/bindings/esp32_camera/Camera.h | 59 +++++ .../bindings/esp32_camera/__init__.c | 243 ++++++++++++++++++ .../bindings/esp32_camera/__init__.h | 43 ++++ .../boards/espressif_esp32s3_eye/board.c | 48 ++++ .../espressif_esp32s3_eye/mpconfigboard.h | 39 +++ .../espressif_esp32s3_eye/mpconfigboard.mk | 17 ++ .../boards/espressif_esp32s3_eye/pins.c | 55 ++++ .../boards/espressif_esp32s3_eye/sdkconfig | 34 +++ .../common-hal/esp32_camera/Camera.c | 144 +++++++++++ .../common-hal/esp32_camera/Camera.h | 38 +++ .../esp-idf-config/sdkconfig-esp32s3.defaults | 28 ++ ports/espressif/esp32-camera | 1 + ports/espressif/mpconfigport.mk | 10 +- ports/espressif/supervisor/port.c | 1 + py/circuitpy_mpconfig.mk | 3 + 19 files changed, 1026 insertions(+), 7 deletions(-) create mode 100644 ports/espressif/bindings/esp32_camera/Camera.c create mode 100644 ports/espressif/bindings/esp32_camera/Camera.h create mode 100644 ports/espressif/bindings/esp32_camera/__init__.c create mode 100644 ports/espressif/bindings/esp32_camera/__init__.h create mode 100644 ports/espressif/boards/espressif_esp32s3_eye/board.c create mode 100644 ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h create mode 100644 ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk create mode 100644 ports/espressif/boards/espressif_esp32s3_eye/pins.c create mode 100644 ports/espressif/boards/espressif_esp32s3_eye/sdkconfig create mode 100644 ports/espressif/common-hal/esp32_camera/Camera.c create mode 100644 ports/espressif/common-hal/esp32_camera/Camera.h create mode 160000 ports/espressif/esp32-camera diff --git a/.gitmodules b/.gitmodules index 0177e5a2ea..e0d0a262ca 100644 --- a/.gitmodules +++ b/.gitmodules @@ -307,3 +307,6 @@ [submodule "frozen/circuitpython_picoed"] path = frozen/circuitpython_picoed url = https://github.com/elecfreaks/circuitpython_picoed.git +[submodule "ports/espressif/esp32-camera"] + path = ports/espressif/esp32-camera + url = https://github.com/adafruit/esp32-camera/ diff --git a/ports/espressif/CMakeLists.txt b/ports/espressif/CMakeLists.txt index 1c79b448fe..d05af27539 100644 --- a/ports/espressif/CMakeLists.txt +++ b/ports/espressif/CMakeLists.txt @@ -8,6 +8,13 @@ set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf) # can build. set(COMPONENTS esptool_py soc driver log main esp-tls mbedtls mdns esp_event esp_adc_cal esp_netif esp_wifi lwip wpa_supplicant freertos bt usb) +if("${CIRCUITPY_ESP32_CAMERA}") +message("Including esp32-camera") +set(EXTRA_COMPONENT_DIRS "esp32-camera") +list(APPEND COMPONENTS "esp32-camera") +message("COMPONENTS = ${COMPONENTS}") +endif() + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(circuitpython) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index e111fa3441..e8baf35935 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -261,7 +261,6 @@ SRC_C += \ peripherals/touch.c ifeq ($(IDF_TARGET),esp32s2) SRC_C += \ - cam.c \ i2s_lcd_esp32s2_driver.c endif endif @@ -283,6 +282,22 @@ endif SRC_C += $(wildcard common-hal/espidf/*.c) +ifneq ($(CIRCUITPY_ESP32_CAMERA),0) +SRC_CAMERA := \ + $(wildcard common-hal/esp32_camera/*.c) \ + $(wildcard bindings/esp32_camera/*.c) +SRC_C += $(SRC_CAMERA) +$(info SRC_CAMERA = $(SRC_CAMERA)) +CFLAGS += -isystem esp32-camera/driver/include +CFLAGS += -isystem esp32-camera/conversions/include +endif + +ifneq ($(CIRCUITPY_IMAGECAPTURE),0) +$(error IMAGECAPTURE) +SRC_C += cam.c +endif + + SRC_COMMON_HAL_EXPANDED = \ $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ @@ -341,8 +356,10 @@ ifneq ($(CIRCUITPY_BLEIO),0) SDKCONFIGS := esp-idf-config/sdkconfig-ble.defaults;$(SDKCONFIGS) endif # create the config headers -$(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig | $(BUILD)/esp-idf - IDF_PATH=$(IDF_PATH) cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="$(SDKCONFIGS)" -DCMAKE_TOOLCHAIN_FILE=$(IDF_PATH)/tools/cmake/toolchain-$(IDF_TARGET).cmake -DIDF_TARGET=$(IDF_TARGET) -GNinja +.PHONY: do-sdkconfig +do-sdkconfig: $(BUILD)/esp-idf/config/sdkconfig.h +$(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig CMakeLists.txt | $(BUILD)/esp-idf + IDF_PATH=$(IDF_PATH) cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="$(SDKCONFIGS)" -DCMAKE_TOOLCHAIN_FILE=$(IDF_PATH)/tools/cmake/toolchain-$(IDF_TARGET).cmake -DIDF_TARGET=$(IDF_TARGET) -GNinja -DCIRCUITPY_ESP32_CAMERA=$(CIRCUITPY_ESP32_CAMERA) # build a lib # Adding -d explain -j 1 -v to the ninja line will output debug info @@ -391,6 +408,11 @@ BINARY_BLOBS += esp-idf/components/xtensa/$(IDF_TARGET)/libxt_hal.a ESP_IDF_COMPONENTS_EXPANDED += esp-idf/components/xtensa/$(IDF_TARGET)/libxt_hal.a endif +ifneq ($(CIRCUITPY_ESP32_CAMERA),0) +ESP_IDF_COMPONENTS_EXPANDED += $(BUILD)/esp-idf/esp-idf/esp32-camera/libesp32-camera.a +#$(error $(ESP_IDF_COMPONENTS_EXPANDED)) +endif + # BOOTLOADER_OFFSET is determined by chip type, based on the ROM bootloader, and is not changeable. ifeq ($(IDF_TARGET),esp32) BOOTLOADER_OFFSET = 0x1000 diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c new file mode 100644 index 0000000000..2dc61f73ca --- /dev/null +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -0,0 +1,232 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/mphal.h" +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +#include "bindings/esp32_camera/__init__.h" +#include "bindings/esp32_camera/Camera.h" +#include "common-hal/esp32_camera/Camera.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "esp_camera.h" +#include "sensor.h" + +//| class Camera: +//| def __init__( +//| self, +//| *, +//| data_pins: List[microcontroller.Pin], +//| pixel_clock: microcontroller.Pin, +//| vsync: microcontroller.Pin, +//| href: microcontroller.Pin, +//| i2c: busio.I2C, +//| external_clock_pin: microcontroller.Pin, +//| external_clock_frequency: int, +//| powerdown_pin: Optional[microcontroller.Pin] = None, +//| reset_pin: Optional[microcontroller.Pin] = None, +//| pixel_format: PixelFormat=PixelFormat.RGB565, +//| frame_size: FrameSize=FrameSize.QQVGA, +//| jpeg_quality: int=15, +//| double_buffered: bool = True, +//| grab_mode: GrabMode = GrabMode.WhenEmpty, +//| ): +//| """ +//| Configure and initialize a camera with the given properties +//| +//| This driver requires that the ``CIRCUITPY_RESERVED_PSRAM`` in ``/.env`` be large enough to hold the camera frambuffer(s). Generally, boards with built-in cameras will have a default setting that is large enough. If the constructor raises a MemoryError, this probably indicates the setting is too small and should be increased. +//| +//| :param data_pins: The 8 data data_pins used for image data transfer from the camera module, least significant bit first +//| :param pixel_clock: The pixel clock output from the camera module +//| :param vsync: The vertical sync pulse output from the camera module +//| :param href: The horizontal reference output from the camera module +//| :param i2c: The I2C bus connected to the camera module +//| :param external_clock_frequency: The frequency generated on the external clock pin +//| :param external_clock_pin: The pin on which to generate the external clock +//| :param powerdown_pin: The powerdown input to the camera module +//| :param reset_pin: The reset input to the camera module +//| :param pixel_format: The pixel format of the captured image +//| :param frame_size: The size of captured image +//| :param jpeg_quality: For `PixelFormat.JPEG`, the quality. Higher numbers increase quality. If the quality is too high, the JPEG data will be larger than the availalble buffer size and the image will be unusable or truncated. The exact range of appropriate values depends on the sensor and must be determined empirically. +//| :param framebuffer_count: The number of framebuffers +//| :param grab_mode: When to grab a new frame +//| """ +//| +STATIC mp_obj_t esp32_camera_camera_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_data_pins, ARG_pixel_clock_pin, ARG_vsync_pin, ARG_href_pin, ARG_i2c, ARG_external_clock_pin, ARG_external_clock_frequency, ARG_powerdown_pin, ARG_reset_pin, ARG_pixel_format, ARG_frame_size, ARG_jpeg_quality, ARG_framebuffer_count, ARG_grab_mode, NUM_ARGS }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_data_pins, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_pixel_clock_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_vsync_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_href_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_i2c, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_external_clock_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY }, + { MP_QSTR_external_clock_frequency, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_powerdown_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_NONE } }, + { MP_QSTR_reset_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_NONE } }, + { MP_QSTR_pixel_format, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_PTR((void *)&pixel_format_RGB565_obj) } }, + { MP_QSTR_frame_size, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_PTR((void *)&frame_size_QQVGA_obj) } }, + { MP_QSTR_jpeg_quality, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 15 } }, + { MP_QSTR_framebuffer_count, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 1 } }, + { MP_QSTR_grab_mode, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_PTR((void *)&grab_mode_WHEN_EMPTY_obj) } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + MP_STATIC_ASSERT(MP_ARRAY_SIZE(allowed_args) == NUM_ARGS); + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + uint8_t data_pins[8]; + uint8_t data_pin_count; + validate_pins(MP_QSTR_data_pins, data_pins, MP_ARRAY_SIZE(data_pins), args[ARG_data_pins].u_obj, &data_pin_count); + mp_arg_validate_length(data_pin_count, 8, MP_QSTR_data_pins); + + const mcu_pin_obj_t *pixel_clock_pin = validate_obj_is_free_pin(args[ARG_pixel_clock_pin].u_obj); + const mcu_pin_obj_t *vsync_pin = validate_obj_is_free_pin(args[ARG_vsync_pin].u_obj); + const mcu_pin_obj_t *href_pin = validate_obj_is_free_pin(args[ARG_href_pin].u_obj); + const busio_i2c_obj_t *i2c = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c)); + const mcu_pin_obj_t *external_clock_pin = validate_obj_is_free_pin(args[ARG_external_clock_pin].u_obj); + const mcu_pin_obj_t *powerdown_pin = validate_obj_is_free_pin_or_none(args[ARG_powerdown_pin].u_obj); + const mcu_pin_obj_t *reset_pin = validate_obj_is_free_pin_or_none(args[ARG_reset_pin].u_obj); + const mp_int_t external_clock_frequency = mp_arg_validate_int_range(args[ARG_external_clock_frequency].u_int, 0, 40000000, MP_QSTR_clock_frequency); + + camera_grab_mode_t grab_mode = validate_grab_mode(args[ARG_grab_mode].u_obj, MP_QSTR_grab_mode); + framesize_t frame_size = validate_frame_size(args[ARG_frame_size].u_obj, MP_QSTR_frame_size); + pixformat_t pixel_format = validate_pixel_format(args[ARG_pixel_format].u_obj, MP_QSTR_pixel_format); + mp_int_t jpeg_quality = mp_arg_validate_int_range(args[ARG_jpeg_quality].u_int, 2, 55, MP_QSTR_jpeg_quality); + mp_int_t framebuffer_count = mp_arg_validate_int_range(args[ARG_framebuffer_count].u_int, 1, 2, MP_QSTR_framebuffer_count); + + esp32_camera_camera_obj_t *self = m_new_obj(esp32_camera_camera_obj_t); + self->base.type = &esp32_camera_camera_type; + common_hal_esp32_camera_camera_construct( + self, + data_pins, + external_clock_pin, + pixel_clock_pin, + vsync_pin, + href_pin, + powerdown_pin, + reset_pin, + i2c, + external_clock_frequency, + pixel_format, + frame_size, + jpeg_quality, + framebuffer_count, + grab_mode); + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the camera and releases all memory resources for reuse.""" +//| ... +//| +STATIC mp_obj_t esp32_camera_camera_deinit(mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_esp32_camera_camera_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_deinit_obj, esp32_camera_camera_deinit); + +STATIC void check_for_deinit(esp32_camera_camera_obj_t *self) { + if (common_hal_esp32_camera_camera_deinited(self)) { + raise_deinited_error(); + } +} + +//| def __enter__(self) -> Camera: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +STATIC mp_obj_t esp32_camera_camera_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_esp32_camera_camera_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera___exit___obj, 4, 4, esp32_camera_camera_obj___exit__); + +//| frame_available: bool +//| """True if a frame is available, False otherwise""" + +STATIC mp_obj_t esp32_camera_camera_frame_available_get(const mp_obj_t self_in) { + return mp_obj_new_bool(false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_frame_available_get_obj, esp32_camera_camera_frame_available_get); + +MP_PROPERTY_GETTER(esp32_camera_camera_frame_available_obj, + (mp_obj_t)&esp32_camera_camera_frame_available_get_obj); + +//| def take(timeout: Optional[float]=0.25) -> Optional[ReadableBuffer]: +//| """Record a frame. Wait up to 'timeout' seconds for a frame to be captured.""" +//| +STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(args[0]); + mp_float_t timeout = n_args < 2 ? MICROPY_FLOAT_CONST(0.25) : mp_obj_get_float(args[1]); + check_for_deinit(self); + camera_fb_t *result = common_hal_esp32_camera_camera_take(self, (int)MICROPY_FLOAT_C_FUN(round)(timeout * 1000)); + if (!result) { + return mp_const_none; + } + return mp_obj_new_memoryview('b', result->len, result->buf); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera_take_obj, 1, 2, esp32_camera_camera_take); + +//| pixel_format: PixelFormat +//| """The pixel format of the camera""" +//| +//| frame_size: FrameSize +//| """The size of the captured image""" +//| +//| contrast: int +//| """The contrast of the sensor""" + +STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { + { MP_ROM_QSTR(MP_QSTR_take), MP_ROM_PTR(&esp32_camera_camera_take_obj) }, + { MP_ROM_QSTR(MP_QSTR_frame_available), MP_ROM_PTR(&esp32_camera_camera_frame_available_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_camera_camera_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&esp32_camera_camera___exit___obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(esp32_camera_camera_locals_dict, esp32_camera_camera_locals_table); + +const mp_obj_type_t esp32_camera_camera_type = { + .base = { &mp_type_type }, + .name = MP_QSTR_Camera, + .make_new = esp32_camera_camera_make_new, + .locals_dict = (mp_obj_t)&esp32_camera_camera_locals_dict, +}; diff --git a/ports/espressif/bindings/esp32_camera/Camera.h b/ports/espressif/bindings/esp32_camera/Camera.h new file mode 100644 index 0000000000..1163b14f61 --- /dev/null +++ b/ports/espressif/bindings/esp32_camera/Camera.h @@ -0,0 +1,59 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "py/enum.h" +#include "py/obj.h" + +#include "esp_camera.h" + +#include "shared-bindings/busio/I2C.h" + +extern const mp_obj_type_t esp32_camera_camera_type; +typedef struct esp32_camera_camera_obj esp32_camera_camera_obj_t; + +extern void common_hal_esp32_camera_camera_construct( + esp32_camera_camera_obj_t *self, + uint8_t data_pins[8], + const mcu_pin_obj_t *external_clock_pin, + const mcu_pin_obj_t *pixel_clock_pin, + const mcu_pin_obj_t *vsync_pin, + const mcu_pin_obj_t *href_pin, + const mcu_pin_obj_t *powerdown_pin, + const mcu_pin_obj_t *reset_pin, + const busio_i2c_obj_t *i2c, + mp_int_t external_clock_frequency, + pixformat_t pixel_format, + framesize_t frame_size, + mp_int_t jpeg_quality, + mp_int_t framebuffer_count, + camera_grab_mode_t grab_mode); + +extern void common_hal_esp32_camera_camera_deinit(esp32_camera_camera_obj_t *self); +extern bool common_hal_esp32_camera_camera_deinited(esp32_camera_camera_obj_t *self); +extern bool common_hal_esp32_camera_camera_available(esp32_camera_camera_obj_t *self); +extern camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self, int timeout_ms); diff --git a/ports/espressif/bindings/esp32_camera/__init__.c b/ports/espressif/bindings/esp32_camera/__init__.c new file mode 100644 index 0000000000..d56084e977 --- /dev/null +++ b/ports/espressif/bindings/esp32_camera/__init__.c @@ -0,0 +1,243 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "bindings/espidf/__init__.h" +#include "bindings/esp32_camera/__init__.h" +#include "bindings/esp32_camera/Camera.h" + +#include "esp_camera.h" +#include "sensor.h" + +int oooo; + +//| """Wrapper for the esp32_camera library +//| +//| This library enables access to any camera sensor supported by the library, +//| including OV5640 and OV2640. +//| """ + +//| class GrabMode: +//| """Controls when a new frame is grabbed.""" +//| +//| WHEN_EMPTY: GrabMode +//| """Fills buffers when they are empty. Less resources but first ``fb_count`` frames might be old""" +//| +//| LATEST: GrabMode +//| """Except when 1 frame buffer is used, queue will always contain the last `fb_count` frames""" +//| + +MAKE_ENUM_VALUE(esp32_camera_grab_mode_type, grab_mode, WHEN_EMPTY, CAMERA_GRAB_WHEN_EMPTY); +MAKE_ENUM_VALUE(esp32_camera_grab_mode_type, grab_mode, LATEST, CAMERA_GRAB_LATEST); + +MAKE_ENUM_MAP(esp32_camera_grab_mode) { + MAKE_ENUM_MAP_ENTRY(grab_mode, WHEN_EMPTY), + MAKE_ENUM_MAP_ENTRY(grab_mode, LATEST), +}; + +STATIC MP_DEFINE_CONST_DICT(esp32_camera_grab_mode_locals_dict, esp32_camera_grab_mode_locals_table); +MAKE_PRINTER(esp32_camera, esp32_camera_grab_mode); +MAKE_ENUM_TYPE(esp32_camera, GrabMode, esp32_camera_grab_mode); + +camera_grab_mode_t validate_grab_mode(mp_obj_t obj, qstr arg_name) { + return cp_enum_value(&esp32_camera_grab_mode_type, mp_arg_validate_type(obj, &esp32_camera_grab_mode_type, arg_name)); +} + +//| class PixelFormat: +//| """Format of data in the captured frames""" +//| +//| RGB565: PixelFormat +//| """A 16-bit format with 5 bits of Red and Blue and 6 bits of Green""" +//| +//| GRAYSCALE: PixelFormat +//| """An 8-bit format with 8-bits of luminance""" +//| +//| JPEG: PixelFormat +//| """A compressed format""" +//| + +MAKE_ENUM_VALUE(esp32_camera_pixel_format_type, pixel_format, RGB565, PIXFORMAT_RGB565); +MAKE_ENUM_VALUE(esp32_camera_pixel_format_type, pixel_format, GRAYSCALE, PIXFORMAT_GRAYSCALE); +MAKE_ENUM_VALUE(esp32_camera_pixel_format_type, pixel_format, JPEG, PIXFORMAT_JPEG); + +MAKE_ENUM_MAP(esp32_camera_pixel_format) { + MAKE_ENUM_MAP_ENTRY(pixel_format, RGB565), + MAKE_ENUM_MAP_ENTRY(pixel_format, GRAYSCALE), + MAKE_ENUM_MAP_ENTRY(pixel_format, JPEG), +}; + +STATIC MP_DEFINE_CONST_DICT(esp32_camera_pixel_format_locals_dict, esp32_camera_pixel_format_locals_table); +MAKE_PRINTER(esp32_camera, esp32_camera_pixel_format); +MAKE_ENUM_TYPE(esp32_camera, PixelFormat, esp32_camera_pixel_format); + +pixformat_t validate_pixel_format(mp_obj_t obj, qstr arg_name) { + return cp_enum_value(&esp32_camera_pixel_format_type, mp_arg_validate_type(obj, &esp32_camera_pixel_format_type, arg_name)); +} + +//| class FrameSize: +//| """The pixel size of the captured frames""" +//| +//| R96X96: FrameSize +//| """96x96""" +//| +//| QQVGA: FrameSize +//| """160x120""" +//| +//| QCIF: FrameSize +//| """176x144""" +//| +//| HQVGA: FrameSize +//| """240x176""" +//| +//| R240X240: FrameSize +//| """240x240""" +//| +//| QVGA: FrameSize +//| """320x240 """ +//| +//| CIF: FrameSize +//| """400x296""" +//| +//| HVGA: FrameSize +//| """480x320""" +//| +//| VGA: FrameSize +//| """640x480""" +//| +//| SVGA: FrameSize +//| """800x600""" +//| +//| XGA: FrameSize +//| """1024x768""" +//| +//| HD: FrameSize +//| """1280x720""" +//| +//| SXGA: FrameSize +//| """1280x1024""" +//| +//| UXGA: FrameSize +//| """1600x1200""" +//| +//| FHD: FrameSize +//| """1920x1080""" +//| +//| P_HD: FrameSize +//| """ 720x1280""" +//| +//| P_3MP: FrameSize +//| """ 864x1536""" +//| +//| QXGA: FrameSize +//| """2048x1536""" +//| +//| QHD: FrameSize +//| """2560x1440""" +//| +//| WQXGA: FrameSize +//| """2560x1600""" +//| +//| P_FHD: FrameSize +//| """1080x1920""" +//| +//| QSXGA: FrameSize +//| """2560x1920""" +//| + +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, R96X96, FRAMESIZE_96X96); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, R240X240, FRAMESIZE_240X240); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, QQVGA, FRAMESIZE_QQVGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, QCIF, FRAMESIZE_QCIF); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, HQVGA, FRAMESIZE_HQVGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, QVGA, FRAMESIZE_QVGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, CIF, FRAMESIZE_CIF); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, HVGA, FRAMESIZE_HVGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, VGA, FRAMESIZE_VGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, SVGA, FRAMESIZE_SVGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, XGA, FRAMESIZE_XGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, HD, FRAMESIZE_HD); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, SXGA, FRAMESIZE_SXGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, UXGA, FRAMESIZE_UXGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, FHD, FRAMESIZE_FHD); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, P_HD, FRAMESIZE_P_HD); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, P_3MP, FRAMESIZE_P_3MP); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, QXGA, FRAMESIZE_QXGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, QHD, FRAMESIZE_QHD); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, WQXGA, FRAMESIZE_WQXGA); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, P_FHD, FRAMESIZE_P_FHD); +MAKE_ENUM_VALUE(esp32_camera_frame_size_type, frame_size, QSXGA, FRAMESIZE_QSXGA); +MAKE_ENUM_MAP(esp32_camera_frame_size) { + MAKE_ENUM_MAP_ENTRY(frame_size, R96X96), + MAKE_ENUM_MAP_ENTRY(frame_size, R240X240), + MAKE_ENUM_MAP_ENTRY(frame_size, QQVGA), + MAKE_ENUM_MAP_ENTRY(frame_size, QCIF), + MAKE_ENUM_MAP_ENTRY(frame_size, HQVGA), + MAKE_ENUM_MAP_ENTRY(frame_size, QVGA), + MAKE_ENUM_MAP_ENTRY(frame_size, CIF), + MAKE_ENUM_MAP_ENTRY(frame_size, HVGA), + MAKE_ENUM_MAP_ENTRY(frame_size, VGA), + MAKE_ENUM_MAP_ENTRY(frame_size, SVGA), + MAKE_ENUM_MAP_ENTRY(frame_size, XGA), + MAKE_ENUM_MAP_ENTRY(frame_size, HD), + MAKE_ENUM_MAP_ENTRY(frame_size, SXGA), + MAKE_ENUM_MAP_ENTRY(frame_size, UXGA), + MAKE_ENUM_MAP_ENTRY(frame_size, FHD), + MAKE_ENUM_MAP_ENTRY(frame_size, P_HD), + MAKE_ENUM_MAP_ENTRY(frame_size, P_3MP), + MAKE_ENUM_MAP_ENTRY(frame_size, QXGA), + MAKE_ENUM_MAP_ENTRY(frame_size, QHD), + MAKE_ENUM_MAP_ENTRY(frame_size, WQXGA), + MAKE_ENUM_MAP_ENTRY(frame_size, P_FHD), + MAKE_ENUM_MAP_ENTRY(frame_size, QSXGA), +}; + +STATIC MP_DEFINE_CONST_DICT(esp32_camera_frame_size_locals_dict, esp32_camera_frame_size_locals_table); +MAKE_PRINTER(esp32_camera, esp32_camera_frame_size); +MAKE_ENUM_TYPE(esp32_camera, FrameSize, esp32_camera_frame_size); + +framesize_t validate_frame_size(mp_obj_t obj, qstr arg_name) { + return cp_enum_value(&esp32_camera_frame_size_type, mp_arg_validate_type(obj, &esp32_camera_frame_size_type, arg_name)); +} + +STATIC const mp_rom_map_elem_t esp32_camera_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32_camera) }, + { MP_ROM_QSTR(MP_QSTR_Camera), MP_ROM_PTR(&esp32_camera_camera_type), }, + { MP_ROM_QSTR(MP_QSTR_FrameSize), &esp32_camera_frame_size_type }, + { MP_ROM_QSTR(MP_QSTR_GrabMode), &esp32_camera_grab_mode_type }, + { MP_ROM_QSTR(MP_QSTR_PixelFormat), &esp32_camera_pixel_format_type }, +}; + +STATIC MP_DEFINE_CONST_DICT(esp32_camera_module_globals, esp32_camera_module_globals_table); + +const mp_obj_module_t esp32_camera_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&esp32_camera_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_esp32_camera, esp32_camera_module, CIRCUITPY_ESP32_CAMERA); diff --git a/ports/espressif/bindings/esp32_camera/__init__.h b/ports/espressif/bindings/esp32_camera/__init__.h new file mode 100644 index 0000000000..ff1f6c6f6d --- /dev/null +++ b/ports/espressif/bindings/esp32_camera/__init__.h @@ -0,0 +1,43 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "py/enum.h" +#include "py/obj.h" + +#include "esp_camera.h" + +extern const mp_obj_type_t esp32_camera_grab_mode_type; +extern const cp_enum_obj_t grab_mode_WHEN_EMPTY_obj; +extern const mp_obj_type_t esp32_camera_pixel_format_type; +extern const cp_enum_obj_t pixel_format_RGB565_obj; +extern const mp_obj_type_t esp32_camera_frame_size_type; +extern const cp_enum_obj_t frame_size_QQVGA_obj; + +extern camera_grab_mode_t validate_grab_mode(mp_obj_t obj, qstr arg_name); +extern pixformat_t validate_pixel_format(mp_obj_t obj, qstr arg_name); +extern framesize_t validate_frame_size(mp_obj_t obj, qstr arg_name); diff --git a/ports/espressif/boards/espressif_esp32s3_eye/board.c b/ports/espressif/boards/espressif_esp32s3_eye/board.c new file mode 100644 index 0000000000..ff9418ec86 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_eye/board.c @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" + +void board_init(void) { + // Debug UART + #ifdef DEBUG + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); + #endif +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} + +void board_deinit(void) { +} diff --git a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h new file mode 100644 index 0000000000..093bcb0e68 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "ESP32-S3-EYE" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// Shared by the camera and accelerometer +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5) + +// This is the SD card connection, not the LCD +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO39) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO40) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO38) diff --git a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk new file mode 100644 index 0000000000..3dc5a14c88 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x303A +USB_PID = 0x7003 +USB_PRODUCT = "ESP32-S3-EYE" +USB_MANUFACTURER = "Espressif" + +IDF_TARGET = esp32s3 + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +# The default queue depth of 16 overflows on release builds, +# so increase it to 32. +CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB diff --git a/ports/espressif/boards/espressif_esp32s3_eye/pins.c b/ports/espressif/boards/espressif_esp32s3_eye/pins.c new file mode 100644 index 0000000000..7ebda4309d --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_eye/pins.c @@ -0,0 +1,55 @@ +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_obj_tuple_t camera_data_tuple = { + {&mp_type_tuple}, + 8, + { + MP_ROM_PTR(&pin_GPIO11), + MP_ROM_PTR(&pin_GPIO9), + MP_ROM_PTR(&pin_GPIO8), + MP_ROM_PTR(&pin_GPIO10), + MP_ROM_PTR(&pin_GPIO12), + MP_ROM_PTR(&pin_GPIO18), + MP_ROM_PTR(&pin_GPIO17), + MP_ROM_PTR(&pin_GPIO16), + } +}; + + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTONS), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_MIC_SDO), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, // LCD + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA), MP_ROM_PTR(&camera_data_tuple) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_VSYNC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_HREF), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_PCLK), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_XCLK), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(&pin_GPIO21) }, // LCD + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_MIC_SCK), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_MIC_WS), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO43) }, // LCD + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO44) }, // LCD + // { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, // LCD -- unused? + // { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // LCD -- unused? + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO47) }, // LCD + { MP_ROM_QSTR(MP_QSTR_BACKLIGHT), MP_ROM_PTR(&pin_GPIO48) }, // LCD + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO48) }, // LCD + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // TODO + // { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32s3_eye/sdkconfig b/ports/espressif/boards/espressif_esp32s3_eye/sdkconfig new file mode 100644 index 0000000000..1a24832767 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_eye/sdkconfig @@ -0,0 +1,34 @@ +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +# +# SPI RAM config +# +# CONFIG_SPIRAM_MODE_QUAD is not set +CONFIG_SPIRAM_MODE_OCT=y +# CONFIG_SPIRAM_TYPE_AUTO is not set +CONFIG_SPIRAM_TYPE_ESPPSRAM64=y +CONFIG_SPIRAM_SIZE=8388608 +# end of SPI RAM config + +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +# +# PSRAM Clock and CS IO for ESP32S3 +# +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# end of PSRAM Clock and CS IO for ESP32S3 + +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3-eye" +# end of LWIP diff --git a/ports/espressif/common-hal/esp32_camera/Camera.c b/ports/espressif/common-hal/esp32_camera/Camera.c new file mode 100644 index 0000000000..83eabe8c2a --- /dev/null +++ b/ports/espressif/common-hal/esp32_camera/Camera.c @@ -0,0 +1,144 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "bindings/esp32_camera/Camera.h" +#include "bindings/espidf/__init__.h" +#include "common-hal/esp32_camera/Camera.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "common-hal/microcontroller/Pin.h" + +static void maybe_claim_pin(const mcu_pin_obj_t *pin) { + if (pin) { + claim_pin(pin); + } +} + +void common_hal_esp32_camera_camera_construct( + esp32_camera_camera_obj_t *self, + uint8_t data_pins[8], + const mcu_pin_obj_t *external_clock_pin, + const mcu_pin_obj_t *pixel_clock_pin, + const mcu_pin_obj_t *vsync_pin, + const mcu_pin_obj_t *href_pin, + const mcu_pin_obj_t *powerdown_pin, + const mcu_pin_obj_t *reset_pin, + const busio_i2c_obj_t *i2c, + mp_int_t external_clock_frequency, + pixformat_t pixel_format, + framesize_t frame_size, + mp_int_t jpeg_quality, + mp_int_t framebuffer_count, + camera_grab_mode_t grab_mode) { + + for (int i = 0; i < 8; i++) { + claim_pin_number(data_pins[i]); + } + claim_pin(external_clock_pin); + claim_pin(pixel_clock_pin); + claim_pin(vsync_pin); + claim_pin(href_pin); + maybe_claim_pin(powerdown_pin); + maybe_claim_pin(reset_pin); + + common_hal_pwmio_pwmout_construct(&self->pwm, external_clock_pin, 1, external_clock_frequency, true); + + self->camera_config.pin_pwdn = common_hal_mcu_pin_number(powerdown_pin); + self->camera_config.pin_reset = common_hal_mcu_pin_number(reset_pin); + self->camera_config.pin_xclk = common_hal_mcu_pin_number(external_clock_pin); + + self->camera_config.pin_sccb_sda = NO_PIN; + self->camera_config.pin_sccb_scl = NO_PIN; + /* sccb i2c port set below */ + + self->camera_config.pin_d7 = data_pins[7]; + self->camera_config.pin_d6 = data_pins[6]; + self->camera_config.pin_d5 = data_pins[5]; + self->camera_config.pin_d4 = data_pins[4]; + self->camera_config.pin_d3 = data_pins[3]; + self->camera_config.pin_d2 = data_pins[2]; + self->camera_config.pin_d1 = data_pins[1]; + self->camera_config.pin_d0 = data_pins[0]; + + self->camera_config.pin_vsync = common_hal_mcu_pin_number(vsync_pin); + self->camera_config.pin_href = common_hal_mcu_pin_number(href_pin); + self->camera_config.pin_pclk = common_hal_mcu_pin_number(pixel_clock_pin); + + self->camera_config.xclk_freq_hz = external_clock_frequency; + + self->camera_config.ledc_timer = self->pwm.tim_handle.timer_num; + self->camera_config.ledc_channel = self->pwm.chan_handle.channel; + + self->camera_config.pixel_format = pixel_format; + self->camera_config.frame_size = frame_size; + self->camera_config.jpeg_quality = jpeg_quality; + self->camera_config.fb_count = framebuffer_count; + self->camera_config.grab_mode = grab_mode; + + self->camera_config.sccb_i2c_port = i2c->i2c_num; + + CHECK_ESP_RESULT(esp_camera_init(&self->camera_config)); +} + +extern void common_hal_esp32_camera_camera_deinit(esp32_camera_camera_obj_t *self) { + if (common_hal_esp32_camera_camera_deinited(self)) { + return; + } + + common_hal_pwmio_pwmout_deinit(&self->pwm); + + reset_pin_number(self->camera_config.pin_pwdn); + reset_pin_number(self->camera_config.pin_reset); + reset_pin_number(self->camera_config.pin_xclk); + + reset_pin_number(self->camera_config.pin_d7); + reset_pin_number(self->camera_config.pin_d6); + reset_pin_number(self->camera_config.pin_d5); + reset_pin_number(self->camera_config.pin_d4); + reset_pin_number(self->camera_config.pin_d3); + reset_pin_number(self->camera_config.pin_d2); + reset_pin_number(self->camera_config.pin_d1); + reset_pin_number(self->camera_config.pin_d0); + + esp_camera_deinit(); + + self->camera_config.xclk_freq_hz = 0; +} + +bool common_hal_esp32_camera_camera_deinited(esp32_camera_camera_obj_t *self) { + return !self->camera_config.xclk_freq_hz; +} + +bool common_hal_esp32_camera_camera_available(esp32_camera_camera_obj_t *self) { + return esp_camera_fb_available(); +} + +camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self, int timeout_ms) { + if (self->buffer_to_return) { + esp_camera_fb_return(self->buffer_to_return); + self->buffer_to_return = NULL; + } + return esp_camera_fb_get_timeout(timeout_ms); +} diff --git a/ports/espressif/common-hal/esp32_camera/Camera.h b/ports/espressif/common-hal/esp32_camera/Camera.h new file mode 100644 index 0000000000..9c21f81b16 --- /dev/null +++ b/ports/espressif/common-hal/esp32_camera/Camera.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "py/obj.h" +#include "esp_camera.h" +#include "shared-bindings/pwmio/PWMOut.h" + +typedef struct esp32_camera_camera_obj { + mp_obj_base_t base; + camera_config_t camera_config; + camera_fb_t *buffer_to_return; + pwmio_pwmout_obj_t pwm; +} esp32_camera_obj_t; diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults index bfb867d923..ce0d9f8d62 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults @@ -191,3 +191,31 @@ CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" # end of Deprecated options for backward compatibility + +# +# Camera configuration +# +CONFIG_OV7670_SUPPORT=y +# CONFIG_OV7725_SUPPORT is not set +# CONFIG_NT99141_SUPPORT is not set +CONFIG_OV2640_SUPPORT=y +CONFIG_OV3660_SUPPORT=y +CONFIG_OV5640_SUPPORT=y +# CONFIG_GC2145_SUPPORT is not set +# CONFIG_GC032A_SUPPORT is not set +# CONFIG_GC0308_SUPPORT is not set +# CONFIG_BF3005_SUPPORT is not set +# CONFIG_BF20A6_SUPPORT is not set +# CONFIG_SC101IOT_SUPPORT is not set +# CONFIG_SC030IOT_SUPPORT is not set +# CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set +CONFIG_SCCB_HARDWARE_I2C_PORT1=y +CONFIG_SCCB_CLK_FREQ=100000 +CONFIG_CAMERA_CORE0=y +# CONFIG_CAMERA_CORE1 is not set +# CONFIG_CAMERA_NO_AFFINITY is not set +CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 +# CONFIG_CAMERA_CONVERTER_ENABLED is not set +# end of Camera configuration +# end of Component config + diff --git a/ports/espressif/esp32-camera b/ports/espressif/esp32-camera new file mode 160000 index 0000000000..28804391c0 --- /dev/null +++ b/ports/espressif/esp32-camera @@ -0,0 +1 @@ +Subproject commit 28804391c002f6a3ea5ce6a55aee3b191be3ecde diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index f390cbb21a..f782f10e27 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -20,7 +20,7 @@ CIRCUITPY_DUALBANK ?= 1 CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_FREQUENCYIO ?= 1 CIRCUITPY_HASHLIB ?= 1 -CIRCUITPY_IMAGECAPTURE ?= 1 +CIRCUITPY_IMAGECAPTURE ?= 0 CIRCUITPY_I2CPERIPHERAL ?= 1 CIRCUITPY_RGBMATRIX ?= 1 CIRCUITPY_ROTARYIO ?= 1 @@ -35,12 +35,12 @@ CIRCUITPY_ESPIDF ?= 1 ifeq ($(IDF_TARGET),esp32) CIRCUITPY_BLEIO = 0 CIRCUITPY_BLEIO_HCI = 0 -CIRCUITPY_IMAGECAPTURE = 0 CIRCUITPY_PARALLELDISPLAY = 0 # Protomatter needs to support ESP32. CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_USB = 0 CIRCUITPY_BUILD_EXTENSIONS ?= bin +CIRCUITPY_ESP32_CAMERA ?= 1 else ifeq ($(IDF_TARGET),esp32c3) CIRCUITPY_AESIO = 0 @@ -51,7 +51,6 @@ CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_DUALBANK = 0 CIRCUITPY_FREQUENCYIO = 0 -CIRCUITPY_IMAGECAPTURE = 0 CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_PS2IO = 0 CIRCUITPY_ROTARYIO = 0 @@ -63,15 +62,16 @@ CIRCUITPY_BUILD_EXTENSIONS ?= bin else ifeq ($(IDF_TARGET),esp32s3) CIRCUITPY_BLEIO = 1 CIRCUITPY_BLEIO_HCI = 0 -CIRCUITPY_IMAGECAPTURE = 0 CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_BUILD_EXTENSIONS ?= bin,uf2 +CIRCUITPY_ESP32_CAMERA ?= 1 else ifeq ($(IDF_TARGET),esp32s2) # No BLE on S2 CIRCUITPY_BLEIO = 0 CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BUILD_EXTENSIONS ?= bin,uf2 +CIRCUITPY_ESP32_CAMERA ?= 1 endif # From ESP32-S2/S3 Technical Reference Manual: @@ -85,3 +85,5 @@ endif # only if something else is turned off, such as HID. USB_NUM_ENDPOINT_PAIRS = 7 USB_NUM_IN_ENDPOINTS = 5 + +CIRCUITPY_ESP32_CAMERA ?= 0 diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index ceedce367d..c6766fdf8a 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -334,6 +334,7 @@ safe_mode_t port_init(void) { } void reset_port(void) { + // TODO deinit for esp32-camera #if CIRCUITPY_IMAGECAPTURE cam_deinit(); #endif diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 4d7d026aa5..157fa35b59 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -214,6 +214,9 @@ CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO) CIRCUITPY_ESPIDF ?= 0 CFLAGS += -DCIRCUITPY_ESPIDF=$(CIRCUITPY_ESPIDF) +CIRCUITPY_ESP32_CAMERA ?= 0 +CFLAGS += -DCIRCUITPY_ESP32_CAMERA=$(CIRCUITPY_ESP32_CAMERA) + CIRCUITPY__EVE ?= 0 CFLAGS += -DCIRCUITPY__EVE=$(CIRCUITPY__EVE) From 8d673bdbf5e50d2614238a8815df658fdb0e54c9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:51 -0500 Subject: [PATCH 05/30] reserve 1MB of PSRAM for camera framebuffer on esp32s3-eye .. this setting can be overridden with a bigger or smaller value in CIRCUITPY/.env but 1/8 of PSRAM seems like a good initial value. It's enough to store a single 800x600 or 640x480 RGB565 frame, or multiple smaller frames such as 320x240. --- ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h index 093bcb0e68..7bf1fa8993 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h +++ b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h @@ -37,3 +37,5 @@ #define DEFAULT_SPI_BUS_SCK (&pin_GPIO39) #define DEFAULT_SPI_BUS_MISO (&pin_GPIO40) #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO38) + +#define DEFAULT_RESERVED_PSRAM (1048576) From b903a020fd5b6c39caf84ddddbda1adf33c0dd8f Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:52 -0500 Subject: [PATCH 06/30] Enable display on esp32-s3-eye --- .../boards/espressif_esp32s3_eye/board.c | 98 ++++++++++++++++++- .../espressif_esp32s3_eye/mpconfigboard.h | 6 ++ 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/ports/espressif/boards/espressif_esp32s3_eye/board.c b/ports/espressif/boards/espressif_esp32s3_eye/board.c index ff9418ec86..7829a4be94 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/board.c +++ b/ports/espressif/boards/espressif_esp32s3_eye/board.c @@ -26,14 +26,104 @@ #include "supervisor/board.h" #include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/displayio/FourWire.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +displayio_fourwire_obj_t board_display_obj; + +#define DELAY 0x80 + +// display init sequence according to LilyGO example app +uint8_t display_init_sequence[] = { + // sw reset + 0x01, 0 | DELAY, 150, + // sleep out + 0x11, 0 | DELAY, 255, + // normal display mode on + 0x13, 0, + // display and color format settings + 0x36, 1, 0x08, + 0xB6, 2, 0x0A, 0x82, + 0x3A, 1 | DELAY, 0x55, 10, + // ST7789V frame rate setting + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + // voltages: VGH / VGL + 0xB7, 1, 0x35, + // ST7789V power setting + 0xBB, 1, 0x28, + 0xC0, 1, 0x0C, + 0xC2, 2, 0x01, 0xFF, + 0xC3, 1, 0x10, + 0xC4, 1, 0x20, + 0xC6, 1, 0x0F, + 0xD0, 2, 0xA4, 0xA1, + // ST7789V gamma setting + 0xE0, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17, + 0xE1, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E, + 0x21, 0, + // display on + 0x29, 0 | DELAY, 255, +}; void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(1); + displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; + bus->base.type = &displayio_fourwire_type; + + common_hal_displayio_fourwire_construct( + bus, + spi, + &pin_GPIO43, // DC + &pin_GPIO44, // CS + NULL, // no reset pin + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + displayio_display_obj_t *display = &displays[0].display; + display->base.type = &displayio_display_type; + + // workaround as board_init() is called before reset_port() in main.c + pwmout_reset(); + + common_hal_displayio_display_construct( + display, + bus, + 240, // width (after rotation) + 240, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO48, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness (ignored) + false, // auto_brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + false, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); + + common_hal_never_reset_pin(&pin_GPIO48); // backlight pin // Debug UART - #ifdef DEBUG - common_hal_never_reset_pin(&pin_GPIO43); - common_hal_never_reset_pin(&pin_GPIO44); - #endif } bool board_requests_safe_mode(void) { diff --git a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h index 7bf1fa8993..d32704c8bf 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h +++ b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h @@ -38,4 +38,10 @@ #define DEFAULT_SPI_BUS_MISO (&pin_GPIO40) #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO38) +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN { \ + {.clock = &pin_GPIO39, .mosi = &pin_GPIO40, .miso = &pin_GPIO38}, \ + {.clock = &pin_GPIO21, .mosi = &pin_GPIO47, .miso = NULL}, \ +} + #define DEFAULT_RESERVED_PSRAM (1048576) From 1d1e139379b1e017c2608880248f6aeb2f023d4c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:53 -0500 Subject: [PATCH 07/30] fix taking multiple pictures --- ports/espressif/common-hal/esp32_camera/Camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/espressif/common-hal/esp32_camera/Camera.c b/ports/espressif/common-hal/esp32_camera/Camera.c index 83eabe8c2a..0b836f034d 100644 --- a/ports/espressif/common-hal/esp32_camera/Camera.c +++ b/ports/espressif/common-hal/esp32_camera/Camera.c @@ -140,5 +140,5 @@ camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self esp_camera_fb_return(self->buffer_to_return); self->buffer_to_return = NULL; } - return esp_camera_fb_get_timeout(timeout_ms); + return self->buffer_to_return = esp_camera_fb_get_timeout(timeout_ms); } From f54c7adddcd829f76752d1ef514e7bb4acab779a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:54 -0500 Subject: [PATCH 08/30] Must treat NO_PIN cast to uint8_t the same as NO_PIN Otherwise, deinitializing a camera with e.g., the powerdown pin unspecified results in an assertion failure in a debug build. --- ports/espressif/common-hal/microcontroller/Pin.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ports/espressif/common-hal/microcontroller/Pin.c b/ports/espressif/common-hal/microcontroller/Pin.c index 4ac98c7927..8a09c98d74 100644 --- a/ports/espressif/common-hal/microcontroller/Pin.c +++ b/ports/espressif/common-hal/microcontroller/Pin.c @@ -100,7 +100,9 @@ static const uint64_t pin_mask_reset_forbidden = void never_reset_pin_number(gpio_num_t pin_number) { - if (pin_number == NO_PIN) { + // Some CircuitPython APIs deal in uint8_t pin numbers, but NO_PIN is -1. + // Also allow pin 255 to be treated as NO_PIN to avoid crashes + if (pin_number == NO_PIN || pin_number == (uint8_t)NO_PIN) { return; } never_reset_pins |= PIN_BIT(pin_number); @@ -141,7 +143,9 @@ STATIC void _reset_pin(gpio_num_t pin_number) { // Mark pin as free and return it to a quiescent state. void reset_pin_number(gpio_num_t pin_number) { - if (pin_number == NO_PIN) { + // Some CircuitPython APIs deal in uint8_t pin numbers, but NO_PIN is -1. + // Also allow pin 255 to be treated as NO_PIN to avoid crashes + if (pin_number == NO_PIN || pin_number == (uint8_t)NO_PIN) { return; } never_reset_pins &= ~PIN_BIT(pin_number); @@ -174,7 +178,9 @@ void reset_all_pins(void) { } void claim_pin_number(gpio_num_t pin_number) { - if (pin_number == NO_PIN) { + // Some CircuitPython APIs deal in uint8_t pin numbers, but NO_PIN is -1. + // Also allow pin 255 to be treated as NO_PIN to avoid crashes + if (pin_number == NO_PIN || pin_number == (uint8_t)NO_PIN) { return; } in_use |= PIN_BIT(pin_number); From d1b89fca91890916ee89826509e7ecc9fe6a2855 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:55 -0500 Subject: [PATCH 09/30] Reset camera when interpreter is reset --- ports/espressif/Makefile | 6 ------ ports/espressif/supervisor/port.c | 8 ++++---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index e8baf35935..1f01513d32 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -292,12 +292,6 @@ CFLAGS += -isystem esp32-camera/driver/include CFLAGS += -isystem esp32-camera/conversions/include endif -ifneq ($(CIRCUITPY_IMAGECAPTURE),0) -$(error IMAGECAPTURE) -SRC_C += cam.c -endif - - SRC_COMMON_HAL_EXPANDED = \ $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index c6766fdf8a..3727d8af44 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -76,8 +76,8 @@ #include "shared-bindings/_bleio/__init__.h" #endif -#if CIRCUITPY_IMAGECAPTURE -#include "cam.h" +#if CIRCUITPY_ESP32_CAMERA +#include "esp_camera.h" #endif #ifndef CONFIG_IDF_TARGET_ESP32 @@ -335,8 +335,8 @@ safe_mode_t port_init(void) { void reset_port(void) { // TODO deinit for esp32-camera - #if CIRCUITPY_IMAGECAPTURE - cam_deinit(); + #if CIRCUITPY_ESP32_CAMERA + esp_camera_deinit(); #endif reset_all_pins(); From 69949ecb4350ceba86b6c865a4dc2d202ae7aada Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:56 -0500 Subject: [PATCH 10/30] update PID for this board --- ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk index 3dc5a14c88..bf9464353f 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.mk @@ -1,5 +1,5 @@ USB_VID = 0x303A -USB_PID = 0x7003 +USB_PID = 0x700F USB_PRODUCT = "ESP32-S3-EYE" USB_MANUFACTURER = "Espressif" From 258f72640afcd1033a3752a50a9d2f327511041e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:57 -0500 Subject: [PATCH 11/30] Implement a pile of getters & setters --- locale/circuitpython.pot | 6 +- .../espressif/bindings/esp32_camera/Camera.c | 632 +++++++++++++++++- .../espressif/bindings/esp32_camera/Camera.h | 41 ++ .../bindings/esp32_camera/__init__.c | 43 +- .../bindings/esp32_camera/__init__.h | 2 + .../common-hal/esp32_camera/Camera.c | 57 ++ 6 files changed, 769 insertions(+), 12 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 332331e14f..da40283128 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -3236,6 +3236,10 @@ msgstr "" msgid "invalid micropython decorator" msgstr "" +#: ports/espressif/common-hal/esp32_camera/Camera.c +msgid "invalid setting" +msgstr "" + #: shared-bindings/random/__init__.c msgid "invalid step" msgstr "" @@ -3491,7 +3495,7 @@ msgstr "" msgid "no response from SD card" msgstr "" -#: py/objobject.c py/runtime.c +#: ports/espressif/common-hal/esp32_camera/Camera.c py/objobject.c py/runtime.c msgid "no such attribute" msgstr "" diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index 2dc61f73ca..d33a5948a4 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -205,21 +205,635 @@ STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera_take_obj, 1, 2, esp32_camera_camera_take); -//| pixel_format: PixelFormat -//| """The pixel format of the camera""" -//| -//| frame_size: FrameSize -//| """The size of the captured image""" -//| + +//| pixel_format: pixformat_t +//| """The pixel format of captured frames""" + +STATIC mp_obj_t esp32_camera_camera_get_pixel_format(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return cp_enum_find(&esp32_camera_pixel_format_type, common_hal_esp32_camera_camera_get_pixel_format(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_pixel_format_obj, esp32_camera_camera_get_pixel_format); + +STATIC mp_obj_t esp32_camera_camera_set_pixel_format(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_pixel_format(self, validate_pixel_format(arg, MP_QSTR_pixel_format)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_pixel_format_obj, esp32_camera_camera_set_pixel_format); +MP_PROPERTY_GETSET(esp32_camera_camera_pixel_format_obj, + (mp_obj_t)&esp32_camera_camera_get_pixel_format_obj, + (mp_obj_t)&esp32_camera_camera_set_pixel_format_obj); + + +//| frame_size: framesize_t +//| """The size of captured frames""" + +STATIC mp_obj_t esp32_camera_camera_get_frame_size(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return cp_enum_find(&esp32_camera_frame_size_type, common_hal_esp32_camera_camera_get_frame_size(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_frame_size_obj, esp32_camera_camera_get_frame_size); + +STATIC mp_obj_t esp32_camera_camera_set_frame_size(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_frame_size(self, validate_frame_size(arg, MP_QSTR_frame_size)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_frame_size_obj, esp32_camera_camera_set_frame_size); +MP_PROPERTY_GETSET(esp32_camera_camera_frame_size_obj, + (mp_obj_t)&esp32_camera_camera_get_frame_size_obj, + (mp_obj_t)&esp32_camera_camera_set_frame_size_obj); + //| contrast: int -//| """The contrast of the sensor""" +//| """Access the contrast property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_contrast(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_contrast(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_contrast_obj, esp32_camera_camera_get_contrast); + +STATIC mp_obj_t esp32_camera_camera_set_contrast(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_contrast(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_contrast_obj, esp32_camera_camera_set_contrast); +MP_PROPERTY_GETSET(esp32_camera_camera_contrast_obj, + (mp_obj_t)&esp32_camera_camera_get_contrast_obj, + (mp_obj_t)&esp32_camera_camera_set_contrast_obj); + +//| brightness: int +//| """Access the brightness property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_brightness(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_brightness(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_brightness_obj, esp32_camera_camera_get_brightness); + +STATIC mp_obj_t esp32_camera_camera_set_brightness(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_brightness(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_brightness_obj, esp32_camera_camera_set_brightness); +MP_PROPERTY_GETSET(esp32_camera_camera_brightness_obj, + (mp_obj_t)&esp32_camera_camera_get_brightness_obj, + (mp_obj_t)&esp32_camera_camera_set_brightness_obj); + +//| saturation: int +//| """Access the saturation property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_saturation(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_saturation(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_saturation_obj, esp32_camera_camera_get_saturation); + +STATIC mp_obj_t esp32_camera_camera_set_saturation(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_saturation(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_saturation_obj, esp32_camera_camera_set_saturation); +MP_PROPERTY_GETSET(esp32_camera_camera_saturation_obj, + (mp_obj_t)&esp32_camera_camera_get_saturation_obj, + (mp_obj_t)&esp32_camera_camera_set_saturation_obj); + +//| sharpness: int +//| """Access the sharpness property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_sharpness(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_sharpness(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_sharpness_obj, esp32_camera_camera_get_sharpness); + +STATIC mp_obj_t esp32_camera_camera_set_sharpness(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_sharpness(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_sharpness_obj, esp32_camera_camera_set_sharpness); +MP_PROPERTY_GETSET(esp32_camera_camera_sharpness_obj, + (mp_obj_t)&esp32_camera_camera_get_sharpness_obj, + (mp_obj_t)&esp32_camera_camera_set_sharpness_obj); + +//| denoise: int +//| """Access the denoise property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_denoise(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_denoise(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_denoise_obj, esp32_camera_camera_get_denoise); + +STATIC mp_obj_t esp32_camera_camera_set_denoise(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_denoise(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_denoise_obj, esp32_camera_camera_set_denoise); +MP_PROPERTY_GETSET(esp32_camera_camera_denoise_obj, + (mp_obj_t)&esp32_camera_camera_get_denoise_obj, + (mp_obj_t)&esp32_camera_camera_set_denoise_obj); + +//| gain_ceiling: GainCeiling +//| """Access the gain ceiling property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_gain_ceiling(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return cp_enum_find(&esp32_camera_gain_ceiling_type, common_hal_esp32_camera_camera_get_gainceiling(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_gain_ceiling_obj, esp32_camera_camera_get_gain_ceiling); + +STATIC mp_obj_t esp32_camera_camera_set_gain_ceiling(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_gainceiling(self, validate_gain_ceiling(arg, MP_QSTR_gain_ceiling)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_gain_ceiling_obj, esp32_camera_camera_set_gain_ceiling); +MP_PROPERTY_GETSET(esp32_camera_camera_gain_ceiling_obj, + (mp_obj_t)&esp32_camera_camera_get_gain_ceiling_obj, + (mp_obj_t)&esp32_camera_camera_set_gain_ceiling_obj); + +//| quality: int +//| """Access the quality property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_quality(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_quality(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_quality_obj, esp32_camera_camera_get_quality); + +STATIC mp_obj_t esp32_camera_camera_set_quality(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_quality(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_quality_obj, esp32_camera_camera_set_quality); +MP_PROPERTY_GETSET(esp32_camera_camera_quality_obj, + (mp_obj_t)&esp32_camera_camera_get_quality_obj, + (mp_obj_t)&esp32_camera_camera_set_quality_obj); + +//| colorbar: bool +//| """Access the colorbar property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_colorbar(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_colorbar(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_colorbar_obj, esp32_camera_camera_get_colorbar); + +STATIC mp_obj_t esp32_camera_camera_set_colorbar(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_colorbar(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_colorbar_obj, esp32_camera_camera_set_colorbar); +MP_PROPERTY_GETSET(esp32_camera_camera_colorbar_obj, + (mp_obj_t)&esp32_camera_camera_get_colorbar_obj, + (mp_obj_t)&esp32_camera_camera_set_colorbar_obj); + +//| whitebal: bool +//| """Access the whitebal property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_whitebal(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_whitebal(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_whitebal_obj, esp32_camera_camera_get_whitebal); + +STATIC mp_obj_t esp32_camera_camera_set_whitebal(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_whitebal(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_whitebal_obj, esp32_camera_camera_set_whitebal); +MP_PROPERTY_GETSET(esp32_camera_camera_whitebal_obj, + (mp_obj_t)&esp32_camera_camera_get_whitebal_obj, + (mp_obj_t)&esp32_camera_camera_set_whitebal_obj); + +//| gain_ctrl: bool +//| """Access the gain_ctrl property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_gain_ctrl(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_gain_ctrl(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_gain_ctrl_obj, esp32_camera_camera_get_gain_ctrl); + +STATIC mp_obj_t esp32_camera_camera_set_gain_ctrl(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_gain_ctrl(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_gain_ctrl_obj, esp32_camera_camera_set_gain_ctrl); +MP_PROPERTY_GETSET(esp32_camera_camera_gain_ctrl_obj, + (mp_obj_t)&esp32_camera_camera_get_gain_ctrl_obj, + (mp_obj_t)&esp32_camera_camera_set_gain_ctrl_obj); + +//| exposure_ctrl: bool +//| """Access the exposure_ctrl property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_exposure_ctrl(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_exposure_ctrl(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_exposure_ctrl_obj, esp32_camera_camera_get_exposure_ctrl); + +STATIC mp_obj_t esp32_camera_camera_set_exposure_ctrl(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_exposure_ctrl(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_exposure_ctrl_obj, esp32_camera_camera_set_exposure_ctrl); +MP_PROPERTY_GETSET(esp32_camera_camera_exposure_ctrl_obj, + (mp_obj_t)&esp32_camera_camera_get_exposure_ctrl_obj, + (mp_obj_t)&esp32_camera_camera_set_exposure_ctrl_obj); + +//| hmirror: bool +//| """Access the hmirror property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_hmirror(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_hmirror(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_hmirror_obj, esp32_camera_camera_get_hmirror); + +STATIC mp_obj_t esp32_camera_camera_set_hmirror(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_hmirror(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_hmirror_obj, esp32_camera_camera_set_hmirror); +MP_PROPERTY_GETSET(esp32_camera_camera_hmirror_obj, + (mp_obj_t)&esp32_camera_camera_get_hmirror_obj, + (mp_obj_t)&esp32_camera_camera_set_hmirror_obj); + +//| vflip: bool +//| """Access the vflip property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_vflip(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_vflip(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_vflip_obj, esp32_camera_camera_get_vflip); + +STATIC mp_obj_t esp32_camera_camera_set_vflip(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_vflip(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_vflip_obj, esp32_camera_camera_set_vflip); +MP_PROPERTY_GETSET(esp32_camera_camera_vflip_obj, + (mp_obj_t)&esp32_camera_camera_get_vflip_obj, + (mp_obj_t)&esp32_camera_camera_set_vflip_obj); + +//| aec2: bool +//| """Access the aec2 property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_aec2(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_aec2(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_aec2_obj, esp32_camera_camera_get_aec2); + +STATIC mp_obj_t esp32_camera_camera_set_aec2(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_aec2(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_aec2_obj, esp32_camera_camera_set_aec2); +MP_PROPERTY_GETSET(esp32_camera_camera_aec2_obj, + (mp_obj_t)&esp32_camera_camera_get_aec2_obj, + (mp_obj_t)&esp32_camera_camera_set_aec2_obj); + +//| awb_gain: bool +//| """Access the awb_gain property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_awb_gain(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_awb_gain(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_awb_gain_obj, esp32_camera_camera_get_awb_gain); + +STATIC mp_obj_t esp32_camera_camera_set_awb_gain(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_awb_gain(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_awb_gain_obj, esp32_camera_camera_set_awb_gain); +MP_PROPERTY_GETSET(esp32_camera_camera_awb_gain_obj, + (mp_obj_t)&esp32_camera_camera_get_awb_gain_obj, + (mp_obj_t)&esp32_camera_camera_set_awb_gain_obj); + +//| agc_gain: int +//| """Access the agc_gain property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_agc_gain(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_agc_gain(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_agc_gain_obj, esp32_camera_camera_get_agc_gain); + +STATIC mp_obj_t esp32_camera_camera_set_agc_gain(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_agc_gain(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_agc_gain_obj, esp32_camera_camera_set_agc_gain); +MP_PROPERTY_GETSET(esp32_camera_camera_agc_gain_obj, + (mp_obj_t)&esp32_camera_camera_get_agc_gain_obj, + (mp_obj_t)&esp32_camera_camera_set_agc_gain_obj); + +//| aec_value: int +//| """Access the aec_value property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_aec_value(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_aec_value(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_aec_value_obj, esp32_camera_camera_get_aec_value); + +STATIC mp_obj_t esp32_camera_camera_set_aec_value(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_aec_value(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_aec_value_obj, esp32_camera_camera_set_aec_value); +MP_PROPERTY_GETSET(esp32_camera_camera_aec_value_obj, + (mp_obj_t)&esp32_camera_camera_get_aec_value_obj, + (mp_obj_t)&esp32_camera_camera_set_aec_value_obj); + +//| special_effect: int +//| """Access the special_effect property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_special_effect(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_special_effect(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_special_effect_obj, esp32_camera_camera_get_special_effect); + +STATIC mp_obj_t esp32_camera_camera_set_special_effect(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_special_effect(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_special_effect_obj, esp32_camera_camera_set_special_effect); +MP_PROPERTY_GETSET(esp32_camera_camera_special_effect_obj, + (mp_obj_t)&esp32_camera_camera_get_special_effect_obj, + (mp_obj_t)&esp32_camera_camera_set_special_effect_obj); + +//| wb_mode: int +//| """Access the wb_mode property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_wb_mode(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_wb_mode(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_wb_mode_obj, esp32_camera_camera_get_wb_mode); + +STATIC mp_obj_t esp32_camera_camera_set_wb_mode(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_wb_mode(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_wb_mode_obj, esp32_camera_camera_set_wb_mode); +MP_PROPERTY_GETSET(esp32_camera_camera_wb_mode_obj, + (mp_obj_t)&esp32_camera_camera_get_wb_mode_obj, + (mp_obj_t)&esp32_camera_camera_set_wb_mode_obj); + +//| ae_level: int +//| """Access the ae_level property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_ae_level(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_ae_level(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_ae_level_obj, esp32_camera_camera_get_ae_level); + +STATIC mp_obj_t esp32_camera_camera_set_ae_level(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_ae_level(self, mp_obj_get_int(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_ae_level_obj, esp32_camera_camera_set_ae_level); +MP_PROPERTY_GETSET(esp32_camera_camera_ae_level_obj, + (mp_obj_t)&esp32_camera_camera_get_ae_level_obj, + (mp_obj_t)&esp32_camera_camera_set_ae_level_obj); + +//| dcw: bool +//| """Access the dcw property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_dcw(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_dcw(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_dcw_obj, esp32_camera_camera_get_dcw); + +STATIC mp_obj_t esp32_camera_camera_set_dcw(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_dcw(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_dcw_obj, esp32_camera_camera_set_dcw); +MP_PROPERTY_GETSET(esp32_camera_camera_dcw_obj, + (mp_obj_t)&esp32_camera_camera_get_dcw_obj, + (mp_obj_t)&esp32_camera_camera_set_dcw_obj); + +//| bpc: bool +//| """Access the bpc property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_bpc(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_bpc(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_bpc_obj, esp32_camera_camera_get_bpc); + +STATIC mp_obj_t esp32_camera_camera_set_bpc(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_bpc(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_bpc_obj, esp32_camera_camera_set_bpc); +MP_PROPERTY_GETSET(esp32_camera_camera_bpc_obj, + (mp_obj_t)&esp32_camera_camera_get_bpc_obj, + (mp_obj_t)&esp32_camera_camera_set_bpc_obj); + +//| wpc: bool +//| """Access the wpc property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_wpc(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_wpc(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_wpc_obj, esp32_camera_camera_get_wpc); + +STATIC mp_obj_t esp32_camera_camera_set_wpc(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_wpc(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_wpc_obj, esp32_camera_camera_set_wpc); +MP_PROPERTY_GETSET(esp32_camera_camera_wpc_obj, + (mp_obj_t)&esp32_camera_camera_get_wpc_obj, + (mp_obj_t)&esp32_camera_camera_set_wpc_obj); + +//| raw_gma: bool +//| """Access the raw_gma property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_raw_gma(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_raw_gma(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_raw_gma_obj, esp32_camera_camera_get_raw_gma); + +STATIC mp_obj_t esp32_camera_camera_set_raw_gma(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_raw_gma(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_raw_gma_obj, esp32_camera_camera_set_raw_gma); +MP_PROPERTY_GETSET(esp32_camera_camera_raw_gma_obj, + (mp_obj_t)&esp32_camera_camera_get_raw_gma_obj, + (mp_obj_t)&esp32_camera_camera_set_raw_gma_obj); + +//| lenc: bool +//| """Access the lenc property of the camera sensor""" +//| + +STATIC mp_obj_t esp32_camera_camera_get_lenc(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_lenc(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_lenc_obj, esp32_camera_camera_get_lenc); + +STATIC mp_obj_t esp32_camera_camera_set_lenc(const mp_obj_t self_in, const mp_obj_t arg) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_esp32_camera_camera_set_lenc(self, mp_obj_is_true(arg)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_lenc_obj, esp32_camera_camera_set_lenc); +MP_PROPERTY_GETSET(esp32_camera_camera_lenc_obj, + (mp_obj_t)&esp32_camera_camera_get_lenc_obj, + (mp_obj_t)&esp32_camera_camera_set_lenc_obj); + + STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { - { MP_ROM_QSTR(MP_QSTR_take), MP_ROM_PTR(&esp32_camera_camera_take_obj) }, - { MP_ROM_QSTR(MP_QSTR_frame_available), MP_ROM_PTR(&esp32_camera_camera_frame_available_obj) }, + { MP_ROM_QSTR(MP_QSTR_aec2), MP_ROM_PTR(&esp32_camera_camera_aec2_obj) }, + { MP_ROM_QSTR(MP_QSTR_aec_value), MP_ROM_PTR(&esp32_camera_camera_aec_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_ae_level), MP_ROM_PTR(&esp32_camera_camera_ae_level_obj) }, + { MP_ROM_QSTR(MP_QSTR_agc_gain), MP_ROM_PTR(&esp32_camera_camera_agc_gain_obj) }, + { MP_ROM_QSTR(MP_QSTR_awb_gain), MP_ROM_PTR(&esp32_camera_camera_awb_gain_obj) }, + { MP_ROM_QSTR(MP_QSTR_bpc), MP_ROM_PTR(&esp32_camera_camera_bpc_obj) }, + { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&esp32_camera_camera_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_colorbar), MP_ROM_PTR(&esp32_camera_camera_colorbar_obj) }, + { MP_ROM_QSTR(MP_QSTR_contrast), MP_ROM_PTR(&esp32_camera_camera_contrast_obj) }, + { MP_ROM_QSTR(MP_QSTR_dcw), MP_ROM_PTR(&esp32_camera_camera_dcw_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_camera_camera_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_denoise), MP_ROM_PTR(&esp32_camera_camera_denoise_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&esp32_camera_camera___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_exposure_ctrl), MP_ROM_PTR(&esp32_camera_camera_exposure_ctrl_obj) }, + { MP_ROM_QSTR(MP_QSTR_frame_available), MP_ROM_PTR(&esp32_camera_camera_frame_available_obj) }, + { MP_ROM_QSTR(MP_QSTR_frame_size), MP_ROM_PTR(&esp32_camera_camera_frame_size_obj) }, + { MP_ROM_QSTR(MP_QSTR_gain_ceiling), MP_ROM_PTR(&esp32_camera_camera_gain_ceiling_obj) }, + { MP_ROM_QSTR(MP_QSTR_gain_ctrl), MP_ROM_PTR(&esp32_camera_camera_gain_ctrl_obj) }, + { MP_ROM_QSTR(MP_QSTR_hmirror), MP_ROM_PTR(&esp32_camera_camera_hmirror_obj) }, + { MP_ROM_QSTR(MP_QSTR_lenc), MP_ROM_PTR(&esp32_camera_camera_lenc_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel_format), MP_ROM_PTR(&esp32_camera_camera_pixel_format_obj) }, + { MP_ROM_QSTR(MP_QSTR_quality), MP_ROM_PTR(&esp32_camera_camera_quality_obj) }, + { MP_ROM_QSTR(MP_QSTR_raw_gma), MP_ROM_PTR(&esp32_camera_camera_raw_gma_obj) }, + { MP_ROM_QSTR(MP_QSTR_saturation), MP_ROM_PTR(&esp32_camera_camera_saturation_obj) }, + { MP_ROM_QSTR(MP_QSTR_sharpness), MP_ROM_PTR(&esp32_camera_camera_sharpness_obj) }, + { MP_ROM_QSTR(MP_QSTR_special_effect), MP_ROM_PTR(&esp32_camera_camera_special_effect_obj) }, + { MP_ROM_QSTR(MP_QSTR_take), MP_ROM_PTR(&esp32_camera_camera_take_obj) }, + { MP_ROM_QSTR(MP_QSTR_vflip), MP_ROM_PTR(&esp32_camera_camera_vflip_obj) }, + { MP_ROM_QSTR(MP_QSTR_wb_mode), MP_ROM_PTR(&esp32_camera_camera_wb_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_whitebal), MP_ROM_PTR(&esp32_camera_camera_whitebal_obj) }, + { MP_ROM_QSTR(MP_QSTR_wpc), MP_ROM_PTR(&esp32_camera_camera_wpc_obj) }, }; STATIC MP_DEFINE_CONST_DICT(esp32_camera_camera_locals_dict, esp32_camera_camera_locals_table); diff --git a/ports/espressif/bindings/esp32_camera/Camera.h b/ports/espressif/bindings/esp32_camera/Camera.h index 1163b14f61..bb79fdb39a 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.h +++ b/ports/espressif/bindings/esp32_camera/Camera.h @@ -57,3 +57,44 @@ extern void common_hal_esp32_camera_camera_deinit(esp32_camera_camera_obj_t *sel extern bool common_hal_esp32_camera_camera_deinited(esp32_camera_camera_obj_t *self); extern bool common_hal_esp32_camera_camera_available(esp32_camera_camera_obj_t *self); extern camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self, int timeout_ms); + +#define DECLARE_SENSOR_GETSET(type, name, field_name, setter_function_name) \ + DECLARE_SENSOR_GET(type, name, field_name, setter_function_name) \ + DECLARE_SENSOR_SET(type, name, setter_function_name) + +#define DECLARE_SENSOR_STATUS_GETSET(type, name, status_field_name, setter_function_name) \ + DECLARE_SENSOR_GETSET(type, name, status.status_field_name, setter_function_name) + +#define DECLARE_SENSOR_GET(type, name, status_field_name, setter_function_name) \ + extern type common_hal_esp32_camera_camera_get_##name(esp32_camera_camera_obj_t * self); + +#define DECLARE_SENSOR_SET(type, name, setter_function_name) \ + extern void common_hal_esp32_camera_camera_set_##name(esp32_camera_camera_obj_t * self, type value); + +DECLARE_SENSOR_GETSET(pixformat_t, pixel_format, pixformat, set_pixformat) +DECLARE_SENSOR_STATUS_GETSET(framesize_t, frame_size, framesize, set_framesize) +DECLARE_SENSOR_STATUS_GETSET(int, contrast, contrast, set_contrast); +DECLARE_SENSOR_STATUS_GETSET(int, brightness, brightness, set_brightness); +DECLARE_SENSOR_STATUS_GETSET(int, saturation, saturation, set_saturation); +DECLARE_SENSOR_STATUS_GETSET(int, sharpness, sharpness, set_sharpness); +DECLARE_SENSOR_STATUS_GETSET(int, denoise, denoise, set_denoise); +DECLARE_SENSOR_STATUS_GETSET(gainceiling_t, gainceiling, gainceiling, set_gainceiling); +DECLARE_SENSOR_STATUS_GETSET(int, quality, quality, set_quality); +DECLARE_SENSOR_STATUS_GETSET(bool, colorbar, colorbar, set_colorbar); +DECLARE_SENSOR_STATUS_GETSET(bool, whitebal, whitebal, set_whitebal); +DECLARE_SENSOR_STATUS_GETSET(bool, gain_ctrl, gain_ctrl, set_gain_ctrl); +DECLARE_SENSOR_STATUS_GETSET(bool, exposure_ctrl, exposure_ctrl, set_exposure_ctrl); +DECLARE_SENSOR_STATUS_GETSET(bool, hmirror, hmirror, set_hmirror); +DECLARE_SENSOR_STATUS_GETSET(bool, vflip, vflip, set_vflip); +DECLARE_SENSOR_STATUS_GETSET(bool, aec2, aec2, set_aec2); +DECLARE_SENSOR_STATUS_GETSET(bool, awb_gain, awb_gain, set_awb_gain); +DECLARE_SENSOR_STATUS_GETSET(int, agc_gain, agc_gain, set_agc_gain); +DECLARE_SENSOR_STATUS_GETSET(int, aec_value, aec_value, set_aec_value); +DECLARE_SENSOR_STATUS_GETSET(int, special_effect, special_effect, set_special_effect); +DECLARE_SENSOR_STATUS_GETSET(int, wb_mode, wb_mode, set_wb_mode); +DECLARE_SENSOR_STATUS_GETSET(int, ae_level, ae_level, set_ae_level); +DECLARE_SENSOR_STATUS_GETSET(bool, dcw, dcw, set_dcw); +DECLARE_SENSOR_STATUS_GETSET(bool, bpc, bpc, set_bpc); +DECLARE_SENSOR_STATUS_GETSET(bool, wpc, wpc, set_wpc); +DECLARE_SENSOR_STATUS_GETSET(bool, raw_gma, raw_gma, set_raw_gma); +DECLARE_SENSOR_STATUS_GETSET(bool, lenc, lenc, set_lenc); diff --git a/ports/espressif/bindings/esp32_camera/__init__.c b/ports/espressif/bindings/esp32_camera/__init__.c index d56084e977..09582d440b 100644 --- a/ports/espressif/bindings/esp32_camera/__init__.c +++ b/ports/espressif/bindings/esp32_camera/__init__.c @@ -35,8 +35,6 @@ #include "esp_camera.h" #include "sensor.h" -int oooo; - //| """Wrapper for the esp32_camera library //| //| This library enables access to any camera sensor supported by the library, @@ -225,10 +223,51 @@ framesize_t validate_frame_size(mp_obj_t obj, qstr arg_name) { return cp_enum_value(&esp32_camera_frame_size_type, mp_arg_validate_type(obj, &esp32_camera_frame_size_type, arg_name)); } +//| class GainCeiling: +//| """The maximum amount of gain applied to raw sensor data. +//| +//| Higher values are useful in darker conditions, but increase image noise.""" +//| +//| GAIN_2X: GainCeiling +//| GAIN_4X: GainCeiling +//| GAIN_8X: GainCeiling +//| GAIN_16X: GainCeiling +//| GAIN_32X: GainCeiling +//| GAIN_64X: GainCeiling +//| GAIN_128X: GainCeiling +//| + +MAKE_ENUM_VALUE(esp32_camera_gain_ceiling_type, gain_ceiling, GAIN_2X, GAINCEILING_2X); +MAKE_ENUM_VALUE(esp32_camera_gain_ceiling_type, gain_ceiling, GAIN_4X, GAINCEILING_4X); +MAKE_ENUM_VALUE(esp32_camera_gain_ceiling_type, gain_ceiling, GAIN_8X, GAINCEILING_8X); +MAKE_ENUM_VALUE(esp32_camera_gain_ceiling_type, gain_ceiling, GAIN_16X, GAINCEILING_16X); +MAKE_ENUM_VALUE(esp32_camera_gain_ceiling_type, gain_ceiling, GAIN_32X, GAINCEILING_32X); +MAKE_ENUM_VALUE(esp32_camera_gain_ceiling_type, gain_ceiling, GAIN_64X, GAINCEILING_64X); +MAKE_ENUM_VALUE(esp32_camera_gain_ceiling_type, gain_ceiling, GAIN_128X, GAINCEILING_128X); + +MAKE_ENUM_MAP(esp32_camera_gain_ceiling) { + MAKE_ENUM_MAP_ENTRY(gain_ceiling, GAIN_2X), + MAKE_ENUM_MAP_ENTRY(gain_ceiling, GAIN_4X), + MAKE_ENUM_MAP_ENTRY(gain_ceiling, GAIN_8X), + MAKE_ENUM_MAP_ENTRY(gain_ceiling, GAIN_16X), + MAKE_ENUM_MAP_ENTRY(gain_ceiling, GAIN_32X), + MAKE_ENUM_MAP_ENTRY(gain_ceiling, GAIN_64X), + MAKE_ENUM_MAP_ENTRY(gain_ceiling, GAIN_128X) +}; + +STATIC MP_DEFINE_CONST_DICT(esp32_camera_gain_ceiling_locals_dict, esp32_camera_gain_ceiling_locals_table); +MAKE_PRINTER(esp32_camera, esp32_camera_gain_ceiling); +MAKE_ENUM_TYPE(esp32_camera, GainCeiling, esp32_camera_gain_ceiling); + +gainceiling_t validate_gain_ceiling(mp_obj_t obj, qstr arg_name) { + return cp_enum_value(&esp32_camera_gain_ceiling_type, mp_arg_validate_type(obj, &esp32_camera_gain_ceiling_type, arg_name)); +} + STATIC const mp_rom_map_elem_t esp32_camera_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32_camera) }, { MP_ROM_QSTR(MP_QSTR_Camera), MP_ROM_PTR(&esp32_camera_camera_type), }, { MP_ROM_QSTR(MP_QSTR_FrameSize), &esp32_camera_frame_size_type }, + { MP_ROM_QSTR(MP_QSTR_GainCeiling), &esp32_camera_gain_ceiling_type }, { MP_ROM_QSTR(MP_QSTR_GrabMode), &esp32_camera_grab_mode_type }, { MP_ROM_QSTR(MP_QSTR_PixelFormat), &esp32_camera_pixel_format_type }, }; diff --git a/ports/espressif/bindings/esp32_camera/__init__.h b/ports/espressif/bindings/esp32_camera/__init__.h index ff1f6c6f6d..a0e7290ff9 100644 --- a/ports/espressif/bindings/esp32_camera/__init__.h +++ b/ports/espressif/bindings/esp32_camera/__init__.h @@ -37,7 +37,9 @@ extern const mp_obj_type_t esp32_camera_pixel_format_type; extern const cp_enum_obj_t pixel_format_RGB565_obj; extern const mp_obj_type_t esp32_camera_frame_size_type; extern const cp_enum_obj_t frame_size_QQVGA_obj; +extern const mp_obj_type_t esp32_camera_gain_ceiling_type; extern camera_grab_mode_t validate_grab_mode(mp_obj_t obj, qstr arg_name); extern pixformat_t validate_pixel_format(mp_obj_t obj, qstr arg_name); extern framesize_t validate_frame_size(mp_obj_t obj, qstr arg_name); +extern gainceiling_t validate_gain_ceiling(mp_obj_t obj, qstr arg_name); diff --git a/ports/espressif/common-hal/esp32_camera/Camera.c b/ports/espressif/common-hal/esp32_camera/Camera.c index 0b836f034d..b77b8ac59e 100644 --- a/ports/espressif/common-hal/esp32_camera/Camera.c +++ b/ports/espressif/common-hal/esp32_camera/Camera.c @@ -24,6 +24,8 @@ * THE SOFTWARE. */ +#include "py/runtime.h" + #include "bindings/esp32_camera/Camera.h" #include "bindings/espidf/__init__.h" #include "common-hal/esp32_camera/Camera.h" @@ -142,3 +144,58 @@ camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self } return self->buffer_to_return = esp_camera_fb_get_timeout(timeout_ms); } + +#define SENSOR_GETSET(type, name, field_name, setter_function_name) \ + SENSOR_GET(type, name, field_name, setter_function_name) \ + SENSOR_SET(type, name, setter_function_name) + +#define SENSOR_STATUS_GETSET(type, name, status_field_name, setter_function_name) \ + SENSOR_GETSET(type, name, status.status_field_name, setter_function_name) + +#define SENSOR_GET(type, name, status_field_name, setter_function_name) \ + type common_hal_esp32_camera_camera_get_##name(esp32_camera_camera_obj_t * self) { \ + sensor_t *sensor = esp_camera_sensor_get(); \ + if (!sensor->setter_function_name) { \ + mp_raise_AttributeError(translate("no such attribute")); \ + } \ + return sensor->status_field_name; \ + } + +#define SENSOR_SET(type, name, setter_function_name) \ + void common_hal_esp32_camera_camera_set_##name(esp32_camera_camera_obj_t * self, type value) { \ + sensor_t *sensor = esp_camera_sensor_get(); \ + if (!sensor->setter_function_name) { \ + mp_raise_AttributeError(translate("no such attribute")); \ + } \ + if (sensor->setter_function_name(sensor, value) < 0) { \ + mp_raise_ValueError(translate("invalid setting")); \ + } \ + } + +SENSOR_GETSET(pixformat_t, pixel_format, pixformat, set_pixformat); +SENSOR_STATUS_GETSET(framesize_t, frame_size, framesize, set_framesize); +SENSOR_STATUS_GETSET(int, contrast, contrast, set_contrast); +SENSOR_STATUS_GETSET(int, brightness, brightness, set_brightness); +SENSOR_STATUS_GETSET(int, saturation, saturation, set_saturation); +SENSOR_STATUS_GETSET(int, sharpness, sharpness, set_sharpness); +SENSOR_STATUS_GETSET(int, denoise, denoise, set_denoise); +SENSOR_STATUS_GETSET(gainceiling_t, gainceiling, gainceiling, set_gainceiling); +SENSOR_STATUS_GETSET(int, quality, quality, set_quality); +SENSOR_STATUS_GETSET(bool, colorbar, colorbar, set_colorbar); +SENSOR_STATUS_GETSET(bool, whitebal, awb, set_whitebal); +SENSOR_STATUS_GETSET(bool, gain_ctrl, agc, set_gain_ctrl); +SENSOR_STATUS_GETSET(bool, exposure_ctrl, aec, set_exposure_ctrl); +SENSOR_STATUS_GETSET(bool, hmirror, hmirror, set_hmirror); +SENSOR_STATUS_GETSET(bool, vflip, vflip, set_vflip); +SENSOR_STATUS_GETSET(bool, aec2, aec2, set_aec2); +SENSOR_STATUS_GETSET(bool, awb_gain, awb_gain, set_awb_gain); +SENSOR_STATUS_GETSET(int, agc_gain, agc_gain, set_agc_gain); +SENSOR_STATUS_GETSET(int, aec_value, aec_value, set_aec_value); +SENSOR_STATUS_GETSET(int, special_effect, special_effect, set_special_effect); +SENSOR_STATUS_GETSET(int, wb_mode, wb_mode, set_wb_mode); +SENSOR_STATUS_GETSET(int, ae_level, ae_level, set_ae_level); +SENSOR_STATUS_GETSET(bool, dcw, dcw, set_dcw); +SENSOR_STATUS_GETSET(bool, bpc, bpc, set_bpc); +SENSOR_STATUS_GETSET(bool, wpc, wpc, set_wpc); +SENSOR_STATUS_GETSET(bool, raw_gma, raw_gma, set_raw_gma); +SENSOR_STATUS_GETSET(bool, lenc, lenc, set_lenc); From 64b1d003df853923c4b5b672acc55fd6f8283736 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:58 -0500 Subject: [PATCH 12/30] Allow a Bitmap to be constructed from a buffer (in C anyway) .. so that Camera.take() can return one without copying --- shared-bindings/displayio/Bitmap.h | 2 ++ shared-module/displayio/Bitmap.c | 30 ++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/shared-bindings/displayio/Bitmap.h b/shared-bindings/displayio/Bitmap.h index 458047510a..074f7dfa5c 100644 --- a/shared-bindings/displayio/Bitmap.h +++ b/shared-bindings/displayio/Bitmap.h @@ -33,6 +33,8 @@ extern const mp_obj_type_t displayio_bitmap_type; void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t width, uint32_t height, uint32_t bits_per_value); +void common_hal_displayio_bitmap_construct_from_buffer(displayio_bitmap_t *self, uint32_t width, + uint32_t height, uint32_t bits_per_value, uint32_t *data, bool read_only); void common_hal_displayio_bitmap_load_row(displayio_bitmap_t *self, uint16_t y, uint8_t *data, uint16_t len); diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index 933d3a8227..676aec2186 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -30,20 +30,29 @@ #include "py/runtime.h" -void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t width, - uint32_t height, uint32_t bits_per_value) { +enum { align_bits = 8 * sizeof(uint32_t) }; + +static int stride(uint32_t width, uint32_t bits_per_value) { uint32_t row_width = width * bits_per_value; // align to uint32_t - uint8_t align_bits = 8 * sizeof(uint32_t); - if (row_width % align_bits != 0) { - self->stride = (row_width / align_bits + 1); - } else { - self->stride = row_width / align_bits; - } + return (row_width + align_bits - 1) / align_bits; +} + +void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t width, + uint32_t height, uint32_t bits_per_value) { + common_hal_displayio_bitmap_construct_from_buffer(self, width, height, bits_per_value, NULL, false); +} + +void common_hal_displayio_bitmap_construct_from_buffer(displayio_bitmap_t *self, uint32_t width, + uint32_t height, uint32_t bits_per_value, uint32_t *data, bool read_only) { self->width = width; self->height = height; - self->data = m_malloc(self->stride * height * sizeof(uint32_t), false); - self->read_only = false; + self->stride = stride(width, bits_per_value); + if (!data) { + data = m_malloc(self->stride * height * sizeof(uint32_t), false); + } + self->data = data; + self->read_only = read_only; self->bits_per_value = bits_per_value; if (bits_per_value > 8 && bits_per_value != 16 && bits_per_value != 32) { @@ -70,6 +79,7 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi self->dirty_area.y2 = height; } + uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self) { return self->height; } From 54fe753602d10866620ddb472c338f5b9d166842 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:11:59 -0500 Subject: [PATCH 13/30] Enable gifio and qrio when appropriate --- ports/espressif/mpconfigport.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index f782f10e27..b48efbae40 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -87,3 +87,5 @@ USB_NUM_ENDPOINT_PAIRS = 7 USB_NUM_IN_ENDPOINTS = 5 CIRCUITPY_ESP32_CAMERA ?= 0 +CIRCUITPY_GIFIO ?= $(CIRCUITPY_ESP32_CAMERA) +CIRCUITPY_QRIO ?= $(CIRCUITPY_ESP32_CAMERA) From aead0dfe45589633521ea57918b4070584c1be82 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:00 -0500 Subject: [PATCH 14/30] Return a Bitmap from take() when appropriate --- .../espressif/bindings/esp32_camera/Camera.c | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index d33a5948a4..307f900680 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -35,6 +35,7 @@ #include "bindings/esp32_camera/Camera.h" #include "common-hal/esp32_camera/Camera.h" +#include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" #include "esp_camera.h" @@ -190,8 +191,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_frame_available_get_obj, es MP_PROPERTY_GETTER(esp32_camera_camera_frame_available_obj, (mp_obj_t)&esp32_camera_camera_frame_available_get_obj); -//| def take(timeout: Optional[float]=0.25) -> Optional[ReadableBuffer]: -//| """Record a frame. Wait up to 'timeout' seconds for a frame to be captured.""" +//| def take(timeout: Optional[float]=0.25) -> Optional[displayio.Bitmap | ReadableBuffer]: +//| """Record a frame. Wait up to 'timeout' seconds for a frame to be captured. +//| +//| In the case of timeout, `None` is returned. +//| If `pixel_format` is `PixelFormat.JPEG`, the returned value is a `ReadableBuffer`. +//| Otherwise, the returned value is a `displayio.Bitmap`. +//| """ //| STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(args[0]); @@ -201,7 +207,18 @@ STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { if (!result) { return mp_const_none; } - return mp_obj_new_memoryview('b', result->len, result->buf); + pixformat_t format = common_hal_esp32_camera_camera_get_pixel_format(self); + if (format == PIXFORMAT_JPEG) { + return mp_obj_new_memoryview('b', result->len, result->buf); + } else { + int width = common_hal_esp32_camera_camera_get_width(self); + int height = common_hal_esp32_camera_camera_get_height(self); + displayio_bitmap_t *bitmap = m_new_obj(displayio_bitmap_t); + bitmap->base.type = &displayio_bitmap_type; + mp_printf(&mp_plat_print, "construct bitmap %dx%d @%p\n", width, height, result->buf); + common_hal_displayio_bitmap_construct_from_buffer(bitmap, width, height, (format == PIXFORMAT_RGB565) ? 16 : 8, (uint32_t *)(void *)result->buf, true); + return bitmap; + } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera_take_obj, 1, 2, esp32_camera_camera_take); From badcae5ace1d32bab334a12276d79900d1ac4460 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:01 -0500 Subject: [PATCH 15/30] Fix docstring errors --- ports/espressif/bindings/esp32_camera/Camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index 307f900680..a9dcf37fd4 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -223,7 +223,7 @@ STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera_take_obj, 1, 2, esp32_camera_camera_take); -//| pixel_format: pixformat_t +//| pixel_format: PixelFormat //| """The pixel format of captured frames""" STATIC mp_obj_t esp32_camera_camera_get_pixel_format(const mp_obj_t self_in) { @@ -245,7 +245,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_pixel_format_obj, (mp_obj_t)&esp32_camera_camera_set_pixel_format_obj); -//| frame_size: framesize_t +//| frame_size: FrameSize //| """The size of captured frames""" STATIC mp_obj_t esp32_camera_camera_get_frame_size(const mp_obj_t self_in) { From 8bdbe0355aef485f7c801b81340a8a80e6c63044 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:02 -0500 Subject: [PATCH 16/30] Add more getters --- .../espressif/bindings/esp32_camera/Camera.c | 87 +++++++++++++++++++ .../espressif/bindings/esp32_camera/Camera.h | 8 ++ .../common-hal/esp32_camera/Camera.c | 36 ++++++++ 3 files changed, 131 insertions(+) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index a9dcf37fd4..f81b076728 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -816,9 +816,91 @@ MP_PROPERTY_GETSET(esp32_camera_camera_lenc_obj, (mp_obj_t)&esp32_camera_camera_get_lenc_obj, (mp_obj_t)&esp32_camera_camera_set_lenc_obj); +//| max_frame_size: FrameSize +//| """The maximum frame size that can be captured""" +//| +STATIC mp_obj_t esp32_camera_camera_get_max_frame_size(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return cp_enum_find(&esp32_camera_frame_size_type, common_hal_esp32_camera_camera_get_max_frame_size(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_max_frame_size_obj, esp32_camera_camera_get_max_frame_size); + +MP_PROPERTY_GETTER(esp32_camera_camera_max_frame_size_obj, + (mp_obj_t)&esp32_camera_camera_get_max_frame_size_obj); + + +//| address: int +//| """The I2C (SCCB) address of the sensor""" +//| +STATIC mp_obj_t esp32_camera_camera_get_address(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_address(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_address_obj, esp32_camera_camera_get_address); + +MP_PROPERTY_GETTER(esp32_camera_camera_address_obj, + (mp_obj_t)&esp32_camera_camera_get_address_obj); + + +//| sensor_name: str +//| """The name of the sensor""" +//| +STATIC mp_obj_t esp32_camera_camera_get_sensor_name(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + const char *sensor_name = common_hal_esp32_camera_camera_get_sensor_name(self); + return mp_obj_new_str(sensor_name, strlen(sensor_name)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_sensor_name_obj, esp32_camera_camera_get_sensor_name); + +MP_PROPERTY_GETTER(esp32_camera_camera_sensor_name_obj, + (mp_obj_t)&esp32_camera_camera_get_sensor_name_obj); + + +//| supports_jpeg: bool +//| """True if the sensor can capture images in JPEG format""" +//| +STATIC mp_obj_t esp32_camera_camera_get_supports_jpeg(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_esp32_camera_camera_get_supports_jpeg(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_supports_jpeg_obj, esp32_camera_camera_get_supports_jpeg); + +MP_PROPERTY_GETTER(esp32_camera_camera_supports_jpeg_obj, + (mp_obj_t)&esp32_camera_camera_get_supports_jpeg_obj); + +//| height: int +//| """The height of the image being captured""" +//| +STATIC mp_obj_t esp32_camera_camera_get_height(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_height(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_height_obj, esp32_camera_camera_get_height); + +MP_PROPERTY_GETTER(esp32_camera_camera_height_obj, + (mp_obj_t)&esp32_camera_camera_get_height_obj); + +//| width: int +//| """The width of the image being captured""" +//| +STATIC mp_obj_t esp32_camera_camera_get_width(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_width(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_width_obj, esp32_camera_camera_get_width); + +MP_PROPERTY_GETTER(esp32_camera_camera_width_obj, + (mp_obj_t)&esp32_camera_camera_get_width_obj); STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { + { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&esp32_camera_camera_address_obj) }, { MP_ROM_QSTR(MP_QSTR_aec2), MP_ROM_PTR(&esp32_camera_camera_aec2_obj) }, { MP_ROM_QSTR(MP_QSTR_aec_value), MP_ROM_PTR(&esp32_camera_camera_aec_value_obj) }, { MP_ROM_QSTR(MP_QSTR_ae_level), MP_ROM_PTR(&esp32_camera_camera_ae_level_obj) }, @@ -838,17 +920,22 @@ STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_frame_size), MP_ROM_PTR(&esp32_camera_camera_frame_size_obj) }, { MP_ROM_QSTR(MP_QSTR_gain_ceiling), MP_ROM_PTR(&esp32_camera_camera_gain_ceiling_obj) }, { MP_ROM_QSTR(MP_QSTR_gain_ctrl), MP_ROM_PTR(&esp32_camera_camera_gain_ctrl_obj) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&esp32_camera_camera_height_obj) }, { MP_ROM_QSTR(MP_QSTR_hmirror), MP_ROM_PTR(&esp32_camera_camera_hmirror_obj) }, { MP_ROM_QSTR(MP_QSTR_lenc), MP_ROM_PTR(&esp32_camera_camera_lenc_obj) }, + { MP_ROM_QSTR(MP_QSTR_max_frame_size), MP_ROM_PTR(&esp32_camera_camera_max_frame_size_obj) }, { MP_ROM_QSTR(MP_QSTR_pixel_format), MP_ROM_PTR(&esp32_camera_camera_pixel_format_obj) }, { MP_ROM_QSTR(MP_QSTR_quality), MP_ROM_PTR(&esp32_camera_camera_quality_obj) }, { MP_ROM_QSTR(MP_QSTR_raw_gma), MP_ROM_PTR(&esp32_camera_camera_raw_gma_obj) }, { MP_ROM_QSTR(MP_QSTR_saturation), MP_ROM_PTR(&esp32_camera_camera_saturation_obj) }, + { MP_ROM_QSTR(MP_QSTR_sensor_name), MP_ROM_PTR(&esp32_camera_camera_sensor_name_obj) }, { MP_ROM_QSTR(MP_QSTR_sharpness), MP_ROM_PTR(&esp32_camera_camera_sharpness_obj) }, { MP_ROM_QSTR(MP_QSTR_special_effect), MP_ROM_PTR(&esp32_camera_camera_special_effect_obj) }, + { MP_ROM_QSTR(MP_QSTR_supports_jpeg), MP_ROM_PTR(&esp32_camera_camera_supports_jpeg_obj) }, { MP_ROM_QSTR(MP_QSTR_take), MP_ROM_PTR(&esp32_camera_camera_take_obj) }, { MP_ROM_QSTR(MP_QSTR_vflip), MP_ROM_PTR(&esp32_camera_camera_vflip_obj) }, { MP_ROM_QSTR(MP_QSTR_wb_mode), MP_ROM_PTR(&esp32_camera_camera_wb_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&esp32_camera_camera_width_obj) }, { MP_ROM_QSTR(MP_QSTR_whitebal), MP_ROM_PTR(&esp32_camera_camera_whitebal_obj) }, { MP_ROM_QSTR(MP_QSTR_wpc), MP_ROM_PTR(&esp32_camera_camera_wpc_obj) }, }; diff --git a/ports/espressif/bindings/esp32_camera/Camera.h b/ports/espressif/bindings/esp32_camera/Camera.h index bb79fdb39a..6d830c9e49 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.h +++ b/ports/espressif/bindings/esp32_camera/Camera.h @@ -98,3 +98,11 @@ DECLARE_SENSOR_STATUS_GETSET(bool, bpc, bpc, set_bpc); DECLARE_SENSOR_STATUS_GETSET(bool, wpc, wpc, set_wpc); DECLARE_SENSOR_STATUS_GETSET(bool, raw_gma, raw_gma, set_raw_gma); DECLARE_SENSOR_STATUS_GETSET(bool, lenc, lenc, set_lenc); + +// From camera_sensor_info_t +extern int common_hal_esp32_camera_camera_get_address(esp32_camera_camera_obj_t *self); +extern const char *common_hal_esp32_camera_camera_get_sensor_name(esp32_camera_camera_obj_t *self); +extern const bool common_hal_esp32_camera_camera_get_supports_jpeg(esp32_camera_camera_obj_t *self); +extern framesize_t common_hal_esp32_camera_camera_get_max_frame_size(esp32_camera_camera_obj_t *self); +extern int common_hal_esp32_camera_camera_get_width(esp32_camera_camera_obj_t *self); +extern int common_hal_esp32_camera_camera_get_height(esp32_camera_camera_obj_t *self); diff --git a/ports/espressif/common-hal/esp32_camera/Camera.c b/ports/espressif/common-hal/esp32_camera/Camera.c index b77b8ac59e..ef62795b14 100644 --- a/ports/espressif/common-hal/esp32_camera/Camera.c +++ b/ports/espressif/common-hal/esp32_camera/Camera.c @@ -199,3 +199,39 @@ SENSOR_STATUS_GETSET(bool, bpc, bpc, set_bpc); SENSOR_STATUS_GETSET(bool, wpc, wpc, set_wpc); SENSOR_STATUS_GETSET(bool, raw_gma, raw_gma, set_raw_gma); SENSOR_STATUS_GETSET(bool, lenc, lenc, set_lenc); + +const char *common_hal_esp32_camera_camera_get_sensor_name(esp32_camera_camera_obj_t *self) { + sensor_t *sensor = esp_camera_sensor_get(); + camera_sensor_info_t *sensor_info = esp_camera_sensor_get_info(&sensor->id); + return sensor_info->name; +} + +const bool common_hal_esp32_camera_camera_get_supports_jpeg(esp32_camera_camera_obj_t *self) { + sensor_t *sensor = esp_camera_sensor_get(); + camera_sensor_info_t *sensor_info = esp_camera_sensor_get_info(&sensor->id); + return sensor_info->support_jpeg; +} + +const framesize_t common_hal_esp32_camera_camera_get_max_frame_size(esp32_camera_camera_obj_t *self) { + sensor_t *sensor = esp_camera_sensor_get(); + camera_sensor_info_t *sensor_info = esp_camera_sensor_get_info(&sensor->id); + return sensor_info->max_size; +} + +const int common_hal_esp32_camera_camera_get_address(esp32_camera_camera_obj_t *self) { + sensor_t *sensor = esp_camera_sensor_get(); + camera_sensor_info_t *sensor_info = esp_camera_sensor_get_info(&sensor->id); + return sensor_info->sccb_addr; +} + +const int common_hal_esp32_camera_camera_get_width(esp32_camera_camera_obj_t *self) { + sensor_t *sensor = esp_camera_sensor_get(); + framesize_t framesize = sensor->status.framesize; + return resolution[framesize].width; +} + +const int common_hal_esp32_camera_camera_get_height(esp32_camera_camera_obj_t *self) { + sensor_t *sensor = esp_camera_sensor_get(); + framesize_t framesize = sensor->status.framesize; + return resolution[framesize].height; +} From 277b439562035a1509e01783778e3f0bfb5f45e6 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:03 -0500 Subject: [PATCH 17/30] Bump setuptools version Building locally I saw this message: ``` /home/jepler/.espressif/python_env/idf4.4_py3.9_env/lib/python3.9/site-packages/setuptools_scm/integration.py:27: RuntimeWarning: ERROR: setuptools==44.1.1 is used in combination with setuptools_scm>=6.x Your build configuration is incomplete and previously worked by accident! setuptools_scm requires setuptools>=45 ``` For some reason this dependency is not automatically met, e.g., by setuptools_scm specifying a versioned dependency itself! So specify it here. --- requirements-doc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-doc.txt b/requirements-doc.txt index 2eaf513d3d..40ab2ad4ac 100644 --- a/requirements-doc.txt +++ b/requirements-doc.txt @@ -5,7 +5,7 @@ isort twine wheel astroid -setuptools +setuptools>=45 setuptools_scm # For sphinx From 81fb9a5f20fc28918e271ba3068b9a1493f75742 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:04 -0500 Subject: [PATCH 18/30] specify return type for docs --- .../espressif/bindings/esp32_camera/Camera.c | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index f81b076728..d1d8bc8c5d 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -59,27 +59,27 @@ //| jpeg_quality: int=15, //| double_buffered: bool = True, //| grab_mode: GrabMode = GrabMode.WhenEmpty, -//| ): -//| """ -//| Configure and initialize a camera with the given properties +//| ) -> None: +//| """ +//| Configure and initialize a camera with the given properties //| -//| This driver requires that the ``CIRCUITPY_RESERVED_PSRAM`` in ``/.env`` be large enough to hold the camera frambuffer(s). Generally, boards with built-in cameras will have a default setting that is large enough. If the constructor raises a MemoryError, this probably indicates the setting is too small and should be increased. +//| This driver requires that the ``CIRCUITPY_RESERVED_PSRAM`` in ``/.env`` be large enough to hold the camera frambuffer(s). Generally, boards with built-in cameras will have a default setting that is large enough. If the constructor raises a MemoryError, this probably indicates the setting is too small and should be increased. //| -//| :param data_pins: The 8 data data_pins used for image data transfer from the camera module, least significant bit first -//| :param pixel_clock: The pixel clock output from the camera module -//| :param vsync: The vertical sync pulse output from the camera module -//| :param href: The horizontal reference output from the camera module -//| :param i2c: The I2C bus connected to the camera module -//| :param external_clock_frequency: The frequency generated on the external clock pin -//| :param external_clock_pin: The pin on which to generate the external clock -//| :param powerdown_pin: The powerdown input to the camera module -//| :param reset_pin: The reset input to the camera module -//| :param pixel_format: The pixel format of the captured image -//| :param frame_size: The size of captured image -//| :param jpeg_quality: For `PixelFormat.JPEG`, the quality. Higher numbers increase quality. If the quality is too high, the JPEG data will be larger than the availalble buffer size and the image will be unusable or truncated. The exact range of appropriate values depends on the sensor and must be determined empirically. -//| :param framebuffer_count: The number of framebuffers -//| :param grab_mode: When to grab a new frame -//| """ +//| :param data_pins: The 8 data data_pins used for image data transfer from the camera module, least significant bit first +//| :param pixel_clock: The pixel clock output from the camera module +//| :param vsync: The vertical sync pulse output from the camera module +//| :param href: The horizontal reference output from the camera module +//| :param i2c: The I2C bus connected to the camera module +//| :param external_clock_frequency: The frequency generated on the external clock pin +//| :param external_clock_pin: The pin on which to generate the external clock +//| :param powerdown_pin: The powerdown input to the camera module +//| :param reset_pin: The reset input to the camera module +//| :param pixel_format: The pixel format of the captured image +//| :param frame_size: The size of captured image +//| :param jpeg_quality: For `PixelFormat.JPEG`, the quality. Higher numbers increase quality. If the quality is too high, the JPEG data will be larger than the availalble buffer size and the image will be unusable or truncated. The exact range of appropriate values depends on the sensor and must be determined empirically. +//| :param framebuffer_count: The number of framebuffers +//| :param grab_mode: When to grab a new frame +//| """ //| STATIC mp_obj_t esp32_camera_camera_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_data_pins, ARG_pixel_clock_pin, ARG_vsync_pin, ARG_href_pin, ARG_i2c, ARG_external_clock_pin, ARG_external_clock_frequency, ARG_powerdown_pin, ARG_reset_pin, ARG_pixel_format, ARG_frame_size, ARG_jpeg_quality, ARG_framebuffer_count, ARG_grab_mode, NUM_ARGS }; From 7cb40c90546777ec0cd63d9bec6e54980574020e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:05 -0500 Subject: [PATCH 19/30] further doc build fixes --- conf.py | 1 + ports/espressif/bindings/esp32_camera/__init__.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/conf.py b/conf.py index b7e2f29914..ad35596d7a 100644 --- a/conf.py +++ b/conf.py @@ -199,6 +199,7 @@ exclude_patterns = ["**/build*", "ports/cxd56/spresense-exported-sdk", "ports/espressif/certificates", "ports/espressif/esp-idf", + "ports/espressif/esp32-camera", "ports/espressif/.idf_tools", "ports/espressif/peripherals", "ports/litex/hw", diff --git a/ports/espressif/bindings/esp32_camera/__init__.c b/ports/espressif/bindings/esp32_camera/__init__.c index 09582d440b..69d8071cb2 100644 --- a/ports/espressif/bindings/esp32_camera/__init__.c +++ b/ports/espressif/bindings/esp32_camera/__init__.c @@ -48,7 +48,7 @@ //| """Fills buffers when they are empty. Less resources but first ``fb_count`` frames might be old""" //| //| LATEST: GrabMode -//| """Except when 1 frame buffer is used, queue will always contain the last `fb_count` frames""" +//| """Except when 1 frame buffer is used, queue will always contain the last ``fb_count`` frames""" //| MAKE_ENUM_VALUE(esp32_camera_grab_mode_type, grab_mode, WHEN_EMPTY, CAMERA_GRAB_WHEN_EMPTY); From a9d53ad2a682890075515dd84a19fe231bc776b5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:06 -0500 Subject: [PATCH 20/30] Fix "check-stubs" problems --- ports/espressif/bindings/esp32_camera/Camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index d1d8bc8c5d..654917c28b 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -58,7 +58,7 @@ //| frame_size: FrameSize=FrameSize.QQVGA, //| jpeg_quality: int=15, //| double_buffered: bool = True, -//| grab_mode: GrabMode = GrabMode.WhenEmpty, +//| grab_mode: GrabMode = GrabMode.WHEN_EMPTY, //| ) -> None: //| """ //| Configure and initialize a camera with the given properties @@ -191,7 +191,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_frame_available_get_obj, es MP_PROPERTY_GETTER(esp32_camera_camera_frame_available_obj, (mp_obj_t)&esp32_camera_camera_frame_available_get_obj); -//| def take(timeout: Optional[float]=0.25) -> Optional[displayio.Bitmap | ReadableBuffer]: +//| def take(self, timeout: Optional[float]=0.25) -> Optional[displayio.Bitmap | ReadableBuffer]: //| """Record a frame. Wait up to 'timeout' seconds for a frame to be captured. //| //| In the case of timeout, `None` is returned. From 230532f0eb02e24a5ca82b25ddfbc8b6d0f3aa31 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:07 -0500 Subject: [PATCH 21/30] one last doc build fix --- ports/espressif/bindings/esp32_camera/Camera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index 654917c28b..1b62f26280 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -195,8 +195,8 @@ MP_PROPERTY_GETTER(esp32_camera_camera_frame_available_obj, //| """Record a frame. Wait up to 'timeout' seconds for a frame to be captured. //| //| In the case of timeout, `None` is returned. -//| If `pixel_format` is `PixelFormat.JPEG`, the returned value is a `ReadableBuffer`. -//| Otherwise, the returned value is a `displayio.Bitmap`. +//| If `pixel_format` is `PixelFormat.JPEG`, the returned value is a read-only `memoryview`. +//| Otherwise, the returned value is a read-only `displayio.Bitmap`. //| """ //| STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { From 0e26a937ccc8187aaf15f98c763a669dd7caa7a5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:08 -0500 Subject: [PATCH 22/30] Disable camera everywhere it doesn't fit --- .../adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk | 1 + .../boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk | 1 + ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk | 2 ++ .../boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk | 2 ++ ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk | 2 ++ ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk | 2 ++ 6 files changed, 10 insertions(+) diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk index 1b4c4015f5..b8bea2c02c 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk @@ -17,3 +17,4 @@ CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB OPTIMIZATION_FLAGS = -Os +CIRCUITPY_ESP32_CAMERA = 0 diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk index dcbd2f9c7a..380423ba10 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk @@ -18,3 +18,4 @@ CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB OPTIMIZATION_FLAGS = -Os +CIRCUITPY_ESP32_CAMERA = 0 diff --git a/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk b/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk index 531627d5a6..4962806178 100644 --- a/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk @@ -16,6 +16,8 @@ CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP32_CAMERA = 0 + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_PortalBase FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_FakeRequests diff --git a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk index e1bd4997b7..2df1532535 100644 --- a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk @@ -16,6 +16,8 @@ CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP32_CAMERA = 0 + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_PortalBase FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_FakeRequests diff --git a/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk b/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk index 31955af81f..b6d165b82d 100644 --- a/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk +++ b/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk @@ -16,6 +16,8 @@ CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP32_CAMERA = 0 + FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/mixgo_cp_lib/mixgoce_lib diff --git a/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk b/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk index 4b8fe6846c..5d6fc8368f 100644 --- a/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk +++ b/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk @@ -16,6 +16,8 @@ CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP32_CAMERA = 0 + FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/mixgo_cp_lib/mixgoce_lib From 428fbcd34328767d1ce8d53f0a494ecce544b566 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:10 -0500 Subject: [PATCH 23/30] remove debug message during build --- ports/espressif/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 1f01513d32..af1788d01e 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -287,7 +287,6 @@ SRC_CAMERA := \ $(wildcard common-hal/esp32_camera/*.c) \ $(wildcard bindings/esp32_camera/*.c) SRC_C += $(SRC_CAMERA) -$(info SRC_CAMERA = $(SRC_CAMERA)) CFLAGS += -isystem esp32-camera/driver/include CFLAGS += -isystem esp32-camera/conversions/include endif From 98202c85688384f702802ad263c30afa8c74da9e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:11 -0500 Subject: [PATCH 24/30] Allow changing camera settings that require reinit These can only be changed in a group, though any items to keep unchanged can be unspecified or specified as None. --- .../espressif/bindings/esp32_camera/Camera.c | 119 ++++++++++++++---- .../espressif/bindings/esp32_camera/Camera.h | 12 +- .../common-hal/esp32_camera/Camera.c | 46 ++++++- 3 files changed, 147 insertions(+), 30 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index 1b62f26280..665c120a70 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -77,7 +77,7 @@ //| :param pixel_format: The pixel format of the captured image //| :param frame_size: The size of captured image //| :param jpeg_quality: For `PixelFormat.JPEG`, the quality. Higher numbers increase quality. If the quality is too high, the JPEG data will be larger than the availalble buffer size and the image will be unusable or truncated. The exact range of appropriate values depends on the sensor and must be determined empirically. -//| :param framebuffer_count: The number of framebuffers +//| :param framebuffer_count: The number of framebuffers (1 for single-buffered and 2 for double-buffered) //| :param grab_mode: When to grab a new frame //| """ //| @@ -175,8 +175,7 @@ STATIC void check_for_deinit(esp32_camera_camera_obj_t *self) { //| STATIC mp_obj_t esp32_camera_camera_obj___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; - common_hal_esp32_camera_camera_deinit(args[0]); - return mp_const_none; + return esp32_camera_camera_deinit(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera___exit___obj, 4, 4, esp32_camera_camera_obj___exit__); @@ -184,7 +183,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera___exit___obj, 4, //| """True if a frame is available, False otherwise""" STATIC mp_obj_t esp32_camera_camera_frame_available_get(const mp_obj_t self_in) { - return mp_obj_new_bool(false); + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(esp_camera_fb_available()); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_frame_available_get_obj, esp32_camera_camera_frame_available_get); @@ -215,7 +216,6 @@ STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { int height = common_hal_esp32_camera_camera_get_height(self); displayio_bitmap_t *bitmap = m_new_obj(displayio_bitmap_t); bitmap->base.type = &displayio_bitmap_type; - mp_printf(&mp_plat_print, "construct bitmap %dx%d @%p\n", width, height, result->buf); common_hal_displayio_bitmap_construct_from_buffer(bitmap, width, height, (format == PIXFORMAT_RGB565) ? 16 : 8, (uint32_t *)(void *)result->buf, true); return bitmap; } @@ -223,6 +223,59 @@ STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera_take_obj, 1, 2, esp32_camera_camera_take); +//| def reconfigure( +//| self, +//| frame_size: Optional[FrameSize] = None, +//| pixel_format: Optional[PixelFormat] = None, +//| grab_mode: Optional[GrabMode] = None, +//| framebuffer_count: Optional[int] = None, +//| ) -> None: +//| """Set the frame size and pixel format +//| +//| Because these settings interact in complex ways, and take longer than +//| the other properties to set, they are set together in a single function call. +//| +//| If an argument is unspecified or None, then the setting is unchanged.""" +//| + +STATIC mp_obj_t esp32_camera_camera_reconfigure(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + + enum { ARG_frame_size, ARG_pixel_format, ARG_grab_mode, ARG_framebuffer_count }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_frame_size, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_pixel_format, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_grab_mode, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_framebuffer_count, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + framesize_t frame_size = + args[ARG_frame_size].u_obj != MP_ROM_NONE + ? validate_frame_size(args[ARG_frame_size].u_obj, MP_QSTR_frame_size) + : common_hal_esp32_camera_camera_get_frame_size(self); + pixformat_t pixel_format = + args[ARG_pixel_format].u_obj != MP_ROM_NONE + ? validate_pixel_format(args[ARG_pixel_format].u_obj, MP_QSTR_pixel_format) + : common_hal_esp32_camera_camera_get_pixel_format(self); + camera_grab_mode_t grab_mode = + args[ARG_grab_mode].u_obj != MP_ROM_NONE + ? validate_grab_mode(args[ARG_grab_mode].u_obj, MP_QSTR_grab_mode) + : common_hal_esp32_camera_camera_get_grab_mode(self); + bool framebuffer_count = + args[ARG_framebuffer_count].u_obj != MP_ROM_NONE + ? mp_obj_get_int(args[ARG_framebuffer_count].u_obj) + : common_hal_esp32_camera_camera_get_framebuffer_count(self); + + common_hal_esp32_camera_camera_reconfigure(self, frame_size, pixel_format, grab_mode, framebuffer_count); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(esp32_camera_camera_reconfigure_obj, 1, esp32_camera_camera_reconfigure); + //| pixel_format: PixelFormat //| """The pixel format of captured frames""" @@ -233,16 +286,8 @@ STATIC mp_obj_t esp32_camera_camera_get_pixel_format(const mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_pixel_format_obj, esp32_camera_camera_get_pixel_format); -STATIC mp_obj_t esp32_camera_camera_set_pixel_format(const mp_obj_t self_in, const mp_obj_t arg) { - esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - common_hal_esp32_camera_camera_set_pixel_format(self, validate_pixel_format(arg, MP_QSTR_pixel_format)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_pixel_format_obj, esp32_camera_camera_set_pixel_format); -MP_PROPERTY_GETSET(esp32_camera_camera_pixel_format_obj, - (mp_obj_t)&esp32_camera_camera_get_pixel_format_obj, - (mp_obj_t)&esp32_camera_camera_set_pixel_format_obj); +MP_PROPERTY_GETTER(esp32_camera_camera_pixel_format_obj, + (mp_obj_t)&esp32_camera_camera_get_pixel_format_obj); //| frame_size: FrameSize @@ -255,16 +300,8 @@ STATIC mp_obj_t esp32_camera_camera_get_frame_size(const mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_frame_size_obj, esp32_camera_camera_get_frame_size); -STATIC mp_obj_t esp32_camera_camera_set_frame_size(const mp_obj_t self_in, const mp_obj_t arg) { - esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - common_hal_esp32_camera_camera_set_frame_size(self, validate_frame_size(arg, MP_QSTR_frame_size)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_camera_camera_set_frame_size_obj, esp32_camera_camera_set_frame_size); -MP_PROPERTY_GETSET(esp32_camera_camera_frame_size_obj, - (mp_obj_t)&esp32_camera_camera_get_frame_size_obj, - (mp_obj_t)&esp32_camera_camera_set_frame_size_obj); +MP_PROPERTY_GETTER(esp32_camera_camera_frame_size_obj, + (mp_obj_t)&esp32_camera_camera_get_frame_size_obj); //| contrast: int //| """Access the contrast property of the camera sensor""" @@ -898,6 +935,33 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_width_obj, esp32_camera MP_PROPERTY_GETTER(esp32_camera_camera_width_obj, (mp_obj_t)&esp32_camera_camera_get_width_obj); +//| grab_mode: GrabMode +//| """The grab mode of the camera""" +//| +STATIC mp_obj_t esp32_camera_camera_get_grab_mode(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return cp_enum_find(&esp32_camera_grab_mode_type, common_hal_esp32_camera_camera_get_grab_mode(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_grab_mode_obj, esp32_camera_camera_get_grab_mode); + +MP_PROPERTY_GETTER(esp32_camera_camera_grab_mode_obj, + (mp_obj_t)&esp32_camera_camera_get_grab_mode_obj); + + +//| framebuffer_count: int +//| """True if double buffering is used""" +//| +STATIC mp_obj_t esp32_camera_camera_get_framebuffer_count(const mp_obj_t self_in) { + esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_esp32_camera_camera_get_framebuffer_count(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_get_framebuffer_count_obj, esp32_camera_camera_get_framebuffer_count); + +MP_PROPERTY_GETTER(esp32_camera_camera_framebuffer_count_obj, + (mp_obj_t)&esp32_camera_camera_get_framebuffer_count_obj); + STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&esp32_camera_camera_address_obj) }, @@ -913,6 +977,7 @@ STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_dcw), MP_ROM_PTR(&esp32_camera_camera_dcw_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_camera_camera_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_denoise), MP_ROM_PTR(&esp32_camera_camera_denoise_obj) }, + { MP_ROM_QSTR(MP_QSTR_framebuffer_count), MP_ROM_PTR(&esp32_camera_camera_framebuffer_count_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&esp32_camera_camera___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_exposure_ctrl), MP_ROM_PTR(&esp32_camera_camera_exposure_ctrl_obj) }, @@ -920,6 +985,7 @@ STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_frame_size), MP_ROM_PTR(&esp32_camera_camera_frame_size_obj) }, { MP_ROM_QSTR(MP_QSTR_gain_ceiling), MP_ROM_PTR(&esp32_camera_camera_gain_ceiling_obj) }, { MP_ROM_QSTR(MP_QSTR_gain_ctrl), MP_ROM_PTR(&esp32_camera_camera_gain_ctrl_obj) }, + { MP_ROM_QSTR(MP_QSTR_grab_mode), MP_ROM_PTR(&esp32_camera_camera_grab_mode_obj) }, { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&esp32_camera_camera_height_obj) }, { MP_ROM_QSTR(MP_QSTR_hmirror), MP_ROM_PTR(&esp32_camera_camera_hmirror_obj) }, { MP_ROM_QSTR(MP_QSTR_lenc), MP_ROM_PTR(&esp32_camera_camera_lenc_obj) }, @@ -927,6 +993,7 @@ STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_pixel_format), MP_ROM_PTR(&esp32_camera_camera_pixel_format_obj) }, { MP_ROM_QSTR(MP_QSTR_quality), MP_ROM_PTR(&esp32_camera_camera_quality_obj) }, { MP_ROM_QSTR(MP_QSTR_raw_gma), MP_ROM_PTR(&esp32_camera_camera_raw_gma_obj) }, + { MP_ROM_QSTR(MP_QSTR_reconfigure), MP_ROM_PTR(&esp32_camera_camera_reconfigure_obj) }, { MP_ROM_QSTR(MP_QSTR_saturation), MP_ROM_PTR(&esp32_camera_camera_saturation_obj) }, { MP_ROM_QSTR(MP_QSTR_sensor_name), MP_ROM_PTR(&esp32_camera_camera_sensor_name_obj) }, { MP_ROM_QSTR(MP_QSTR_sharpness), MP_ROM_PTR(&esp32_camera_camera_sharpness_obj) }, @@ -935,8 +1002,8 @@ STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_take), MP_ROM_PTR(&esp32_camera_camera_take_obj) }, { MP_ROM_QSTR(MP_QSTR_vflip), MP_ROM_PTR(&esp32_camera_camera_vflip_obj) }, { MP_ROM_QSTR(MP_QSTR_wb_mode), MP_ROM_PTR(&esp32_camera_camera_wb_mode_obj) }, - { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&esp32_camera_camera_width_obj) }, { MP_ROM_QSTR(MP_QSTR_whitebal), MP_ROM_PTR(&esp32_camera_camera_whitebal_obj) }, + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&esp32_camera_camera_width_obj) }, { MP_ROM_QSTR(MP_QSTR_wpc), MP_ROM_PTR(&esp32_camera_camera_wpc_obj) }, }; diff --git a/ports/espressif/bindings/esp32_camera/Camera.h b/ports/espressif/bindings/esp32_camera/Camera.h index 6d830c9e49..146cd0da05 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.h +++ b/ports/espressif/bindings/esp32_camera/Camera.h @@ -57,6 +57,7 @@ extern void common_hal_esp32_camera_camera_deinit(esp32_camera_camera_obj_t *sel extern bool common_hal_esp32_camera_camera_deinited(esp32_camera_camera_obj_t *self); extern bool common_hal_esp32_camera_camera_available(esp32_camera_camera_obj_t *self); extern camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self, int timeout_ms); +extern void common_hal_esp32_camera_camera_reconfigure(esp32_camera_camera_obj_t *self, framesize_t frame_size, pixformat_t pixel_format, camera_grab_mode_t grab_mode, mp_int_t framebuffer_count); #define DECLARE_SENSOR_GETSET(type, name, field_name, setter_function_name) \ DECLARE_SENSOR_GET(type, name, field_name, setter_function_name) \ @@ -65,14 +66,17 @@ extern camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_ #define DECLARE_SENSOR_STATUS_GETSET(type, name, status_field_name, setter_function_name) \ DECLARE_SENSOR_GETSET(type, name, status.status_field_name, setter_function_name) +#define DECLARE_SENSOR_STATUS_GET(type, name, status_field_name, setter_function_name) \ + DECLARE_SENSOR_GET(type, name, status.status_field_name, setter_function_name) + #define DECLARE_SENSOR_GET(type, name, status_field_name, setter_function_name) \ extern type common_hal_esp32_camera_camera_get_##name(esp32_camera_camera_obj_t * self); #define DECLARE_SENSOR_SET(type, name, setter_function_name) \ extern void common_hal_esp32_camera_camera_set_##name(esp32_camera_camera_obj_t * self, type value); -DECLARE_SENSOR_GETSET(pixformat_t, pixel_format, pixformat, set_pixformat) -DECLARE_SENSOR_STATUS_GETSET(framesize_t, frame_size, framesize, set_framesize) +DECLARE_SENSOR_GET(pixformat_t, pixel_format, pixformat, set_pixformat) +DECLARE_SENSOR_STATUS_GET(framesize_t, frame_size, framesize, set_framesize) DECLARE_SENSOR_STATUS_GETSET(int, contrast, contrast, set_contrast); DECLARE_SENSOR_STATUS_GETSET(int, brightness, brightness, set_brightness); DECLARE_SENSOR_STATUS_GETSET(int, saturation, saturation, set_saturation); @@ -99,6 +103,10 @@ DECLARE_SENSOR_STATUS_GETSET(bool, wpc, wpc, set_wpc); DECLARE_SENSOR_STATUS_GETSET(bool, raw_gma, raw_gma, set_raw_gma); DECLARE_SENSOR_STATUS_GETSET(bool, lenc, lenc, set_lenc); +// From settings +extern camera_grab_mode_t common_hal_esp32_camera_camera_get_grab_mode(esp32_camera_camera_obj_t *self); +extern int common_hal_esp32_camera_camera_get_framebuffer_count(esp32_camera_camera_obj_t *self); + // From camera_sensor_info_t extern int common_hal_esp32_camera_camera_get_address(esp32_camera_camera_obj_t *self); extern const char *common_hal_esp32_camera_camera_get_sensor_name(esp32_camera_camera_obj_t *self); diff --git a/ports/espressif/common-hal/esp32_camera/Camera.c b/ports/espressif/common-hal/esp32_camera/Camera.c index ef62795b14..af1d20542a 100644 --- a/ports/espressif/common-hal/esp32_camera/Camera.c +++ b/ports/espressif/common-hal/esp32_camera/Camera.c @@ -32,6 +32,8 @@ #include "shared-bindings/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h" +#include "esp32-camera/driver/private_include/cam_hal.h" + static void maybe_claim_pin(const mcu_pin_obj_t *pin) { if (pin) { claim_pin(pin); @@ -172,8 +174,40 @@ camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self } \ } -SENSOR_GETSET(pixformat_t, pixel_format, pixformat, set_pixformat); -SENSOR_STATUS_GETSET(framesize_t, frame_size, framesize, set_framesize); +pixformat_t common_hal_esp32_camera_camera_get_pixel_format(esp32_camera_camera_obj_t *self) { + return self->camera_config.pixel_format; +} + +framesize_t common_hal_esp32_camera_camera_get_frame_size(esp32_camera_camera_obj_t *self) { + return self->camera_config.frame_size; +} + +#include "esp_log.h" + +void common_hal_esp32_camera_camera_reconfigure(esp32_camera_camera_obj_t *self, framesize_t frame_size, pixformat_t pixel_format, camera_grab_mode_t grab_mode, mp_int_t framebuffer_count) { + sensor_t *sensor = esp_camera_sensor_get(); + camera_sensor_info_t *sensor_info = esp_camera_sensor_get_info(&sensor->id); + + if (PIXFORMAT_JPEG == pixel_format && (!sensor_info->support_jpeg)) { + raise_esp_error(ESP_ERR_NOT_SUPPORTED); + } + + if (frame_size > sensor_info->max_size) { + frame_size = sensor_info->max_size; + } + + cam_deinit(); + self->camera_config.pixel_format = pixel_format; + self->camera_config.frame_size = frame_size; + self->camera_config.grab_mode = grab_mode; + self->camera_config.fb_count = framebuffer_count; + sensor->set_pixformat(sensor, self->camera_config.pixel_format); + sensor->set_framesize(sensor, self->camera_config.frame_size); + cam_init(&self->camera_config); + cam_config(&self->camera_config, frame_size, sensor_info->pid); + cam_start(); +} + SENSOR_STATUS_GETSET(int, contrast, contrast, set_contrast); SENSOR_STATUS_GETSET(int, brightness, brightness, set_brightness); SENSOR_STATUS_GETSET(int, saturation, saturation, set_saturation); @@ -235,3 +269,11 @@ const int common_hal_esp32_camera_camera_get_height(esp32_camera_camera_obj_t *s framesize_t framesize = sensor->status.framesize; return resolution[framesize].height; } + +const camera_grab_mode_t common_hal_esp32_camera_camera_get_grab_mode(esp32_camera_camera_obj_t *self) { + return self->camera_config.grab_mode; +} + +const int common_hal_esp32_camera_camera_get_framebuffer_count(esp32_camera_camera_obj_t *self) { + return self->camera_config.fb_count; +} From 861fa9625dc4229638ced6bd91ab6ea55a49a047 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 4 Aug 2022 15:12:12 -0500 Subject: [PATCH 25/30] Add the ESP32-EYE aka ESP-EYE --- .../boards/espressif_esp32_eye/board.c | 46 ++++++++++++ .../espressif_esp32_eye/mpconfigboard.h | 39 ++++++++++ .../espressif_esp32_eye/mpconfigboard.mk | 14 ++++ .../boards/espressif_esp32_eye/pins.c | 39 ++++++++++ .../boards/espressif_esp32_eye/sdkconfig | 72 +++++++++++++++++++ 5 files changed, 210 insertions(+) create mode 100644 ports/espressif/boards/espressif_esp32_eye/board.c create mode 100644 ports/espressif/boards/espressif_esp32_eye/mpconfigboard.h create mode 100644 ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk create mode 100644 ports/espressif/boards/espressif_esp32_eye/pins.c create mode 100644 ports/espressif/boards/espressif_esp32_eye/sdkconfig diff --git a/ports/espressif/boards/espressif_esp32_eye/board.c b/ports/espressif/boards/espressif_esp32_eye/board.c new file mode 100644 index 0000000000..d66ab9e5f1 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_eye/board.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "components/driver/include/driver/gpio.h" +#include "components/hal/include/hal/gpio_hal.h" +#include "common-hal/microcontroller/Pin.h" + +void board_init(void) { + reset_board(); +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} + +void board_deinit(void) { +} diff --git a/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.h b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.h new file mode 100644 index 0000000000..63a6f2307e --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.h @@ -0,0 +1,39 @@ +/* + * 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-EYE" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO23, .sda = &pin_GPIO18}} + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) + +#define DEFAULT_RESERVED_PSRAM (1048576) diff --git a/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk new file mode 100644 index 0000000000..a23b6ef6a8 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk @@ -0,0 +1,14 @@ +CIRCUITPY_CREATOR_ID = 0x000C303A +CIRCUITPY_CREATION_ID = 0x00320001 + +IDF_TARGET = esp32 + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +CIRCUITPY_STATUS_BAR = 0 +CIRCUITPY_WEB_WORKFLOW = 0 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 40m +CIRCUITPY_ESP_FLASH_SIZE = 4MB diff --git a/ports/espressif/boards/espressif_esp32_eye/pins.c b/ports/espressif/boards/espressif_esp32_eye/pins.c new file mode 100644 index 0000000000..2b640681c9 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_eye/pins.c @@ -0,0 +1,39 @@ +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_obj_tuple_t camera_data_tuple = { + {&mp_type_tuple}, + 8, + { + MP_ROM_PTR(&pin_GPIO34), + MP_ROM_PTR(&pin_GPIO13), + MP_ROM_PTR(&pin_GPIO14), + MP_ROM_PTR(&pin_GPIO35), + MP_ROM_PTR(&pin_GPIO39), // "S_VN" + MP_ROM_PTR(&pin_GPIO38), + MP_ROM_PTR(&pin_GPIO37), + MP_ROM_PTR(&pin_GPIO36), // "S_VP" + } +}; + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_I2S_SCK), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WS), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_I2S_SDO), MP_ROM_PTR(&pin_GPIO32) }, + + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_LED_RED), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_LED_WHITE), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA), MP_ROM_PTR(&camera_data_tuple) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_VSYNC), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_HREF), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_PCLK), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_XCLK), MP_ROM_PTR(&pin_GPIO4) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32_eye/sdkconfig b/ports/espressif/boards/espressif_esp32_eye/sdkconfig new file mode 100644 index 0000000000..a73d92e0a2 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32_eye/sdkconfig @@ -0,0 +1,72 @@ +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +# +# Component config +# +# +# ESP32-specific +# +CONFIG_ESP32_SPIRAM_SUPPORT=y +# +# SPI RAM config +# +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_SIZE=-1 +CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MEMMAP=y +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +# CONFIG_SPIRAM_USE_MALLOC is not set +CONFIG_SPIRAM_MEMTEST=y +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +CONFIG_SPIRAM_CACHE_WORKAROUND=y +# CONFIG_SPIRAM_BANKSWITCH_ENABLE is not set +# end of SPI RAM config + +# end of ESP32-specific + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# Camera configuration +# +CONFIG_OV7670_SUPPORT=y +CONFIG_OV7725_SUPPORT=y +CONFIG_NT99141_SUPPORT=y +CONFIG_OV2640_SUPPORT=y +CONFIG_OV3660_SUPPORT=y +CONFIG_OV5640_SUPPORT=y +CONFIG_GC2145_SUPPORT=y +CONFIG_GC032A_SUPPORT=y +CONFIG_GC0308_SUPPORT=y +CONFIG_BF3005_SUPPORT=y +CONFIG_BF20A6_SUPPORT=y +# CONFIG_SC101IOT_SUPPORT is not set +CONFIG_SC030IOT_SUPPORT=y +# CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set +CONFIG_SCCB_HARDWARE_I2C_PORT1=y +CONFIG_SCCB_CLK_FREQ=100000 +# CONFIG_GC_SENSOR_WINDOWING_MODE is not set +CONFIG_GC_SENSOR_SUBSAMPLE_MODE=y +CONFIG_CAMERA_CORE0=y +# CONFIG_CAMERA_CORE1 is not set +# CONFIG_CAMERA_NO_AFFINITY is not set +CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 +# end of Camera configuration + +# end of Component config +# +CONFIG_ESP_CONSOLE_UART_TX_GPIO=1 +CONFIG_ESP_CONSOLE_UART_RX_GPIO=3 + From 3f49d77036d0ef213eb15b54a8e6efefe80a3ebd Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 5 Aug 2022 09:59:10 -0500 Subject: [PATCH 26/30] Improve esp32-s3-eye board definition --- .../boards/espressif_esp32s3_eye/board.c | 2 +- .../espressif_esp32s3_eye/mpconfigboard.h | 2 +- .../boards/espressif_esp32s3_eye/pins.c | 27 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/ports/espressif/boards/espressif_esp32s3_eye/board.c b/ports/espressif/boards/espressif_esp32s3_eye/board.c index 7829a4be94..4edf8b5c08 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/board.c +++ b/ports/espressif/boards/espressif_esp32s3_eye/board.c @@ -70,7 +70,7 @@ uint8_t display_init_sequence[] = { }; void board_init(void) { - busio_spi_obj_t *spi = common_hal_board_create_spi(1); + busio_spi_obj_t *spi = common_hal_board_create_spi(0); displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus; bus->base.type = &displayio_fourwire_type; diff --git a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h index d32704c8bf..43ade4f6c8 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h +++ b/ports/espressif/boards/espressif_esp32s3_eye/mpconfigboard.h @@ -40,8 +40,8 @@ #define CIRCUITPY_BOARD_SPI (2) #define CIRCUITPY_BOARD_SPI_PIN { \ - {.clock = &pin_GPIO39, .mosi = &pin_GPIO40, .miso = &pin_GPIO38}, \ {.clock = &pin_GPIO21, .mosi = &pin_GPIO47, .miso = NULL}, \ + {.clock = &pin_GPIO39, .mosi = &pin_GPIO40, .miso = &pin_GPIO38}, \ } #define DEFAULT_RESERVED_PSRAM (1048576) diff --git a/ports/espressif/boards/espressif_esp32s3_eye/pins.c b/ports/espressif/boards/espressif_esp32s3_eye/pins.c index 7ebda4309d..defa4e9c52 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/pins.c +++ b/ports/espressif/boards/espressif_esp32s3_eye/pins.c @@ -1,5 +1,6 @@ #include "py/objtuple.h" #include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" STATIC const mp_rom_obj_tuple_t camera_data_tuple = { {&mp_type_tuple}, @@ -32,24 +33,24 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_CAMERA_PCLK), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_CAMERA_XCLK), MP_ROM_PTR(&pin_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(&pin_GPIO21) }, // LCD - { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO38) }, - { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO39) }, - { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO40) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_MISO1), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_MOSI1), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_SCK1), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_MIC_SCK), MP_ROM_PTR(&pin_GPIO41) }, { MP_ROM_QSTR(MP_QSTR_MIC_WS), MP_ROM_PTR(&pin_GPIO42) }, - { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO43) }, // LCD - { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO44) }, // LCD - // { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, // LCD -- unused? - // { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // LCD -- unused? - { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO47) }, // LCD - { MP_ROM_QSTR(MP_QSTR_BACKLIGHT), MP_ROM_PTR(&pin_GPIO48) }, // LCD - { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO48) }, // LCD + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_BACKLIGHT), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO48) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, - // TODO - // { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); From f87e34b9edd97af33f480de7c260a90f4d76f2c5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 8 Aug 2022 09:34:40 -0500 Subject: [PATCH 27/30] add shutter button --- ports/espressif/boards/espressif_esp32_eye/pins.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/espressif/boards/espressif_esp32_eye/pins.c b/ports/espressif/boards/espressif_esp32_eye/pins.c index 2b640681c9..1824ba1cc0 100644 --- a/ports/espressif/boards/espressif_esp32_eye/pins.c +++ b/ports/espressif/boards/espressif_esp32_eye/pins.c @@ -24,6 +24,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2S_SDO), MP_ROM_PTR(&pin_GPIO32) }, { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO15) }, { MP_ROM_QSTR(MP_QSTR_LED_RED), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_LED_WHITE), MP_ROM_PTR(&pin_GPIO22) }, From ec839d6f9044e1009efcd5d1d18d2dd26520a9db Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 9 Aug 2022 10:52:22 -0500 Subject: [PATCH 28/30] these items should not have been disabled --- ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk | 3 --- 1 file changed, 3 deletions(-) diff --git a/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk index a23b6ef6a8..4bd091d723 100644 --- a/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk @@ -6,9 +6,6 @@ IDF_TARGET = esp32 INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = MPZ -CIRCUITPY_STATUS_BAR = 0 -CIRCUITPY_WEB_WORKFLOW = 0 - CIRCUITPY_ESP_FLASH_MODE = dio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB From 5a85b8ab95e7c5eab7a35b789e7cdc625debca6c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 9 Aug 2022 11:41:31 -0500 Subject: [PATCH 29/30] improve docstrings based on my best sleuthing --- .../espressif/bindings/esp32_camera/Camera.c | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index 665c120a70..9a7b79a3ed 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -65,6 +65,18 @@ //| //| This driver requires that the ``CIRCUITPY_RESERVED_PSRAM`` in ``/.env`` be large enough to hold the camera frambuffer(s). Generally, boards with built-in cameras will have a default setting that is large enough. If the constructor raises a MemoryError, this probably indicates the setting is too small and should be increased. //| +//| +//| .. IMPORTANT: +//| Not all supported sensors have all +//| of the properties listed below. For instance, the +//| OV5640 supports `denoise`, but the +//| OV2640 does not. The underlying esp32-camera +//| library does not provide a reliable API to check +//| which settings are supported. CircuitPython makes +//| a best effort to determine when an unsupported +//| property is set and will raise an exception in +//| that case. +//| //| :param data_pins: The 8 data data_pins used for image data transfer from the camera module, least significant bit first //| :param pixel_clock: The pixel clock output from the camera module //| :param vsync: The vertical sync pulse output from the camera module @@ -230,7 +242,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera_take_obj, 1, 2, e //| grab_mode: Optional[GrabMode] = None, //| framebuffer_count: Optional[int] = None, //| ) -> None: -//| """Set the frame size and pixel format +//| """Change multiple related camera settings simultaneously //| //| Because these settings interact in complex ways, and take longer than //| the other properties to set, they are set together in a single function call. @@ -304,7 +316,7 @@ MP_PROPERTY_GETTER(esp32_camera_camera_frame_size_obj, (mp_obj_t)&esp32_camera_camera_get_frame_size_obj); //| contrast: int -//| """Access the contrast property of the camera sensor""" +//| """The sensor contrast. Positive values increase contrast, negative values lower it. The total range is device-specific but is often from -2 to +2 inclusive.""" //| STATIC mp_obj_t esp32_camera_camera_get_contrast(const mp_obj_t self_in) { @@ -326,7 +338,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_contrast_obj, (mp_obj_t)&esp32_camera_camera_set_contrast_obj); //| brightness: int -//| """Access the brightness property of the camera sensor""" +//| """The sensor brightness. Positive values increase brightness, negative values lower it. The total range is device-specific but is often from -2 to +2 inclusive.""" //| STATIC mp_obj_t esp32_camera_camera_get_brightness(const mp_obj_t self_in) { @@ -348,7 +360,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_brightness_obj, (mp_obj_t)&esp32_camera_camera_set_brightness_obj); //| saturation: int -//| """Access the saturation property of the camera sensor""" +//| """The sensor saturation. Positive values increase saturation (more vibrant colors), negative values lower it (more muted colors). The total range is device-specific but the value is often from -2 to +2 inclusive.""" //| STATIC mp_obj_t esp32_camera_camera_get_saturation(const mp_obj_t self_in) { @@ -370,7 +382,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_saturation_obj, (mp_obj_t)&esp32_camera_camera_set_saturation_obj); //| sharpness: int -//| """Access the sharpness property of the camera sensor""" +//| """The sensor sharpness. Positive values increase sharpness (more defined edges), negative values lower it (softer edges). The total range is device-specific but the value is often from -2 to +2 inclusive.""" //| STATIC mp_obj_t esp32_camera_camera_get_sharpness(const mp_obj_t self_in) { @@ -392,7 +404,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_sharpness_obj, (mp_obj_t)&esp32_camera_camera_set_sharpness_obj); //| denoise: int -//| """Access the denoise property of the camera sensor""" +//| """The sensor 'denoise' setting. Any camera sensor has inherent 'noise', especially in low brightness environments. Software algorithms can decrease noise at the expense of fine detail. A larger value increases the amount of software noise removal. The total range is device-specific but the value is often from 0 to 10.""" //| STATIC mp_obj_t esp32_camera_camera_get_denoise(const mp_obj_t self_in) { @@ -414,7 +426,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_denoise_obj, (mp_obj_t)&esp32_camera_camera_set_denoise_obj); //| gain_ceiling: GainCeiling -//| """Access the gain ceiling property of the camera sensor""" +//| """The sensor 'gain ceiling' setting. "Gain" is an analog multiplier applied to the raw sensor data. The 'ceiling' is the maximum gain value that the sensor will use. A higher gain means that the sensor has a greater response to light, but also makes sensor noise more visible.""" //| STATIC mp_obj_t esp32_camera_camera_get_gain_ceiling(const mp_obj_t self_in) { @@ -436,7 +448,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_gain_ceiling_obj, (mp_obj_t)&esp32_camera_camera_set_gain_ceiling_obj); //| quality: int -//| """Access the quality property of the camera sensor""" +//| """The 'quality' setting when capturing JPEG images. This is similar to the quality setting when exporting a jpeg image from photo editing software. Typical values range from 5 to 40, with higher numbers leading to larger image sizes and better overall image quality. However, when the quality is set to a high number, the total size of the JPEG data can exceed the size of an internal buffer, causing image capture to fail.""" //| STATIC mp_obj_t esp32_camera_camera_get_quality(const mp_obj_t self_in) { @@ -458,7 +470,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_quality_obj, (mp_obj_t)&esp32_camera_camera_set_quality_obj); //| colorbar: bool -//| """Access the colorbar property of the camera sensor""" +//| """When `True`, a test pattern image is captured and the real sensor data is not used.""" //| STATIC mp_obj_t esp32_camera_camera_get_colorbar(const mp_obj_t self_in) { @@ -480,7 +492,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_colorbar_obj, (mp_obj_t)&esp32_camera_camera_set_colorbar_obj); //| whitebal: bool -//| """Access the whitebal property of the camera sensor""" +//| """When `True`, the camera attempts to automatically control white balance. When `False`, the `wb_mode` setting is used instead.""" //| STATIC mp_obj_t esp32_camera_camera_get_whitebal(const mp_obj_t self_in) { @@ -502,7 +514,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_whitebal_obj, (mp_obj_t)&esp32_camera_camera_set_whitebal_obj); //| gain_ctrl: bool -//| """Access the gain_ctrl property of the camera sensor""" +//| """When `True`, the camera attempts to automatically control the sensor gain, up to the value in the `gain_ceiling` property. When `False`, the `agc_gain` setting is used instead.""" //| STATIC mp_obj_t esp32_camera_camera_get_gain_ctrl(const mp_obj_t self_in) { @@ -524,7 +536,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_gain_ctrl_obj, (mp_obj_t)&esp32_camera_camera_set_gain_ctrl_obj); //| exposure_ctrl: bool -//| """Access the exposure_ctrl property of the camera sensor""" +//| """When `True` the camera attempts to automatically control the exposure. When `False`, the `aec_value` setting is used instead.""" //| STATIC mp_obj_t esp32_camera_camera_get_exposure_ctrl(const mp_obj_t self_in) { @@ -546,7 +558,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_exposure_ctrl_obj, (mp_obj_t)&esp32_camera_camera_set_exposure_ctrl_obj); //| hmirror: bool -//| """Access the hmirror property of the camera sensor""" +//| """When `true` the camera image is mirrored left-to-right""" //| STATIC mp_obj_t esp32_camera_camera_get_hmirror(const mp_obj_t self_in) { @@ -568,7 +580,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_hmirror_obj, (mp_obj_t)&esp32_camera_camera_set_hmirror_obj); //| vflip: bool -//| """Access the vflip property of the camera sensor""" +//| """When `True` the camera image is flipped top-to-bottom""" //| STATIC mp_obj_t esp32_camera_camera_get_vflip(const mp_obj_t self_in) { @@ -590,7 +602,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_vflip_obj, (mp_obj_t)&esp32_camera_camera_set_vflip_obj); //| aec2: bool -//| """Access the aec2 property of the camera sensor""" +//| """When `True` the sensor's "night mode" is enabled, extending the range of automatic gain control.""" //| STATIC mp_obj_t esp32_camera_camera_get_aec2(const mp_obj_t self_in) { @@ -634,7 +646,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_awb_gain_obj, (mp_obj_t)&esp32_camera_camera_set_awb_gain_obj); //| agc_gain: int -//| """Access the agc_gain property of the camera sensor""" +//| """Access the gain level of the sensor. Higher values produce brighter images. Typical settings range from 0 to 30. """ //| STATIC mp_obj_t esp32_camera_camera_get_agc_gain(const mp_obj_t self_in) { @@ -656,7 +668,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_agc_gain_obj, (mp_obj_t)&esp32_camera_camera_set_agc_gain_obj); //| aec_value: int -//| """Access the aec_value property of the camera sensor""" +//| """Access the exposure value of the camera. Higher values produce brighter images. Typical settings range from 0 to 1200.""" //| STATIC mp_obj_t esp32_camera_camera_get_aec_value(const mp_obj_t self_in) { @@ -678,7 +690,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_aec_value_obj, (mp_obj_t)&esp32_camera_camera_set_aec_value_obj); //| special_effect: int -//| """Access the special_effect property of the camera sensor""" +//| """Enable a "special effect". Zero is no special effect. On OV5640, special effects range from 0 to 6 inclusive and select various color modes.""" //| STATIC mp_obj_t esp32_camera_camera_get_special_effect(const mp_obj_t self_in) { @@ -700,7 +712,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_special_effect_obj, (mp_obj_t)&esp32_camera_camera_set_special_effect_obj); //| wb_mode: int -//| """Access the wb_mode property of the camera sensor""" +//| """The white balance mode. 0 is automatic white balance. Typical values range from 0 to 4 inclusive.""" //| STATIC mp_obj_t esp32_camera_camera_get_wb_mode(const mp_obj_t self_in) { @@ -722,7 +734,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_wb_mode_obj, (mp_obj_t)&esp32_camera_camera_set_wb_mode_obj); //| ae_level: int -//| """Access the ae_level property of the camera sensor""" +//| """The exposure offset for automatic exposure. Typical values range from -2 to +2.""" //| STATIC mp_obj_t esp32_camera_camera_get_ae_level(const mp_obj_t self_in) { @@ -744,7 +756,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_ae_level_obj, (mp_obj_t)&esp32_camera_camera_set_ae_level_obj); //| dcw: bool -//| """Access the dcw property of the camera sensor""" +//| """When `True` an advanced white balance mode is selected.""" //| STATIC mp_obj_t esp32_camera_camera_get_dcw(const mp_obj_t self_in) { @@ -766,7 +778,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_dcw_obj, (mp_obj_t)&esp32_camera_camera_set_dcw_obj); //| bpc: bool -//| """Access the bpc property of the camera sensor""" +//| """When `True`, "black point compensation" is enabled. This can make black parts of the image darker.""" //| STATIC mp_obj_t esp32_camera_camera_get_bpc(const mp_obj_t self_in) { @@ -788,7 +800,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_bpc_obj, (mp_obj_t)&esp32_camera_camera_set_bpc_obj); //| wpc: bool -//| """Access the wpc property of the camera sensor""" +//| """When `True`, "white point compensation" is enabled. This can make white parts of the image whiter.""" //| STATIC mp_obj_t esp32_camera_camera_get_wpc(const mp_obj_t self_in) { @@ -810,7 +822,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_wpc_obj, (mp_obj_t)&esp32_camera_camera_set_wpc_obj); //| raw_gma: bool -//| """Access the raw_gma property of the camera sensor""" +//| """When `True`, raw gamma mode is enabled.""" //| STATIC mp_obj_t esp32_camera_camera_get_raw_gma(const mp_obj_t self_in) { @@ -832,7 +844,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_raw_gma_obj, (mp_obj_t)&esp32_camera_camera_set_raw_gma_obj); //| lenc: bool -//| """Access the lenc property of the camera sensor""" +//| """Enable "lens correction". This can help compensate for light fall-off at the edge of the sensor area.""" //| STATIC mp_obj_t esp32_camera_camera_get_lenc(const mp_obj_t self_in) { From c74746f05286bfbfb050adf51e0d7735d8250921 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 9 Aug 2022 11:47:58 -0500 Subject: [PATCH 30/30] Cross references in documentation always help --- ports/espressif/bindings/esp32_camera/Camera.c | 5 +++-- ports/espressif/bindings/esp32_camera/__init__.c | 5 +++++ shared-bindings/imagecapture/ParallelImageCapture.c | 2 ++ shared-bindings/imagecapture/__init__.c | 8 ++++++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ports/espressif/bindings/esp32_camera/Camera.c b/ports/espressif/bindings/esp32_camera/Camera.c index 9a7b79a3ed..3cd5d93682 100644 --- a/ports/espressif/bindings/esp32_camera/Camera.c +++ b/ports/espressif/bindings/esp32_camera/Camera.c @@ -66,7 +66,8 @@ //| This driver requires that the ``CIRCUITPY_RESERVED_PSRAM`` in ``/.env`` be large enough to hold the camera frambuffer(s). Generally, boards with built-in cameras will have a default setting that is large enough. If the constructor raises a MemoryError, this probably indicates the setting is too small and should be increased. //| //| -//| .. IMPORTANT: +//| .. important:: +//| //| Not all supported sensors have all //| of the properties listed below. For instance, the //| OV5640 supports `denoise`, but the @@ -558,7 +559,7 @@ MP_PROPERTY_GETSET(esp32_camera_camera_exposure_ctrl_obj, (mp_obj_t)&esp32_camera_camera_set_exposure_ctrl_obj); //| hmirror: bool -//| """When `true` the camera image is mirrored left-to-right""" +//| """When `True` the camera image is mirrored left-to-right""" //| STATIC mp_obj_t esp32_camera_camera_get_hmirror(const mp_obj_t self_in) { diff --git a/ports/espressif/bindings/esp32_camera/__init__.c b/ports/espressif/bindings/esp32_camera/__init__.c index 69d8071cb2..f1ee4b6891 100644 --- a/ports/espressif/bindings/esp32_camera/__init__.c +++ b/ports/espressif/bindings/esp32_camera/__init__.c @@ -39,6 +39,11 @@ //| //| This library enables access to any camera sensor supported by the library, //| including OV5640 and OV2640. +//| +//| .. seealso:: +//| +//| Non-Espressif microcontrollers use the `imagecapture` module together with wrapper libraries such as `adafruit_ov5640 `_. +//| //| """ //| class GrabMode: diff --git a/shared-bindings/imagecapture/ParallelImageCapture.c b/shared-bindings/imagecapture/ParallelImageCapture.c index 7f90f0923b..bbe96026bf 100644 --- a/shared-bindings/imagecapture/ParallelImageCapture.c +++ b/shared-bindings/imagecapture/ParallelImageCapture.c @@ -47,6 +47,8 @@ //| ) -> None: //| """Create a parallel image capture object //| +//| This object is usually used with a camera-specific wrapper library such as `adafruit_ov5640 `_. +//| //| :param List[microcontroller.Pin] data_pins: The data pins. //| :param microcontroller.Pin clock: The pixel clock input. //| :param microcontroller.Pin vsync: The vertical sync input, which has a negative-going pulse at the beginning of each frame. diff --git a/shared-bindings/imagecapture/__init__.c b/shared-bindings/imagecapture/__init__.c index 0e5092aee8..fdd4424114 100644 --- a/shared-bindings/imagecapture/__init__.c +++ b/shared-bindings/imagecapture/__init__.c @@ -31,9 +31,13 @@ #include "shared-bindings/imagecapture/ParallelImageCapture.h" -//| """Support for "Parallel capture" interfaces""" +//| """Support for "Parallel capture" interfaces //| - +//| .. seealso:: +//| +//| Espressif microcontrollers use the `esp32_camera` module together. +//| +//| """ STATIC const mp_rom_map_elem_t imagecapture_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_imagecapture) }, { MP_ROM_QSTR(MP_QSTR_ParallelImageCapture), MP_ROM_PTR(&imagecapture_parallelimagecapture_type) },