diff options
Diffstat (limited to 'ports/esp32s2')
33 files changed, 1287 insertions, 42 deletions
diff --git a/ports/esp32s2/Makefile b/ports/esp32s2/Makefile index f33a1d2eb..aac934782 100644 --- a/ports/esp32s2/Makefile +++ b/ports/esp32s2/Makefile @@ -299,6 +299,8 @@ ESP_AUTOGEN_LD = $(BUILD)/esp-idf/esp-idf/esp32s2/esp32s2_out.ld $(BUILD)/esp-id FLASH_FLAGS = --flash_mode $(CIRCUITPY_ESP_FLASH_MODE) --flash_freq $(CIRCUITPY_ESP_FLASH_FREQ) --flash_size $(CIRCUITPY_ESP_FLASH_SIZE) +ESPTOOL_FLAGS ?= -b 460800 --before=default_reset --after=no_reset + all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 .PHONY: esp-idf-stamp @@ -337,10 +339,10 @@ $(BUILD)/firmware.uf2: $(BUILD)/circuitpython-firmware.bin $(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xbfdd4eee -b 0x0000 -c -o $@ $^ flash: $(BUILD)/firmware.bin - esptool.py --chip esp32s2 -p $(PORT) -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x0000 $^ + esptool.py --chip esp32s2 -p $(PORT) $(ESPTOOL_FLAGS) write_flash $(FLASH_FLAGS) 0x0000 $^ flash-circuitpython-only: $(BUILD)/circuitpython-firmware.bin - esptool.py --chip esp32s2 -p $(PORT) -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x10000 $^ + esptool.py --chip esp32s2 -p $(PORT) $(ESPTOOL_FLAGS) write_flash $(FLASH_FLAGS) 0x10000 $^ include $(TOP)/py/mkrules.mk diff --git a/ports/esp32s2/bindings/espidf/__init__.c b/ports/esp32s2/bindings/espidf/__init__.c index 554bfaa39..708c30c39 100644 --- a/ports/esp32s2/bindings/espidf/__init__.c +++ b/ports/esp32s2/bindings/espidf/__init__.c @@ -65,12 +65,12 @@ STATIC mp_obj_t espidf_heap_caps_get_largest_free_block(void) { } MP_DEFINE_CONST_FUN_OBJ_0(espidf_heap_caps_get_largest_free_block_obj, espidf_heap_caps_get_largest_free_block); -//| class MemoryError(MemoryError): -//| """Raised when an ESP IDF memory allocation fails.""" +//| class IDFError(OSError): +//| """Raised for certain generic ESP IDF errors.""" //| ... //| -NORETURN void mp_raise_espidf_MemoryError(void) { - nlr_raise(mp_obj_new_exception(&mp_type_espidf_MemoryError)); +NORETURN void mp_raise_espidf_IDFError(void) { + nlr_raise(mp_obj_new_exception(&mp_type_espidf_IDFError)); } void espidf_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { @@ -83,6 +83,24 @@ void espidf_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin mp_obj_exception_print(print, o_in, kind); } +const mp_obj_type_t mp_type_espidf_IDFError = { + { &mp_type_type }, + .name = MP_QSTR_IDFError, + .print = espidf_exception_print, + .make_new = mp_obj_exception_make_new, + .attr = mp_obj_exception_attr, + .parent = &mp_type_OSError, +}; + + +//| class MemoryError(MemoryError): +//| """Raised when an ESP IDF memory allocation fails.""" +//| ... +//| +NORETURN void mp_raise_espidf_MemoryError(void) { + nlr_raise(mp_obj_new_exception(&mp_type_espidf_MemoryError)); +} + const mp_obj_type_t mp_type_espidf_MemoryError = { { &mp_type_type }, .name = MP_QSTR_MemoryError, @@ -99,6 +117,7 @@ STATIC const mp_rom_map_elem_t espidf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_heap_caps_get_free_size), MP_ROM_PTR(&espidf_heap_caps_get_free_size_obj)}, { MP_ROM_QSTR(MP_QSTR_heap_caps_get_largest_free_block), MP_ROM_PTR(&espidf_heap_caps_get_largest_free_block_obj)}, + { MP_ROM_QSTR(MP_QSTR_IDFError), MP_ROM_PTR(&mp_type_espidf_IDFError) }, { MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_espidf_MemoryError) }, }; @@ -108,3 +127,64 @@ const mp_obj_module_t espidf_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&espidf_module_globals, }; + +void raise_esp_error(esp_err_t err) { + const compressed_string_t *msg = NULL; + const mp_obj_type_t * exception_type = &mp_type_espidf_IDFError; + switch(err) { + case ESP_FAIL: + msg = translate("Generic Failure"); + break; + case ESP_ERR_NO_MEM: + exception_type = &mp_type_espidf_MemoryError; + msg = translate("Out of memory"); + break; + case ESP_ERR_INVALID_ARG: + msg = translate("Invalid argument"); + break; + case ESP_ERR_INVALID_STATE: + msg = translate("Invalid state"); + break; + case ESP_ERR_INVALID_SIZE: + msg = translate("Invalid size"); + break; + case ESP_ERR_NOT_FOUND: + msg = translate("Requested resource not found"); + break; + case ESP_ERR_NOT_SUPPORTED: + msg = translate("Operation or feature not supported"); + break; + case ESP_ERR_TIMEOUT: + msg = translate("Operation timed out"); + break; + case ESP_ERR_INVALID_RESPONSE: + msg = translate("Received response was invalid"); + break; + case ESP_ERR_INVALID_CRC: + msg = translate("CRC or checksum was invalid"); + break; + case ESP_ERR_INVALID_VERSION: + msg = translate("Version was invalid"); + break; + case ESP_ERR_INVALID_MAC: + msg = translate("MAC address was invalid"); + break; + } + if (msg) { + mp_raise_msg(exception_type, msg); + } + + const char *group = "ESP-IDF"; + + // tests must be in descending order + MP_STATIC_ASSERT( ESP_ERR_FLASH_BASE > ESP_ERR_MESH_BASE ); + MP_STATIC_ASSERT( ESP_ERR_MESH_BASE > ESP_ERR_WIFI_BASE ); + if(err >= ESP_ERR_FLASH_BASE) { + group = "Flash"; + } else if (err >= ESP_ERR_MESH_BASE) { + group = "Mesh"; + } else if (err >= ESP_ERR_WIFI_BASE) { + group = "WiFi"; + } + mp_raise_msg_varg(exception_type, translate("%s error 0x%x"), group, err); +} diff --git a/ports/esp32s2/bindings/espidf/__init__.h b/ports/esp32s2/bindings/espidf/__init__.h index 356c1c814..9248b01ac 100644 --- a/ports/esp32s2/bindings/espidf/__init__.h +++ b/ports/esp32s2/bindings/espidf/__init__.h @@ -27,8 +27,16 @@ #ifndef MICROPY_INCLUDED_ESP32S2_BINDINGS_ESPIDF___INIT___H #define MICROPY_INCLUDED_ESP32S2_BINDINGS_ESPIDF___INIT___H +#include "esp_err.h" +#include "py/mpconfig.h" +#include "py/obj.h" + +extern const mp_obj_type_t mp_type_espidf_IDFError; extern const mp_obj_type_t mp_type_espidf_MemoryError; NORETURN void mp_raise_espidf_MemoryError(void); +void raise_esp_error(esp_err_t err) NORETURN; +#define CHECK_ESP_RESULT(x) do { int res = (x); if(res != ESP_OK) raise_esp_error(res); } while(0) + #endif // MICROPY_INCLUDED_ESP32S2_BINDINGS_ESPIDF___INIT___H diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/board.c b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/board.c new file mode 100644 index 000000000..aaef97c7d --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/board.c @@ -0,0 +1,52 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" + +void board_init(void) { + // USB + common_hal_never_reset_pin(&pin_GPIO19); + common_hal_never_reset_pin(&pin_GPIO20); + + // Debug UART +#ifdef DEBUG + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); +#endif /* DEBUG */ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} + +void board_deinit(void) { +} diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.h b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.h new file mode 100644 index 000000000..9d95e8e43 --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +//Micropython setup + +#define MICROPY_HW_BOARD_NAME "Feather ESP32S2 without PSRAM" +#define MICROPY_HW_MCU_NAME "ESP32S2" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO33) + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n") + +#define AUTORESET_DELAY_MS 500 + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO3) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO37) diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.mk b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.mk new file mode 100644 index 000000000..3290f8cae --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.mk @@ -0,0 +1,22 @@ +USB_VID = 0x239A +USB_PID = 0x80EC +USB_PRODUCT = "Feather ESP32S2 no PSRAM" +USB_MANUFACTURER = "Adafruit" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +# The default queue depth of 16 overflows on release builds, +# so increase it to 32. +CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32 + +CIRCUITPY_ESP_FLASH_MODE=dio +CIRCUITPY_ESP_FLASH_FREQ=40m +CIRCUITPY_ESP_FLASH_SIZE=4MB + +CIRCUITPY_MODULE=wroom + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/pins.c b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/pins.c new file mode 100644 index 000000000..d4704c224 --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/pins.c @@ -0,0 +1,63 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO33) }, + + { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_ROM_QSTR(MP_QSTR_D36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_D37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) }, + + + { MP_ROM_QSTR(MP_QSTR_D38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_D39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/sdkconfig b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/sdkconfig new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/sdkconfig diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/board.c b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/board.c new file mode 100644 index 000000000..c8be18747 --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/board.c @@ -0,0 +1,122 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/displayio/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +/* +displayio_fourwire_obj_t board_display_obj; + +#define DELAY 0x80 + +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 150, // SWRESET + 0x11, 0 | DELAY, 255, // SLPOUT + 0x36, 1, 0x00, // _MADCTL bottom to top refresh in vsync aligned order. + 0x3a, 1, 0x55, // COLMOD - 16bit color + 0x21, 0 | DELAY, 10, // _INVON + 0x13, 0 | DELAY, 10, // _NORON + 0x29, 0 | DELAY, 255, // _DISPON +}; + +*/ + +void board_init(void) { + // USB + common_hal_never_reset_pin(&pin_GPIO19); + common_hal_never_reset_pin(&pin_GPIO20); + + // Debug UART +#ifdef DEBUG + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); +#endif /* DEBUG */ + + /* + busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL); + common_hal_busio_spi_never_reset(spi); + + displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus; + bus->base.type = &displayio_fourwire_type; + common_hal_displayio_fourwire_construct(bus, + spi, + &pin_GPIO40, // TFT_DC Command or data + &pin_GPIO42, // TFT_CS Chip select + &pin_GPIO41, // TFT_RST Reset + 4000000, // Baudrate + 0, // Polarity + 0); // Phase + + displayio_display_obj_t* display = &displays[0].display; + display->base.type = &displayio_display_type; + common_hal_displayio_display_construct(display, + bus, + 240, // Width (after rotation) + 135, // Height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // Color depth + false, // Grayscale + false, // Pixels in a byte share a row. Only used for depth < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command + MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command + 0x37, // set vertical scroll command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO7, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness (ignored) + true, // auto_brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false); // not SH1107 + */ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} + +void board_deinit(void) { +} diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.h b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.h new file mode 100644 index 000000000..9d95e8e43 --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +//Micropython setup + +#define MICROPY_HW_BOARD_NAME "Feather ESP32S2 without PSRAM" +#define MICROPY_HW_MCU_NAME "ESP32S2" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO33) + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n") + +#define AUTORESET_DELAY_MS 500 + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO3) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO37) diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.mk b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.mk new file mode 100644 index 000000000..3ba6f6228 --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.mk @@ -0,0 +1,22 @@ +USB_VID = 0x239A +USB_PID = 0x80EE +USB_PRODUCT = "Feather ESP32S2 TFT no PSRAM" +USB_MANUFACTURER = "Adafruit" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = MPZ + +# The default queue depth of 16 overflows on release builds, +# so increase it to 32. +CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32 + +CIRCUITPY_ESP_FLASH_MODE=dio +CIRCUITPY_ESP_FLASH_FREQ=40m +CIRCUITPY_ESP_FLASH_SIZE=4MB + +CIRCUITPY_MODULE=wroom + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/pins.c b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/pins.c new file mode 100644 index 000000000..7e1a72374 --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/pins.c @@ -0,0 +1,72 @@ +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO33) }, + + { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_ROM_QSTR(MP_QSTR_D36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_D37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) }, + + { MP_ROM_QSTR(MP_QSTR_D38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_D39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/sdkconfig b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/sdkconfig new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/sdkconfig diff --git a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c index 645dc12a1..ff44d9edb 100644 --- a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c +++ b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c @@ -4,7 +4,11 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO18) }, + // Previous name from schematic. { MP_ROM_QSTR(MP_QSTR_AD1), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO17) }, diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c b/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c index d8fd3a0a2..ac08190a5 100644 --- a/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c +++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c @@ -27,6 +27,8 @@ #include "supervisor/board.h" #include "mpconfigboard.h" #include "shared-bindings/microcontroller/Pin.h" +#include "components/driver/include/driver/gpio.h" +#include "components/soc/include/hal/gpio_hal.h" void board_init(void) { // USB @@ -47,6 +49,12 @@ void board_init(void) { common_hal_never_reset_pin(&pin_GPIO30); common_hal_never_reset_pin(&pin_GPIO31); common_hal_never_reset_pin(&pin_GPIO32); + + + // Add LDO2 to never reset list, set to output and enable + common_hal_never_reset_pin(&pin_GPIO21); + gpio_set_direction(pin_GPIO21.number, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(pin_GPIO21.number, true); } bool board_requests_safe_mode(void) { diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h index e100ac118..6b1a0c4aa 100644 --- a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h +++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h @@ -34,8 +34,8 @@ #define AUTORESET_DELAY_MS 500 -// #define MICROPY_HW_APA102_MOSI (&pin_GPIO40) -// #define MICROPY_HW_APA102_SCK (&pin_GPIO45) +#define MICROPY_HW_APA102_MOSI (&pin_GPIO40) +#define MICROPY_HW_APA102_SCK (&pin_GPIO45) #define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 47764a03a..1cec5d4ae 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -92,9 +92,9 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); } - case ESP_SLEEP_WAKEUP_TOUCHPAD: + case ESP_SLEEP_WAKEUP_TOUCHPAD: { return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms); - break; + } case ESP_SLEEP_WAKEUP_UNDEFINED: default: diff --git a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c index 20553877c..3095bc9e8 100644 --- a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c +++ b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c @@ -31,8 +31,8 @@ #include "peripherals/touch.h" #include "supervisor/esp_port.h" +static uint16_t touch_channel_mask; static volatile bool woke_up = false; -static touch_pad_t touch_channel = TOUCH_PAD_MAX; void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { if (pin->touch_channel == TOUCH_PAD_MAX) { @@ -50,14 +50,20 @@ mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(const size_t n_alarms, const mp } } + // Create TouchAlarm object. alarm_touch_touchalarm_obj_t *alarm = m_new_obj(alarm_touch_touchalarm_obj_t); alarm->base.type = &alarm_touch_touchalarm_type; alarm->pin = NULL; + touch_pad_t wake_channel = touch_pad_get_current_meas_channel(); + if (wake_channel == TOUCH_PAD_MAX) { + return alarm; + } + // Map the pin number back to a pin object. for (size_t i = 0; i < mcu_pin_globals.map.used; i++) { const mcu_pin_obj_t* pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value); - if (pin_obj->touch_channel == touch_channel) { + if (pin_obj->touch_channel == wake_channel) { alarm->pin = mcu_pin_globals.map.table[i].value; break; } @@ -83,46 +89,66 @@ void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alar for (size_t i = 0; i < n_alarms; i++) { if (MP_OBJ_IS_TYPE(alarms[i], &alarm_touch_touchalarm_type)) { - if (!touch_alarm_set) { - touch_alarm = MP_OBJ_TO_PTR(alarms[i]); - touch_alarm_set = true; - } else { - mp_raise_ValueError(translate("Only one alarm.touch alarm can be set.")); + if (deep_sleep && touch_alarm_set) { + mp_raise_ValueError(translate("Only one TouchAlarm can be set in deep sleep.")); } + touch_alarm = MP_OBJ_TO_PTR(alarms[i]); + touch_channel_mask |= 1 << touch_alarm->pin->number; + touch_alarm_set = true; } } + if (!touch_alarm_set) { return; } - touch_channel = touch_alarm->pin->touch_channel; - // configure interrupt for pretend to deep sleep // this will be disabled if we actually deep sleep - // intialize touchpad + // reset touch peripheral peripherals_touch_reset(); peripherals_touch_never_reset(true); - peripherals_touch_init(touch_channel); - // wait for touch data to reset - mp_hal_delay_ms(10); + for (uint8_t i = 1; i <= 14; i++) { + if ((touch_channel_mask & 1 << i) != 0) { + touch_pad_t touch_channel = (touch_pad_t)i; + // intialize touchpad + peripherals_touch_init(touch_channel); - // configure trigger threshold - uint32_t touch_value; - touch_pad_read_benchmark(touch_channel, &touch_value); - touch_pad_set_thresh(touch_channel, touch_value * 0.1); //10% + // wait for touch data to reset + mp_hal_delay_ms(10); + + // configure trigger threshold + uint32_t touch_value; + touch_pad_read_benchmark(touch_channel, &touch_value); + touch_pad_set_thresh(touch_channel, touch_value * 0.1); //10% + } + } // configure touch interrupt touch_pad_timeout_set(true, SOC_TOUCH_PAD_THRESHOLD_MAX); touch_pad_isr_register(touch_interrupt, NULL, TOUCH_PAD_INTR_MASK_ALL); - touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE | TOUCH_PAD_INTR_MASK_TIMEOUT); + touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); } void alarm_touch_touchalarm_prepare_for_deep_sleep(void) { - // intialize touchpad + if (!touch_channel_mask) { + return; + } + + touch_pad_t touch_channel = TOUCH_PAD_MAX; + for (uint8_t i = 1; i <= 14; i++) { + if ((touch_channel_mask & 1 << i) != 0) { + touch_channel = (touch_pad_t)i; + break; + } + } + + // reset touch peripheral peripherals_touch_never_reset(false); peripherals_touch_reset(); + + // intialize touchpad peripherals_touch_init(touch_channel); // configure touchpad for sleep @@ -148,6 +174,6 @@ bool alarm_touch_touchalarm_woke_us_up(void) { void alarm_touch_touchalarm_reset(void) { woke_up = false; - touch_channel = TOUCH_PAD_MAX; + touch_channel_mask = 0; peripherals_touch_never_reset(false); } diff --git a/ports/esp32s2/common-hal/audiobusio/I2SOut.c b/ports/esp32s2/common-hal/audiobusio/I2SOut.c new file mode 100644 index 000000000..86322be86 --- /dev/null +++ b/ports/esp32s2/common-hal/audiobusio/I2SOut.c @@ -0,0 +1,126 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdint.h> +#include <string.h> + +#include "mpconfigport.h" + +#include "bindings/espidf/__init__.h" + +// Some boards don't implement I2SOut, so suppress any routines from here. +#if CIRCUITPY_AUDIOBUSIO_I2SOUT + +#include "extmod/vfs_fat.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "common-hal/audiobusio/I2SOut.h" +#include "shared-bindings/audiobusio/I2SOut.h" +#include "shared-bindings/audiocore/RawSample.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "supervisor/shared/translate.h" + +#include "driver/i2s.h" + +// Caller validates that pins are free. +void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t* self, + const mcu_pin_obj_t* bit_clock, const mcu_pin_obj_t* word_select, + const mcu_pin_obj_t* data, bool left_justified) { + + port_i2s_allocate_init(&self->peripheral, left_justified); + + i2s_pin_config_t i2s_pin_config = { + .bck_io_num = bit_clock->number, + .ws_io_num = word_select->number, + .data_out_num = data->number, + .data_in_num = I2S_PIN_NO_CHANGE, + }; + CHECK_ESP_RESULT(i2s_set_pin(self->peripheral.instance, &i2s_pin_config)); + self->bit_clock = bit_clock; + self->word_select = word_select; + self->data = data; +} + +bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t* self) { + return self->peripheral.instance == -1; +} + +void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t* self) { + if (common_hal_audiobusio_i2sout_deinited(self)) { + return; + } + + if (self->bit_clock) { + reset_pin_number(self->bit_clock->number); + } + self->bit_clock = NULL; + + if (self->word_select) { + reset_pin_number(self->word_select->number); + } + self->word_select = NULL; + + if (self->data) { + reset_pin_number(self->data->number); + } + self->data = NULL; + + if (self->peripheral.instance >= 0) { + port_i2s_reset_instance(self->peripheral.instance); + } + self->peripheral.instance = -1; +} + +void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t* self, + mp_obj_t sample, bool loop) { + if (common_hal_audiobusio_i2sout_get_playing(self)) { + common_hal_audiobusio_i2sout_stop(self); + } + port_i2s_play(&self->peripheral, sample, loop); +} + +void common_hal_audiobusio_i2sout_pause(audiobusio_i2sout_obj_t* self) { + port_i2s_pause(&self->peripheral); +} + +void common_hal_audiobusio_i2sout_resume(audiobusio_i2sout_obj_t* self) { + port_i2s_resume(&self->peripheral); +} + +bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t* self) { + return port_i2s_paused(&self->peripheral); +} + +void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t* self) { + port_i2s_stop(&self->peripheral); +} + +bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) { + return port_i2s_playing(&self->peripheral); +} + +#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT diff --git a/ports/esp32s2/common-hal/audiobusio/I2SOut.h b/ports/esp32s2/common-hal/audiobusio/I2SOut.h new file mode 100644 index 000000000..891e9af67 --- /dev/null +++ b/ports/esp32s2/common-hal/audiobusio/I2SOut.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "supervisor/background_callback.h" +#include "common-hal/microcontroller/Pin.h" + +#include "common-hal/audiobusio/__init__.h" + +// Some boards don't implement I2SOut, so suppress any routines from here. +#if CIRCUITPY_AUDIOBUSIO_I2SOUT + +typedef struct { + mp_obj_base_t base; + i2s_t peripheral; + const mcu_pin_obj_t *bit_clock; + const mcu_pin_obj_t *word_select; + const mcu_pin_obj_t *data; +} audiobusio_i2sout_obj_t; + +#endif diff --git a/ports/esp32s2/common-hal/audiobusio/PDMIn.c b/ports/esp32s2/common-hal/audiobusio/PDMIn.c new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ports/esp32s2/common-hal/audiobusio/PDMIn.c diff --git a/ports/esp32s2/common-hal/audiobusio/PDMIn.h b/ports/esp32s2/common-hal/audiobusio/PDMIn.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ports/esp32s2/common-hal/audiobusio/PDMIn.h diff --git a/ports/esp32s2/common-hal/audiobusio/__init__.c b/ports/esp32s2/common-hal/audiobusio/__init__.c new file mode 100644 index 000000000..01c77c531 --- /dev/null +++ b/ports/esp32s2/common-hal/audiobusio/__init__.c @@ -0,0 +1,245 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "py/runtime.h" + +#include "common-hal/audiobusio/__init__.h" +#include "bindings/espidf/__init__.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "shared-module/audiocore/__init__.h" + +#define I2S_QUEUE_SIZE (3) + +static i2s_t *i2s_instance[I2S_NUM_MAX]; +static QueueHandle_t i2s_queues[I2S_NUM_MAX]; +static TaskHandle_t i2s_tasks[I2S_NUM_MAX]; + +static int8_t port_i2s_allocate(void) { +#if defined(I2S_NUM_1) + if(!i2s_instance[1]) return 1; +#endif + if(!i2s_instance[0]) return 0; + + mp_raise_RuntimeError(translate("Peripheral in use")); +} + +void port_i2s_reset_instance(int i) { + assert(i >= 0 && i < I2S_NUM_MAX); + if (i2s_tasks[i]) { + vTaskDelete(i2s_tasks[i]); + } + i2s_tasks[i] = NULL; + + (void)i2s_driver_uninstall(i); + i2s_instance[i] = NULL; +} + +void i2s_reset(void) { + for (int i=0; i < I2S_NUM_MAX; i++) { + port_i2s_reset_instance(i); + } +} + +static void i2s_fill_buffer(i2s_t *self) { + if (self->instance < 0 || self->instance >= I2S_NUM_MAX) { + return; + } +#define STACK_BUFFER_SIZE (512) + int16_t signed_samples[STACK_BUFFER_SIZE / sizeof(int16_t)]; + + if (!self->playing || self->paused || !self->sample || self->stopping) { + memset(signed_samples, 0, sizeof(signed_samples)); + + size_t bytes_written = 0; + do { + CHECK_ESP_RESULT(i2s_write(self->instance, signed_samples, sizeof(signed_samples), &bytes_written, 0)); + } while (bytes_written != 0); + return; + } + while (!self->stopping) { + if (self->sample_data == self->sample_end) { + uint32_t sample_buffer_length; + audioio_get_buffer_result_t get_buffer_result = + audiosample_get_buffer(self->sample, false, 0, + &self->sample_data, &sample_buffer_length); + self->sample_end = self->sample_data + sample_buffer_length; + if (get_buffer_result == GET_BUFFER_DONE) { + if (self->loop) { + audiosample_reset_buffer(self->sample, false, 0); + } else { + self->stopping = true; + break; + } + } + if (get_buffer_result == GET_BUFFER_ERROR || sample_buffer_length == 0) { + self->stopping = true; + break; + } + } + size_t bytes_written = 0; + size_t bytecount = self->sample_end - self->sample_data; + if (self->samples_signed && self->channel_count == 2) { + if (self->bytes_per_sample == 2) { + CHECK_ESP_RESULT(i2s_write(self->instance, self->sample_data, bytecount, &bytes_written, 0)); + } else { + CHECK_ESP_RESULT(i2s_write_expand(self->instance, self->sample_data, bytecount, 8, 16, &bytes_written, 0)); + } + } else { + const size_t bytes_per_output_frame = 4; + size_t bytes_per_input_frame = self->channel_count * self->bytes_per_sample; + size_t framecount = MIN(STACK_BUFFER_SIZE / bytes_per_output_frame, bytecount / bytes_per_input_frame); + if (self->samples_signed) { + assert(self->channel_count == 1); + if (self->bytes_per_sample == 1) { + audiosample_convert_s8m_s16s(signed_samples, (int8_t*)(void*)self->sample_data, framecount); + } else { + audiosample_convert_s16m_s16s(signed_samples, (int16_t*)(void*)self->sample_data, framecount); + } + } else { + if (self->channel_count == 1) { + if (self->bytes_per_sample == 1) { + audiosample_convert_u8m_s16s(signed_samples, (uint8_t*)(void*)self->sample_data, framecount); + } else { + audiosample_convert_u16m_s16s(signed_samples, (uint16_t*)(void*)self->sample_data, framecount); + } + } else { + if (self->bytes_per_sample == 1) { + audiosample_convert_u8s_s16s(signed_samples, (uint8_t*)(void*)self->sample_data, framecount); + } else { + audiosample_convert_u16s_s16s(signed_samples, (uint16_t*)(void*)self->sample_data, framecount); + } + } + } + size_t expanded_bytes_written = 0; + CHECK_ESP_RESULT(i2s_write(self->instance, signed_samples, bytes_per_output_frame*framecount, &expanded_bytes_written, 0)); + assert(expanded_bytes_written % 4 == 0); + bytes_written = expanded_bytes_written / bytes_per_output_frame * bytes_per_input_frame; + } + self->sample_data += bytes_written; + // We have filled the DMA buffer + if (!bytes_written) { + break; + } + } +} + +static void i2s_callback_fun(void *self_in) { + i2s_t *self = self_in; + i2s_fill_buffer(self); +} + +static void i2s_event_task(void *self_in) { + i2s_t *self = self_in; + while(true) { + i2s_event_type_t event; + BaseType_t result = xQueueReceive(i2s_queues[self->instance], &event, portMAX_DELAY); + if (result && event == I2S_EVENT_TX_DONE) { + background_callback_add(&self->callback, i2s_callback_fun, self_in); + } + } +} + +void port_i2s_allocate_init(i2s_t *self, bool left_justified) { + self->instance = port_i2s_allocate(); + + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = 44100, + .bits_per_sample = 16, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = left_justified ? I2S_COMM_FORMAT_STAND_I2S : I2S_COMM_FORMAT_STAND_I2S, + .dma_buf_count = 2, + .dma_buf_len = 128, // in _frames_, so 128 is 512 bytes per dma buf + .use_apll = false, + }; + CHECK_ESP_RESULT(i2s_driver_install(self->instance, &i2s_config, I2S_QUEUE_SIZE, &i2s_queues[self->instance])); + + if (!xTaskCreate(i2s_event_task, "I2S_task", 3 * configMINIMAL_STACK_SIZE, self, CONFIG_PTHREAD_TASK_PRIO_DEFAULT, &i2s_tasks[self->instance])) { + mp_raise_OSError_msg(translate("xTaskCreate failed")); + } + i2s_instance[self->instance] = self; + +} + + +void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) { + self->sample = sample; + self->loop = loop; + self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8; + self->channel_count = audiosample_channel_count(sample); + bool single_buffer; + bool samples_signed; + uint32_t max_buffer_length; + uint8_t spacing; + audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, + &max_buffer_length, &spacing); + self->samples_signed = samples_signed; + self->playing = true; + self->paused = false; + self->stopping = false; + self->sample_data = self->sample_end = NULL; + // We always output stereo so output twice as many bits. + // uint16_t bits_per_sample_output = bits_per_sample * 2; + + audiosample_reset_buffer(self->sample, false, 0); + + CHECK_ESP_RESULT(i2s_set_sample_rates(self->instance, audiosample_sample_rate(sample))); + + background_callback_add(&self->callback, i2s_callback_fun, self); +} + +bool port_i2s_playing(i2s_t *self) { + return self->playing && !self->stopping; +} + +bool port_i2s_paused(i2s_t *self) { + return self->paused; +} + +void port_i2s_stop(i2s_t *self) { + self->sample = NULL; + self->paused = false; + self->playing = false; + self->stopping = false; +} + +void port_i2s_pause(i2s_t *self) { + if (!self->paused) { + self->paused = true; + CHECK_ESP_RESULT(i2s_stop(self->instance)); + } +} + +void port_i2s_resume(i2s_t *self) { + if (self->paused) { + self->paused = false; + CHECK_ESP_RESULT(i2s_start(self->instance)); + } +} diff --git a/ports/esp32s2/common-hal/audiobusio/__init__.h b/ports/esp32s2/common-hal/audiobusio/__init__.h new file mode 100644 index 000000000..7709735da --- /dev/null +++ b/ports/esp32s2/common-hal/audiobusio/__init__.h @@ -0,0 +1,61 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include "py/obj.h" + +#include "supervisor/background_callback.h" + +#include "driver/i2s.h" + +typedef struct { + mp_obj_t *sample; + bool left_justified; + bool loop; + bool paused; + bool playing; + bool stopping; + bool samples_signed; + int8_t bytes_per_sample; + int8_t channel_count; + int8_t instance; + uint16_t buffer_length; + uint8_t *sample_data, *sample_end; + i2s_config_t i2s_config; + background_callback_t callback; +} i2s_t; + + +void port_i2s_allocate_init(i2s_t *self, bool left_justified); +void port_i2s_reset_instance(int i); +void i2s_reset(void); +void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop); +void port_i2s_stop(i2s_t *self); +bool port_i2s_playing(i2s_t *self); +bool port_i2s_paused(i2s_t *self); +void port_i2s_pause(i2s_t *self); +void port_i2s_resume(i2s_t *self); diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.c b/ports/esp32s2/common-hal/microcontroller/Pin.c index fca89ce8e..6889720e8 100644 --- a/ports/esp32s2/common-hal/microcontroller/Pin.c +++ b/ports/esp32s2/common-hal/microcontroller/Pin.c @@ -37,13 +37,14 @@ #ifdef MICROPY_HW_NEOPIXEL bool neopixel_in_use; #endif +#ifdef MICROPY_HW_APA102_MOSI +bool apa102_sck_in_use; +bool apa102_mosi_in_use; +#endif STATIC uint32_t never_reset_pins[2]; STATIC uint32_t in_use[2]; -bool apa102_mosi_in_use; -bool apa102_sck_in_use; - STATIC void floating_gpio_reset(gpio_num_t pin_number) { // This is the same as gpio_reset_pin(), but without the pullup. // Note that gpio_config resets the iomatrix to GPIO_FUNC as well. @@ -86,6 +87,20 @@ void reset_pin_number(gpio_num_t pin_number) { return; } #endif + #ifdef MICROPY_HW_APA102_MOSI + if (pin_number == MICROPY_HW_APA102_MOSI->number || + pin_number == MICROPY_HW_APA102_SCK->number) { + apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number; + apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number; + if (!apa102_sck_in_use && !apa102_mosi_in_use) { + rgb_led_status_init(); + } + return; + } + #endif + + + } void common_hal_reset_pin(const mcu_pin_obj_t* pin) { @@ -110,6 +125,11 @@ void reset_all_pins(void) { #ifdef MICROPY_HW_NEOPIXEL neopixel_in_use = false; #endif + #ifdef MICROPY_HW_APA102_MOSI + apa102_sck_in_use = false; + apa102_mosi_in_use = false; + #endif + } void claim_pin(const mcu_pin_obj_t* pin) { @@ -119,6 +139,15 @@ void claim_pin(const mcu_pin_obj_t* pin) { neopixel_in_use = true; } #endif + #ifdef MICROPY_HW_APA102_MOSI + if (pin == MICROPY_HW_APA102_MOSI) { + apa102_mosi_in_use = true; + } + if (pin == MICROPY_HW_APA102_SCK) { + apa102_sck_in_use = true; + } + #endif + } void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin) { @@ -131,10 +160,18 @@ bool pin_number_is_free(gpio_num_t pin_number) { return !neopixel_in_use; } #endif + #ifdef MICROPY_HW_APA102_MOSI + if (pin_number == MICROPY_HW_APA102_MOSI->number) { + return !apa102_mosi_in_use; + } + if (pin_number == MICROPY_HW_APA102_SCK->number) { + return !apa102_sck_in_use; + } + #endif uint8_t offset = pin_number / 32; uint32_t mask = 1 << (pin_number % 32); - return (never_reset_pins[offset] & mask) == 0 && (in_use[offset] & mask) == 0; + return (in_use[offset] & mask) == 0; } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.h b/ports/esp32s2/common-hal/microcontroller/Pin.h index f6c008703..65f57a82d 100644 --- a/ports/esp32s2/common-hal/microcontroller/Pin.h +++ b/ports/esp32s2/common-hal/microcontroller/Pin.h @@ -31,8 +31,10 @@ #include "peripherals/pins.h" -extern bool apa102_mosi_in_use; +#ifdef MICROPY_HW_APA102_MOSI extern bool apa102_sck_in_use; +extern bool apa102_mosi_in_use; +#endif #ifdef MICROPY_HW_NEOPIXEL extern bool neopixel_in_use; diff --git a/ports/esp32s2/common-hal/socketpool/Socket.c b/ports/esp32s2/common-hal/socketpool/Socket.c index 32c5fc72f..5e943f8fd 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.c +++ b/ports/esp32s2/common-hal/socketpool/Socket.c @@ -178,7 +178,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se struct sockaddr_in source_addr; socklen_t socklen = sizeof(source_addr); - int bytes_received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen); + int bytes_received = lwip_recvfrom(self->num, buf, len, 0, (struct sockaddr *)&source_addr, &socklen); memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof source_addr.sin_addr.s_addr); *port = source_addr.sin_port; @@ -186,10 +186,9 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se if (bytes_received < 0) { mp_raise_BrokenPipeError(); return 0; - } else { - buf[bytes_received] = 0; // Null-terminate whatever we received - return bytes_received; } + + return bytes_received; } void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) { diff --git a/ports/esp32s2/common-hal/wifi/Network.c b/ports/esp32s2/common-hal/wifi/Network.c index 2674df065..b6eb6bb43 100644 --- a/ports/esp32s2/common-hal/wifi/Network.c +++ b/ports/esp32s2/common-hal/wifi/Network.c @@ -54,3 +54,37 @@ mp_obj_t common_hal_wifi_network_get_country(wifi_network_obj_t *self) { // 2 instead of strlen(cstr) as this gives us only the country-code return mp_obj_new_str(cstr, 2); } + +mp_obj_t common_hal_wifi_network_get_authmode(wifi_network_obj_t *self) { + const char* authmode = ""; + switch (self->record.authmode) { + case WIFI_AUTH_OPEN: + authmode = "OPEN"; + break; + case WIFI_AUTH_WEP: + authmode = "WEP"; + break; + case WIFI_AUTH_WPA_PSK: + authmode = "WPA_PSK"; + break; + case WIFI_AUTH_WPA2_PSK: + authmode = "WPA2_PSK"; + break; + case WIFI_AUTH_WPA_WPA2_PSK: + authmode = "WPA_WPA2_PSK"; + break; + case WIFI_AUTH_WPA2_ENTERPRISE: + authmode = "WPA2_ENTERPRISE"; + break; + case WIFI_AUTH_WPA3_PSK: + authmode = "WPA3_PSK"; + break; + case WIFI_AUTH_WPA2_WPA3_PSK: + authmode = "WPA2_WPA3_PSK"; + break; + default: + authmode = "UNKNOWN"; + break; + } + return mp_obj_new_str(authmode, strlen(authmode)); +} diff --git a/ports/esp32s2/esp-idf-config/sdkconfig-debug.defaults b/ports/esp32s2/esp-idf-config/sdkconfig-debug.defaults index f45f6ae9f..b108532aa 100644 --- a/ports/esp32s2/esp-idf-config/sdkconfig-debug.defaults +++ b/ports/esp32s2/esp-idf-config/sdkconfig-debug.defaults @@ -10,4 +10,7 @@ CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y # CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT is not set # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set -# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set
\ No newline at end of file +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
\ No newline at end of file diff --git a/ports/esp32s2/esp_error.c b/ports/esp32s2/esp_error.c new file mode 100644 index 000000000..57bc51528 --- /dev/null +++ b/ports/esp32s2/esp_error.c @@ -0,0 +1,91 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "esp_error.h" +#include "py/runtime.h" + +#include "bindings/espidf/__init__.h" + +void raise_esp_error(esp_err_t err) { + const compressed_string_t *msg = NULL; + const mp_obj_type_t * exception_type = &mp_type_espidf_IDFError; + switch(err) { + case ESP_FAIL: + msg = translate("Generic Failure"); + break; + case ESP_ERR_NO_MEM: + exception_type = &mp_type_espidf_MemoryError; + msg = translate("Out of memory"); + break; + case ESP_ERR_INVALID_ARG: + msg = translate("Invalid argument"); + break; + case ESP_ERR_INVALID_STATE: + msg = translate("Invalid state"); + break; + case ESP_ERR_INVALID_SIZE: + msg = translate("Invalid size"); + break; + case ESP_ERR_NOT_FOUND: + msg = translate("Requested resource not found"); + break; + case ESP_ERR_NOT_SUPPORTED: + msg = translate("Operation or feature not supported"); + break; + case ESP_ERR_TIMEOUT: + msg = translate("Operation timed out"); + break; + case ESP_ERR_INVALID_RESPONSE: + msg = translate("Received response was invalid"); + break; + case ESP_ERR_INVALID_CRC: + msg = translate("CRC or checksum was invalid"); + break; + case ESP_ERR_INVALID_VERSION: + msg = translate("Version was invalid"); + break; + case ESP_ERR_INVALID_MAC: + msg = translate("MAC address was invalid"); + break; + } + if (msg) { + mp_raise_msg(exception_type, msg); + } + + const char *group = "ESP-IDF"; + + // tests must be in descending order + MP_STATIC_ASSERT( ESP_ERR_FLASH_BASE > ESP_ERR_MESH_BASE ); + MP_STATIC_ASSERT( ESP_ERR_MESH_BASE > ESP_ERR_WIFI_BASE ); + if(err >= ESP_ERR_FLASH_BASE) { + group = "Flash"; + } else if (err >= ESP_ERR_MESH_BASE) { + group = "Mesh"; + } else if (err >= ESP_ERR_WIFI_BASE) { + group = "WiFi"; + } + mp_raise_msg_varg(exception_type, translate("%s error 0x%x"), group, err); +} diff --git a/ports/esp32s2/mpconfigport.h b/ports/esp32s2/mpconfigport.h index db7393d8e..9c0fd9da3 100644 --- a/ports/esp32s2/mpconfigport.h +++ b/ports/esp32s2/mpconfigport.h @@ -32,6 +32,7 @@ #define MICROPY_PY_UJSON (1) #define MICROPY_USE_INTERNAL_PRINTF (0) +#define MICROPY_PY_SYS_PLATFORM "Espressif ESP32-S2" #include "py/circuitpy_mpconfig.h" diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index 2ad8afb51..562c60998 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -15,7 +15,11 @@ LONGINT_IMPL = MPZ # These modules are implemented in ports/<port>/common-hal: CIRCUITPY_FULL_BUILD = 1 CIRCUITPY_ALARM = 1 -CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOCORE = 1 +CIRCUITPY_AUDIOMP3 = 0 +CIRCUITPY_AUDIOBUSIO = 1 +CIRCUITPY_AUDIOBUSIO_PDMIN = 0 +CIRCUITPY_AUDIOBUSIO_I2SOUT = 1 CIRCUITPY_AUDIOIO = 0 CIRCUITPY_CANIO = 1 CIRCUITPY_COUNTIO = 1 diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index 213473b8d..6491e7430 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -61,6 +61,10 @@ #include "components/soc/soc/esp32s2/include/soc/cache_memory.h" #include "components/soc/soc/esp32s2/include/soc/rtc_cntl_reg.h" +#if CIRCUITPY_AUDIOBUSIO +#include "common-hal/audiobusio/__init__.h" +#endif + #define HEAP_SIZE (48 * 1024) uint32_t* heap; @@ -107,6 +111,20 @@ safe_mode_t port_init(void) { heap = NULL; never_reset_module_internal_pins(); + #if defined(DEBUG) + // debug UART + common_hal_never_reset_pin(&pin_GPIO43); + common_hal_never_reset_pin(&pin_GPIO44); + #endif + + #if defined(DEBUG) || defined(ENABLE_JTAG) + // JTAG + common_hal_never_reset_pin(&pin_GPIO39); + common_hal_never_reset_pin(&pin_GPIO40); + common_hal_never_reset_pin(&pin_GPIO41); + common_hal_never_reset_pin(&pin_GPIO42); + #endif + #ifdef CONFIG_SPIRAM heap = (uint32_t*) (DRAM0_CACHE_ADDRESS_HIGH - CONFIG_SPIRAM_SIZE); heap_size = CONFIG_SPIRAM_SIZE / sizeof(uint32_t); @@ -153,6 +171,10 @@ void reset_port(void) { ps2_reset(); #endif +#if CIRCUITPY_AUDIOBUSIO + i2s_reset(); +#endif + #if CIRCUITPY_PULSEIO esp32s2_peripherals_rmt_reset(); pulsein_reset(); @@ -275,10 +297,14 @@ void port_disable_tick(void) { esp_timer_stop(_tick_timer); } -void sleep_timer_cb(void* arg) { +void port_wake_main_task() { xTaskNotifyGive(circuitpython_task); } +void sleep_timer_cb(void* arg) { + port_wake_main_task(); +} + void port_interrupt_after_ticks(uint32_t ticks) { uint64_t timeout_us = ticks * 1000000ull / 1024; if (esp_timer_start_once(_sleep_timer, timeout_us) != ESP_OK) { |
