Merge remote-tracking branch 'origin/main' into main

This commit is contained in:
Hosted Weblate 2021-04-23 22:32:02 +02:00
commit 63fd57a5bc
37 changed files with 857 additions and 43 deletions

View File

@ -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 ""
@ -2114,6 +2120,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 ""
@ -2791,6 +2805,11 @@ msgstr ""
msgid "data must be of equal length"
msgstr ""
#: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c
#, c-format
msgid "data pin #%d in use"
msgstr ""
#: extmod/ulab/code/ndarray.c
msgid "data type not understood"
msgstr ""

View File

@ -45,7 +45,15 @@ static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT];
static bool audio_dma_allocated[AUDIO_DMA_CHANNEL_COUNT];
uint8_t audio_dma_allocate_channel(void) {
uint8_t find_sync_event_channel_raise() {
uint8_t event_channel = find_sync_event_channel();
if (event_channel >= EVSYS_SYNCH_NUM) {
mp_raise_RuntimeError(translate("All sync event channels in use"));
}
return event_channel;
}
uint8_t dma_allocate_channel(void) {
uint8_t channel;
for (channel = 0; channel < AUDIO_DMA_CHANNEL_COUNT; channel++) {
if (!audio_dma_allocated[channel]) {
@ -56,7 +64,7 @@ uint8_t audio_dma_allocate_channel(void) {
return channel; // i.e., return failure
}
void audio_dma_free_channel(uint8_t channel) {
void dma_free_channel(uint8_t channel) {
assert(channel < AUDIO_DMA_CHANNEL_COUNT);
assert(audio_dma_allocated[channel]);
audio_dma_disable_channel(channel);
@ -180,7 +188,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma,
bool output_signed,
uint32_t output_register_address,
uint8_t dma_trigger_source) {
uint8_t dma_channel = audio_dma_allocate_channel();
uint8_t dma_channel = dma_allocate_channel();
if (dma_channel >= AUDIO_DMA_CHANNEL_COUNT) {
return AUDIO_DMA_DMA_BUSY;
}
@ -230,11 +238,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma,
// We're likely double buffering so set up the block interrupts.
turn_on_event_system();
dma->event_channel = find_sync_event_channel();
if (dma->event_channel >= EVSYS_SYNCH_NUM) {
mp_raise_RuntimeError(translate("All sync event channels in use"));
}
dma->event_channel = find_sync_event_channel_raise();
init_event_channel_interrupt(dma->event_channel, CORE_GCLK, EVSYS_ID_GEN_DMAC_CH_0 + dma_channel);
// We keep the audio_dma_t for internal use and the sample as a root pointer because it
@ -302,7 +306,7 @@ void audio_dma_stop(audio_dma_t *dma) {
disable_event_channel(dma->event_channel);
MP_STATE_PORT(playing_audio)[channel] = NULL;
audio_dma_state[channel] = NULL;
audio_dma_free_channel(dma->dma_channel);
dma_free_channel(dma->dma_channel);
}
dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT;
}

View File

@ -66,8 +66,8 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj);
void audio_dma_init(audio_dma_t *dma);
void audio_dma_reset(void);
uint8_t audio_dma_allocate_channel(void);
void audio_dma_free_channel(uint8_t channel);
uint8_t dma_allocate_channel(void);
void dma_free_channel(uint8_t channel);
// This sets everything up but doesn't start the timer.
// Sample is the python object for the sample to play.
@ -97,4 +97,6 @@ bool audio_dma_get_paused(audio_dma_t *dma);
void audio_dma_background(void);
uint8_t find_sync_event_channel_raise(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_AUDIO_DMA_H

View File

@ -11,3 +11,4 @@ EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ, GD25Q64C"
LONGINT_IMPL = MPZ
CIRCUITPY_SDIOIO = 1
CIRCUITPY_IMAGECAPTURE = 1

View File

@ -367,11 +367,8 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) {
// output_buffer_length is the number of slots, not the number of bytes.
uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self,
uint16_t* output_buffer, uint32_t output_buffer_length) {
uint8_t dma_channel = audio_dma_allocate_channel();
uint8_t event_channel = find_sync_event_channel();
if (event_channel >= EVSYS_SYNCH_NUM) {
mp_raise_RuntimeError(translate("All sync event channels in use"));
}
uint8_t dma_channel = dma_allocate_channel();
uint8_t event_channel = find_sync_event_channel_raise();
// We allocate two buffers on the stack to use for double buffering.
const uint8_t samples_per_buffer = SAMPLES_PER_BUFFER;
@ -476,7 +473,7 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* se
}
disable_event_channel(event_channel);
audio_dma_free_channel(dma_channel);
dma_free_channel(dma_channel);
// Turn off serializer, but leave clock on, to avoid mic startup delay.
i2s_set_serializer_enable(self->serializer, false);

View File

@ -0,0 +1,198 @@
/*
* 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"
#include "audio_dma.h"
#include "samd/clocks.h"
#include "samd/events.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_reference,
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_reference && horizontal_reference->number != PIN_PCC_DEN2) {
mp_raise_ValueError_varg(translate("Invalid %q pin"), MP_QSTR_href);
}
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; i<data_count; i++) {
if (!pin_number_is_free(data0->number + i)) {
mp_raise_ValueError_varg(translate("data pin #%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_reference = horizontal_reference ? horizontal_reference->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_reference) {
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; i<data_count; i++) {
gpio_set_pin_direction(PIN_PCC_D0+i, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(PIN_PCC_D0+i, GPIO_PULL_OFF);
gpio_set_pin_function(PIN_PCC_D0+i, GPIO_PIN_FUNCTION_PCC);
//claim_pin_number(PIN_PCC_D0+i);
}
}
void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self)
{
if (common_hal_imagecapture_parallelimagecapture_deinited(self)) {
return;
}
reset_pin_number(self->vertical_sync);
reset_pin_number(self->horizontal_reference);
reset_pin_number(PIN_PCC_CLK);
for (int i=0; i<self->data_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;
}
static void setup_dma(DmacDescriptor* descriptor, size_t count, uint32_t *buffer) {
descriptor->BTCTRL.reg = DMAC_BTCTRL_VALID |
DMAC_BTCTRL_BLOCKACT_NOACT |
DMAC_BTCTRL_EVOSEL_BLOCK |
DMAC_BTCTRL_DSTINC |
DMAC_BTCTRL_BEATSIZE_WORD;
descriptor->BTCNT.reg = count;
descriptor->DSTADDR.reg = (uint32_t)buffer + 4*count;
descriptor->SRCADDR.reg = (uint32_t)&PCC->RHR.reg;
descriptor->DESCADDR.reg = 0;
}
#include <string.h>
void common_hal_imagecapture_parallelimagecapture_capture(imagecapture_parallelimagecapture_obj_t *self, void *buffer, size_t bufsize)
{
uint8_t dma_channel = dma_allocate_channel();
uint32_t *dest = buffer;
size_t count = bufsize / 4; // PCC receives 4 bytes (2 pixels) at a time
turn_on_event_system();
setup_dma(dma_descriptor(dma_channel), count, dest);
dma_configure(dma_channel, PCC_DMAC_ID_RX, true);
if (self->vertical_sync) {
const volatile uint32_t *vsync_reg = &PORT->Group[(self->vertical_sync / 32)].IN.reg;
uint32_t vsync_bit = 1 << (self->vertical_sync % 32);
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()) {
dma_free_channel(dma_channel);
return;
}
}
}
dma_enable_channel(dma_channel);
while (DMAC->Channel[dma_channel].CHCTRLA.bit.ENABLE) {
RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) {
break;
}
}
dma_disable_channel(dma_channel);
dma_free_channel(dma_channel);
}

View File

@ -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_reference, data_count;
};

View File

@ -156,7 +156,8 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
return PWMOUT_INVALID_PIN;
}
if (frequency == 0 || frequency > 6000000) {
uint32_t system_clock = common_hal_mcu_processor_get_frequency();
if (frequency == 0 || frequency > system_clock/2) {
return PWMOUT_INVALID_FREQUENCY;
}
@ -237,7 +238,6 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self,
resolution = tcc_sizes[timer->index];
}
// First determine the divisor that gets us the highest resolution.
uint32_t system_clock = common_hal_mcu_processor_get_frequency();
uint32_t top;
uint8_t divisor;
for (divisor = 0; divisor < 8; divisor++) {
@ -413,7 +413,8 @@ uint16_t common_hal_pwmio_pwmout_get_duty_cycle(pwmio_pwmout_obj_t* self) {
void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self,
uint32_t frequency) {
if (frequency == 0 || frequency > 6000000) {
uint32_t system_clock = common_hal_mcu_processor_get_frequency();
if (frequency == 0 || frequency > system_clock/2) {
mp_raise_ValueError(translate("Invalid PWM frequency"));
}
const pin_timer_t* t = self->timer;
@ -424,7 +425,6 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self,
// TCC resolution varies so look it up.
resolution = tcc_sizes[t->index];
}
uint32_t system_clock = common_hal_mcu_processor_get_frequency();
uint32_t new_top;
uint8_t new_divisor;
for (new_divisor = 0; new_divisor < 8; new_divisor++) {

View File

@ -241,6 +241,7 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
first_in_pin, args[ARG_in_pin_count].u_int, args[ARG_pull_in_pin_up].u_int, args[ARG_pull_in_pin_down].u_int,
first_set_pin, args[ARG_set_pin_count].u_int, args[ARG_initial_set_pin_state].u_int, args[ARG_initial_set_pin_direction].u_int,
first_sideset_pin, args[ARG_sideset_pin_count].u_int, args[ARG_initial_sideset_pin_state].u_int, args[ARG_initial_sideset_pin_direction].u_int,
0,
args[ARG_exclusive_pin_use].u_bool,
args[ARG_auto_pull].u_bool, pull_threshold, args[ARG_out_shift_right].u_bool,
args[ARG_wait_for_txstall].u_bool,

View File

@ -44,6 +44,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
const mcu_pin_obj_t *first_in_pin, uint8_t in_pin_count, uint32_t pull_pin_up, uint32_t pull_pin_down,
const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, uint32_t initial_set_pin_state, uint32_t initial_set_pin_direction,
const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, uint32_t initial_sideset_pin_state, uint32_t initial_sideset_pin_direction,
uint32_t wait_gpio_mask,
bool exclusive_pin_use,
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
bool wait_for_txstall,

View File

@ -126,6 +126,7 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
0, 0, // in pulls
NULL, 0, 0, 0x1f, // set pins
bit_clock, 2, 0, 0x1f, // sideset pins
0, // wait gpio pins
true, // exclusive pin use
false, 32, false, // shift out left to start with MSB
false, // Wait for txstall

View File

@ -71,6 +71,7 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self,
0, 0, // in pulls
NULL, 0, 0, 0x1f, // set pins
clock_pin, 1, 0, 0x1f, // sideset pins
0, // wait gpio pins
true, // exclusive pin use
false, 32, false, // out settings
false, // Wait for txstall

View File

@ -99,6 +99,7 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *sel
NULL, 0, 0, 0, // first in pin, # in pins
NULL, 0, 0, 0, // first set pin
write, 1, 0, 1, // first sideset pin
0, // wait gpio pins
true, // exclusive pin usage
true, 8, true, // TX, auto pull every 8 bits. shift left to output msb first
false, // wait for TX stall

View File

@ -0,0 +1,135 @@
/*
* 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 "bindings/rp2pio/StateMachine.h"
#include "bindings/rp2pio/__init__.h"
#include "common-hal/imagecapture/ParallelImageCapture.h"
#include "shared-bindings/imagecapture/ParallelImageCapture.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "src/rp2_common/hardware_pio/include/hardware/pio.h"
#include "src/rp2_common/hardware_pio/include/hardware/pio_instructions.h"
// Define this to (1), and you can scope the instruction-pointer of the state machine on D26..28 (note the weird encoding though!)
#define DEBUG_STATE_MACHINE (0)
#if DEBUG_STATE_MACHINE
#define SIDE(x) ((x)<<8)
#else
#define SIDE(x) (0)
#endif
#define _0 SIDE(0b11100)
#define _1 SIDE(0b00000)
#define _2 SIDE(0b10000)
#define _3 SIDE(0b10100)
#define _4 SIDE(0b11000)
#define _5 SIDE(0b10100)
#define IMAGECAPTURE_CODE(width, pclk, vsync, href) \
{ \
/* 0 */ pio_encode_wait_gpio(0, vsync) | _0, \
/* 1 */ pio_encode_wait_gpio(1, vsync) | _1, \
/* .wrap_target */ \
/* 2 */ pio_encode_wait_gpio(1, href) | _2, \
/* 3 */ pio_encode_wait_gpio(1, pclk) | _3, \
/* 4 */ pio_encode_in(pio_pins, width) | _4, \
/* 5 */ pio_encode_wait_gpio(0, pclk) | _5, \
/* .wrap */ \
}
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_reference,
int data_count)
{
uint16_t imagecapture_code[] = IMAGECAPTURE_CODE(data_count, data_clock->number, vertical_sync->number, horizontal_reference->number);
common_hal_rp2pio_statemachine_construct(&self->state_machine,
imagecapture_code, MP_ARRAY_SIZE(imagecapture_code),
common_hal_mcu_processor_get_frequency(), // full speed (4 instructions per loop -> max pclk 30MHz @ 120MHz)
0, 0, // init
NULL, 0, 0, 0, // out pins
data0, data_count, // in pins
0, 0, // in pulls
NULL, 0, 0, 0, // set pins
#if DEBUG_STATE_MACHINE
&pin_GPIO26, 3, 7, 7, // sideset pins
#else
NULL, 0, 0, 0, // sideset pins
#endif
(1<<vertical_sync->number) | (1<<horizontal_reference->number) | (1<<data_clock->number), // wait gpio pins
true, // exclusive pin use
false, 32, false, // out settings
false, // wait for txstall
true, 32, true); // in settings
PIO pio = self->state_machine.pio;
uint8_t pio_index = pio_get_index(pio);
uint sm = self->state_machine.state_machine;
rp2pio_statemachine_set_wrap(&self->state_machine, 2, 5);
}
void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self)
{
if (common_hal_imagecapture_parallelimagecapture_deinited(self)) {
return;
}
return common_hal_rp2pio_statemachine_deinit(&self->state_machine);
}
bool common_hal_imagecapture_parallelimagecapture_deinited(imagecapture_parallelimagecapture_obj_t *self)
{
return common_hal_rp2pio_statemachine_deinited(&self->state_machine);
}
void common_hal_imagecapture_parallelimagecapture_capture(imagecapture_parallelimagecapture_obj_t *self, void *buffer, size_t bufsize)
{
PIO pio = self->state_machine.pio;
uint sm = self->state_machine.state_machine;
uint8_t offset = rp2pio_statemachine_program_offset(&self->state_machine);
pio_sm_set_enabled(pio, sm, false);
pio_sm_clear_fifos(pio, sm);
pio_sm_restart(pio, sm);
pio_sm_exec(pio, sm, pio_encode_jmp(offset));
pio_sm_set_enabled(pio, sm, true);
common_hal_rp2pio_statemachine_readinto(&self->state_machine, buffer, bufsize, 4);
pio_sm_set_enabled(pio, sm, false);
}

View File

@ -0,0 +1,35 @@
/*
* 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/rp2pio/StateMachine.h"
#include "shared-bindings/imagecapture/ParallelImageCapture.h"
struct imagecapture_parallelimagecapture_obj {
mp_obj_base_t base;
rp2pio_statemachine_obj_t state_machine;
};

View File

@ -84,6 +84,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
3, 0, // in pulls
NULL, 0, 0, 0x1f, // set pins
NULL, 0, 0, 0x1f, // sideset pins
0, // wait gpio pins
true, // exclusive pin use
false, 32, false, // out settings
false, // Wait for txstall

View File

@ -329,13 +329,14 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
uint32_t pull_pin_up, uint32_t pull_pin_down,
const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, uint32_t initial_set_pin_state, uint32_t initial_set_pin_direction,
const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, uint32_t initial_sideset_pin_state, uint32_t initial_sideset_pin_direction,
uint32_t wait_gpio_mask,
bool exclusive_pin_use,
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
bool wait_for_txstall,
bool auto_push, uint8_t push_threshold, bool in_shift_right) {
// First, check that all pins are free OR already in use by any PIO if exclusive_pin_use is false.
uint32_t pins_we_use = 0;
uint32_t pins_we_use = wait_gpio_mask;
pins_we_use |= _check_pins_free(first_out_pin, out_pin_count, exclusive_pin_use);
pins_we_use |= _check_pins_free(first_in_pin, in_pin_count, exclusive_pin_use);
pins_we_use |= _check_pins_free(first_set_pin, set_pin_count, exclusive_pin_use);
@ -801,3 +802,16 @@ STATIC void rp2pio_statemachine_interrupt_handler(void) {
}
}
}
uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self) {
uint8_t pio_index = pio_get_index(self->pio);
uint8_t sm = self->state_machine;
return _current_program_offset[pio_index][sm];
}
void rp2pio_statemachine_set_wrap(rp2pio_statemachine_obj_t *self, uint wrap_target, uint wrap) {
uint8_t sm = self->state_machine;
uint8_t offset = rp2pio_statemachine_program_offset(self);
pio_sm_set_wrap(self->pio, sm, offset+wrap_target, offset+wrap);
}

View File

@ -74,6 +74,9 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
bool auto_push, uint8_t push_threshold, bool in_shift_right,
bool claim_pins);
uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self);
void rp2pio_statemachine_set_wrap(rp2pio_statemachine_obj_t *self, uint wrap_target, uint wrap);
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins);
extern const mp_obj_type_t rp2pio_statemachine_type;

View File

@ -23,6 +23,7 @@ CIRCUITPY_FRAMEBUFFERIO ?= 1
CIRCUITPY_FULL_BUILD ?= 1
CIRCUITPY_AUDIOMP3 ?= 1
CIRCUITPY_BITOPS ?= 1
CIRCUITPY_IMAGECAPTURE ?= 1
CIRCUITPY_PWMIO ?= 1
CIRCUITPY_RGBMATRIX ?= 1
CIRCUITPY_ROTARYIO ?= 1

View File

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

View File

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

View File

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

View File

@ -55,6 +55,13 @@ typedef unsigned int uint;
// Static assertion macro
#define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
// Explicit fallthrough delcarations for case statements
#ifdef __GNUC__
#define FALLTHROUGH __attribute__((fallthrough))
#else
#define FALLTHROUGH ((void)0) /* FALLTHROUGH */
#endif
/** memory allocation ******************************************/
// TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element)

View File

@ -30,6 +30,7 @@
#include "lib/utils/context_manager_helpers.h"
#include "py/binary.h"
#include "py/enum.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h"
@ -39,20 +40,20 @@
//| class ColorConverter:
//| """Converts one color format to another."""
//|
//| def __init__(self, *, dither: bool = False) -> None:
//| """Create a ColorConverter object to convert color formats. Only supports RGB888 to RGB565
//| currently.
//| def __init__(self, *, colorspace: Colorspace=Colorspace.RGB888, dither: bool = False) -> None:
//| """Create a ColorConverter object to convert color formats.
//|
//| :param Colorspace colorspace: The source colorspace, one of the Colorspace constants
//| :param bool dither: Adds random noise to dither the output image"""
//| ...
//|
// TODO(tannewt): Add support for other color formats.
//|
STATIC mp_obj_t displayio_colorconverter_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_dither};
enum { ARG_dither, ARG_input_colorspace };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_dither, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }
{ MP_QSTR_dither, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_input_colorspace, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = (void *)&displayio_colorspace_RGB888_obj} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@ -60,13 +61,13 @@ STATIC mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, siz
displayio_colorconverter_t *self = m_new_obj(displayio_colorconverter_t);
self->base.type = &displayio_colorconverter_type;
common_hal_displayio_colorconverter_construct(self, args[ARG_dither].u_bool);
common_hal_displayio_colorconverter_construct(self, args[ARG_dither].u_bool, (displayio_colorspace_t)cp_enum_value(&displayio_colorspace_type, args[ARG_input_colorspace].u_obj));
return MP_OBJ_FROM_PTR(self);
}
//| def convert(self, color: int) -> int:
//| """Converts the given RGB888 color to RGB565"""
//| """Converts the given color to RGB565 according to the Colorspace"""
//| ...
//|
STATIC mp_obj_t displayio_colorconverter_obj_convert(mp_obj_t self_in, mp_obj_t color_obj) {

View File

@ -27,13 +27,14 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_COLORCONVERTER_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_COLORCONVERTER_H
#include "shared-bindings/displayio/__init__.h"
#include "shared-module/displayio/ColorConverter.h"
#include "shared-module/displayio/Palette.h"
extern const mp_obj_type_t displayio_colorconverter_type;
void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither);
void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither, displayio_colorspace_t input_colorspace);
void common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *colorconverter, const _displayio_colorspace_t *colorspace, uint32_t input_color, uint32_t *output_color);
void common_hal_displayio_colorconverter_set_dither(displayio_colorconverter_t *self, bool dither);

View File

@ -26,6 +26,7 @@
#include <stdint.h>
#include "py/enum.h"
#include "py/obj.h"
#include "py/runtime.h"
@ -49,7 +50,6 @@
//| including synchronizing with refresh rates and partial updating."""
//|
//| def release_displays() -> None:
//| """Releases any actively used displays so their busses and pins can be used again. This will also
//| release the builtin display on boards that have one. You will need to reinitialize it yourself
@ -65,10 +65,48 @@ STATIC mp_obj_t displayio_release_displays(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(displayio_release_displays_obj, displayio_release_displays);
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB888, DISPLAYIO_COLORSPACE_RGB888);
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565, DISPLAYIO_COLORSPACE_RGB565);
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB565_SWAPPED, DISPLAYIO_COLORSPACE_RGB565_SWAPPED);
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555, DISPLAYIO_COLORSPACE_RGB555);
MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, RGB555_SWAPPED, DISPLAYIO_COLORSPACE_RGB555_SWAPPED);
//| class Colorspace:
//| """The colorspace for a `ColorConverter` to operate in"""
//|
//| RGB888: Colorspace
//| """The standard 24-bit colorspace. Bits 0-7 are blue, 8-15 are green, and 16-24 are red. (0xRRGGBB)"""
//|
//| RGB565: Colorspace
//| """The standard 16-bit colorspace. Bits 0-4 are blue, bits 5-10 are green, and 11-15 are red (0bRRRRRGGGGGGBBBBB)"""
//|
//| RGB565_SWAPPED: Colorspace
//| """The swapped 16-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB565"""
//|
//| RGB555: Colorspace
//| """The standard 15-bit colorspace. Bits 0-4 are blue, bits 5-9 are green, and 11-14 are red. The top bit is ignored. (0bxRRRRRGGGGGBBBBB)"""
//|
//| RGB555_SWAPPED: Colorspace
//| """The swapped 15-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB555"""
//|
MAKE_ENUM_MAP(displayio_colorspace) {
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB888),
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565),
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565_SWAPPED),
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555),
MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB555_SWAPPED),
};
STATIC MP_DEFINE_CONST_DICT(displayio_colorspace_locals_dict, displayio_colorspace_locals_table);
MAKE_PRINTER(displayio, displayio_colorspace);
MAKE_ENUM_TYPE(displayio, ColorSpace, displayio_colorspace);
STATIC const mp_rom_map_elem_t displayio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_displayio) },
{ MP_ROM_QSTR(MP_QSTR_Bitmap), MP_ROM_PTR(&displayio_bitmap_type) },
{ MP_ROM_QSTR(MP_QSTR_ColorConverter), MP_ROM_PTR(&displayio_colorconverter_type) },
{ MP_ROM_QSTR(MP_QSTR_Colorspace), MP_ROM_PTR(&displayio_colorspace_type) },
{ MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&displayio_display_type) },
{ MP_ROM_QSTR(MP_QSTR_EPaperDisplay), MP_ROM_PTR(&displayio_epaperdisplay_type) },
{ MP_ROM_QSTR(MP_QSTR_Group), MP_ROM_PTR(&displayio_group_type) },

View File

@ -27,6 +27,7 @@
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H
#include "py/enum.h"
#include "py/obj.h"
typedef enum {
@ -39,6 +40,14 @@ typedef enum {
CHIP_SELECT_TOGGLE_EVERY_BYTE
} display_chip_select_behavior_t;
typedef enum {
DISPLAYIO_COLORSPACE_RGB888,
DISPLAYIO_COLORSPACE_RGB565,
DISPLAYIO_COLORSPACE_RGB555,
DISPLAYIO_COLORSPACE_RGB565_SWAPPED,
DISPLAYIO_COLORSPACE_RGB555_SWAPPED,
} displayio_colorspace_t;
typedef bool (*display_bus_bus_reset)(mp_obj_t bus);
typedef bool (*display_bus_bus_free)(mp_obj_t bus);
typedef bool (*display_bus_begin_transaction)(mp_obj_t bus);
@ -48,4 +57,7 @@ typedef void (*display_bus_end_transaction)(mp_obj_t bus);
void common_hal_displayio_release_displays(void);
extern const mp_obj_type_t displayio_colorspace_type;
extern const cp_enum_obj_t displayio_colorspace_RGB888_obj;
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H

View File

@ -0,0 +1,145 @@
/*
* 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],
//| href: Optional[microcontroller.Pin],
//| ):
//| """Create a parallel image capture object
//| :param microcontroller.Pin data0: The first data pin. Additional data pins are assumed to follow this pin directly in the microcontroller's standard pin ordering.
//| :param int data_count: The number of data pins.
//| :param microcontroller.Pin clock: The pixel clock input.
//| :param microcontroller.Pin vsync: The vertical sync input, which has a negative-going pulse at the beginning of each frame.
//| :param microcontroller.Pin href: The horizontal reference input, which is high whenever the camera is transmitting valid pixel information.
//| """
//| ...
//|
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_href,
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_href, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY },
};
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 *href = validate_obj_is_free_pin_or_none(args[ARG_href].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, href, 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,
};

View File

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

View File

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

View File

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

View File

@ -41,9 +41,10 @@ uint32_t displayio_colorconverter_dither_noise_2(uint32_t x, uint32_t y) {
return displayio_colorconverter_dither_noise_1(x + y * 0xFFFF);
}
void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither) {
void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t *self, bool dither, displayio_colorspace_t input_colorspace) {
self->dither = dither;
self->transparent_color = NO_TRANSPARENT_COLOR;
self->input_colorspace = input_colorspace;
}
uint16_t displayio_colorconverter_compute_rgb565(uint32_t color_rgb888) {
@ -152,6 +153,33 @@ void displayio_colorconverter_convert(displayio_colorconverter_t *self, const _d
return;
}
switch (self->input_colorspace) {
case DISPLAYIO_COLORSPACE_RGB565_SWAPPED:
pixel = __builtin_bswap16(pixel);
FALLTHROUGH;
case DISPLAYIO_COLORSPACE_RGB565: {
uint32_t r8 = (pixel >> 11) << 3;
uint32_t g8 = ((pixel >> 5) << 2) & 0xff;
uint32_t b8 = (pixel << 3) & 0xff;
pixel = (r8 << 16) | (g8 << 8) | b8;
}
break;
case DISPLAYIO_COLORSPACE_RGB555_SWAPPED:
pixel = __builtin_bswap16(pixel);
FALLTHROUGH;
case DISPLAYIO_COLORSPACE_RGB555: {
uint32_t r8 = (pixel >> 10) << 3;
uint32_t g8 = ((pixel >> 5) << 3) & 0xff;
uint32_t b8 = (pixel << 3) & 0xff;
pixel = (r8 << 16) | (g8 << 8) | b8;
}
break;
case DISPLAYIO_COLORSPACE_RGB888:
break;
}
if (self->dither) {
uint8_t randr = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x,input_pixel->tile_y));
uint8_t randg = (displayio_colorconverter_dither_noise_2(input_pixel->tile_x + 33,input_pixel->tile_y));

View File

@ -36,6 +36,7 @@
typedef struct {
mp_obj_base_t base;
bool dither;
uint8_t input_colorspace;
uint32_t transparent_color;
} displayio_colorconverter_t;