Skip to content

Commit 5db6db0

Browse files
committed
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.
1 parent 07afb3e commit 5db6db0

19 files changed

Lines changed: 1026 additions & 7 deletions

File tree

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,6 @@
307307
[submodule "frozen/circuitpython_picoed"]
308308
path = frozen/circuitpython_picoed
309309
url = https://github.com/elecfreaks/circuitpython_picoed.git
310+
[submodule "ports/espressif/esp32-camera"]
311+
path = ports/espressif/esp32-camera
312+
url = https://github.com/adafruit/esp32-camera/

ports/espressif/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf)
88
# can build.
99
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)
1010

11+
if("${CIRCUITPY_ESP32_CAMERA}")
12+
message("Including esp32-camera")
13+
set(EXTRA_COMPONENT_DIRS "esp32-camera")
14+
list(APPEND COMPONENTS "esp32-camera")
15+
message("COMPONENTS = ${COMPONENTS}")
16+
endif()
17+
1118
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
1219
project(circuitpython)
1320

ports/espressif/Makefile

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ SRC_C += \
261261
peripherals/touch.c
262262
ifeq ($(IDF_TARGET),esp32s2)
263263
SRC_C += \
264-
cam.c \
265264
i2s_lcd_esp32s2_driver.c
266265
endif
267266
endif
@@ -283,6 +282,22 @@ endif
283282

284283
SRC_C += $(wildcard common-hal/espidf/*.c)
285284

285+
ifneq ($(CIRCUITPY_ESP32_CAMERA),0)
286+
SRC_CAMERA := \
287+
$(wildcard common-hal/esp32_camera/*.c) \
288+
$(wildcard bindings/esp32_camera/*.c)
289+
SRC_C += $(SRC_CAMERA)
290+
$(info SRC_CAMERA = $(SRC_CAMERA))
291+
CFLAGS += -isystem esp32-camera/driver/include
292+
CFLAGS += -isystem esp32-camera/conversions/include
293+
endif
294+
295+
ifneq ($(CIRCUITPY_IMAGECAPTURE),0)
296+
$(error IMAGECAPTURE)
297+
SRC_C += cam.c
298+
endif
299+
300+
286301
SRC_COMMON_HAL_EXPANDED = \
287302
$(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
288303
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
@@ -341,8 +356,10 @@ ifneq ($(CIRCUITPY_BLEIO),0)
341356
SDKCONFIGS := esp-idf-config/sdkconfig-ble.defaults;$(SDKCONFIGS)
342357
endif
343358
# create the config headers
344-
$(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig | $(BUILD)/esp-idf
345-
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
359+
.PHONY: do-sdkconfig
360+
do-sdkconfig: $(BUILD)/esp-idf/config/sdkconfig.h
361+
$(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig CMakeLists.txt | $(BUILD)/esp-idf
362+
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)
346363

347364
# build a lib
348365
# 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
391408
ESP_IDF_COMPONENTS_EXPANDED += esp-idf/components/xtensa/$(IDF_TARGET)/libxt_hal.a
392409
endif
393410

411+
ifneq ($(CIRCUITPY_ESP32_CAMERA),0)
412+
ESP_IDF_COMPONENTS_EXPANDED += $(BUILD)/esp-idf/esp-idf/esp32-camera/libesp32-camera.a
413+
#$(error $(ESP_IDF_COMPONENTS_EXPANDED))
414+
endif
415+
394416
# BOOTLOADER_OFFSET is determined by chip type, based on the ROM bootloader, and is not changeable.
395417
ifeq ($(IDF_TARGET),esp32)
396418
BOOTLOADER_OFFSET = 0x1000
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <math.h>
28+
29+
#include "py/mphal.h"
30+
#include "py/obj.h"
31+
#include "py/objproperty.h"
32+
#include "py/runtime.h"
33+
34+
#include "bindings/esp32_camera/__init__.h"
35+
#include "bindings/esp32_camera/Camera.h"
36+
#include "common-hal/esp32_camera/Camera.h"
37+
38+
#include "shared-bindings/microcontroller/Pin.h"
39+
#include "shared-bindings/util.h"
40+
#include "esp_camera.h"
41+
#include "sensor.h"
42+
43+
//| class Camera:
44+
//| def __init__(
45+
//| self,
46+
//| *,
47+
//| data_pins: List[microcontroller.Pin],
48+
//| pixel_clock: microcontroller.Pin,
49+
//| vsync: microcontroller.Pin,
50+
//| href: microcontroller.Pin,
51+
//| i2c: busio.I2C,
52+
//| external_clock_pin: microcontroller.Pin,
53+
//| external_clock_frequency: int,
54+
//| powerdown_pin: Optional[microcontroller.Pin] = None,
55+
//| reset_pin: Optional[microcontroller.Pin] = None,
56+
//| pixel_format: PixelFormat=PixelFormat.RGB565,
57+
//| frame_size: FrameSize=FrameSize.QQVGA,
58+
//| jpeg_quality: int=15,
59+
//| double_buffered: bool = True,
60+
//| grab_mode: GrabMode = GrabMode.WhenEmpty,
61+
//| ):
62+
//| """
63+
//| Configure and initialize a camera with the given properties
64+
//|
65+
//| 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.
66+
//|
67+
//| :param data_pins: The 8 data data_pins used for image data transfer from the camera module, least significant bit first
68+
//| :param pixel_clock: The pixel clock output from the camera module
69+
//| :param vsync: The vertical sync pulse output from the camera module
70+
//| :param href: The horizontal reference output from the camera module
71+
//| :param i2c: The I2C bus connected to the camera module
72+
//| :param external_clock_frequency: The frequency generated on the external clock pin
73+
//| :param external_clock_pin: The pin on which to generate the external clock
74+
//| :param powerdown_pin: The powerdown input to the camera module
75+
//| :param reset_pin: The reset input to the camera module
76+
//| :param pixel_format: The pixel format of the captured image
77+
//| :param frame_size: The size of captured image
78+
//| :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.
79+
//| :param framebuffer_count: The number of framebuffers
80+
//| :param grab_mode: When to grab a new frame
81+
//| """
82+
//|
83+
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) {
84+
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 };
85+
static const mp_arg_t allowed_args[] = {
86+
{ MP_QSTR_data_pins, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
87+
{ MP_QSTR_pixel_clock_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
88+
{ MP_QSTR_vsync_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
89+
{ MP_QSTR_href_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
90+
{ MP_QSTR_i2c, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
91+
{ MP_QSTR_external_clock_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY },
92+
{ MP_QSTR_external_clock_frequency, MP_ARG_INT | MP_ARG_REQUIRED },
93+
{ MP_QSTR_powerdown_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_NONE } },
94+
{ MP_QSTR_reset_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_NONE } },
95+
{ MP_QSTR_pixel_format, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_PTR((void *)&pixel_format_RGB565_obj) } },
96+
{ MP_QSTR_frame_size, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_PTR((void *)&frame_size_QQVGA_obj) } },
97+
{ MP_QSTR_jpeg_quality, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 15 } },
98+
{ MP_QSTR_framebuffer_count, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 1 } },
99+
{ MP_QSTR_grab_mode, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = MP_ROM_PTR((void *)&grab_mode_WHEN_EMPTY_obj) } },
100+
};
101+
102+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
103+
MP_STATIC_ASSERT(MP_ARRAY_SIZE(allowed_args) == NUM_ARGS);
104+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
105+
106+
uint8_t data_pins[8];
107+
uint8_t data_pin_count;
108+
validate_pins(MP_QSTR_data_pins, data_pins, MP_ARRAY_SIZE(data_pins), args[ARG_data_pins].u_obj, &data_pin_count);
109+
mp_arg_validate_length(data_pin_count, 8, MP_QSTR_data_pins);
110+
111+
const mcu_pin_obj_t *pixel_clock_pin = validate_obj_is_free_pin(args[ARG_pixel_clock_pin].u_obj);
112+
const mcu_pin_obj_t *vsync_pin = validate_obj_is_free_pin(args[ARG_vsync_pin].u_obj);
113+
const mcu_pin_obj_t *href_pin = validate_obj_is_free_pin(args[ARG_href_pin].u_obj);
114+
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));
115+
const mcu_pin_obj_t *external_clock_pin = validate_obj_is_free_pin(args[ARG_external_clock_pin].u_obj);
116+
const mcu_pin_obj_t *powerdown_pin = validate_obj_is_free_pin_or_none(args[ARG_powerdown_pin].u_obj);
117+
const mcu_pin_obj_t *reset_pin = validate_obj_is_free_pin_or_none(args[ARG_reset_pin].u_obj);
118+
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);
119+
120+
camera_grab_mode_t grab_mode = validate_grab_mode(args[ARG_grab_mode].u_obj, MP_QSTR_grab_mode);
121+
framesize_t frame_size = validate_frame_size(args[ARG_frame_size].u_obj, MP_QSTR_frame_size);
122+
pixformat_t pixel_format = validate_pixel_format(args[ARG_pixel_format].u_obj, MP_QSTR_pixel_format);
123+
mp_int_t jpeg_quality = mp_arg_validate_int_range(args[ARG_jpeg_quality].u_int, 2, 55, MP_QSTR_jpeg_quality);
124+
mp_int_t framebuffer_count = mp_arg_validate_int_range(args[ARG_framebuffer_count].u_int, 1, 2, MP_QSTR_framebuffer_count);
125+
126+
esp32_camera_camera_obj_t *self = m_new_obj(esp32_camera_camera_obj_t);
127+
self->base.type = &esp32_camera_camera_type;
128+
common_hal_esp32_camera_camera_construct(
129+
self,
130+
data_pins,
131+
external_clock_pin,
132+
pixel_clock_pin,
133+
vsync_pin,
134+
href_pin,
135+
powerdown_pin,
136+
reset_pin,
137+
i2c,
138+
external_clock_frequency,
139+
pixel_format,
140+
frame_size,
141+
jpeg_quality,
142+
framebuffer_count,
143+
grab_mode);
144+
return MP_OBJ_FROM_PTR(self);
145+
}
146+
147+
//| def deinit(self) -> None:
148+
//| """Deinitialises the camera and releases all memory resources for reuse."""
149+
//| ...
150+
//|
151+
STATIC mp_obj_t esp32_camera_camera_deinit(mp_obj_t self_in) {
152+
esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in);
153+
common_hal_esp32_camera_camera_deinit(self);
154+
return mp_const_none;
155+
}
156+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_deinit_obj, esp32_camera_camera_deinit);
157+
158+
STATIC void check_for_deinit(esp32_camera_camera_obj_t *self) {
159+
if (common_hal_esp32_camera_camera_deinited(self)) {
160+
raise_deinited_error();
161+
}
162+
}
163+
164+
//| def __enter__(self) -> Camera:
165+
//| """No-op used by Context Managers."""
166+
//| ...
167+
//|
168+
// Provided by context manager helper.
169+
170+
//| def __exit__(self) -> None:
171+
//| """Automatically deinitializes the hardware when exiting a context. See
172+
//| :ref:`lifetime-and-contextmanagers` for more info."""
173+
//| ...
174+
//|
175+
STATIC mp_obj_t esp32_camera_camera_obj___exit__(size_t n_args, const mp_obj_t *args) {
176+
(void)n_args;
177+
common_hal_esp32_camera_camera_deinit(args[0]);
178+
return mp_const_none;
179+
}
180+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera___exit___obj, 4, 4, esp32_camera_camera_obj___exit__);
181+
182+
//| frame_available: bool
183+
//| """True if a frame is available, False otherwise"""
184+
185+
STATIC mp_obj_t esp32_camera_camera_frame_available_get(const mp_obj_t self_in) {
186+
return mp_obj_new_bool(false);
187+
}
188+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_camera_camera_frame_available_get_obj, esp32_camera_camera_frame_available_get);
189+
190+
MP_PROPERTY_GETTER(esp32_camera_camera_frame_available_obj,
191+
(mp_obj_t)&esp32_camera_camera_frame_available_get_obj);
192+
193+
//| def take(timeout: Optional[float]=0.25) -> Optional[ReadableBuffer]:
194+
//| """Record a frame. Wait up to 'timeout' seconds for a frame to be captured."""
195+
//|
196+
STATIC mp_obj_t esp32_camera_camera_take(size_t n_args, const mp_obj_t *args) {
197+
esp32_camera_camera_obj_t *self = MP_OBJ_TO_PTR(args[0]);
198+
mp_float_t timeout = n_args < 2 ? MICROPY_FLOAT_CONST(0.25) : mp_obj_get_float(args[1]);
199+
check_for_deinit(self);
200+
camera_fb_t *result = common_hal_esp32_camera_camera_take(self, (int)MICROPY_FLOAT_C_FUN(round)(timeout * 1000));
201+
if (!result) {
202+
return mp_const_none;
203+
}
204+
return mp_obj_new_memoryview('b', result->len, result->buf);
205+
}
206+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_camera_camera_take_obj, 1, 2, esp32_camera_camera_take);
207+
208+
//| pixel_format: PixelFormat
209+
//| """The pixel format of the camera"""
210+
//|
211+
//| frame_size: FrameSize
212+
//| """The size of the captured image"""
213+
//|
214+
//| contrast: int
215+
//| """The contrast of the sensor"""
216+
217+
STATIC const mp_rom_map_elem_t esp32_camera_camera_locals_table[] = {
218+
{ MP_ROM_QSTR(MP_QSTR_take), MP_ROM_PTR(&esp32_camera_camera_take_obj) },
219+
{ MP_ROM_QSTR(MP_QSTR_frame_available), MP_ROM_PTR(&esp32_camera_camera_frame_available_obj) },
220+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_camera_camera_deinit_obj) },
221+
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
222+
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&esp32_camera_camera___exit___obj) },
223+
};
224+
225+
STATIC MP_DEFINE_CONST_DICT(esp32_camera_camera_locals_dict, esp32_camera_camera_locals_table);
226+
227+
const mp_obj_type_t esp32_camera_camera_type = {
228+
.base = { &mp_type_type },
229+
.name = MP_QSTR_Camera,
230+
.make_new = esp32_camera_camera_make_new,
231+
.locals_dict = (mp_obj_t)&esp32_camera_camera_locals_dict,
232+
};
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#pragma once
28+
29+
#include "py/enum.h"
30+
#include "py/obj.h"
31+
32+
#include "esp_camera.h"
33+
34+
#include "shared-bindings/busio/I2C.h"
35+
36+
extern const mp_obj_type_t esp32_camera_camera_type;
37+
typedef struct esp32_camera_camera_obj esp32_camera_camera_obj_t;
38+
39+
extern void common_hal_esp32_camera_camera_construct(
40+
esp32_camera_camera_obj_t *self,
41+
uint8_t data_pins[8],
42+
const mcu_pin_obj_t *external_clock_pin,
43+
const mcu_pin_obj_t *pixel_clock_pin,
44+
const mcu_pin_obj_t *vsync_pin,
45+
const mcu_pin_obj_t *href_pin,
46+
const mcu_pin_obj_t *powerdown_pin,
47+
const mcu_pin_obj_t *reset_pin,
48+
const busio_i2c_obj_t *i2c,
49+
mp_int_t external_clock_frequency,
50+
pixformat_t pixel_format,
51+
framesize_t frame_size,
52+
mp_int_t jpeg_quality,
53+
mp_int_t framebuffer_count,
54+
camera_grab_mode_t grab_mode);
55+
56+
extern void common_hal_esp32_camera_camera_deinit(esp32_camera_camera_obj_t *self);
57+
extern bool common_hal_esp32_camera_camera_deinited(esp32_camera_camera_obj_t *self);
58+
extern bool common_hal_esp32_camera_camera_available(esp32_camera_camera_obj_t *self);
59+
extern camera_fb_t *common_hal_esp32_camera_camera_take(esp32_camera_camera_obj_t *self, int timeout_ms);

0 commit comments

Comments
 (0)