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(<BIG PASTE FROM REPL>)
```
and open my.jpg in a viewer.
This commit is contained in:
Jeff Epler 2022-08-04 15:11:50 -05:00
parent 07afb3eab8
commit 5db6db0128
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
19 changed files with 1026 additions and 7 deletions

3
.gitmodules vendored
View File

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

View File

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

View File

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

View File

@ -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 <math.h>
#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,
};

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {
}

View File

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

View File

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

View File

@ -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);

View File

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

View File

@ -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);
}

View File

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

View File

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

@ -0,0 +1 @@
Subproject commit 28804391c002f6a3ea5ce6a55aee3b191be3ecde

View File

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

View File

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

View File

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