Merge branch 'master' of https://github.com/adafruit/circuitpython into en_ARR

This commit is contained in:
sommersoft 2019-03-07 18:51:14 -06:00
commit 3a738af510
109 changed files with 19405 additions and 23943 deletions

3
.gitmodules vendored
View File

@ -92,3 +92,6 @@
[submodule "tools/Tecate-bitmap-fonts"]
path = tools/Tecate-bitmap-fonts
url = https://github.com/Tecate/bitmap-fonts.git
[submodule "frozen/pew-pewpew-standalone-10.x"]
path = frozen/pew-pewpew-standalone-10.x
url = https://github.com/pewpew-game/pew-pewpew-standalone-10.x.git

View File

@ -194,10 +194,10 @@ pseudoxml:
all-source:
locale/circuitpython.pot: all-source
find . -iname "*.c" | xargs xgettext -L C --keyword=translate -F -o circuitpython.pot -p locale
find . -iname "*.c" | xargs xgettext -L C -s --no-location --keyword=translate -o circuitpython.pot -p locale
translate: locale/circuitpython.pot
for po in $(shell ls locale/*.po); do msgmerge -U -F $$po locale/circuitpython.pot; done
for po in $(shell ls locale/*.po); do msgmerge -U $$po -s --no-fuzzy-matching --no-location locale/circuitpython.pot; done
check-translate: locale/circuitpython.pot $(wildcard locale/*.po)
$(PYTHON) tools/check_translations.py $^

View File

@ -292,7 +292,11 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = {
#if CIRCUITPY
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_json) },
#else
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) },
#endif
{ MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_ujson_dump_obj) },
{ MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) },
{ MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) },

View File

@ -405,7 +405,11 @@ STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
STATIC const mp_obj_type_t re_type = {
{ &mp_type_type },
#if CIRCUITPY
.name = MP_QSTR_re,
#else
.name = MP_QSTR_ure,
#endif
.print = re_print,
.locals_dict = (void*)&re_locals_dict,
};
@ -462,7 +466,11 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_sub_obj, 3, 5, mod_re_sub);
#endif
STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = {
#if CIRCUITPY
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_re) },
#else
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ure) },
#endif
{ MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) },
{ MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&mod_re_match_obj) },
{ MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&mod_re_search_obj) },

View File

@ -38,6 +38,8 @@
#define FSUSER_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it
// Device is writable over USB and read-only to MicroPython.
#define FSUSER_USB_WRITABLE (0x0010)
// Bit set when the above flag is checked before opening a file for write.
#define FSUSER_CONCURRENT_WRITE_PROTECTED (0x0020)
typedef struct _fs_user_mount_t {
mp_obj_base_t base;

View File

@ -34,6 +34,7 @@
#include "py/mperrno.h"
#include "lib/oofatfs/ff.h"
#include "extmod/vfs_fat.h"
#include "supervisor/filesystem.h"
// this table converts from FRESULT to POSIX errno
const byte fresult_to_errno_table[20] = {
@ -187,7 +188,7 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
}
}
assert(vfs != NULL);
if ((vfs->flags & FSUSER_USB_WRITABLE) != 0 && (mode & FA_WRITE) != 0) {
if ((mode & FA_WRITE) != 0 && !filesystem_is_writable_by_python(vfs)) {
mp_raise_OSError(MP_EROFS);
}

@ -0,0 +1 @@
Subproject commit 87755e088150cc9bce42f4104cbd74d91b923c6f

@ -1 +1 @@
Subproject commit 29b49199beb8e9b5fead83e5cd36105f8746f1d7
Subproject commit 55874813f82157b7509729b1a0c66e68f86e2d07

View File

@ -89,6 +89,9 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
}
// source is a lexer, parse and compile the script
qstr source_name = lex->source_name;
if (input_kind == MP_PARSE_FILE_INPUT) {
mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
}
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL);
// Clear the parse tree because it has a heap pointer we don't need anymore.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

7
main.c
View File

@ -323,12 +323,12 @@ void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
mp_hal_delay_ms(1500);
// USB isn't up, so we can write the file.
filesystem_writable_by_python(true);
filesystem_set_internal_writable_by_usb(false);
f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS);
// Switch the filesystem back to non-writable by Python now instead of later,
// since boot.py might change it back to writable.
filesystem_writable_by_python(false);
filesystem_set_internal_writable_by_usb(true);
// Write version info to boot_out.txt.
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
@ -416,7 +416,8 @@ int __attribute__((used)) main(void) {
// By default our internal flash is readonly to local python code and
// writable over USB. Set it here so that boot.py can change it.
filesystem_writable_by_python(false);
filesystem_set_internal_concurrent_write_protection(true);
filesystem_set_internal_writable_by_usb(true);
run_boot_py(safe_mode);

View File

@ -245,6 +245,7 @@ SRC_C = \
reset.c \
supervisor/shared/memory.c \
tick.c \
timer_handler.c \
ifeq ($(CIRCUITPY_NETWORK),1)

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -11,6 +11,7 @@ LONGINT_IMPL = MPZ
# Make room for frozen libs.
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21

View File

@ -12,6 +12,7 @@ LONGINT_IMPL = NONE
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_PIXELBUF = 0
CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -14,3 +14,5 @@ CHIP_FAMILY = samd21
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_FREQUENCYIO = 0

View File

@ -11,6 +11,7 @@ LONGINT_IMPL = MPZ
# Make space for frozen libs
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -16,3 +16,7 @@ CHIP_FAMILY = samd21
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
# To keep the build small
CIRCUITPY_I2CSLAVE = 0
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -13,5 +13,9 @@ LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CFLAGS_INLINE_LIMIT = 70
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_FREQUENCYIO = 0

View File

@ -0,0 +1,37 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "boards/board.h"
void board_init(void) {
}
bool board_requests_safe_mode(void) {
return false;
}
void reset_board(void) {
}

View File

@ -0,0 +1,34 @@
#define MICROPY_HW_BOARD_NAME "PewPew 10.2"
#define MICROPY_HW_MCU_NAME "samd21e18"
#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25)
#define MICROPY_PORT_B (0)
#define MICROPY_PORT_C (0)
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
#define IGNORE_PIN_PB00 1
#define IGNORE_PIN_PB01 1
#define IGNORE_PIN_PB02 1
#define IGNORE_PIN_PB03 1
#define IGNORE_PIN_PB04 1
#define IGNORE_PIN_PB05 1
#define IGNORE_PIN_PB06 1
#define IGNORE_PIN_PB07 1
#define IGNORE_PIN_PB08 1
#define IGNORE_PIN_PB09 1
#define IGNORE_PIN_PB10 1
#define IGNORE_PIN_PB11 1
#define IGNORE_PIN_PB12 1
#define IGNORE_PIN_PB13 1
#define IGNORE_PIN_PB14 1
#define IGNORE_PIN_PB15 1
#define IGNORE_PIN_PB16 1
#define IGNORE_PIN_PB17 1
#define IGNORE_PIN_PB22 1
#define IGNORE_PIN_PB23 1
#define IGNORE_PIN_PB30 1
#define IGNORE_PIN_PB31 1

View File

@ -0,0 +1,23 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x801D
USB_PRODUCT = "PewPew 10.2"
USB_MANUFACTURER = "Radomir Dopieralski"
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
FROZEN_MPY_DIRS += $(TOP)/frozen/pew-pewpew-standalone-10.x
CIRCUITPY_PEW = 1
CIRCUITPY_ANALOGIO = 1
CIRCUITPY_MATH = 1
CIRCUITPY_NEOPIXEL_WRITE = 1
CIRCUITPY_RTC = 0
CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_SMALL_BUILD = 1
CIRCUITPY_FREQUENCYIO = 0

View File

@ -0,0 +1,35 @@
#include "shared-bindings/board/__init__.h"
#include "supervisor/shared/board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR__R1), MP_ROM_PTR(&pin_PA05) },
{ MP_ROM_QSTR(MP_QSTR__R2), MP_ROM_PTR(&pin_PA11) },
{ MP_ROM_QSTR(MP_QSTR__R3), MP_ROM_PTR(&pin_PA28) },
{ MP_ROM_QSTR(MP_QSTR__R4), MP_ROM_PTR(&pin_PA09) },
{ MP_ROM_QSTR(MP_QSTR__R5), MP_ROM_PTR(&pin_PA16) },
{ MP_ROM_QSTR(MP_QSTR__R6), MP_ROM_PTR(&pin_PA27) },
{ MP_ROM_QSTR(MP_QSTR__R7), MP_ROM_PTR(&pin_PA17) },
{ MP_ROM_QSTR(MP_QSTR__R8), MP_ROM_PTR(&pin_PA22) },
{ MP_ROM_QSTR(MP_QSTR__C8), MP_ROM_PTR(&pin_PA10) },
{ MP_ROM_QSTR(MP_QSTR__C7), MP_ROM_PTR(&pin_PA18) },
{ MP_ROM_QSTR(MP_QSTR__C6), MP_ROM_PTR(&pin_PA19) },
{ MP_ROM_QSTR(MP_QSTR__C5), MP_ROM_PTR(&pin_PA06) },
{ MP_ROM_QSTR(MP_QSTR__C4), MP_ROM_PTR(&pin_PA23) },
{ MP_ROM_QSTR(MP_QSTR__C3), MP_ROM_PTR(&pin_PA07) },
{ MP_ROM_QSTR(MP_QSTR__C2), MP_ROM_PTR(&pin_PA14) },
{ MP_ROM_QSTR(MP_QSTR__C1), MP_ROM_PTR(&pin_PA15) },
{ MP_ROM_QSTR(MP_QSTR_P1), MP_ROM_PTR(&pin_PA30) },
{ MP_ROM_QSTR(MP_QSTR_P2), MP_ROM_PTR(&pin_PA31) },
{ MP_ROM_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_PA00) },
{ MP_ROM_QSTR(MP_QSTR_P4), MP_ROM_PTR(&pin_PA01) },
{ MP_ROM_QSTR(MP_QSTR_P5), MP_ROM_PTR(&pin_PA02) },
{ MP_ROM_QSTR(MP_QSTR_P6), MP_ROM_PTR(&pin_PA03) },
{ MP_ROM_QSTR(MP_QSTR_P7), MP_ROM_PTR(&pin_PA04) },
{ MP_ROM_QSTR(MP_QSTR__BUTTONS), MP_ROM_PTR(&pin_PA08) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);

View File

@ -17,6 +17,7 @@ CIRCUITPY_RTC = 0
CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_SMALL_BUILD = 1
CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21

View File

@ -10,18 +10,22 @@
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUDIO_OUT), MP_ROM_PTR(&pin_PA02) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, // analog out/in
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PA27) },
// Light sensor
{ MP_OBJ_NEW_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA07) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA07) },
// STEMMA connectors
{ MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB02) }, // SDA
{ MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB03) }, // SCL
{ MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, // D3
{ MP_OBJ_NEW_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA04) }, // D3
{ MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, // D4
{ MP_OBJ_NEW_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA05) }, // D4
{ MP_OBJ_NEW_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA04) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA04) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA05) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) },
// Indicator LED
{ MP_OBJ_NEW_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA27) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PA27) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB23) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PB23) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL),MP_ROM_PTR(&pin_PB22) },
// LCD pins
@ -49,10 +53,11 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_TOUCH_XR), MP_ROM_PTR(&pin_PB08) },
// ESP control
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_PA15) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_BUSY), MP_ROM_PTR(&pin_PB14) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_PB14) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_GPIO0), MP_ROM_PTR(&pin_PB15) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_PB16) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_BUSY), MP_ROM_PTR(&pin_PB16) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_PB17) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ESP_RTS), MP_ROM_PTR(&pin_PA15) },
// UART
{ MP_OBJ_NEW_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB12) },

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -11,3 +11,5 @@ LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -47,6 +47,7 @@
#endif
#include "audio_dma.h"
#include "timer_handler.h"
#include "samd/dma.h"
#include "samd/events.h"
@ -251,6 +252,7 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self,
tc_gclk = 1;
#endif
set_timer_handler(true, tc_index, TC_HANDLER_NO_INTERRUPT);
turn_on_clocks(true, tc_index, tc_gclk);
// Don't bother setting the period. We set it before you playback anything.

View File

@ -0,0 +1,547 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Michael Schroeder
*
* 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 "hal/include/hal_gpio.h"
#include "atmel_start_pins.h"
#include "supervisor/shared/translate.h"
#include "mpconfigport.h"
#include "py/runtime.h"
#include "timer_handler.h"
#include "background.h"
#include "samd/clocks.h"
#include "samd/timers.h"
#include "samd/events.h"
#include "samd/pins.h"
#include "samd/external_interrupts.h"
#include "shared-bindings/frequencyio/FrequencyIn.h"
#include "peripheral_clk_config.h"
#include "hpl_gclk_config.h"
#include "tick.h"
#ifdef SAMD21
#include "hpl/gclk/hpl_gclk_base.h"
#endif
static frequencyio_frequencyin_obj_t *active_frequencyins[TC_INST_NUM];
volatile uint8_t reference_tc = 0xff;
#ifdef SAMD51
static uint8_t dpll_gclk;
#endif
void frequencyin_emergency_cancel_capture(uint8_t index) {
frequencyio_frequencyin_obj_t* self = active_frequencyins[index];
NVIC_DisableIRQ(self->TC_IRQ);
NVIC_ClearPendingIRQ(self->TC_IRQ);
#ifdef SAMD21
NVIC_DisableIRQ(EIC_IRQn);
NVIC_ClearPendingIRQ(EIC_IRQn);
#endif
#ifdef SAMD51
NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
#endif
common_hal_frequencyio_frequencyin_pause(self); // pause any further captures
NVIC_EnableIRQ(self->TC_IRQ);
#ifdef SAMD21
NVIC_EnableIRQ(EIC_IRQn);
#endif
#ifdef SAMD51
NVIC_EnableIRQ(EIC_0_IRQn + self->channel);
#endif
mp_raise_RuntimeError(translate("Frequency captured is above capability. Capture Paused."));
}
void frequencyin_interrupt_handler(uint8_t index) {
Tc* ref_tc = tc_insts[reference_tc];
if (!ref_tc->COUNT16.INTFLAG.bit.OVF) return; // false trigger
uint32_t current_us;
uint64_t current_ms;
current_tick(&current_ms, &current_us);
for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
if (active_frequencyins[i] != NULL) {
frequencyio_frequencyin_obj_t* self = active_frequencyins[i];
Tc* tc = tc_insts[self->tc_index];
uint32_t mask = 1 << self->channel;
if ((EIC->INTFLAG.reg & mask) == mask) {
// Make sure capture_period has elapsed before we
// record a new event count.
if (current_ms - self->last_ms >= self->capture_period) {
float new_factor = self->last_us + (1000 - current_us);
self->factor = (current_ms - self->last_ms) + (new_factor / 1000);
self->last_ms = current_ms;
self->last_us = current_us;
#ifdef SAMD51
tc->COUNT16.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val;
while ((tc->COUNT16.SYNCBUSY.bit.COUNT == 1) ||
(tc->COUNT16.CTRLBSET.bit.CMD == TC_CTRLBSET_CMD_READSYNC_Val)) {
}
#endif
uint16_t new_freq = tc->COUNT16.COUNT.reg;
if ((tc->COUNT16.INTFLAG.reg & TC_INTFLAG_OVF) == 1) {
new_freq += 65535;
tc->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;
}
self->frequency = new_freq;
#ifdef SAMD51
tc->COUNT16.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_RETRIGGER_Val;
while ((tc->COUNT16.SYNCBUSY.bit.COUNT == 1) ||
(tc->COUNT16.CTRLBSET.bit.CMD == TC_CTRLBSET_CMD_RETRIGGER_Val)) {
}
#endif
}
EIC->INTFLAG.reg |= mask;
}
// Check if we've reached the upper limit of detection
if (!background_tasks_ok() || self->errored_too_fast) {
self->errored_too_fast = true;
frequencyin_emergency_cancel_capture(i);
}
}
}
ref_tc->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;
}
void frequencyin_reference_tc_init() {
if (reference_tc == 0xff) {
return;
}
#ifdef SAMD21
set_timer_handler(true, reference_tc, TC_HANDLER_FREQUENCYIN);
turn_on_clocks(true, reference_tc, 0);
#endif
// use the DPLL we setup so that the reference_tc and freqin_tc(s)
// are using the same clock frequency.
#ifdef SAMD51
if (dpll_gclk == 0xff) {
frequencyin_samd51_start_dpll();
}
set_timer_handler(true, reference_tc, TC_HANDLER_FREQUENCYIN);
turn_on_clocks(true, reference_tc, dpll_gclk);
#endif
Tc *tc = tc_insts[reference_tc];
tc_set_enable(tc, false);
tc_reset(tc);
#ifdef SAMD21
tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_PRESCALER_DIV1;
tc->COUNT16.INTENSET.bit.OVF = 1;
NVIC_EnableIRQ(TC3_IRQn + reference_tc);
#endif
#ifdef SAMD51
tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
TC_CTRLA_PRESCALER_DIV1;
tc->COUNT16.INTENSET.bit.OVF = 1;
NVIC_EnableIRQ(TC0_IRQn + reference_tc);
#endif
}
bool frequencyin_reference_tc_enabled() {
if (reference_tc == 0xff) {
return false;
}
Tc *tc = tc_insts[reference_tc];
return tc->COUNT16.CTRLA.bit.ENABLE;
}
void frequencyin_reference_tc_enable(bool enable) {
if (reference_tc == 0xff) {
return;
}
Tc *tc = tc_insts[reference_tc];
tc_set_enable(tc, enable);
}
#ifdef SAMD51
void frequencyin_samd51_start_dpll() {
if (clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
return;
}
uint8_t free_gclk = find_free_gclk(1);
if (free_gclk == 0xff) {
dpll_gclk = 0xff;
return;
}
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(free_gclk);
// TC4-7 can only have a max of 100MHz source
// DPLL1 frequency equation with [X]OSC32K as source: 98.304MHz = 32768(2999 + 1 + 0/32)
// Will also enable the Lock Bypass due to low-frequency sources causing DPLL unlocks
// as outlined in the Errata (1.12.1)
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(2999);
if (board_has_crystal()) { // we can use XOSC32K directly as the source
OSC32KCTRL->XOSC32K.bit.EN32K = 1;
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(1) |
OSCCTRL_DPLLCTRLB_LBYPASS;
} else {
// can't use OSCULP32K directly; need to setup a GCLK as a reference,
// which must be done in samd/clocks.c to avoid waiting for sync
return;
//OSC32KCTRL->OSCULP32K.bit.EN32K = 1;
//OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0);
}
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
while (!(OSCCTRL->Dpll[1].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY)) {}
enable_clock_generator(free_gclk, GCLK_GENCTRL_SRC_DPLL1_Val, 1);
dpll_gclk = free_gclk;
}
void frequencyin_samd51_stop_dpll() {
if (!clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
return;
}
disable_clock_generator(dpll_gclk);
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = 0;
OSCCTRL->Dpll[1].DPLLCTRLA.reg = 0;
OSCCTRL->Dpll[1].DPLLRATIO.reg = 0;
OSCCTRL->Dpll[1].DPLLCTRLB.reg = 0;
while (OSCCTRL->Dpll[1].DPLLSYNCBUSY.bit.ENABLE) {
}
dpll_gclk = 0xff;
}
#endif
void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t* self, const mcu_pin_obj_t* pin, const uint16_t capture_period) {
if (!pin->has_extint) {
mp_raise_RuntimeError(translate("No hardware support on pin"));
}
if ((capture_period == 0) || (capture_period > 500)) {
mp_raise_ValueError(translate("Invalid capture period. Valid range: 1 - 500"));
}
uint32_t mask = 1 << pin->extint_channel;
if (eic_get_enable() == 1 &&
#ifdef SAMD21
((EIC->INTENSET.vec.EXTINT & mask) != 0 || (EIC->EVCTRL.vec.EXTINTEO & mask) != 0)) {
#endif
#ifdef SAMD51
((EIC->INTENSET.bit.EXTINT & mask) != 0 || (EIC->EVCTRL.bit.EXTINTEO & mask) != 0)) {
#endif
mp_raise_RuntimeError(translate("EXTINT channel already in use"));
}
uint8_t timer_index = find_free_timer();
if (timer_index == 0xff) {
mp_raise_RuntimeError(translate("All timers in use"));
}
Tc *tc = tc_insts[timer_index];
self->tc_index = timer_index;
self->pin = pin->number;
self->channel = pin->extint_channel;
self->errored_too_fast = false;
self->last_ms = 0;
self->last_us = 1000;
self->capture_period = capture_period;
#ifdef SAMD21
self->TC_IRQ = TC3_IRQn + timer_index;
#endif
#ifdef SAMD51
self->TC_IRQ = TC0_IRQn + timer_index;
#endif
active_frequencyins[timer_index] = self;
// SAMD21: We use GCLK0 generated from DFLL running at 48mhz
// SAMD51: We use a GCLK generated from DPLL1 running at <100mhz
#ifdef SAMD21
set_timer_handler(timer_index, 0, TC_HANDLER_NO_INTERRUPT);
turn_on_clocks(true, timer_index, 0);
#endif
#ifdef SAMD51
frequencyin_samd51_start_dpll();
if (dpll_gclk == 0xff && !clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
common_hal_frequencyio_frequencyin_deinit(self);
mp_raise_RuntimeError(translate("No available clocks"));
}
set_timer_handler(timer_index, dpll_gclk, TC_HANDLER_NO_INTERRUPT);
turn_on_clocks(true, timer_index, dpll_gclk);
#endif
// Ensure EIC is on
if (eic_get_enable() == 0) {
turn_on_external_interrupt_controller(); // enables EIC, so disable it after
}
eic_set_enable(false);
uint8_t sense_setting = EIC_CONFIG_SENSE0_HIGH_Val;
uint8_t config_index = self->channel / 8;
uint8_t position = (self->channel % 8) * 4;
uint32_t masked_value = EIC->CONFIG[config_index].reg & ~(0xf << position);
EIC->CONFIG[config_index].reg = masked_value | (sense_setting << position);
#ifdef SAMD21
masked_value = EIC->EVCTRL.vec.EXTINTEO;
EIC->EVCTRL.vec.EXTINTEO = masked_value | (1 << self->channel);
#endif
#ifdef SAMD51
masked_value = EIC->EVCTRL.bit.EXTINTEO;
EIC->EVCTRL.bit.EXTINTEO = masked_value | (1 << self->channel);
EIC->ASYNCH.bit.ASYNCH = 1;
#endif
turn_on_cpu_interrupt(self->channel);
eic_set_enable(true);
// Turn on EVSYS
turn_on_event_system();
uint8_t evsys_channel = find_async_event_channel();
#ifdef SAMD21
connect_event_user_to_channel((EVSYS_ID_USER_TC3_EVU + timer_index), evsys_channel);
#endif
#ifdef SAMD51
connect_event_user_to_channel((EVSYS_ID_USER_TC0_EVU + timer_index), evsys_channel);
#endif
init_async_event_channel(evsys_channel, (EVSYS_ID_GEN_EIC_EXTINT_0 + self->channel));
self->event_channel = evsys_channel;
tc_set_enable(tc, false);
tc_reset(tc);
#ifdef SAMD21
tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
TC_CTRLA_PRESCALER_DIV1;
tc->COUNT16.EVCTRL.bit.TCEI = 1;
tc->COUNT16.EVCTRL.bit.EVACT = TC_EVCTRL_EVACT_COUNT_Val;
#endif
#ifdef SAMD51
tc->COUNT16.EVCTRL.reg = TC_EVCTRL_EVACT(TC_EVCTRL_EVACT_COUNT_Val) | TC_EVCTRL_TCEI;
tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
TC_CTRLA_PRESCALER_DIV1;
#endif
NVIC_EnableIRQ(self->TC_IRQ);
gpio_set_pin_function(pin->number, GPIO_PIN_FUNCTION_A);
tc_set_enable(tc, true);
// setup reference TC if not already
if (reference_tc == 0xff) {
reference_tc = find_free_timer();
if (reference_tc == 0xff) {
common_hal_frequencyio_frequencyin_deinit(self);
mp_raise_RuntimeError(translate("All timers in use"));
}
frequencyin_reference_tc_init();
}
if (!frequencyin_reference_tc_enabled()) {
frequencyin_reference_tc_enable(true);
}
}
bool common_hal_frequencyio_frequencyin_deinited(frequencyio_frequencyin_obj_t* self) {
return self->pin == NO_PIN;
}
void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t* self) {
if (common_hal_frequencyio_frequencyin_deinited(self)) {
return;
}
reset_pin_number(self->pin);
// turn off EIC & EVSYS utilized by this TC
disable_event_channel(self->event_channel);
eic_set_enable(false);
#ifdef SAMD21
disable_event_user(EVSYS_ID_USER_TC3_EVU + self->tc_index);
uint32_t masked_value = EIC->EVCTRL.vec.EXTINTEO;
EIC->EVCTRL.vec.EXTINTEO = masked_value ^ (1 << self->channel);
#endif
#ifdef SAMD51
disable_event_user(EVSYS_ID_USER_TC0_EVU + self->tc_index);
uint32_t masked_value = EIC->EVCTRL.bit.EXTINTEO;
EIC->EVCTRL.bit.EXTINTEO = masked_value ^ (1 << self->channel);
NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
#endif
eic_set_enable(true);
// check if any other objects are using the EIC; if not, turn it off
if (EIC->EVCTRL.reg == 0 && EIC->INTENSET.reg == 0) {
eic_reset();
turn_off_external_interrupt_controller();
}
// turn off the TC we were using
Tc *tc = tc_insts[self->tc_index];
tc_set_enable(tc, false);
tc_reset(tc);
NVIC_DisableIRQ(self->TC_IRQ);
NVIC_ClearPendingIRQ(self->TC_IRQ);
active_frequencyins[self->tc_index] = NULL;
self->tc_index = 0xff;
self->pin = NO_PIN;
bool check_active = false;
for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
if (active_frequencyins[i] != NULL) {
check_active = true;
}
}
if (!check_active) {
frequencyin_reference_tc_enable(false);
reference_tc = 0xff;
#ifdef SAMD51
frequencyin_samd51_stop_dpll();
#endif
}
}
uint32_t common_hal_frequencyio_frequencyin_get_item(frequencyio_frequencyin_obj_t* self) {
NVIC_DisableIRQ(self->TC_IRQ);
#ifdef SAMD21
NVIC_DisableIRQ(EIC_IRQn);
#endif
#ifdef SAMD51
NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
#endif
// adjust for actual capture period vs base `capture_period`
float frequency_adjustment = 0.0;
if (self->factor > self->capture_period) {
float time_each_event = self->factor / self->frequency; // get the time for each event during actual period
float capture_diff = self->factor - self->capture_period; // get the difference of actual and base periods
// we only need to adjust if the capture_diff can contain 1 or more events
// if so, we add how many events could have occured during the diff time
if (time_each_event > capture_diff) {
frequency_adjustment = capture_diff / time_each_event;
}
}
float value = 1000 / (self->capture_period / (self->frequency + frequency_adjustment));
NVIC_ClearPendingIRQ(self->TC_IRQ);
NVIC_EnableIRQ(self->TC_IRQ);
#ifdef SAMD21
NVIC_ClearPendingIRQ(EIC_IRQn);
NVIC_EnableIRQ(EIC_IRQn);
#endif
#ifdef SAMD51
NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
NVIC_EnableIRQ(EIC_0_IRQn + self->channel);
#endif
return value;
}
void common_hal_frequencyio_frequencyin_pause(frequencyio_frequencyin_obj_t* self) {
Tc *tc = tc_insts[self->tc_index];
if (!tc->COUNT16.EVCTRL.bit.TCEI) {
return;
}
tc->COUNT16.EVCTRL.bit.TCEI = 0;
#ifdef SAMD21
uint32_t masked_value = EIC->EVCTRL.vec.EXTINTEO;
EIC->EVCTRL.vec.EXTINTEO = masked_value ^ (1 << self->channel);
#endif
#ifdef SAMD51
uint32_t masked_value = EIC->EVCTRL.bit.EXTINTEO;
EIC->EVCTRL.bit.EXTINTEO = masked_value ^ (1 << self->channel);
#endif
return;
}
void common_hal_frequencyio_frequencyin_resume(frequencyio_frequencyin_obj_t* self) {
Tc *tc = tc_insts[self->tc_index];
if (tc->COUNT16.EVCTRL.bit.TCEI) {
return;
}
tc->COUNT16.EVCTRL.bit.TCEI = 1;
#ifdef SAMD21
uint32_t masked_value = EIC->EVCTRL.vec.EXTINTEO;
EIC->EVCTRL.vec.EXTINTEO = masked_value | (1 << self->channel);
#endif
#ifdef SAMD51
uint32_t masked_value = EIC->EVCTRL.bit.EXTINTEO;
EIC->EVCTRL.bit.EXTINTEO = masked_value | (1 << self->channel);
#endif
self->errored_too_fast = false;
return;
}
void common_hal_frequencyio_frequencyin_clear(frequencyio_frequencyin_obj_t* self) {
NVIC_DisableIRQ(self->TC_IRQ);
#ifdef SAMD21
NVIC_DisableIRQ(EIC_IRQn);
#endif
#ifdef SAMD51
NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
#endif
self->frequency = 0;
NVIC_ClearPendingIRQ(self->TC_IRQ);
NVIC_EnableIRQ(self->TC_IRQ);
#ifdef SAMD21
NVIC_ClearPendingIRQ(EIC_IRQn);
NVIC_EnableIRQ(EIC_IRQn);
#endif
#ifdef SAMD51
NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
NVIC_EnableIRQ(EIC_0_IRQn + self->channel);
#endif
return;
}
uint16_t common_hal_frequencyio_frequencyin_get_capture_period(frequencyio_frequencyin_obj_t *self) {
return self->capture_period;
}
void common_hal_frequencyio_frequencyin_set_capture_period(frequencyio_frequencyin_obj_t *self, uint16_t capture_period) {
if ((capture_period == 0) || (capture_period > 500)) {
mp_raise_ValueError(translate("Invalid capture period. Valid range: 1 - 500"));
}
self->capture_period = capture_period;
common_hal_frequencyio_frequencyin_clear(self);
}

View File

@ -0,0 +1,60 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Michael Schroeder
*
* 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.
*/
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
typedef struct {
mp_obj_base_t base;
uint8_t tc_index;
uint8_t pin;
uint8_t channel;
uint8_t event_channel;
uint32_t frequency;
volatile uint64_t last_ms;
volatile uint32_t last_us;
float factor;
uint32_t capture_period;
uint8_t TC_IRQ;
volatile bool errored_too_fast;
} frequencyio_frequencyin_obj_t;
void frequencyin_interrupt_handler(uint8_t index);
void frequencyin_emergency_cancel_capture(uint8_t index);
void frequencyin_reference_tc_init(void);
void frequencyin_reference_tc_enable(bool enable);
bool frequencyin_reference_tc_enabled(void);
#ifdef SAMD51
void frequencyin_samd51_start_dpll(void);
void frequencyin_samd51_stop_dpll(void);
#endif
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H

View File

@ -0,0 +1 @@
// No ferquencyio module functions.

View File

@ -31,6 +31,7 @@
#include "common-hal/pulseio/PWMOut.h"
#include "shared-bindings/pulseio/PWMOut.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "timer_handler.h"
#include "atmel_start_pins.h"
#include "hal/utils/include/utils_repeat_macro.h"
@ -234,6 +235,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
}
}
set_timer_handler(timer->is_tc, timer->index, TC_HANDLER_NO_INTERRUPT);
// We use the zeroeth clock on either port to go full speed.
turn_on_clocks(timer->is_tc, timer->index, 0);
@ -326,32 +328,29 @@ extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self,
#endif
#ifdef SAMD51
Tc* tc = tc_insts[t->index];
while (tc->COUNT16.SYNCBUSY.bit.CC1 != 0) {
// Wait for a previous value to be written. This can wait up to one period so we do
// other stuff in the meantime.
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
}
while (tc->COUNT16.SYNCBUSY.bit.CC1 != 0) {}
tc->COUNT16.CCBUF[1].reg = adjusted_duty;
#endif
} else {
uint32_t adjusted_duty = ((uint64_t) tcc_periods[t->index]) * duty / 0xffff;
uint8_t channel = tcc_channel(t);
Tcc* tcc = tcc_insts[t->index];
while ((tcc->SYNCBUSY.vec.CC & (1 << channel)) != 0) {
// Wait for a previous value to be written. This can wait up to one period so we do
// other stuff in the meantime.
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
}
// Write into the CC buffer register, which will be transferred to the
// CC register on an UPDATE (when period is finished).
// Do clock domain syncing as necessary.
while (tcc->SYNCBUSY.reg != 0) {}
// Lock out double-buffering while updating the CCB value.
tcc->CTRLBSET.bit.LUPD = 1;
#ifdef SAMD21
tcc->CCB[channel].reg = adjusted_duty;
#endif
#ifdef SAMD51
tcc->CCBUF[channel].reg = adjusted_duty;
#endif
tcc->CTRLBCLR.bit.LUPD = 1;
}
}
@ -366,7 +365,12 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
Tcc* tcc = tcc_insts[t->index];
uint8_t channel = tcc_channel(t);
uint32_t cv = 0;
while (tcc->SYNCBUSY.bit.CTRLB) {}
#ifdef SAMD21
// If CCBV (CCB valid) is set, the CCB value hasn't yet been copied
// to the CC value.
if ((tcc->STATUS.vec.CCBV & (1 << channel)) != 0) {
cv = tcc->CCB[channel].reg;
} else {
@ -423,9 +427,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
tc->COUNT16.CC[0].reg = new_top;
#endif
#ifdef SAMD51
while (tc->COUNT16.SYNCBUSY.reg != 0) {
/* Wait for sync */
}
while (tc->COUNT16.SYNCBUSY.reg != 0) {}
tc->COUNT16.CCBUF[0].reg = new_top;
#endif
} else {
@ -436,14 +438,12 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
tcc->CTRLA.bit.PRESCALER = new_divisor;
tcc_set_enable(tcc, true);
}
while (tcc->SYNCBUSY.reg != 0) {}
tcc_periods[t->index] = new_top;
#ifdef SAMD21
tcc->PERB.bit.PERB = new_top;
#endif
#ifdef SAMD51
while (tcc->SYNCBUSY.reg != 0) {
/* Wait for sync */
}
tcc->PERBUF.bit.PERBUF = new_top;
#endif
}

View File

@ -37,6 +37,7 @@
#include "py/runtime.h"
#include "shared-bindings/pulseio/PulseOut.h"
#include "supervisor/shared/translate.h"
#include "timer_handler.h"
// This timer is shared amongst all PulseOut objects under the assumption that
// the code is single threaded.
@ -112,6 +113,7 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
pulseout_tc_index = index;
set_timer_handler(true, index, TC_HANDLER_PULSEOUT);
// We use GCLK0 for SAMD21 and GCLK1 for SAMD51 because they both run at 48mhz making our
// math the same across the boards.
#ifdef SAMD21

View File

@ -79,11 +79,10 @@
#include "peripherals/samd/dma.h"
#define MICROPY_PORT_ROOT_POINTERS \
CIRCUITPY_COMMON_ROOT_POINTERS \
mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT] \
;
#include "py/circuitpy_mpconfig.h"
#define MICROPY_PORT_ROOT_POINTERS \
CIRCUITPY_COMMON_ROOT_POINTERS \
mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT];
#endif // __INCLUDED_MPCONFIGPORT_H

@ -1 +1 @@
Subproject commit 235cb97d72648ec2889aba25ff4a34c4f32e2ac3
Subproject commit 6416828bb6821779d4c62fa3c7d41c95634173c0

View File

@ -68,9 +68,10 @@
#include "tusb.h"
#ifdef CIRCUITPY_GAMEPAD_TICKS
#if CIRCUITPY_GAMEPAD
#include "shared-module/gamepad/__init__.h"
#endif
#include "shared-module/_pew/PewPew.h"
extern volatile bool mp_msc_enabled;
@ -222,9 +223,12 @@ void reset_port(void) {
reset_gclks();
#ifdef CIRCUITPY_GAMEPAD_TICKS
#if CIRCUITPY_GAMEPAD
gamepad_reset();
#endif
#if CIRCUITPY_PEW
pew_reset();
#endif
reset_event_system();

View File

@ -0,0 +1,67 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdbool.h>
#include <stdint.h>
#include "timer_handler.h"
#include "common-hal/pulseio/PulseOut.h"
#include "shared-module/_pew/PewPew.h"
#include "common-hal/frequencyio/FrequencyIn.h"
static uint8_t tc_handler[TC_INST_NUM];
void set_timer_handler(bool is_tc, uint8_t index, uint8_t timer_handler) {
if (is_tc) {
tc_handler[index] = timer_handler;
}
}
void shared_timer_handler(bool is_tc, uint8_t index) {
// Add calls to interrupt handlers for specific functionality here.
// Make sure to add the handler #define to timer_handler.h
if (is_tc) {
uint8_t handler = tc_handler[index];
switch(handler) {
case TC_HANDLER_PULSEOUT:
pulseout_interrupt_handler(index);
break;
case TC_HANDLER_PEW:
#if CIRCUITPY_PEW
pewpew_interrupt_handler(index);
#endif
break;
case TC_HANDLER_FREQUENCYIN:
#if CIRCUITPY_FREQUENCYIO
frequencyin_interrupt_handler(index);
#endif
break;
default:
break;
}
}
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_TIMER_HANDLER_H
#define MICROPY_INCLUDED_ATMEL_SAMD_TIMER_HANDLER_H
#define TC_HANDLER_NO_INTERRUPT 0x0
#define TC_HANDLER_PULSEOUT 0x1
#define TC_HANDLER_PEW 0x2
#define TC_HANDLER_FREQUENCYIN 0x3
void set_timer_handler(bool is_tc, uint8_t index, uint8_t timer_handler);
void shared_timer_handler(bool is_tc, uint8_t index);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_TIMER_HANDLER_H

View File

@ -35,27 +35,20 @@
#include "nrf_soc.h"
#include "nrfx_power.h"
#include "py/misc.h"
#include "py/mpstate.h"
nrf_nvic_state_t nrf_nvic_state = { 0 };
__attribute__((aligned(4)))
static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (BLE_GATT_ATT_MTU_DEFAULT)];
typedef struct event_handler {
struct event_handler *next;
void *param;
ble_drv_evt_handler_t func;
} event_handler_t;
static event_handler_t *m_event_handlers = NULL;
void ble_drv_reset() {
// Linked list items will be gc'd.
m_event_handlers = NULL;
MP_STATE_VM(ble_drv_evt_handler_entries) = NULL;
}
void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) {
event_handler_t *it = m_event_handlers;
ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries);
while (it != NULL) {
// If event handler and its corresponding param are already on the list, don't add again.
if ((it->func == func) && (it->param == param)) {
@ -65,17 +58,17 @@ void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) {
}
// Add a new handler to the front of the list
event_handler_t *handler = m_new_ll(event_handler_t, 1);
handler->next = m_event_handlers;
ble_drv_evt_handler_entry_t *handler = m_new_ll(ble_drv_evt_handler_entry_t, 1);
handler->next = MP_STATE_VM(ble_drv_evt_handler_entries);
handler->param = param;
handler->func = func;
m_event_handlers = handler;
MP_STATE_VM(ble_drv_evt_handler_entries) = handler;
}
void ble_drv_remove_event_handler(ble_drv_evt_handler_t func, void *param) {
event_handler_t *it = m_event_handlers;
event_handler_t **prev = &m_event_handlers;
ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries);
ble_drv_evt_handler_entry_t **prev = &MP_STATE_VM(ble_drv_evt_handler_entries);
while (it != NULL) {
if ((it->func == func) && (it->param == param)) {
// Splice out the matching handler.
@ -122,7 +115,7 @@ void SD_EVT_IRQHandler(void) {
break;
}
event_handler_t *it = m_event_handlers;
ble_drv_evt_handler_entry_t *it = MP_STATE_VM(ble_drv_evt_handler_entries);
while (it != NULL) {
it->func((ble_evt_t *)m_ble_evt_buf, it->param);
it = it->next;

View File

@ -50,6 +50,12 @@
typedef void (*ble_drv_evt_handler_t)(ble_evt_t*, void*);
typedef struct ble_drv_evt_handler_entry {
struct ble_drv_evt_handler_entry *next;
void *param;
ble_drv_evt_handler_t func;
} ble_drv_evt_handler_entry_t;
void ble_drv_reset(void);
void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param);
void ble_drv_remove_event_handler(ble_drv_evt_handler_t func, void *param);

View File

@ -61,6 +61,12 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ESP_BOOT_MODE), MP_ROM_PTR(&pin_P0_16) },
{ MP_ROM_QSTR(MP_QSTR_ESP_WIFI_EN), MP_ROM_PTR(&pin_P0_24) },
{ MP_ROM_QSTR(MP_QSTR_ESP_HOST_WK), MP_ROM_PTR(&pin_P0_07) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -59,6 +59,14 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_UBLOX_POWER_MONITOR), MP_ROM_PTR(&pin_P0_02) },
{ MP_ROM_QSTR(MP_QSTR_UBLOX_RESET), MP_ROM_PTR(&pin_P0_12) },
{ MP_ROM_QSTR(MP_QSTR_UBLOX_POWER_ON), MP_ROM_PTR(&pin_P0_16) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -52,6 +52,14 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ANTENNA_EXTERNAL), MP_ROM_PTR(&pin_P0_25) },
{ MP_ROM_QSTR(MP_QSTR_ANTENNA_PCB), MP_ROM_PTR(&pin_P0_24) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -29,7 +29,7 @@
#include "ble_drv.h"
#include "ble_gatts.h"
#include "sd_mutex.h"
#include "nrf_nvic.h"
#include "lib/utils/interrupt_char.h"
#include "py/runtime.h"
@ -47,14 +47,14 @@ STATIC void characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) {
ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
// Event handle must match the handle for my characteristic.
if (evt_write->handle == self->characteristic->handle) {
// Push all the data onto the ring buffer, but wait for any reads to finish.
sd_mutex_acquire_wait_no_vm(&self->ringbuf_mutex);
// Push all the data onto the ring buffer.
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);
for (size_t i = 0; i < evt_write->len; i++) {
ringbuf_put(&self->ringbuf, evt_write->data[i]);
}
// Don't check for errors: we're in an event handler.
sd_mutex_release(&self->ringbuf_mutex);
break;
sd_nvic_critical_region_exit(is_nested_critical_region);
break;
}
}
}
@ -72,7 +72,6 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe
// This is a macro.
// true means long-lived, so it won't be moved.
ringbuf_alloc(&self->ringbuf, buffer_size, true);
sd_mutex_new(&self->ringbuf_mutex);
ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self);
@ -92,8 +91,9 @@ int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_
#endif
}
// Copy received data. Lock out writes while copying.
sd_mutex_acquire_wait(&self->ringbuf_mutex);
// Copy received data. Lock out write interrupt handler while copying.
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);
size_t rx_bytes = MIN(ringbuf_count(&self->ringbuf), len);
for ( size_t i = 0; i < rx_bytes; i++ ) {
@ -101,20 +101,25 @@ int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_
}
// Writes now OK.
sd_mutex_release_check(&self->ringbuf_mutex);
sd_nvic_critical_region_exit(is_nested_critical_region);
return rx_bytes;
}
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
return ringbuf_count(&self->ringbuf);
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);
uint16_t count = ringbuf_count(&self->ringbuf);
sd_nvic_critical_region_exit(is_nested_critical_region);
return count;
}
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
// prevent conflict with uart irq
sd_mutex_acquire_wait(&self->ringbuf_mutex);
uint8_t is_nested_critical_region;
sd_nvic_critical_region_enter(&is_nested_critical_region);
ringbuf_clear(&self->ringbuf);
sd_mutex_release_check(&self->ringbuf_mutex);
sd_nvic_critical_region_exit(is_nested_critical_region);
}
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) {

View File

@ -38,7 +38,6 @@ typedef struct {
uint32_t timeout_ms;
// Ring buffer storing consecutive incoming values.
ringbuf_t ringbuf;
nrf_mutex_t ringbuf_mutex;
} bleio_characteristic_buffer_obj_t;
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H

View File

@ -28,6 +28,8 @@
#ifndef NRF5_MPCONFIGPORT_H__
#define NRF5_MPCONFIGPORT_H__
#include "ble_drv.h"
#define MICROPY_CPYTHON_COMPAT (1)
//#define MICROPY_MODULE_BUILTIN_INIT (1) // TODO check this
//#define MICROPY_MODULE_WEAK_LINKS (1) // TODO check this
@ -52,10 +54,11 @@
// 24kiB stack
#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000
#define MICROPY_PORT_ROOT_POINTERS \
CIRCUITPY_COMMON_ROOT_POINTERS \
;
#include "py/circuitpy_mpconfig.h"
#define MICROPY_PORT_ROOT_POINTERS \
CIRCUITPY_COMMON_ROOT_POINTERS \
ble_drv_evt_handler_entry_t* ble_drv_evt_handler_entries; \
#endif // NRF5_MPCONFIGPORT_H__

View File

@ -24,3 +24,6 @@ CIRCUITPY_NVM = 0
# rtc not yet implemented
CIRCUITPY_RTC = 0
# frequencyio not yet implemented
CIRCUITPY_FREQUENCYIO = 0

View File

@ -149,6 +149,7 @@ SRC_C = \
alloc.c \
coverage.c \
fatfs_port.c \
supervisor/stub/filesystem.c \
supervisor/stub/serial.c \
supervisor/stub/stack.c \
supervisor/shared/translate.c \

View File

@ -126,6 +126,9 @@ endif
ifeq ($(CIRCUITPY_DISPLAYIO),1)
SRC_PATTERNS += displayio/% terminalio/%
endif
ifeq ($(CIRCUITPY_FREQUENCYIO),1)
SRC_PATTERNS += frequencyio/%
endif
ifeq ($(CIRCUITPY_GAMEPAD),1)
SRC_PATTERNS += gamepad/%
endif
@ -198,6 +201,9 @@ endif
ifeq ($(CIRCUITPY_USTACK),1)
SRC_PATTERNS += ustack/%
endif
ifeq ($(CIRCUITPY_PEW),1)
SRC_PATTERNS += _pew/%
endif
# All possible sources are listed here, and are filtered by SRC_PATTERNS.
SRC_COMMON_HAL = \
@ -228,6 +234,8 @@ $(filter $(SRC_PATTERNS), \
digitalio/DigitalInOut.c \
digitalio/__init__.c \
displayio/ParallelBus.c \
frequencyio/__init__.c \
frequencyio/FrequencyIn.c \
i2cslave/I2CSlave.c \
i2cslave/__init__.c \
microcontroller/Pin.c \
@ -318,6 +326,8 @@ $(filter $(SRC_PATTERNS), \
terminalio/__init__.c \
uheap/__init__.c \
ustack/__init__.c \
_pew/__init__.c \
_pew/PewPew.c \
)
ifeq ($(INTERNAL_LIBM),1)

View File

@ -33,6 +33,9 @@
#ifndef __INCLUDED_MPCONFIG_CIRCUITPY_H
#define __INCLUDED_MPCONFIG_CIRCUITPY_H
// This is CircuitPython.
#define CIRCUITPY 1
// REPR_C encodes qstrs, 31-bit ints, and 30-bit floats in a single 32-bit word.
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
@ -278,6 +281,13 @@ extern const struct _mp_obj_module_t terminalio_module;
#define CIRCUITPY_DISPLAY_LIMIT (0)
#endif
#if CIRCUITPY_FREQUENCYIO
extern const struct _mp_obj_module_t frequencyio_module;
#define FREQUENCYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_frequencyio), (mp_obj_t)&frequencyio_module },
#else
#define FREQUENCYIO_MODULE
#endif
#if CIRCUITPY_GAMEPAD
extern const struct _mp_obj_module_t gamepad_module;
// Scan gamepad every 32ms
@ -460,6 +470,13 @@ extern const struct _mp_obj_module_t ustack_module;
#define USTACK_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 },
#else
#define PEW_MODULE
#endif
// These modules are not yet in shared-bindings, but we prefer the non-uxxx names.
#if MICROPY_PY_UERRNO
#define ERRNO_MODULE { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) },
@ -509,6 +526,7 @@ extern const struct _mp_obj_module_t ustack_module;
TERMINALIO_MODULE \
DISPLAYIO_MODULE \
ERRNO_MODULE \
FREQUENCYIO_MODULE \
GAMEPAD_MODULE \
I2CSLAVE_MODULE \
JSON_MODULE \
@ -518,6 +536,7 @@ extern const struct _mp_obj_module_t ustack_module;
NETWORK_MODULE \
SOCKET_MODULE \
WIZNET_MODULE \
PEW_MODULE \
PIXELBUF_MODULE \
PULSEIO_MODULE \
RANDOM_MODULE \
@ -559,6 +578,7 @@ extern const struct _mp_obj_module_t ustack_module;
vstr_t *repl_line; \
mp_obj_t rtc_time_source; \
mp_obj_t gamepad_singleton; \
mp_obj_t pew_singleton; \
mp_obj_t terminal_tilegrid_tiles; \
FLASH_ROOT_POINTERS \
NETWORK_ROOT_POINTERS \

View File

@ -92,6 +92,11 @@ CIRCUITPY_DISPLAYIO = $(CIRCUITPY_FULL_BUILD)
endif
CFLAGS += -DCIRCUITPY_DISPLAYIO=$(CIRCUITPY_DISPLAYIO)
ifndef CIRCUITPY_FREQUENCYIO
CIRCUITPY_FREQUENCYIO = 1
endif
CFLAGS += -DCIRCUITPY_FREQUENCYIO=$(CIRCUITPY_FREQUENCYIO)
ifndef CIRCUITPY_GAMEPAD
CIRCUITPY_GAMEPAD = $(CIRCUITPY_FULL_BUILD)
endif
@ -213,6 +218,11 @@ CIRCUITPY_USB_MIDI = 1
endif
CFLAGS += -DCIRCUITPY_USB_MIDI=$(CIRCUITPY_USB_MIDI)
ifndef CIRCUITPY_PEW
CIRCUITPY_PEW = 0
endif
CFLAGS += -DCIRCUITPY_PEW=$(CIRCUITPY_PEW)
# For debugging.
ifndef CIRCUITPY_USTACK
CIRCUITPY_USTACK = 0

View File

@ -84,7 +84,11 @@ STATIC const mp_obj_dict_t errorcode_dict = {
#endif
STATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = {
#if CIRCUITPY
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_errno) },
#else
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) },
#endif
#if MICROPY_PY_UERRNO_ERRORCODE
{ MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) },
#endif

View File

@ -45,6 +45,11 @@
#include <mpconfigport.h>
#endif
// Is this a CircuitPython build?
#ifndef CIRCUITPY
#define CIRCUITPY 0
#endif
// Any options not explicitly set in mpconfigport.h will get default
// values below.

View File

@ -148,12 +148,16 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
{ MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_module_array) },
#endif
#if MICROPY_PY_IO
#if CIRCUITPY
{ MP_ROM_QSTR(MP_QSTR_io), MP_ROM_PTR(&mp_module_io) },
#else
{ MP_ROM_QSTR(MP_QSTR_uio), MP_ROM_PTR(&mp_module_io) },
#endif
#endif
#if MICROPY_PY_COLLECTIONS
{ MP_ROM_QSTR(MP_QSTR_collections), MP_ROM_PTR(&mp_module_collections) },
#endif
// CircuitPython: Now in shared-bindings/, so not defined here.
#if MICROPY_PY_STRUCT
{ MP_ROM_QSTR(MP_QSTR_ustruct), MP_ROM_PTR(&mp_module_ustruct) },
#endif
@ -179,8 +183,13 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
// extmod modules
#if MICROPY_PY_UERRNO
#if CIRCUITPY
// CircuitPython: Defined in MICROPY_PORT_BUILTIN_MODULES, so not defined here.
// TODO: move to shared-bindings/
#else
{ MP_ROM_QSTR(MP_QSTR_uerrno), MP_ROM_PTR(&mp_module_uerrno) },
#endif
#endif
#if MICROPY_PY_UCTYPES
{ MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
#endif
@ -188,11 +197,21 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
{ MP_ROM_QSTR(MP_QSTR_uzlib), MP_ROM_PTR(&mp_module_uzlib) },
#endif
#if MICROPY_PY_UJSON
#if CIRCUITPY
// CircuitPython: Defined in MICROPY_PORT_BUILTIN_MODULES, so not defined here.
// TODO: move to shared-bindings/
#else
{ MP_ROM_QSTR(MP_QSTR_ujson), MP_ROM_PTR(&mp_module_ujson) },
#endif
#endif
#if MICROPY_PY_URE
#if CIRCUITPY
// CircuitPython: Defined in MICROPY_PORT_BUILTIN_MODULES, so not defined here.
// TODO: move to shared-bindings/
#else
{ MP_ROM_QSTR(MP_QSTR_ure), MP_ROM_PTR(&mp_module_ure) },
#endif
#endif
#if MICROPY_PY_UHEAPQ
{ MP_ROM_QSTR(MP_QSTR_uheapq), MP_ROM_PTR(&mp_module_uheapq) },
#endif

View File

@ -0,0 +1,151 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Radomir Dopieralski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/gc.h"
#include "py/mpstate.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/util.h"
#include "PewPew.h"
#include "shared-module/_pew/PewPew.h"
#include "supervisor/shared/translate.h"
//| .. currentmodule:: _pew
//|
//| :class:`PewPew` -- LED matrix and button driver
//| ===============================================
//|
//| This is an internal module to be used by the ``pew.py`` library from
//| https://github.com/pewpew-game/pew-pewpew-standalone-10.x to handle the
//| LED matrix display and buttons on the ``pewpew10`` board.
//|
//| Usage::
//|
//| This singleton class is instantiated by the ``pew`` library, and
//| used internally by it. All user-visible interactions are done through
//| that library.
//|
//| .. class:: PewPew(buffer, rows, cols, buttons)
//|
//| Initializes matrix scanning routines.
//|
//| The ``buffer`` is a 64 byte long ``bytearray`` that stores what should
//| be displayed on the matrix. ``rows`` and ``cols`` are both lists of
//| eight ``DigitalInputOutput`` objects that are connected to the matrix
//| rows and columns. ``buttons`` is a ``DigitalInputOutput`` object that
//| is connected to the common side of all buttons (the other sides of the
//| buttons are connected to rows of the matrix).
//|
STATIC mp_obj_t pewpew_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 4, 4, true);
enum { ARG_buffer, ARG_rows, ARG_cols, ARG_buttons };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_rows, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_cols, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_buttons, MP_ARG_OBJ | MP_ARG_REQUIRED },
};
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);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
size_t rows_size = 0;
mp_obj_t *rows;
mp_obj_get_array(args[ARG_rows].u_obj, &rows_size, &rows);
size_t cols_size = 0;
mp_obj_t *cols;
mp_obj_get_array(args[ARG_cols].u_obj, &cols_size, &cols);
if (bufinfo.len != rows_size * cols_size) {
mp_raise_ValueError(translate(""));
}
for (size_t i = 0; i < rows_size; ++i) {
if (!MP_OBJ_IS_TYPE(rows[i], &digitalio_digitalinout_type)) {
mp_raise_TypeError(translate(""));
}
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(rows[i]);
raise_error_if_deinited(
common_hal_digitalio_digitalinout_deinited(pin));
}
for (size_t i = 0; i < cols_size; ++i) {
if (!MP_OBJ_IS_TYPE(cols[i], &digitalio_digitalinout_type)) {
mp_raise_TypeError(translate(""));
}
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(cols[i]);
raise_error_if_deinited(
common_hal_digitalio_digitalinout_deinited(pin));
}
if (!MP_OBJ_IS_TYPE(args[ARG_buttons].u_obj,
&digitalio_digitalinout_type)) {
mp_raise_TypeError(translate(""));
}
digitalio_digitalinout_obj_t *buttons = MP_OBJ_TO_PTR(
args[ARG_buttons].u_obj);
raise_error_if_deinited(
common_hal_digitalio_digitalinout_deinited(buttons));
pew_obj_t *pew = MP_STATE_VM(pew_singleton);
if (!pew) {
pew = m_new_obj(pew_obj_t);
pew->base.type = &pewpew_type;
pew = gc_make_long_lived(pew);
MP_STATE_VM(pew_singleton) = pew;
}
pew->buffer = bufinfo.buf;
pew->rows = rows;
pew->rows_size = rows_size;
pew->cols = cols;
pew->cols_size = cols_size;
pew->buttons = buttons;
pew->pressed = 0;
pew_init();
return MP_OBJ_FROM_PTR(pew);
}
STATIC const mp_rom_map_elem_t pewpew_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pewpew_locals_dict, pewpew_locals_dict_table);
const mp_obj_type_t pewpew_type = {
{ &mp_type_type },
.name = MP_QSTR_PewPew,
.make_new = pewpew_make_new,
.locals_dict = (mp_obj_dict_t*)&pewpew_locals_dict,
};

View File

@ -0,0 +1,33 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Radomir Dopieralski
*
* 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.
*/
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_PEW_PEWPEW_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_PEW_PEWPEW_H
extern const mp_obj_type_t pewpew_type;
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PEW_PEWPEW_H

View File

@ -0,0 +1,67 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Radomir Dopieralski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "PewPew.h"
#include "shared-module/_pew/PewPew.h"
STATIC mp_obj_t get_pressed(void) {
pew_obj_t *pew = MP_STATE_VM(pew_singleton);
if (!pew) {
return mp_const_none;
}
uint8_t pressed = pew->pressed;
pew->pressed = 0;
return mp_obj_new_int(pressed);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_pressed_obj, get_pressed);
//| :mod:`_pew` --- LED matrix driver
//| ==================================
//|
//| .. module:: _pew
//| :synopsis: LED matrix driver
//| :platform: SAMD21
//|
//| .. toctree::
//| :maxdepth: 3
//|
//| PewPew
//|
STATIC const mp_rom_map_elem_t pew_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pew) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PewPew), MP_ROM_PTR(&pewpew_type)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_pressed), MP_ROM_PTR(&get_pressed_obj)},
};
STATIC MP_DEFINE_CONST_DICT(pew_module_globals,
pew_module_globals_table);
const mp_obj_module_t pew_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&pew_module_globals,
};

View File

@ -48,6 +48,9 @@ enum {
DescriptorUuidTimeTriggerSetting = 0x290E,
};
// Work-in-progress: orphaned for now.
//| :orphan:
//|
//| .. currentmodule:: bleio
//|
//| :class:`Descriptor` -- BLE descriptor

View File

@ -43,6 +43,9 @@
#include "shared-module/bleio/Device.h"
#include "shared-module/bleio/ScanEntry.h"
// Work-in-progress: orphaned for now.
//| :orphan:
//|
//| .. currentmodule:: bleio
//|
//| :class:`Device` -- BLE device

View File

@ -37,6 +37,9 @@
#include "shared-module/bleio/AdvertisementData.h"
#include "shared-module/bleio/ScanEntry.h"
// Work-in-progress: orphaned for now.
//| :orphan:
//|
//| .. currentmodule:: bleio
//|
//| :class:`ScanEntry` -- BLE scan response entry

View File

@ -32,6 +32,9 @@
#define DEFAULT_INTERVAL 100
#define DEFAULT_WINDOW 100
// Work-in-progress: orphaned for now.
//| :orphan:
//|
//| .. currentmodule:: bleio
//|
//| :class:`Scanner` -- scan for nearby BLE devices

View File

@ -60,11 +60,12 @@
//| Broadcaster
//| Characteristic
//| CharacteristicBuffer
//| Descriptor
//| Device
// Work-in-progress classes are omitted, and marked as :orphan: in their files.
// Descriptor
// Device
//| Peripheral
//| ScanEntry
//| Scanner
// ScanEntry
// Scanner
//| Service
//| UUID
//|
@ -82,10 +83,11 @@ STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_Broadcaster), MP_ROM_PTR(&bleio_broadcaster_type) },
{ MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) },
{ MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) },
{ MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
// { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) },
{ MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) },
{ MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
{ MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
// Hide work-in-progress.
// { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) },
// { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) },
{ MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) },
{ MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) },

View File

@ -253,6 +253,42 @@ const mp_obj_property_t displayio_display_auto_brightness_obj = {
(mp_obj_t)&mp_const_none_obj},
};
//| .. attribute:: width
//|
//| Gets the width of the board
//|
//|
STATIC mp_obj_t displayio_display_obj_get_width(mp_obj_t self_in) {
displayio_display_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_display_get_width(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_get_width_obj, displayio_display_obj_get_width);
const mp_obj_property_t displayio_display_width_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&displayio_display_get_width_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
//| .. attribute:: height
//|
//| Gets the height of the board
//|
//|
STATIC mp_obj_t displayio_display_obj_get_height(mp_obj_t self_in) {
displayio_display_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_display_get_height(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(displayio_display_get_height_obj, displayio_display_obj_get_height);
const mp_obj_property_t displayio_display_height_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&displayio_display_get_height_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
STATIC const mp_rom_map_elem_t displayio_display_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&displayio_display_show_obj) },
{ MP_ROM_QSTR(MP_QSTR_refresh_soon), MP_ROM_PTR(&displayio_display_refresh_soon_obj) },
@ -260,6 +296,9 @@ STATIC const mp_rom_map_elem_t displayio_display_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&displayio_display_brightness_obj) },
{ MP_ROM_QSTR(MP_QSTR_auto_brightness), MP_ROM_PTR(&displayio_display_auto_brightness_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_display_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_display_height_obj) },
};
STATIC MP_DEFINE_CONST_DICT(displayio_display_locals_dict, displayio_display_locals_dict_table);

View File

@ -48,17 +48,22 @@ void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_
void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self);
void displayio_display_start_region_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void displayio_display_finish_region_update(displayio_display_obj_t* self);
bool displayio_display_begin_transaction(displayio_display_obj_t* self);
void displayio_display_end_transaction(displayio_display_obj_t* self);
void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
bool displayio_display_frame_queued(displayio_display_obj_t* self);
bool displayio_display_refresh_queued(displayio_display_obj_t* self);
void displayio_display_finish_refresh(displayio_display_obj_t* self);
bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length);
void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length);
bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self);
void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness);
uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self);
uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self);
mp_float_t common_hal_displayio_display_get_brightness(displayio_display_obj_t* self);
bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self, mp_float_t brightness);

View File

@ -110,7 +110,12 @@ STATIC mp_obj_t displayio_fourwire_obj_send(mp_obj_t self, mp_obj_t command_obj,
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
common_hal_displayio_fourwire_begin_transaction(self);
// Wait for display bus to be available.
while (!common_hal_displayio_fourwire_begin_transaction(self)) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP ;
#endif
}
common_hal_displayio_fourwire_send(self, true, &command, 1);
common_hal_displayio_fourwire_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
common_hal_displayio_fourwire_end_transaction(self);

View File

@ -52,21 +52,22 @@
//| import time
//| import pulseio
//|
//| backlight = pulseio.PWMOut(board.TFT_BACKLIGHT)
//| board.DISPLAY.auto_brightness = False
//| board.DISPLAY.brightness = 0
//| splash = displayio.Group()
//| board.DISPLAY.show(splash)
//|
//| with open("/sample.bmp", "rb") as f:
//| odb = displayio.OnDiskBitmap(f)
//| face = displayio.Sprite(odb, pixel_shader=displayio.ColorConverter(), position=(0,0))
//| face = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter(), position=(0,0))
//| splash.append(face)
//| # Wait for the image to load.
//| board.DISPLAY.wait_for_frame()
//|
//| # Fade up the backlight
//| for i in range(100):
//| backlight.duty_cycle = i * (2 ** 15) // 100
//| time.sleep(0.01)
//| board.DISPLAY.brightness = 0.01 * i
//| time.sleep(0.05)
//|
//| # Wait forever
//| while True:

View File

@ -114,7 +114,12 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
common_hal_displayio_parallelbus_begin_transaction(self);
// Wait for display bus to be available.
while (!common_hal_displayio_parallelbus_begin_transaction(self)) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP ;
#endif
}
common_hal_displayio_parallelbus_send(self, true, &command, 1);
common_hal_displayio_parallelbus_send(self, false, ((uint8_t*) bufinfo.buf), bufinfo.len);
common_hal_displayio_parallelbus_end_transaction(self);

View File

@ -0,0 +1,241 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Michael Schroeder
*
* 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 "lib/utils/context_manager_helpers.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "py/runtime0.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/frequencyio/FrequencyIn.h"
#include "shared-bindings/util.h"
#include "supervisor/shared/translate.h"
//| .. currentmodule:: frequencyio
//|
//| :class:`FrequencyIn` -- Read a frequency signal
//| ========================================================
//|
//| FrequencyIn is used to measure the frequency, in hertz, of a digital signal
//| on an incoming pin. Accuracy has shown to be within 10%, if not better. It
//| is recommended to utilize an average of multiple samples to smooth out readings.
//|
//| Frequencies below 1KHz are not currently detectable.
//|
//| FrequencyIn will not determine pulse width (use ``PulseIn``).
//|
//| .. class:: FrequencyIn(pin, capture_period=10)
//|
//| Create a FrequencyIn object associated with the given pin.
//|
//| :param ~microcontroller.Pin pin: Pin to read frequency from.
//| :param int capture_period: Keyword argument to set the measurement period, in
//| milliseconds. Default is 10ms; range is 1ms - 500ms.
//|
//| Read the incoming frequency from a pin::
//|
//| import frequencyio
//| import board
//|
//| frequency = frequencyio.FrequencyIn(board.D11)
//|
//| # Loop while printing the detected frequency
//| while True:
//| print(frequency.value)
//|
//| # Optional clear() will reset the value
//| # to zero. Without this, if the incoming
//| # signal stops, the last reading will remain
//| # as the value.
//| frequency.clear()
//|
STATIC mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size_t n_args,
const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_check_num(n_args, kw_args, 1, 1, true);
frequencyio_frequencyin_obj_t *self = m_new_obj(frequencyio_frequencyin_obj_t);
self->base.type = &frequencyio_frequencyin_type;
enum { ARG_pin, ARG_capture_period };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_capture_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 10} },
};
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);
assert_pin(args[ARG_pin].u_obj, false);
mcu_pin_obj_t* pin = MP_OBJ_TO_PTR(args[ARG_pin].u_obj);
assert_pin_free(pin);
const uint16_t capture_period = args[ARG_capture_period].u_int;
common_hal_frequencyio_frequencyin_construct(self, pin, capture_period);
return MP_OBJ_FROM_PTR(self);
}
//| .. method:: deinit()
//|
//| Deinitialises the FrequencyIn and releases any hardware resources for reuse.
//|
STATIC mp_obj_t frequencyio_frequencyin_deinit(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_frequencyio_frequencyin_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_deinit_obj, frequencyio_frequencyin_deinit);
//| .. method:: __enter__()
//|
//| No-op used by Context Managers.
//|
// Provided by context manager helper.
//| .. method:: __exit__()
//|
//| Automatically deinitializes the hardware when exiting a context. See
//| :ref:`lifetime-and-contextmanagers` for more info.
//|
STATIC mp_obj_t frequencyio_frequencyin_obj___exit__(size_t n_args, const mp_obj_t *args) {
(void)n_args;
common_hal_frequencyio_frequencyin_deinit(args[0]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(frequencyio_frequencyin___exit___obj, 4, 4, frequencyio_frequencyin_obj___exit__);
//| .. method:: pause()
//|
//| Pause frequency capture.
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_pause(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
common_hal_frequencyio_frequencyin_pause(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_pause_obj, frequencyio_frequencyin_obj_pause);
//| .. method:: resume()
//|
//| Resumes frequency capture.
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_resume(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
common_hal_frequencyio_frequencyin_resume(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_resume_obj, frequencyio_frequencyin_obj_resume);
//| .. method:: clear()
//|
//| Clears the last detected frequency capture value.
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_clear(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
common_hal_frequencyio_frequencyin_clear(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_clear_obj, frequencyio_frequencyin_obj_clear);
//| .. attribute:: capture_period
//|
//| The capture measurement period. Lower incoming frequencies will be measured
//| more accurately with longer capture periods. Higher frequencies are more
//| accurate with shorter capture periods.
//|
//| .. note:: When setting a new ``capture_period``, all previous capture information is
//| cleared with a call to ``clear()``.
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_get_capture_period(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
return MP_OBJ_NEW_SMALL_INT(common_hal_frequencyio_frequencyin_get_capture_period(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequency_get_capture_period_obj, frequencyio_frequencyin_obj_get_capture_period);
STATIC mp_obj_t frequencyio_frequencyin_obj_set_capture_period(mp_obj_t self_in, mp_obj_t capture_period) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
common_hal_frequencyio_frequencyin_set_capture_period(self, mp_obj_get_int(capture_period));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(frequencyio_frequency_set_capture_period_obj, frequencyio_frequencyin_obj_set_capture_period);
const mp_obj_property_t frequencyio_frequencyin_capture_period_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&frequencyio_frequency_get_capture_period_obj,
(mp_obj_t)&frequencyio_frequency_set_capture_period_obj,
(mp_obj_t)&mp_const_none_obj},
};
//| .. method:: __get__(index)
//|
//| Returns the value of the last frequency captured.
//|
STATIC mp_obj_t frequencyio_frequencyin_obj_get_value(mp_obj_t self_in) {
frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
//return MP_OBJ_NEW_SMALL_INT(common_hal_frequencyio_frequencyin_get_item(self));
return mp_obj_new_int_from_float(common_hal_frequencyio_frequencyin_get_item(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_get_value_obj, frequencyio_frequencyin_obj_get_value);
const mp_obj_property_t frequencyio_frequencyin_value_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&frequencyio_frequencyin_get_value_obj,
(mp_obj_t)&mp_const_none_obj,
(mp_obj_t)&mp_const_none_obj},
};
STATIC const mp_rom_map_elem_t frequencyio_frequencyin_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&frequencyio_frequencyin_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&frequencyio_frequencyin___exit___obj) },
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&frequencyio_frequencyin_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&frequencyio_frequencyin_pause_obj) },
{ MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&frequencyio_frequencyin_resume_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&frequencyio_frequencyin_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_capture_period), MP_ROM_PTR(&frequencyio_frequencyin_capture_period_obj) },
};
STATIC MP_DEFINE_CONST_DICT(frequencyio_frequencyin_locals_dict, frequencyio_frequencyin_locals_dict_table);
const mp_obj_type_t frequencyio_frequencyin_type = {
{ &mp_type_type },
.name = MP_QSTR_frequencyin,
.make_new = frequencyio_frequencyin_make_new,
.locals_dict = (mp_obj_dict_t*)&frequencyio_frequencyin_locals_dict,
};

View File

@ -0,0 +1,46 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Michael Schroeder
*
* 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.
*/
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO_FREQUENCYIN_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO_FREQUENCYIN_H
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/frequencyio/FrequencyIn.h"
extern const mp_obj_type_t frequencyio_frequencyin_type;
extern void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t *self,
const mcu_pin_obj_t *pin, uint16_t capture_period);
extern void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t *self);
extern bool common_hal_frequencyio_frequencyin_deinited(frequencyio_frequencyin_obj_t *self);
extern void common_hal_frequencyio_frequencyin_pause(frequencyio_frequencyin_obj_t *self);
extern void common_hal_frequencyio_frequencyin_resume(frequencyio_frequencyin_obj_t *self);
extern void common_hal_frequencyio_frequencyin_clear(frequencyio_frequencyin_obj_t *self);
extern uint32_t common_hal_frequencyio_frequencyin_get_item(frequencyio_frequencyin_obj_t *self);
extern uint16_t common_hal_frequencyio_frequencyin_get_capture_period(frequencyio_frequencyin_obj_t *self);
extern void common_hal_frequencyio_frequencyin_set_capture_period(frequencyio_frequencyin_obj_t *self, uint16_t capture_period);
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO_FREQUENCYIN_H

View File

@ -0,0 +1,89 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Michael Schroeder
*
* 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/microcontroller/Pin.h"
#include "shared-bindings/frequencyio/__init__.h"
#include "shared-bindings/frequencyio/FrequencyIn.h"
//| :mod:`frequencyio` --- Support for frequency based protocols
//| =============================================================
//|
//| .. module:: frequencyio
//| :synopsis: Support for frequency based protocols
//| :platform: SAMD51
//|
//| The `frequencyio` module contains classes to provide access to basic frequency IO.
//|
//| Libraries
//|
//| .. toctree::
//| :maxdepth: 3
//|
//| FrequencyIn
//|
//| .. warning:: This module is not available in SAMD21 builds. See the
//| :ref:`module-support-matrix` for more info.
//|
//| All classes change hardware state and should be deinitialized when they
//| are no longer needed if the program continues after use. To do so, either
//| call :py:meth:`!deinit` or use a context manager. See
//| :ref:`lifetime-and-contextmanagers` for more info.
//|
//| For example::
//|
//| import frequencyio
//| import time
//| from board import *
//|
//| frequency = frequencyio.FrequencyIn(D13)
//| frequency.capture_period = 15
//| time.sleep(0.1)
//|
//| This example will initialize the the device, set
//| :py:data:`~frequencyio.FrequencyIn.capture_period`, and then sleep 0.1 seconds.
//| CircuitPython will automatically turn off FrequencyIn capture when it resets all
//| hardware after program completion. Use ``deinit()`` or a ``with`` statement
//| to do it yourself.
//|
STATIC const mp_rom_map_elem_t frequencyio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_frequencyio) },
{ MP_ROM_QSTR(MP_QSTR_FrequencyIn), MP_ROM_PTR(&frequencyio_frequencyin_type) },
};
STATIC MP_DEFINE_CONST_DICT(frequencyio_module_globals, frequencyio_module_globals_table);
const mp_obj_module_t frequencyio_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&frequencyio_module_globals,
};

View File

@ -0,0 +1,34 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Michael Schroeder
*
* 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.
*/
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO___INIT___H
#include "py/obj.h"
// Nothing now.
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO___INIT___H

View File

@ -42,6 +42,7 @@ Module Supported Ports
`bleio` **nRF**
`busio` **All Supported**
`digitalio` **All Supported**
`frequencyio` **SAMD51**
`gamepad` **SAMD Express, nRF**
`hashlib` **ESP8266**
`i2cslave` **SAMD Express**

View File

@ -54,10 +54,12 @@
//|
//| This is the CircuitPython analog to the UNIX ``mount`` command.
//|
//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
//|
mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_readonly };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_false} },
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// parse args
@ -77,7 +79,7 @@ mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
mp_raise_ValueError(translate("filesystem must provide mount method"));
}
common_hal_storage_mount(vfs_obj, mnt_str, mp_obj_is_true(args[ARG_readonly].u_obj));
common_hal_storage_mount(vfs_obj, mnt_str, args[ARG_readonly].u_bool);
return mp_const_none;
}
@ -101,14 +103,21 @@ mp_obj_t storage_umount(mp_obj_t mnt_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(storage_umount_obj, storage_umount);
//| .. function:: remount(mount_path, readonly=False)
//| .. function:: remount(mount_path, readonly=False, *, disable_concurrent_write_protection=False)
//|
//| Remounts the given path with new parameters.
//|
//| :param bool readonly: True when the filesystem should be readonly to CircuitPython.
//| :param bool disable_concurrent_write_protection: When True, the check that makes sure the
//| underlying filesystem data is written by one computer is disabled. Disabling the protection
//| allows CircuitPython and a host to write to the same filesystem with the risk that the
//| filesystem will be corrupted.
//|
mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_readonly };
enum { ARG_readonly, ARG_disable_concurrent_write_protection };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_readonly, MP_ARG_BOOL | MP_ARG_REQUIRED, {.u_bool = false} },
{ MP_QSTR_readonly, MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_disable_concurrent_write_protection, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// get the mount point
@ -118,7 +127,7 @@ mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
common_hal_storage_remount(mnt_str, args[ARG_readonly].u_bool);
common_hal_storage_remount(mnt_str, args[ARG_readonly].u_bool, args[ARG_disable_concurrent_write_protection].u_bool);
return mp_const_none;
}

View File

@ -33,7 +33,7 @@
void common_hal_storage_mount(mp_obj_t vfs_obj, const char* path, bool readonly);
void common_hal_storage_umount_path(const char* path);
void common_hal_storage_umount_object(mp_obj_t vfs_obj);
void common_hal_storage_remount(const char* path, bool readonly);
void common_hal_storage_remount(const char* path, bool readonly, bool disable_concurrent_write_protection);
mp_obj_t common_hal_storage_getmount(const char* path);
void common_hal_storage_erase_filesystem(void);

125
shared-module/_pew/PewPew.c Normal file
View File

@ -0,0 +1,125 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Radomir Dopieralski
*
* 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 <stdbool.h>
#include "py/mpstate.h"
#include "py/runtime.h"
#include "__init__.h"
#include "PewPew.h"
#include "shared-bindings/digitalio/Pull.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/util.h"
#include "samd/timers.h"
#include "supervisor/shared/translate.h"
#include "timer_handler.h"
static uint8_t pewpew_tc_index = 0xff;
void pewpew_interrupt_handler(uint8_t index) {
if (index != pewpew_tc_index) {
return;
}
Tc* tc = tc_insts[index];
if (!tc->COUNT16.INTFLAG.bit.MC0) {
return;
}
pew_tick();
// Clear the interrupt bit.
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
}
void pew_init() {
pew_obj_t* pew = MP_STATE_VM(pew_singleton);
common_hal_digitalio_digitalinout_switch_to_input(pew->buttons, PULL_UP);
for (size_t i = 0; i < pew->rows_size; ++i) {
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pew->rows[i]);
common_hal_digitalio_digitalinout_switch_to_output(pin, false,
DRIVE_MODE_PUSH_PULL);
}
for (size_t i = 0; i < pew->cols_size; ++i) {
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pew->cols[i]);
common_hal_digitalio_digitalinout_switch_to_output(pin, true,
DRIVE_MODE_OPEN_DRAIN);
}
if (pewpew_tc_index == 0xff) {
// Find a spare timer.
uint8_t index = find_free_timer();
if (index == 0xff) {
mp_raise_RuntimeError(translate(""));
}
Tc *tc = tc_insts[index];
pewpew_tc_index = index;
set_timer_handler(true, index, TC_HANDLER_PEW);
// We use GCLK0 for SAMD21 and GCLK1 for SAMD51 because they both run
// at 48mhz making our math the same across the boards.
#ifdef SAMD21
turn_on_clocks(true, index, 0);
#endif
#ifdef SAMD51
turn_on_clocks(true, index, 1);
#endif
#ifdef SAMD21
tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
TC_CTRLA_PRESCALER_DIV64 |
TC_CTRLA_WAVEGEN_MFRQ;
#endif
#ifdef SAMD51
tc_reset(tc);
tc_set_enable(tc, false);
tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16
| TC_CTRLA_PRESCALER_DIV64;
tc->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
#endif
tc_set_enable(tc, true);
tc->COUNT16.CC[0].reg = 160;
// Clear our interrupt in case it was set earlier
tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0;
tc->COUNT16.INTENSET.reg = TC_INTENSET_MC0;
tc_enable_interrupts(pewpew_tc_index);
}
}
void pew_reset(void) {
if (pewpew_tc_index != 0xff) {
tc_reset(tc_insts[pewpew_tc_index]);
pewpew_tc_index = 0xff;
}
MP_STATE_VM(pew_singleton) = NULL;
}

View File

@ -0,0 +1,48 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Radomir Dopieralski
*
* 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.
*/
#ifndef MICROPY_INCLUDED_PEW_PEWPEW_H
#define MICROPY_INCLUDED_PEW_PEWPEW_H
#include <stdint.h>
#include "shared-bindings/digitalio/DigitalInOut.h"
typedef struct {
mp_obj_base_t base;
uint8_t* buffer;
mp_obj_t* rows;
mp_obj_t* cols;
digitalio_digitalinout_obj_t *buttons;
uint8_t rows_size;
uint8_t cols_size;
uint8_t pressed;
} pew_obj_t;
void pew_init(void);
void pewpew_interrupt_handler(uint8_t index);
void pew_reset(void);
#endif // MICROPY_INCLUDED_PEW_PEWPEW_H

View File

@ -0,0 +1,85 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Radomir Dopieralski
*
* 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 <stdbool.h>
#include "py/mpstate.h"
#include "__init__.h"
#include "PewPew.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
void pew_tick(void) {
static uint8_t col = 0;
static uint8_t turn = 0;
static uint8_t pressed = 0;
static uint8_t last_pressed = 0;
digitalio_digitalinout_obj_t *pin;
pew_obj_t* pew = MP_STATE_VM(pew_singleton);
if (!pew) { return; }
pin = MP_OBJ_TO_PTR(pew->cols[col]);
++col;
if (col >= pew->cols_size) {
pew->pressed |= last_pressed & pressed;
last_pressed = pressed;
pressed = 0;
col = 0;
++turn;
if (turn >= 8) {
turn = 0;
}
}
if (!common_hal_digitalio_digitalinout_get_value(pew->buttons)) {
pressed |= 1 << col;
}
common_hal_digitalio_digitalinout_set_value(pin, true);
for (size_t x = 0; x < pew->rows_size; ++x) {
pin = MP_OBJ_TO_PTR(pew->rows[x]);
uint8_t color = pew->buffer[col * (pew->rows_size) + x];
bool value = false;
switch (color & 0x03) {
case 3:
value = true;
break;
case 2:
if (turn == 2 || turn == 4 || turn == 6) {
value = true;
}
case 1:
if (turn == 0) {
value = true;
}
case 0:
break;
}
common_hal_digitalio_digitalinout_set_value(pin, value);
}
pin = MP_OBJ_TO_PTR(pew->cols[col]);
common_hal_digitalio_digitalinout_set_value(pin, false);
}

View File

@ -0,0 +1,32 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Radomir Dopieralski
*
* 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.
*/
#ifndef MICROPY_INCLUDED_PEW_H
#define MICROPY_INCLUDED_PEW_H
void pew_tick(void);
#endif // MICROPY_INCLUDED_PEW_H

View File

@ -69,7 +69,11 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
self->bus = bus;
uint32_t i = 0;
self->begin_transaction(self->bus);
while (!self->begin_transaction(self->bus)) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP ;
#endif
}
while (i < init_sequence_len) {
uint8_t *cmd = init_sequence + i;
uint8_t data_size = *(cmd + 1);
@ -121,7 +125,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
// Always set the backlight type in case we're reusing memory.
self->backlight_inout.base.type = &mp_type_NoneType;
if (backlight_pin != NULL && common_hal_mcu_pin_is_free(backlight_pin)) {
pwmout_result_t result = common_hal_pulseio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 5000, false);
pwmout_result_t result = common_hal_pulseio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 50000, false);
if (result != PWMOUT_OK) {
self->backlight_inout.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin);
@ -147,7 +151,8 @@ void common_hal_displayio_display_refresh_soon(displayio_display_obj_t* self) {
int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* self) {
uint64_t last_refresh = self->last_refresh;
while (last_refresh == self->last_refresh) {
// Don't try to refresh if we got an exception.
while (last_refresh == self->last_refresh && MP_STATE_VM(mp_pending_exception) == NULL) {
MICROPY_VM_HOOK_LOOP
}
return 0;
@ -157,6 +162,14 @@ bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* s
return self->auto_brightness;
}
uint16_t common_hal_displayio_display_get_width(displayio_display_obj_t* self){
return self->width;
}
uint16_t common_hal_displayio_display_get_height(displayio_display_obj_t* self){
return self->height;
}
void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness) {
self->auto_brightness = auto_brightness;
}
@ -189,9 +202,16 @@ bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self,
return ok;
}
void displayio_display_start_region_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
bool displayio_display_begin_transaction(displayio_display_obj_t* self) {
return self->begin_transaction(self->bus);
}
void displayio_display_end_transaction(displayio_display_obj_t* self) {
self->end_transaction(self->bus);
}
void displayio_display_set_region_to_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
// TODO(tannewt): Handle displays with single byte bounds.
self->begin_transaction(self->bus);
uint16_t data[2];
self->send(self->bus, true, &self->set_column_command, 1);
data[0] = __builtin_bswap16(x0 + self->colstart);
@ -204,10 +224,6 @@ void displayio_display_start_region_update(displayio_display_obj_t* self, uint16
self->send(self->bus, true, &self->write_ram_command, 1);
}
void displayio_display_finish_region_update(displayio_display_obj_t* self) {
self->end_transaction(self->bus);
}
bool displayio_display_frame_queued(displayio_display_obj_t* self) {
// Refresh at ~30 fps.
return (ticks_ms - self->last_refresh) > 32;
@ -225,9 +241,8 @@ void displayio_display_finish_refresh(displayio_display_obj_t* self) {
self->last_refresh = ticks_ms;
}
bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
void displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixels, uint32_t length) {
self->send(self->bus, false, (uint8_t*) pixels, length * 4);
return true;
}
void displayio_display_update_backlight(displayio_display_obj_t* self) {

View File

@ -38,13 +38,13 @@ static uint32_t read_word(uint16_t* bmp_header, uint16_t index) {
void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, pyb_file_obj_t* file) {
// Load the wave
self->file = file;
uint16_t bmp_header[24];
uint16_t bmp_header[69];
f_rewind(&self->file->fp);
UINT bytes_read;
if (f_read(&self->file->fp, bmp_header, 48, &bytes_read) != FR_OK) {
if (f_read(&self->file->fp, bmp_header, 138, &bytes_read) != FR_OK) {
mp_raise_OSError(MP_EIO);
}
if (bytes_read != 48 ||
if (bytes_read != 138 ||
memcmp(bmp_header, "BM", 2) != 0) {
mp_raise_ValueError(translate("Invalid BMP file"));
}
@ -53,25 +53,68 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self,
self->data_offset = read_word(bmp_header, 5);
uint32_t header_size = read_word(bmp_header, 7);
uint32_t compression = read_word(bmp_header, 15);
if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124) ||
!(compression == 0)) {
mp_raise_ValueError_varg(translate("Only Windows format, uncompressed BMP supported %d"), header_size);
}
// TODO(tannewt): Support bitfield compressed colors since RGB565 can be produced by the GIMP.
uint16_t bits_per_pixel = bmp_header[14];
if (bits_per_pixel < 24) {
mp_raise_ValueError_varg(translate("Only true color (24 bpp or higher) BMP supported %x"), bits_per_pixel);
}
self->bytes_per_pixel = bits_per_pixel / 8;
uint32_t compression = read_word(bmp_header, 15);
uint32_t number_of_colors = read_word(bmp_header, 23);
bool indexed = ((bits_per_pixel <= 8) && (number_of_colors != 0));
self->bitfield_compressed = (compression == 3);
self->bits_per_pixel = bits_per_pixel;
self->width = read_word(bmp_header, 9);
self->height = read_word(bmp_header, 11);
uint32_t byte_width = self->width * self->bytes_per_pixel;
self->stride = byte_width;
// Rows are word aligned.
if (self->stride % 4 != 0) {
self->stride += 4 - self->stride % 4;
if (bits_per_pixel == 16){
if (((header_size >= 56)) || (self->bitfield_compressed)) {
self->r_bitmask = read_word(bmp_header, 27);
self->g_bitmask = read_word(bmp_header, 29);
self->b_bitmask = read_word(bmp_header, 31);
} else { // no compression or short header means 5:5:5
self->r_bitmask = 0x7c00;
self->g_bitmask = 0x3e0;
self->b_bitmask = 0x1f;
}
} else if ((indexed) && (self->bits_per_pixel != 1)) {
uint16_t palette_size = number_of_colors * sizeof(uint32_t);
uint16_t palette_offset = 0xe + header_size;
self->palette_data = m_malloc(palette_size, false);
f_rewind(&self->file->fp);
f_lseek(&self->file->fp, palette_offset);
UINT palette_bytes_read;
if (f_read(&self->file->fp, self->palette_data, palette_size, &palette_bytes_read) != FR_OK) {
mp_raise_OSError(MP_EIO);
}
if (palette_bytes_read != palette_size) {
mp_raise_ValueError(translate("Unable to read color palette data"));
}
} else if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124)) {
mp_raise_ValueError_varg(translate("Only Windows format, uncompressed BMP supported: given header size is %d"), header_size);
}
if ((bits_per_pixel == 4 ) || (( bits_per_pixel == 8) && (number_of_colors == 0))) {
mp_raise_ValueError_varg(translate("Only monochrome, indexed 8bpp, and 16bpp or greater BMPs supported: %d bpp given"), bits_per_pixel);
}
if (self->bits_per_pixel >=8){
self->stride = (self->width * (bits_per_pixel / 8));
// Rows are word aligned.
if (self->stride % 4 != 0) {
self->stride += 4 - self->stride % 4;
}
} else {
uint32_t bit_stride = self->width;
if (bit_stride % 32 != 0) {
bit_stride += 32 - bit_stride % 32;
}
self->stride = (bit_stride / 8);
}
}
@ -80,14 +123,54 @@ uint32_t common_hal_displayio_ondiskbitmap_get_pixel(displayio_ondiskbitmap_t *s
if (x < 0 || x >= self->width || y < 0 || y >= self->height) {
return 0;
}
uint32_t location = self->data_offset + (self->height - y) * self->stride + x * self->bytes_per_pixel;
uint32_t location;
uint8_t bytes_per_pixel = (self->bits_per_pixel / 8) ? (self->bits_per_pixel /8) : 1;
if (self->bits_per_pixel >= 8){
location = self->data_offset + (self->height - y) * self->stride + x * bytes_per_pixel;
} else {
location = self->data_offset + (self->height - y) * self->stride + x / 8;
}
// We don't cache here because the underlying FS caches sectors.
f_lseek(&self->file->fp, location);
UINT bytes_read;
uint32_t pixel = 0;
uint32_t result = f_read(&self->file->fp, &pixel, self->bytes_per_pixel, &bytes_read);
uint32_t pixel_data = 0;
uint32_t result = f_read(&self->file->fp, &pixel_data, bytes_per_pixel, &bytes_read);
if (result == FR_OK) {
return pixel;
uint32_t tmp = 0;
uint8_t red;
uint8_t green;
uint8_t blue;
if (self->bits_per_pixel == 1){
uint8_t bit_offset = x%8;
tmp = ( pixel_data & (0x80 >> (bit_offset))) >> (7 - bit_offset);
if (tmp == 1) {
return 0x00FFFFFF;
} else {
return 0x00000000;
}
} else if (bytes_per_pixel == 1){
blue = ((self->palette_data[pixel_data] & 0xFF) >> 0);
red = ((self->palette_data[pixel_data] & 0xFF0000) >> 16);
green = ((self->palette_data[pixel_data] & 0xFF00) >> 8);
tmp = (red << 16 | green << 8 | blue );
return tmp;
} else if (bytes_per_pixel == 2) {
if (self->g_bitmask == 0x07e0) { // 565
red =((pixel_data & self->r_bitmask) >>11);
green = ((pixel_data & self->g_bitmask) >>5);
blue = ((pixel_data & self->b_bitmask) >> 0);
} else { // 555
red =((pixel_data & self->r_bitmask) >>10);
green = ((pixel_data & self->g_bitmask) >>4);
blue = ((pixel_data & self->b_bitmask) >> 0);
}
tmp = (red << 19 | green << 10 | blue << 3);
return tmp;
} else if ((bytes_per_pixel == 4) && (self->bitfield_compressed)) {
return pixel_data & 0x00FFFFFF;
} else {
return pixel_data;
}
}
return 0;
}

View File

@ -40,8 +40,13 @@ typedef struct {
uint16_t height;
uint16_t data_offset;
uint16_t stride;
uint32_t r_bitmask;
uint32_t g_bitmask;
uint32_t b_bitmask;
bool bitfield_compressed;
pyb_file_obj_t* file;
uint8_t bytes_per_pixel;
uint8_t bits_per_pixel;
uint32_t* palette_data;
} displayio_ondiskbitmap_t;
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_ONDISKBITMAP_H

View File

@ -2,7 +2,9 @@
#include <string.h>
#include "shared-module/displayio/__init__.h"
#include "lib/utils/interrupt_char.h"
#include "py/reload.h"
#include "py/runtime.h"
#include "shared-bindings/displayio/Bitmap.h"
#include "shared-bindings/displayio/Display.h"
#include "shared-bindings/displayio/Group.h"
@ -20,29 +22,39 @@ static inline void swap(uint16_t* a, uint16_t* b) {
*b = temp;
}
bool refreshing_displays = false;
// Check for recursive calls to displayio_refresh_displays.
bool refresh_displays_in_progress = false;
void displayio_refresh_displays(void) {
if (mp_hal_is_interrupted()) {
return;
}
// Somehow reloads from the sdcard are being lost. So, cheat and reraise.
if (reload_requested) {
// But don't re-raise if already pending.
if (reload_requested && MP_STATE_VM(mp_pending_exception) == MP_OBJ_NULL) {
mp_raise_reload_exception();
return;
}
if (refreshing_displays) {
if (refresh_displays_in_progress) {
// Don't allow recursive calls to this routine.
return;
}
refreshing_displays = true;
refresh_displays_in_progress = true;
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].display.base.type == NULL || displays[i].display.base.type == &mp_type_NoneType) {
// Skip null display.
continue;
}
displayio_display_obj_t* display = &displays[i].display;
displayio_display_update_backlight(display);
// Time to refresh at specified frame rate?
if (!displayio_display_frame_queued(display)) {
refreshing_displays = false;
return;
// Too soon. Try next display.
continue;
}
if (displayio_display_refresh_queued(display)) {
// We compute the pixels. r and c are row and column to match the display memory
@ -54,7 +66,13 @@ void displayio_refresh_displays(void) {
if (display->transpose_xy) {
swap(&c1, &r1);
}
displayio_display_start_region_update(display, c0, r0, c1, r1);
if (!displayio_display_begin_transaction(display)) {
// Can't acquire display bus; skip updating this display. Try next display.
continue;
}
displayio_display_set_region_to_update(display, c0, r0, c1, r1);
displayio_display_end_transaction(display);
uint16_t x0 = 0;
uint16_t x1 = display->width - 1;
@ -88,6 +106,8 @@ void displayio_refresh_displays(void) {
size_t index = 0;
uint16_t buffer_size = 256;
uint32_t buffer[buffer_size / 2];
bool skip_this_display = false;
for (uint16_t y = starty; y0 <= y && y <= y1; y += dy) {
for (uint16_t x = startx; x0 <= x && x <= x1; x += dx) {
uint16_t* pixel = &(((uint16_t*)buffer)[index]);
@ -104,11 +124,14 @@ void displayio_refresh_displays(void) {
index += 1;
// The buffer is full, send it.
if (index >= buffer_size) {
if (!displayio_display_send_pixels(display, buffer, buffer_size / 2) || reload_requested) {
displayio_display_finish_region_update(display);
refreshing_displays = false;
return;
if (!displayio_display_begin_transaction(display)) {
// Can't acquire display bus; skip the rest of the data. Try next display.
index = 0;
skip_this_display = true;
break;
}
displayio_display_send_pixels(display, buffer, buffer_size / 2);
displayio_display_end_transaction(display);
// TODO(tannewt): Make refresh displays faster so we don't starve other
// background tasks.
usb_background();
@ -116,17 +139,26 @@ void displayio_refresh_displays(void) {
}
}
}
// Send the remaining data.
if (index && !displayio_display_send_pixels(display, buffer, index * 2)) {
displayio_display_finish_region_update(display);
refreshing_displays = false;
return;
if (skip_this_display) {
// Go on to next display.
continue;
}
displayio_display_finish_region_update(display);
// Send the remaining data.
if (index) {
if (!displayio_display_begin_transaction(display)) {
// Can't get display bus. Skip the rest of the data. Try next display.
continue;
}
displayio_display_send_pixels(display, buffer, index * 2);
}
displayio_display_end_transaction(display);
}
displayio_display_finish_refresh(display);
}
refreshing_displays = false;
// All done.
refresh_displays_in_progress = false;
}
void common_hal_displayio_release_displays(void) {

Some files were not shown because too many files have changed in this diff Show More