From fc4538f8453e92eaacab7aface8e0f49f5ca4877 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 16 Apr 2021 17:18:59 -0500 Subject: [PATCH] WIP: Implement 'ParallelImageCapture' for samd51 --- locale/circuitpython.pot | 19 ++ .../grandcentral_m4_express/mpconfigboard.mk | 1 + .../imagecapture/ParallelImageCapture.c | 187 ++++++++++++++++++ .../imagecapture/ParallelImageCapture.h | 34 ++++ .../common-hal/imagecapture/__init__.c | 0 .../common-hal/imagecapture/__init__.h | 0 py/circuitpy_defns.mk | 7 +- py/circuitpy_mpconfig.h | 24 ++- py/circuitpy_mpconfig.mk | 3 + .../imagecapture/ParallelImageCapture.c | 146 ++++++++++++++ .../imagecapture/ParallelImageCapture.h | 42 ++++ shared-bindings/imagecapture/__init__.c | 47 +++++ shared-bindings/imagecapture/__init__.h | 27 +++ 13 files changed, 528 insertions(+), 9 deletions(-) create mode 100644 ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c create mode 100644 ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.h create mode 100644 ports/atmel-samd/common-hal/imagecapture/__init__.c create mode 100644 ports/atmel-samd/common-hal/imagecapture/__init__.h create mode 100644 shared-bindings/imagecapture/ParallelImageCapture.c create mode 100644 shared-bindings/imagecapture/ParallelImageCapture.h create mode 100644 shared-bindings/imagecapture/__init__.c create mode 100644 shared-bindings/imagecapture/__init__.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 5ddce15209..73a0357dd9 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1185,6 +1185,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c +#: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Invalid %q pin" msgstr "" @@ -1255,6 +1256,11 @@ msgstr "" msgid "Invalid channel count" msgstr "" +#: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c +#, c-format +msgid "Invalid data_count %d" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Invalid direction." msgstr "" @@ -1705,6 +1711,11 @@ msgstr "" msgid "Oversample must be multiple of 8." msgstr "" +#: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c +#, c-format +msgid "PCC_D%d in use" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "PDMIn not available" msgstr "" @@ -2114,6 +2125,14 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c +msgid "Timeout waiting for DRDY" +msgstr "" + +#: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c +msgid "Timeout waiting for VSYNC" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "To exit, please reset the board without " msgstr "" diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk index 88c6e9bf16..6d9ecff636 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk @@ -11,3 +11,4 @@ EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ, GD25Q64C" LONGINT_IMPL = MPZ CIRCUITPY_SDIOIO = 1 +CIRCUITPY_IMAGECAPTURE = 1 diff --git a/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c new file mode 100644 index 0000000000..3445c179ed --- /dev/null +++ b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c @@ -0,0 +1,187 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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 "lib/utils/context_manager_helpers.h" +#include "lib/utils/interrupt_char.h" + +#include "shared-bindings/imagecapture/ParallelImageCapture.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "common-hal/imagecapture/ParallelImageCapture.h" + +#include "hal/include/hal_gpio.h" +#include "atmel_start_pins.h" + +#define GPIO_PIN_FUNCTION_PCC (GPIO_PIN_FUNCTION_K) + +#define PIN_PCC_D0 (PIN_PA16) +#define PIN_PCC_DEN1 (PIN_PA12) +#define PIN_PCC_DEN2 (PIN_PA13) +#define PIN_PCC_CLK (PIN_PA14) + +void common_hal_imagecapture_parallelimagecapture_construct(imagecapture_parallelimagecapture_obj_t *self, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data_clock, + const mcu_pin_obj_t *vertical_sync, + const mcu_pin_obj_t *horizontal_sync, + int data_count) +{ + if (data0->number != PIN_PCC_D0) { + mp_raise_ValueError_varg(translate("Invalid %q pin"), MP_QSTR_data0); + } + // The peripheral supports 8, 10, 12, or 14 data bits, but the code only supports 8 at present + if (data_count != 8) + { + mp_raise_ValueError_varg(translate("Invalid data_count %d"), data_count); + } + if (vertical_sync && vertical_sync->number != PIN_PCC_DEN1) { + mp_raise_ValueError_varg(translate("Invalid %q pin"), MP_QSTR_vsync); + } + if (horizontal_sync && horizontal_sync->number != PIN_PCC_DEN2) { + mp_raise_ValueError_varg(translate("Invalid %q pin"), MP_QSTR_hsync); + } + if (data_clock->number != PIN_PCC_CLK) { + mp_raise_ValueError_varg(translate("Invalid %q pin"), MP_QSTR_data_clock); + } + // technically, 0 was validated as free already but check again + for (int i=0; inumber + i)) { + mp_raise_ValueError_varg(translate("PCC_D%d in use"), i); + } + } + + PCC->MR.bit.PCEN = 0; // Make sure PCC is disabled before setting MR reg + + PCC->IDR.reg = 0b1111; // Disable all PCC interrupts + MCLK->APBDMASK.bit.PCC_ = 1; // Enable PCC clock + + // Accumulate 4 bytes into RHR register (two 16-bit pixels) + PCC->MR.reg = PCC_MR_CID(0x1) | // Clear on falling DEN1 (VSYNC) + PCC_MR_ISIZE(0x0) | // Input data bus is 8 bits + PCC_MR_DSIZE(0x2); // "4 data" at a time (accumulate in RHR) + + PCC->MR.bit.PCEN = 1; // Enable PCC + + + // Now we know we can allocate all pins + self->data_count = data_count; + self->vertical_sync = vertical_sync ? vertical_sync->number : NO_PIN; + self->horizontal_sync = horizontal_sync ? vertical_sync->number : NO_PIN; + gpio_set_pin_direction(PIN_PCC_CLK, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(PIN_PCC_CLK, GPIO_PULL_OFF); + gpio_set_pin_function(PIN_PCC_CLK, GPIO_PIN_FUNCTION_PCC); + //claim_pin_number(PIN_PCC_CLK); + if (vertical_sync) { + gpio_set_pin_direction(PIN_PCC_DEN1, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(PIN_PCC_DEN1, GPIO_PULL_OFF); + gpio_set_pin_function(PIN_PCC_DEN1, GPIO_PIN_FUNCTION_PCC); // VSYNC + //claim_pin_number(PIN_PCC_DEN1); + } + if (horizontal_sync) { + gpio_set_pin_direction(PIN_PCC_DEN2, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(PIN_PCC_DEN2, GPIO_PULL_OFF); + gpio_set_pin_function(PIN_PCC_DEN2, GPIO_PIN_FUNCTION_PCC); // HSYNC + //claim_pin_number(PIN_PCC_DEN2); + } + for (int i=0; ivertical_sync); + reset_pin_number(self->horizontal_sync); + reset_pin_number(PIN_PCC_CLK); + for (int i=0; idata_count; i++) { + reset_pin_number(PIN_PCC_D0 + i); + } + self->data_count = 0; +} + +bool common_hal_imagecapture_parallelimagecapture_deinited(imagecapture_parallelimagecapture_obj_t *self) +{ + return self->data_count == 0; +} + +void common_hal_imagecapture_parallelimagecapture_capture(imagecapture_parallelimagecapture_obj_t *self, void *buffer, size_t bufsize) +{ + uint32_t *dest = buffer; + size_t count = bufsize / 4; // PCC receives 4 bytes (2 pixels) at a time + + const volatile uint32_t *vsync_reg = self->vertical_sync == NO_PIN ? NULL : &PORT->Group[(self->vertical_sync / 32)].IN.reg; + uint32_t vsync_bit = 1 << (self->vertical_sync % 32); + + if (vsync_reg) { + while (*vsync_reg & vsync_bit) + { + // Wait for VSYNC low (frame end) + + RUN_BACKGROUND_TASKS; + // Allow user to break out of a timeout with a KeyboardInterrupt. + if (mp_hal_is_interrupted()) { + return; + } + } + } + + common_hal_mcu_disable_interrupts(); + + if (vsync_reg) { + size_t j = 1000000; // Don't freeze forever (this is ballpark 100ms timeout) + while (!(*vsync_reg & vsync_bit)) { + // Wait for VSYNC high (frame start) + if (!--j) { + common_hal_mcu_enable_interrupts(); + mp_raise_RuntimeError(translate("Timeout waiting for VSYNC")); + } + } + } + + // TODO: use DMA + for (size_t i = 0; iISR.bit.DRDY) { + if (!--j) { + common_hal_mcu_enable_interrupts(); + mp_raise_RuntimeError(translate("Timeout waiting for DRDY")); + } + // Wait for PCC data ready + } + *dest++ = PCC->RHR.reg; // Store 2 pixels + } + + common_hal_mcu_enable_interrupts(); +} diff --git a/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.h b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.h new file mode 100644 index 0000000000..37df982dea --- /dev/null +++ b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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 "shared-bindings/imagecapture/ParallelImageCapture.h" + +struct imagecapture_parallelimagecapture_obj { + mp_obj_base_t base; + uint8_t data_pin, data_clock, vertical_sync, horizontal_sync, data_count; +}; diff --git a/ports/atmel-samd/common-hal/imagecapture/__init__.c b/ports/atmel-samd/common-hal/imagecapture/__init__.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ports/atmel-samd/common-hal/imagecapture/__init__.h b/ports/atmel-samd/common-hal/imagecapture/__init__.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 5745c4f1d2..93488d3d90 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -319,6 +319,9 @@ endif ifeq ($(CIRCUITPY_PEW),1) SRC_PATTERNS += _pew/% endif +ifeq ($(CIRCUITPY_IMAGECAPTURE),1) +SRC_PATTERNS += imagecapture/% +endif ifeq ($(CIRCUITPY_MSGPACK),1) SRC_PATTERNS += msgpack/% endif @@ -367,8 +370,11 @@ SRC_COMMON_HAL_ALL = \ digitalio/DigitalInOut.c \ digitalio/__init__.c \ displayio/ParallelBus.c \ + dualbank/__init__.c \ frequencyio/FrequencyIn.c \ frequencyio/__init__.c \ + imagecapture/ParallelImageCapture.c \ + imagecapture/__init__.c \ gnss/__init__.c \ gnss/GNSS.c \ gnss/PositionFix.c \ @@ -382,7 +388,6 @@ SRC_COMMON_HAL_ALL = \ nvm/ByteArray.c \ nvm/__init__.c \ os/__init__.c \ - dualbank/__init__.c \ ps2io/Ps2.c \ ps2io/__init__.c \ pulseio/PulseIn.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 801e1867e7..15881f41bd 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -412,6 +412,13 @@ extern const struct _mp_obj_module_t terminalio_module; #define TERMINALIO_MODULE #endif +#if CIRCUITPY_DUALBANK +extern const struct _mp_obj_module_t dualbank_module; +#define DUALBANK_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_dualbank), (mp_obj_t)&dualbank_module }, +#else +#define DUALBANK_MODULE +#endif + #if CIRCUITPY_ERRNO #define MICROPY_PY_UERRNO (1) // Uses about 80 bytes. @@ -486,6 +493,13 @@ extern const struct _mp_obj_module_t i2cperipheral_module; #define I2CPERIPHERAL_MODULE #endif +#if CIRCUITPY_IMAGECAPTURE +extern const struct _mp_obj_module_t imagecapture_module; +#define IMAGECAPTURE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_imagecapture), (mp_obj_t)&imagecapture_module }, +#else +#define IMAGECAPTURE_MODULE +#endif + #if CIRCUITPY_IPADDRESS extern const struct _mp_obj_module_t ipaddress_module; #define IPADDRESS_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_ipaddress), (mp_obj_t)&ipaddress_module }, @@ -574,13 +588,6 @@ extern const struct _mp_obj_module_t os_module; #define OS_MODULE_ALT_NAME #endif -#if CIRCUITPY_DUALBANK -extern const struct _mp_obj_module_t dualbank_module; -#define DUALBANK_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_dualbank), (mp_obj_t)&dualbank_module }, -#else -#define DUALBANK_MODULE -#endif - #if CIRCUITPY_PEW extern const struct _mp_obj_module_t pew_module; #define PEW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pew),(mp_obj_t)&pew_module }, @@ -860,6 +867,7 @@ extern const struct _mp_obj_module_t msgpack_module; COUNTIO_MODULE \ DIGITALIO_MODULE \ DISPLAYIO_MODULE \ + DUALBANK_MODULE \ FONTIO_MODULE \ TERMINALIO_MODULE \ VECTORIO_MODULE \ @@ -872,6 +880,7 @@ extern const struct _mp_obj_module_t msgpack_module; GNSS_MODULE \ I2CPERIPHERAL_MODULE \ IPADDRESS_MODULE \ + IMAGECAPTURE_MODULE \ JSON_MODULE \ MATH_MODULE \ _EVE_MODULE \ @@ -882,7 +891,6 @@ extern const struct _mp_obj_module_t msgpack_module; NETWORK_MODULE \ SOCKET_MODULE \ WIZNET_MODULE \ - DUALBANK_MODULE \ PEW_MODULE \ PIXELBUF_MODULE \ PS2IO_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 600e56ee23..965b5dde42 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -218,6 +218,9 @@ CFLAGS += -DCIRCUITPY_NVM=$(CIRCUITPY_NVM) CIRCUITPY_OS ?= 1 CFLAGS += -DCIRCUITPY_OS=$(CIRCUITPY_OS) +CIRCUITPY_IMAGECAPTURE ?= 0 +CFLAGS += -DCIRCUITPY_IMAGECAPTURE=$(CIRCUITPY_IMAGECAPTURE) + CIRCUITPY_PEW ?= 0 CFLAGS += -DCIRCUITPY_PEW=$(CIRCUITPY_PEW) diff --git a/shared-bindings/imagecapture/ParallelImageCapture.c b/shared-bindings/imagecapture/ParallelImageCapture.c new file mode 100644 index 0000000000..b9940a5bf3 --- /dev/null +++ b/shared-bindings/imagecapture/ParallelImageCapture.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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 "lib/utils/context_manager_helpers.h" + +#include "shared-bindings/imagecapture/ParallelImageCapture.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "common-hal/imagecapture/ParallelImageCapture.h" + +//| class ParallelImageCapture: +//| """Capture image frames from a camera with parallel data interface""" +//| +//| def __init__( +//| self, +//| *, +//| data0: microcontroller.Pin, +//| data_count: int=8, +//| clock: microcontroller.Pin, +//| vsync: Optional[microcontroller.Pin], +//| hsync: Optional[microcontroller.Pin], +//|# clock_invert: bool=False, +//|# vsync_invert: bool=False, +//|# hsync_invert: bool=False, +//| ): +//| """Create a parallel image capture object""" +//| ... +//| +STATIC mp_obj_t imagecapture_parallelimagecapture_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data0, ARG_data_count, ARG_clock, ARG_vsync, ARG_hsync, + // ARG_clock_invert, ARG_vsync_invert, ARG_hsync_invert, + NUM_ARGS }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_data0, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_data_count, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = 8 } }, + { MP_QSTR_clock, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_vsync, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + { MP_QSTR_hsync, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY }, + // { MP_QSTR_clock_invert, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = False} }, + // { MP_QSTR_vsync_invert, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = False} }, + // { MP_QSTR_hsync_invert, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = False} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + MP_STATIC_ASSERT(MP_ARRAY_SIZE(allowed_args) == NUM_ARGS); + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mcu_pin_obj_t *data0 = validate_obj_is_free_pin(args[ARG_data0].u_obj); + mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj); + mcu_pin_obj_t *vsync = validate_obj_is_free_pin_or_none(args[ARG_vsync].u_obj); + mcu_pin_obj_t *hsync = validate_obj_is_free_pin_or_none(args[ARG_hsync].u_obj); + + imagecapture_parallelimagecapture_obj_t *self = m_new_obj(imagecapture_parallelimagecapture_obj_t); + self->base.type = &imagecapture_parallelimagecapture_type; + + common_hal_imagecapture_parallelimagecapture_construct(self, data0, clock, vsync, hsync, args[ARG_data_count].u_int); + + return self; +} + +//| def capture(self, buffer: WriteableBuffer, width: int, height: int, bpp: int=16) -> None: +//| """Capture a single frame into the given buffer""" +//| ... +//| +STATIC mp_obj_t imagecapture_parallelimagecapture_capture(mp_obj_t self_in, mp_obj_t buffer) { + imagecapture_parallelimagecapture_obj_t *self = (imagecapture_parallelimagecapture_obj_t *)self_in; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_RW); + common_hal_imagecapture_parallelimagecapture_capture(self, bufinfo.buf, bufinfo.len); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(imagecapture_parallelimagecapture_capture_obj, imagecapture_parallelimagecapture_capture); + +//| def deinit(self) -> None: +//| """Deinitialize this instance""" +//| ... +//| +STATIC mp_obj_t imagecapture_parallelimagecapture_deinit(mp_obj_t self_in) { + imagecapture_parallelimagecapture_obj_t *self = (imagecapture_parallelimagecapture_obj_t *)self_in; + common_hal_imagecapture_parallelimagecapture_deinit(self); + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(imagecapture_parallelimagecapture_deinit_obj, imagecapture_parallelimagecapture_deinit); + +//| def __enter__(self) -> ParallelImagecapture: +//| """No-op used in Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware on context exit. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +STATIC mp_obj_t imagecapture_parallelimagecapture___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_imagecapture_parallelimagecapture_deinit(args[0]); + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(imagecapture_parallelimagecapture___exit___obj, 4, 4, imagecapture_parallelimagecapture___exit__); + + +STATIC const mp_rom_map_elem_t imagecapture_parallelimagecapture_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&imagecapture_parallelimagecapture_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&imagecapture_parallelimagecapture___exit___obj) }, + + { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&imagecapture_parallelimagecapture_capture_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(imagecapture_parallelimagecapture_locals_dict, imagecapture_parallelimagecapture_locals_dict_table); + +const mp_obj_type_t imagecapture_parallelimagecapture_type = { + { &mp_type_type }, + .name = MP_QSTR_ParallelImagecapture, + .make_new = imagecapture_parallelimagecapture_make_new, + .locals_dict = (mp_obj_dict_t *)&imagecapture_parallelimagecapture_locals_dict, +}; diff --git a/shared-bindings/imagecapture/ParallelImageCapture.h b/shared-bindings/imagecapture/ParallelImageCapture.h new file mode 100644 index 0000000000..67e05f2bf2 --- /dev/null +++ b/shared-bindings/imagecapture/ParallelImageCapture.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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 "common-hal/microcontroller/Pin.h" + +typedef struct imagecapture_parallelimagecapture_obj imagecapture_parallelimagecapture_obj_t; +extern const mp_obj_type_t imagecapture_parallelimagecapture_type; + +void common_hal_imagecapture_parallelimagecapture_construct(imagecapture_parallelimagecapture_obj_t *self, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data_clock, + const mcu_pin_obj_t *vertical_sync, + const mcu_pin_obj_t *horizontal_sync, + int data_count); +void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self); +bool common_hal_imagecapture_parallelimagecapture_deinited(imagecapture_parallelimagecapture_obj_t *self); +void common_hal_imagecapture_parallelimagecapture_capture(imagecapture_parallelimagecapture_obj_t *self, void *buffer, size_t bufsize); diff --git a/shared-bindings/imagecapture/__init__.c b/shared-bindings/imagecapture/__init__.c new file mode 100644 index 0000000000..8f7ce231a6 --- /dev/null +++ b/shared-bindings/imagecapture/__init__.c @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/imagecapture/ParallelImageCapture.h" + +//| """Support for "Parallel capture" interfaces""" +//| + +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) }, +}; + +STATIC MP_DEFINE_CONST_DICT(imagecapture_module_globals, imagecapture_module_globals_table); + +const mp_obj_module_t imagecapture_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&imagecapture_module_globals, +}; diff --git a/shared-bindings/imagecapture/__init__.h b/shared-bindings/imagecapture/__init__.h new file mode 100644 index 0000000000..1e170aa941 --- /dev/null +++ b/shared-bindings/imagecapture/__init__.h @@ -0,0 +1,27 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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