diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 86143c8efb..c393afe7d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,6 +75,7 @@ jobs: board: - "arduino_mkr1300" - "arduino_mkrzero" + - "arduino_nano_33_ble" - "arduino_zero" - "bast_pro_mini_m0" - "capablerobot_usbhub" @@ -109,6 +110,7 @@ jobs: - "hallowing_m4_express" - "itsybitsy_m0_express" - "itsybitsy_m4_express" + - "itsybitsy_nrf52840_express" - "kicksat-sprite" - "makerdiary_nrf52840_mdk" - "makerdiary_nrf52840_mdk_usb_dongle" diff --git a/locale/de_DE.po b/locale/de_DE.po index b790e86bdf..971687d19f 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -737,7 +737,7 @@ msgstr "" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c msgid "Frequency captured is above capability. Capture Paused." -msgstr "" +msgstr "Die aufgezeichnete Frequenz liegt über der Leistungsgrenze. Aufnahme angehalten." #: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c #: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c diff --git a/ports/atmel-samd/boards/pyportal_titano/board.c b/ports/atmel-samd/boards/pyportal_titano/board.c index a18bb380bb..828ceebc4e 100644 --- a/ports/atmel-samd/boards/pyportal_titano/board.c +++ b/ports/atmel-samd/boards/pyportal_titano/board.c @@ -74,24 +74,21 @@ uint8_t display_init_sequence[] = { 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01, 0x3a, 1, 0x55, - 0x36, 1, 0x00, + 0x36, 1, 0x60, 0x11, DELAY, 150/5, // Exit Sleep, then delay 150 ms 0x29, DELAY, 50/5 }; void board_init(void) { - busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus; - common_hal_busio_spi_construct(spi, &pin_PA13, &pin_PA12, &pin_PA14); - 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_PB05, // TFT_DC Command or data - &pin_PB06, // TFT_CS Chip select - &pin_PA00, // TFT_RST Reset - 24000000); + displayio_parallelbus_obj_t* bus = &displays[0].parallel_bus; + bus->base.type = &displayio_parallelbus_type; + common_hal_displayio_parallelbus_construct(bus, + &pin_PA16, // Data0 + &pin_PB05, // Command or data + &pin_PB06, // Chip select + &pin_PB09, // Write + &pin_PB04, // Read + &pin_PA00); // Reset displayio_display_obj_t* display = &displays[0].display; display->base.type = &displayio_display_type; @@ -101,7 +98,7 @@ void board_init(void) { 320, // Height 0, // column start 0, // row start - 270, // rotation + 0, // rotation 16, // Color depth false, // grayscale false, // pixels_in_byte_share_row (unused for depths > 8) diff --git a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h index 91c1188108..f2af07371c 100644 --- a/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h +++ b/ports/atmel-samd/boards/pyportal_titano/mpconfigboard.h @@ -3,7 +3,6 @@ #define CIRCUITPY_MCU_FAMILY samd51 - #define MICROPY_HW_LED_STATUS (&pin_PA27) #define MICROPY_HW_NEOPIXEL (&pin_PB22) diff --git a/ports/atmel-samd/boards/pyportal_titano/pins.c b/ports/atmel-samd/boards/pyportal_titano/pins.c index 6bc0a504a4..14699a209d 100644 --- a/ports/atmel-samd/boards/pyportal_titano/pins.c +++ b/ports/atmel-samd/boards/pyportal_titano/pins.c @@ -80,15 +80,6 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, - // TFT control pins - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_LITE), MP_ROM_PTR(&pin_PB31)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_PA12)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_PA13)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MISO), MP_ROM_PTR(&pin_PA14)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_PA00)}, - {MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PB06)}, - {MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PB05)}, - { 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/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index cdc616bbc8..b0e5714a79 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -116,6 +116,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (i2c_m_sync_set_baudrate(&self->i2c_desc, 0, frequency / 1000) != ERR_NONE) { reset_pin_number(sda->number); reset_pin_number(scl->number); + common_hal_busio_i2c_deinit(self); mp_raise_ValueError(translate("Unsupported baudrate")); } diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c index 6dcace21fd..0adb23fc5d 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c @@ -135,6 +135,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, bool variable_frequency) { self->pin = pin; self->variable_frequency = variable_frequency; + self->duty_cycle = duty; if (pin->timer[0].index >= TC_INST_NUM && pin->timer[1].index >= TCC_INST_NUM @@ -322,6 +323,13 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { } extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) { + // Store the unadjusted duty cycle. It turns out the the process of adjusting and calculating + // the duty cycle here and reading it back is lossy - the value will decay over time. + // Track it here so that if frequency is changed we can use this value to recalculate the + // proper duty cycle. + // See https://github.com/adafruit/circuitpython/issues/2086 for more details + self->duty_cycle = duty; + const pin_timer_t* t = self->timer; if (t->is_tc) { uint16_t adjusted_duty = tc_periods[t->index] * duty / 0xffff; @@ -415,7 +423,6 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, break; } } - uint16_t old_duty = common_hal_pulseio_pwmout_get_duty_cycle(self); if (t->is_tc) { Tc* tc = tc_insts[t->index]; uint8_t old_divisor = tc->COUNT16.CTRLA.bit.PRESCALER; @@ -450,7 +457,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, #endif } - common_hal_pulseio_pwmout_set_duty_cycle(self, old_duty); + common_hal_pulseio_pwmout_set_duty_cycle(self, self->duty_cycle); } uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.h b/ports/atmel-samd/common-hal/pulseio/PWMOut.h index eef653bcb2..09abda8196 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.h +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.h @@ -36,6 +36,7 @@ typedef struct { const mcu_pin_obj_t *pin; const pin_timer_t* timer; bool variable_frequency; + uint16_t duty_cycle; } pulseio_pwmout_obj_t; void pwmout_reset(void); diff --git a/ports/cxd56/boards/spresense/mpconfigboard.h b/ports/cxd56/boards/spresense/mpconfigboard.h index b20d006586..0245e20450 100644 --- a/ports/cxd56/boards/spresense/mpconfigboard.h +++ b/ports/cxd56/boards/spresense/mpconfigboard.h @@ -26,7 +26,6 @@ #define MICROPY_HW_BOARD_NAME "SPRESENSE" #define MICROPY_HW_MCU_NAME "CXD5602" -#define MICROPY_PY_SYS_PLATFORM "SPRESENSE" #define DEFAULT_I2C_BUS_SCL (&pin_I2C0_BCK) #define DEFAULT_I2C_BUS_SDA (&pin_I2C0_BDT) diff --git a/ports/cxd56/mpconfigport.h b/ports/cxd56/mpconfigport.h index 91ebfd98f6..df87946b95 100644 --- a/ports/cxd56/mpconfigport.h +++ b/ports/cxd56/mpconfigport.h @@ -27,6 +27,8 @@ #ifndef __INCLUDED_MPCONFIGPORT_H #define __INCLUDED_MPCONFIGPORT_H +#define MICROPY_PY_SYS_PLATFORM "CXD56" + // 64kiB stack #define CIRCUITPY_DEFAULT_STACK_SIZE 0x10000 diff --git a/ports/nrf/boards/arduino_nano_33_ble/README.md b/ports/nrf/boards/arduino_nano_33_ble/README.md new file mode 100644 index 0000000000..42d7a86184 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble/README.md @@ -0,0 +1,27 @@ +# Arduino Nano 33 BLE and Nano 33 BLE Sense + +The [Arduino Nano 33 BLE](https://store.arduino.cc/usa/nano-33-ble-with-headers) and +[Arduino Nano 33 BLE Sense](https://store.arduino.cc/usa/nano-33-ble-sense) and +are built around the NINA B306 module, based on Nordic nRF 52840 and containing +a powerful Cortex M4F. Both include an onboard 9 axis Inertial Measurement Unit (IMU), the LSM9DS1. +The Nano 33 BLE Sense adds an LPS22HB barometric pressure and temperature sensor, +an ADPS-9960 digital proximity, ambient light, RGB, and gensture sensor, +and an MP34DT05 digital microphone. + +Note: the Arduino Nano 33 BLE and BLE Sense do not include a QSPI external +flash. Any Python code will need to be stored on the internal flash +filesystem. + +I2C pins `board.SCL1` and `board.SDA1` are not exposed and are used for onboard peripherals. +Pin `board.R_PULLUP` must be set to high to enable the `SCL1` and `SDA1` pullups for proper operation. + +Pin `board.VDD_ENV` applies power to the LSM9DS1, and must be high for it to be operational. + +Pins `board.MIC_PWR`, `board.PDMDIN`, and `board.PDMCLK` are for the Nano 33 BLE Sense onboard microphone. + +Pin `board.INT_ADPS` is the interrupt pin from the ADPS-9960. + +Pins `board.RGB_LED_R`, `board.RGB_LED_G`, and `board.RGB_LED_B` +are the red, green and blue LEDS in the onboard RGB LED. + +Pins `board.LED_G` and `board.LED_Y` are onboard green and red LEDs. `board.LED_Y` is also `board.SCK`. diff --git a/ports/nrf/boards/arduino_nano_33_ble/board.c b/ports/nrf/boards/arduino_nano_33_ble/board.c new file mode 100644 index 0000000000..ddfcde2848 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble/board.c @@ -0,0 +1,63 @@ +/* + * 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" +#include "nrf.h" +#include "nrf_rtc.h" + +void board_init(void) { + // Initializations below from Arduino variant.cpp. + + // // turn power LED on + // pinMode(LED_PWR, OUTPUT); + // digitalWrite(LED_PWR, HIGH); + + // Errata Nano33BLE - I2C pullup is on SWO line, need to disable TRACE + // was being enabled by nrfx_clock_anomaly_132 + CoreDebug->DEMCR = 0; + NRF_CLOCK->TRACECONFIG = 0; + + // FIXME: bootloader enables interrupt on COMPARE[0], which we don't handle + // Disable it here to avoid getting stuck when OVERFLOW irq is triggered + nrf_rtc_event_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK); + nrf_rtc_int_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK); + + // // FIXME: always enable I2C pullup and power @startup + // // Change for maximum powersave + // pinMode(PIN_ENABLE_SENSORS_3V3, OUTPUT); + // pinMode(PIN_ENABLE_I2C_PULLUP, OUTPUT); + + // digitalWrite(PIN_ENABLE_SENSORS_3V3, HIGH); + // digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { + +} diff --git a/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.h b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.h new file mode 100644 index 0000000000..d34a862439 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.h @@ -0,0 +1,16 @@ +#include "nrfx/hal/nrf_gpio.h" + +#define MICROPY_HW_BOARD_NAME "Arduino Nano 33 BLE" +#define MICROPY_HW_MCU_NAME "nRF52840" + +#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 + +#define DEFAULT_I2C_BUS_SCL (&pin_P0_02) +#define DEFAULT_I2C_BUS_SDA (&pin_P0_31) + +#define DEFAULT_SPI_BUS_SCK (&pin_P0_13) +#define DEFAULT_SPI_BUS_MOSI (&pin_P0_01) +#define DEFAULT_SPI_BUS_MISO (&pin_P1_08) + +#define DEFAULT_UART_BUS_RX (&pin_P1_10) +#define DEFAULT_UART_BUS_TX (&pin_P1_03) diff --git a/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk new file mode 100644 index 0000000000..9a875ac442 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.mk @@ -0,0 +1,31 @@ +USB_VID = 0x2341 +USB_PID = 0x805A +USB_PRODUCT = "Arduino_Nano_33_BLE" +USB_MANUFACTURER = "Arduino" + +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52840 +MCU_CHIP = nrf52840 +SD ?= s140 +SOFTDEV_VERSION ?= 6.1.0 + +BOOT_SETTING_ADDR = 0xFF000 + +ifeq ($(SD),) + LD_FILE = boards/nrf52840_1M_256k.ld +else + LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld + CIRCUITPY_BLEIO = 1 +endif + +NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +INTERNAL_FLASH_FILESYSTEM = 1 + +# Allocate two, not just one I2C peripheral, so that we have both +# on-board and off-board I2C available. +# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals. +# We use a CFLAGS define here because there are include order issues +# if we try to include "mpconfigport.h" into nrfx_config.h . +CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2 diff --git a/ports/nrf/boards/arduino_nano_33_ble/pins.c b/ports/nrf/boards/arduino_nano_33_ble/pins.c new file mode 100644 index 0000000000..9cdd369331 --- /dev/null +++ b/ports/nrf/boards/arduino_nano_33_ble/pins.c @@ -0,0 +1,63 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P1_11) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P1_12) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_13) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P1_14) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P1_02) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_29) }, + + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_31) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_31) }, + + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_02) }, + + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_P0_03) }, + + { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_P0_15) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P1_01) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P1_08) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_LED_Y), MP_ROM_PTR(&pin_P0_13) }, + + { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_P1_09) }, + + { MP_ROM_QSTR(MP_QSTR_RGB_LED_R), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_RGB_LED_G), MP_ROM_PTR(&pin_P0_16) }, + { MP_ROM_QSTR(MP_QSTR_RGB_LED_B), MP_ROM_PTR(&pin_P0_06) }, + + // Power line to LSM9DS1. + { MP_ROM_QSTR(MP_QSTR_VDD_ENV), MP_ROM_PTR(&pin_P0_22) }, + + // Pullup voltage for SDA1 and SCL1 + { MP_ROM_QSTR(MP_QSTR_R_PULLUP), MP_ROM_PTR(&pin_P1_00) }, + + { MP_ROM_QSTR(MP_QSTR_MIC_PWR), MP_ROM_PTR(&pin_P0_17) }, + { MP_ROM_QSTR(MP_QSTR_PDMCLK), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_PDMDIN), MP_ROM_PTR(&pin_P0_25) }, + + { MP_ROM_QSTR(MP_QSTR_INT_APDS), MP_ROM_PTR(&pin_P0_19) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P1_03) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P1_10) }, + + { 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); diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h index 1e55cd0260..4e37eae0aa 100644 --- a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h +++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.h @@ -29,7 +29,6 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Circuit Playground Bluefruit" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "CircuitPlaygroundBluefruit" #define FLASH_SIZE (0x100000) #define FLASH_PAGE_SIZE (4096) @@ -70,3 +69,5 @@ #define DEFAULT_UART_BUS_RX (&pin_P0_30) #define DEFAULT_UART_BUS_TX (&pin_P0_14) + +#define SPEAKER_ENABLE_PIN (&pin_P1_04) diff --git a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk index dbb32629c6..d53e486f9d 100644 --- a/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk +++ b/ports/nrf/boards/circuitplayground_bluefruit/mpconfigboard.mk @@ -24,3 +24,10 @@ NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICE_COUNT = 1 EXTERNAL_FLASH_DEVICES = "GD25Q16C" + +# Allocate two, not just one I2C peripheral for CPB, so that we have both +# on-board and off-board I2C available. +# When SPIM3 becomes available we'll be able to have two I2C and two SPI peripherals. +# We use a CFLAGS define here because there are include order issues +# if we try to include "mpconfigport.h" into nrfx_config.h . +CFLAGS += -DCIRCUITPY_NRF_NUM_I2C=2 diff --git a/ports/nrf/boards/electronut_labs_blip/mpconfigboard.h b/ports/nrf/boards/electronut_labs_blip/mpconfigboard.h index 21e8c3ef61..6fe969d4ac 100644 --- a/ports/nrf/boards/electronut_labs_blip/mpconfigboard.h +++ b/ports/nrf/boards/electronut_labs_blip/mpconfigboard.h @@ -32,7 +32,6 @@ #define MICROPY_HW_BOARD_NAME "Electronut Labs Blip" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "ElectronutLabsPapyr" #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 diff --git a/ports/nrf/boards/electronut_labs_papyr/mpconfigboard.h b/ports/nrf/boards/electronut_labs_papyr/mpconfigboard.h index 7f5021fdca..6fc1c5fad7 100644 --- a/ports/nrf/boards/electronut_labs_papyr/mpconfigboard.h +++ b/ports/nrf/boards/electronut_labs_papyr/mpconfigboard.h @@ -31,7 +31,6 @@ #define MICROPY_HW_BOARD_NAME "Electronut Labs Papyr" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "ElectronutLabsPapyr" #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h index 70ccffc3f3..b5319032c9 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h @@ -29,7 +29,6 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "Feather52840Express" #define FLASH_SIZE (0x100000) #define FLASH_PAGE_SIZE (4096) diff --git a/ports/nrf/boards/itsybitsy_nrf52840_express/board.c b/ports/nrf/boards/itsybitsy_nrf52840_express/board.c new file mode 100644 index 0000000000..4421970eef --- /dev/null +++ b/ports/nrf/boards/itsybitsy_nrf52840_express/board.c @@ -0,0 +1,38 @@ +/* + * 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) { + +} diff --git a/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.h new file mode 100644 index 0000000000..2f17460ae7 --- /dev/null +++ b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.h @@ -0,0 +1,46 @@ +#include "nrfx/hal/nrf_gpio.h" + +#define MICROPY_HW_BOARD_NAME "Adafruit ItsyBitsy nRF52840 Express" +#define MICROPY_HW_MCU_NAME "nRF52840" + +#define FLASH_SIZE (0x100000) +#define FLASH_PAGE_SIZE (4096) + +#define MICROPY_HW_LED_STATUS (&pin_P0_06) + +#define MICROPY_HW_APA102_MOSI (&pin_P0_08) +#define MICROPY_HW_APA102_SCK (&pin_P1_09) + +#if QSPI_FLASH_FILESYSTEM +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 21) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 22) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(1, 00) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 17) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 23) +#endif + +#if SPI_FLASH_FILESYSTEM +#define SPI_FLASH_MOSI_PIN &pin_P0_21 +#define SPI_FLASH_MISO_PIN &pin_P0_22 +#define SPI_FLASH_SCK_PIN &pin_P0_19 +#define SPI_FLASH_CS_PIN &pin_P0_23 +#endif + +#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 + +#define CIRCUITPY_INTERNAL_NVM_SIZE (4096) + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_P0_14) +#define DEFAULT_I2C_BUS_SDA (&pin_P0_16) + +#define DEFAULT_SPI_BUS_SCK (&pin_P0_13) +#define DEFAULT_SPI_BUS_MOSI (&pin_P0_15) +#define DEFAULT_SPI_BUS_MISO (&pin_P0_20) + +#define DEFAULT_UART_BUS_RX (&pin_P0_25) +#define DEFAULT_UART_BUS_TX (&pin_P0_24) diff --git a/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk new file mode 100644 index 0000000000..d290077e75 --- /dev/null +++ b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.mk @@ -0,0 +1,29 @@ +USB_VID = 0x239A +USB_PID = 0x8052 +USB_PRODUCT = "ItsyBitsy nRF52840 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52840 +MCU_CHIP = nrf52840 +SD ?= s140 +SOFTDEV_VERSION ?= 6.1.0 + +BOOT_SETTING_ADDR = 0xFF000 + +ifeq ($(SD),) + LD_FILE = boards/nrf52840_1M_256k.ld +else + LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld + CIRCUITPY_BLEIO = 1 +endif + +NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +# Don't use up a hardware SPI peripheral for the status DotStar: we only have one or two. +CIRCUITPY_BITBANG_APA102 = 1 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "GD25Q16C" diff --git a/ports/nrf/boards/itsybitsy_nrf52840_express/pins.c b/ports/nrf/boards/itsybitsy_nrf52840_express/pins.c new file mode 100644 index 0000000000..364fbfd470 --- /dev/null +++ b/ports/nrf/boards/itsybitsy_nrf52840_express/pins.c @@ -0,0 +1,46 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_31) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_03) }, + + { MP_ROM_QSTR(MP_QSTR_SWITCH), MP_ROM_PTR(&pin_P0_29) }, + + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_25) }, + + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_24) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P1_08) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P0_12) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_16) }, + + { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_P1_09) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_20) }, + + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P0_06) }, + + { 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); diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h index ed48364942..ce0abe724e 100644 --- a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h @@ -31,7 +31,6 @@ #define MICROPY_HW_BOARD_NAME "MakerDiary nRF52840 MDK" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "MakerDiary52840MDK" #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 5) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 4) diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk_usb_dongle/mpconfigboard.h b/ports/nrf/boards/makerdiary_nrf52840_mdk_usb_dongle/mpconfigboard.h index d4096503d7..86c7243e57 100644 --- a/ports/nrf/boards/makerdiary_nrf52840_mdk_usb_dongle/mpconfigboard.h +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk_usb_dongle/mpconfigboard.h @@ -31,7 +31,6 @@ #define MICROPY_HW_BOARD_NAME "MakerDiary nRF52840 MDK USB Dongle" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "MakerDiary52840MDKDongle" #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 diff --git a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h index 520eef90d9..797cc9668c 100644 --- a/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/metro_nrf52840_express/mpconfigboard.h @@ -29,7 +29,6 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Metro nRF52840 Express" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "Metro52840Express" #define FLASH_SIZE (0x100000) #define FLASH_PAGE_SIZE (4096) diff --git a/ports/nrf/boards/particle_argon/mpconfigboard.h b/ports/nrf/boards/particle_argon/mpconfigboard.h index a4ecb2bb43..1eeb7291bc 100644 --- a/ports/nrf/boards/particle_argon/mpconfigboard.h +++ b/ports/nrf/boards/particle_argon/mpconfigboard.h @@ -29,7 +29,6 @@ #define MICROPY_HW_BOARD_NAME "Particle Argon" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "Particle Argon" #define MICROPY_HW_LED_STATUS (&pin_P1_12) diff --git a/ports/nrf/boards/particle_boron/mpconfigboard.h b/ports/nrf/boards/particle_boron/mpconfigboard.h index 5e817311f9..af69924841 100644 --- a/ports/nrf/boards/particle_boron/mpconfigboard.h +++ b/ports/nrf/boards/particle_boron/mpconfigboard.h @@ -29,7 +29,6 @@ #define MICROPY_HW_BOARD_NAME "Particle Boron" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "Particle Boron" #define MICROPY_HW_LED_STATUS (&pin_P1_12) diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h index 6c8cc7cef2..34ca6421e6 100644 --- a/ports/nrf/boards/particle_xenon/mpconfigboard.h +++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h @@ -29,7 +29,6 @@ #define MICROPY_HW_BOARD_NAME "Particle Xenon" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "Particle Xenon" #define MICROPY_HW_LED_STATUS (&pin_P1_12) diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index 48ef7f1c39..5b30c7fe83 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -28,7 +28,6 @@ #define MICROPY_HW_BOARD_NAME "PCA10056 nRF52840-DK" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 diff --git a/ports/nrf/boards/pca10059/mpconfigboard.h b/ports/nrf/boards/pca10059/mpconfigboard.h index d5ce212292..b79d3c88f2 100644 --- a/ports/nrf/boards/pca10059/mpconfigboard.h +++ b/ports/nrf/boards/pca10059/mpconfigboard.h @@ -26,7 +26,6 @@ #define MICROPY_HW_BOARD_NAME "PCA10059 nRF52840 Dongle" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" #define MICROPY_HW_LED_STATUS (&pin_P0_06) diff --git a/ports/nrf/boards/sparkfun_nrf52840_mini/mpconfigboard.h b/ports/nrf/boards/sparkfun_nrf52840_mini/mpconfigboard.h index a5ed69b2bd..cc7e68864e 100644 --- a/ports/nrf/boards/sparkfun_nrf52840_mini/mpconfigboard.h +++ b/ports/nrf/boards/sparkfun_nrf52840_mini/mpconfigboard.h @@ -28,7 +28,6 @@ #define MICROPY_HW_BOARD_NAME "SparkFun Pro nRF52840 Mini" #define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "SFE_NRF52840_Mini" #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c index 71835d16ad..8a2ebde3bd 100644 --- a/ports/nrf/common-hal/busio/I2C.c +++ b/ports/nrf/common-hal/busio/I2C.c @@ -28,13 +28,12 @@ */ #include "shared-bindings/busio/I2C.h" +#include "shared-bindings/microcontroller/__init__.h" #include "py/mperrno.h" #include "py/runtime.h" #include "supervisor/shared/translate.h" #include "nrfx_twim.h" -#include "nrf_gpio.h" - #include "nrfx_spim.h" #include "nrf_gpio.h" @@ -107,7 +106,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) { if (!twim_peripherals[i].in_use) { self->twim_peripheral = &twim_peripherals[i]; - self->twim_peripheral->in_use = true; + // Mark it as in_use later after other validation is finished. break; } } @@ -116,10 +115,27 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * mp_raise_ValueError(translate("All I2C peripherals are in use")); } + // Test that the pins are in a high state. (Hopefully indicating they are pulled up.) + nrf_gpio_cfg_input(scl->number, NRF_GPIO_PIN_PULLDOWN); + nrf_gpio_cfg_input(sda->number, NRF_GPIO_PIN_PULLDOWN); + + common_hal_mcu_delay_us(10); + + nrf_gpio_cfg_input(scl->number, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(sda->number, NRF_GPIO_PIN_NOPULL); + + // We must pull up within 3us to achieve 400khz. + common_hal_mcu_delay_us(3); + + if (!nrf_gpio_pin_read(sda->number) || !nrf_gpio_pin_read(scl->number)) { + reset_pin_number(sda->number); + reset_pin_number(scl->number); + mp_raise_RuntimeError(translate("SDA or SCL needs a pull up")); + } + nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG; config.scl = scl->number; config.sda = sda->number; - // change freq. only if it's less than the default 400K if (frequency < 100000) { config.frequency = NRF_TWIM_FREQ_100K; @@ -132,6 +148,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * claim_pin(sda); claim_pin(scl); + // About to init. If we fail after this point, common_hal_busio_i2c_deinit() will set in_use to false. + self->twim_peripheral->in_use = true; nrfx_err_t err = nrfx_twim_init(&self->twim_peripheral->twim, &config, NULL, NULL); // A soft reset doesn't uninit the driver so we might end up with a invalid state @@ -152,8 +170,9 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { } void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { - if (common_hal_busio_i2c_deinited(self)) + if (common_hal_busio_i2c_deinited(self)) { return; + } nrfx_twim_uninit(&self->twim_peripheral->twim); diff --git a/ports/nrf/common-hal/microcontroller/Pin.c b/ports/nrf/common-hal/microcontroller/Pin.c index 3cee784b63..ce55317e54 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.c +++ b/ports/nrf/common-hal/microcontroller/Pin.c @@ -25,6 +25,7 @@ */ #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" #include "nrf_gpio.h" #include "py/mphal.h" @@ -47,6 +48,19 @@ bool speaker_enable_in_use; STATIC uint32_t claimed_pins[GPIO_COUNT]; STATIC uint32_t never_reset_pins[GPIO_COUNT]; +STATIC void reset_speaker_enable_pin(void) { +#ifdef SPEAKER_ENABLE_PIN + speaker_enable_in_use = false; + nrf_gpio_cfg(SPEAKER_ENABLE_PIN->number, + NRF_GPIO_PIN_DIR_OUTPUT, + NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_H0H1, + NRF_GPIO_PIN_NOSENSE); + nrf_gpio_pin_write(SPEAKER_ENABLE_PIN->number, false); +#endif +} + void reset_all_pins(void) { for (size_t i = 0; i < GPIO_COUNT; i++) { claimed_pins[i] = never_reset_pins[i]; @@ -68,10 +82,7 @@ void reset_all_pins(void) { #endif // After configuring SWD because it may be shared. - #ifdef SPEAKER_ENABLE_PIN - speaker_enable_in_use = false; - // TODO set pin to out and turn off. - #endif + reset_speaker_enable_pin(); } // Mark pin as free and return it to a quiescent state. @@ -91,8 +102,8 @@ void reset_pin_number(uint8_t pin_number) { } #endif #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI->number || - pin == MICROPY_HW_APA102_SCK->number) { + 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) { @@ -104,10 +115,7 @@ void reset_pin_number(uint8_t pin_number) { #ifdef SPEAKER_ENABLE_PIN if (pin_number == SPEAKER_ENABLE_PIN->number) { - speaker_enable_in_use = false; - common_hal_digitalio_digitalinout_switch_to_output(SPEAKER_ENABLE_PIN, true, DRIVE_MODE_PUSH_PULL); - nrf_gpio_pin_dir_set(pin_number, NRF_GPIO_PIN_DIR_OUTPUT); - nrf_gpio_pin_write(pin_number, false); + reset_speaker_enable_pin(); } #endif } diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 0b755a156b..bbe6419a5f 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -30,6 +30,10 @@ #include "ble_drv.h" +#ifdef NRF52840 +#define MICROPY_PY_SYS_PLATFORM "nRF52840" +#endif + #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_IO (1) diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index 8fa6721e2c..cafec6aa1d 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -5,12 +5,9 @@ #define NRFX_POWER_ENABLED 1 #define NRFX_POWER_CONFIG_IRQ_PRIORITY 7 -// Turn on nrfx supported workarounds for errata in Rev1/Rev2 of nRF52832 -#ifdef NRF52832_XXAA - #define NRFX_SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1 -#endif - -// NOTE: THIS WORKAROUND CAUSES BLE CODE TO CRASH; tested on 2019-03-11. +// NOTE: THIS WORKAROUND CAUSES BLE CODE TO CRASH. +// It doesn't work with the SoftDevice. +// See https://devzone.nordicsemi.com/f/nordic-q-a/33982/sdk-15-software-crash-during-spi-session // Turn on nrfx supported workarounds for errata in Rev1 of nRF52840 #ifdef NRF52840_XXAA // #define NRFX_SPIM3_NRF52840_ANOMALY_198_WORKAROUND_ENABLED 1 @@ -24,11 +21,26 @@ // so out of the box TWIM0/SPIM0 and TWIM1/SPIM1 cannot be shared // between common-hal/busio/I2C.c and SPI.c. // We could write an interrupt handler that checks whether it's -// being used for SPI or I2C, but perhaps two I2C's and 1-2 SPI's are good enough for now. +// being used for SPI or I2C, but perhaps one I2C and two SPI or two I2C and one SPI +// are good enough for now. + +// CIRCUITPY_NRF_NUM_I2C is 1 or 2 to choose how many I2C (TWIM) peripherals +// to provide. +// This can go away once we have SPIM3 working: then we can have two +// I2C and two SPI. +#ifndef CIRCUITPY_NRF_NUM_I2C +#define CIRCUITPY_NRF_NUM_I2C 1 +#endif + +#if CIRCUITPY_NRF_NUM_I2C != 1 && CIRCUITPY_NRF_NUM_I2C != 2 +# error CIRCUITPY_NRF_NUM_I2C must be 1 or 2 +#endif // Enable SPIM1, SPIM2 and SPIM3 (if available) // No conflict with TWIM0. +#if CIRCUITPY_NRF_NUM_I2C == 1 #define NRFX_SPIM1_ENABLED 1 +#endif #define NRFX_SPIM2_ENABLED 1 // DON'T ENABLE SPIM3 DUE TO ANOMALY WORKAROUND FAILURE (SEE ABOVE). // #ifdef NRF52840_XXAA @@ -45,10 +57,13 @@ // QSPI #define NRFX_QSPI_ENABLED 1 -// TWI aka. I2C; enable a single bus: TWIM0 (no conflict with SPIM1 and SPIM2) +// TWI aka. I2C; always enable TWIM0 (no conflict with SPIM1 and SPIM2) #define NRFX_TWIM_ENABLED 1 #define NRFX_TWIM0_ENABLED 1 -//#define NRFX_TWIM1_ENABLED 1 + +#if CIRCUITPY_NRF_NUM_I2C == 2 +#define NRFX_TWIM1_ENABLED 1 +#endif #define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY NRF_TWIM_FREQ_400K diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index da5633f2a3..c9b8288070 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -49,7 +49,7 @@ //| //| .. classmethod:: add_to_peripheral(peripheral, uuid, *, secondary=False) //| -//| Create a new Service object, identitied by the specified UUID, and add it +//| Create a new Service object, identified by the specified UUID, and add it //| to the given Peripheral. //| //| To mark the service as secondary, pass `True` as :py:data:`secondary`. diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c index 48b9f1cef1..eb0cb29842 100644 --- a/shared-bindings/_pixelbuf/__init__.c +++ b/shared-bindings/_pixelbuf/__init__.c @@ -55,7 +55,7 @@ //| .. class:: ByteOrder() //| -//| Classes representing byteorders for circuitpython +//| Classes representing byteorders for CircuitPython //| .. attribute:: bpp @@ -284,7 +284,7 @@ PIXELBUF_BYTEORDER(LBRG, 4, 3, 1, 2, 0, false, true) //| * **bpp** 4 //| * **has_luminosity** True //| -//| Actual format commonly used by DotStar (5 bit luninance value) +//| Actual format commonly used by DotStar (5 bit luminance value) PIXELBUF_BYTEORDER(LBGR, 4, 3, 2, 1, 0, false, true) STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = { diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c index 2cd2b67289..81383c7776 100644 --- a/shared-bindings/audiobusio/I2SOut.c +++ b/shared-bindings/audiobusio/I2SOut.c @@ -62,7 +62,7 @@ //| import time //| import math //| -//| # Generate one period of sine wav. +//| # Generate one period of sine wave. //| length = 8000 // 440 //| sine_wave = array.array("H", [0] * length) //| for i in range(length): diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c index 7fa37d5c51..02a5fe1eee 100644 --- a/shared-bindings/audioio/__init__.c +++ b/shared-bindings/audioio/__init__.c @@ -68,7 +68,7 @@ //| //| For compatibility with CircuitPython 4.x, some builds allow the items in //| `audiocore` to be imported from `audioio`. This will be removed for all -//| boards in a future build of CicuitPython. +//| boards in a future build of CircuitPython. //| STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = { diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index 3bd89e2e20..50a95beb2e 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -60,6 +60,10 @@ //| :param int frequency: The clock frequency in Hertz //| :param int timeout: The maximum clock stretching timeut - (used only for bitbangio.I2C; ignored for busio.I2C) //| +//| .. note:: On the nRF52840, only one I2C object may be created, +//| except on the Circuit Playground Bluefruit, which allows two, +//| one for the onboard accelerometer, and one for offboard use. +//| STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { busio_i2c_obj_t *self = m_new_obj(busio_i2c_obj_t); self->base.type = &busio_i2c_type; diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index d47bf499a2..d1791bef3b 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -154,11 +154,12 @@ STATIC void check_for_deinit(busio_spi_obj_t *self) { //| within spec for the SAMD21. //| //| .. note:: On the nRF52840, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz, -//| and 8MHz. 16MHz and 32MHz are also available, but only on the first -//| `busio.SPI` object you create. Two more ``busio.SPI`` objects can be created, but they are restricted -//| to 8MHz maximum. This is a hardware restriction: there is only one high-speed SPI peripheral. +//| and 8MHz. //| If you pick a a baudrate other than one of these, the nearest lower //| baudrate will be chosen, with a minimum of 125kHz. +//| Two SPI objects may be created, except on the Circuit Playground Bluefruit, +//| which allows only one (to allow for an additional I2C object). +//| STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pulseio/PWMOut.c index 40981e0a81..53b88c61a5 100644 --- a/shared-bindings/pulseio/PWMOut.c +++ b/shared-bindings/pulseio/PWMOut.c @@ -162,6 +162,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pwmout___exit___obj, 4, 4, pu //| 16 bit value that dictates how much of one cycle is high (1) versus low //| (0). 0xffff will always be high, 0 will always be low and 0x7fff will //| be half high and then half low. +//| +//| Depending on how PWM is implemented on a specific board, the internal +//| representation for duty cycle might have less than 16 bits of resolution. +//| Reading this property will return the value from the internal representation, +//| so it may differ from the value set. STATIC mp_obj_t pulseio_pwmout_obj_get_duty_cycle(mp_obj_t self_in) { pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -193,6 +198,12 @@ const mp_obj_property_t pulseio_pwmout_duty_cycle_obj = { //| 32 bit value that dictates the PWM frequency in Hertz (cycles per //| second). Only writeable when constructed with ``variable_frequency=True``. //| +//| Depending on how PWM is implemented on a specific board, the internal value +//| for the PWM's duty cycle may need to be recalculated when the frequency +//| changes. In these cases, the duty cycle is automatically recalculated +//| from the original duty cycle value. This should happen without any need +//| to manually re-set the duty cycle. +//| STATIC mp_obj_t pulseio_pwmout_obj_get_frequency(mp_obj_t self_in) { pulseio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); diff --git a/shared-bindings/rtc/RTC.c b/shared-bindings/rtc/RTC.c index 17dccdb03c..3ff09a4ec5 100644 --- a/shared-bindings/rtc/RTC.c +++ b/shared-bindings/rtc/RTC.c @@ -57,7 +57,23 @@ STATIC mp_obj_t rtc_rtc_make_new(const mp_obj_type_t *type, size_t n_args, const //| .. attribute:: datetime //| -//| The date and time of the RTC. +//| The current date and time of the RTC as a `time.struct_time`. +//| +//| This must be set to the current date and time whenever the board loses power:: +//| +//| import rtc +//| import time +//| +//| r = rtc.RTC() +//| r.datetime = rtctime.struct_time((2019, 5, 29, 15, 14, 15, 0, -1, -1)) +//| +//| +//| Once set, the RTC will automatically update this value as time passes. You can read this +//| property to get a snapshot of the current time:: +//| +//| current_time = r.datetime +//| print(current_time) +//| # struct_time(tm_year=2019, tm_month=5, ...) //| STATIC mp_obj_t rtc_rtc_obj_get_datetime(mp_obj_t self_in) { timeutils_struct_time_t tm; @@ -83,9 +99,10 @@ const mp_obj_property_t rtc_rtc_datetime_obj = { //| .. attribute:: calibration //| -//| The RTC calibration value. +//| The RTC calibration value as an `int`. +//| //| A positive value speeds up the clock and a negative value slows it down. -//| Range and value is hardware specific, but one step is often approx. 1 ppm. +//| Range and value is hardware specific, but one step is often approximately 1 ppm. //| STATIC mp_obj_t rtc_rtc_obj_get_calibration(mp_obj_t self_in) { int calibration = common_hal_rtc_get_calibration(); diff --git a/shared-bindings/rtc/__init__.c b/shared-bindings/rtc/__init__.c index ac67a7131c..22eda9b663 100644 --- a/shared-bindings/rtc/__init__.c +++ b/shared-bindings/rtc/__init__.c @@ -36,12 +36,13 @@ //| //| .. module:: rtc //| :synopsis: Real Time Clock -//| :platform: SAMD21 +//| :platform: SAMD21, SAMD51, nRF52 //| -//| The `rtc` module provides support for a Real Time Clock. -//| It also backs the `time.time()` and `time.localtime()` functions using the onboard RTC if present. +//| The `rtc` module provides support for a Real Time Clock. You can access and manage the +//| RTC using :class:`rtc.RTC`. It also backs the :func:`time.time` and :func:`time.localtime` +//| functions using the onboard RTC if present. //| -//| Libraries +//| Classes //| //| .. toctree:: //| :maxdepth: 3 @@ -63,10 +64,9 @@ mp_obj_t rtc_get_time_source_time(void) { //| .. function:: set_time_source(rtc) //| -//| Sets the rtc time source used by time.localtime(). -//| The default is `rtc.RTC()`. -//| -//| Example usage:: +//| Sets the RTC time source used by :func:`time.localtime`. +//| The default is :class:`rtc.RTC`, but it's useful to use this to override the +//| time source for testing purposes. For example:: //| //| import rtc //| import time diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c index 6d3a285231..d02adf34fb 100644 --- a/shared-module/bitbangio/SPI.c +++ b/shared-module/bitbangio/SPI.c @@ -43,6 +43,8 @@ void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, if (result != DIGITALINOUT_OK) { mp_raise_ValueError(translate("Clock pin init failed.")); } + common_hal_digitalio_digitalinout_switch_to_output(&self->clock, self->polarity == 1, DRIVE_MODE_PUSH_PULL); + if (mosi != mp_const_none) { result = common_hal_digitalio_digitalinout_construct(&self->mosi, mosi); if (result != DIGITALINOUT_OK) { @@ -50,8 +52,11 @@ void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, mp_raise_ValueError(translate("MOSI pin init failed.")); } self->has_mosi = true; + common_hal_digitalio_digitalinout_switch_to_output(&self->mosi, false, DRIVE_MODE_PUSH_PULL); } + if (miso != mp_const_none) { + // Starts out as input by default, no need to change. result = common_hal_digitalio_digitalinout_construct(&self->miso, miso); if (result != DIGITALINOUT_OK) { common_hal_digitalio_digitalinout_deinit(&self->clock); diff --git a/supervisor/shared/rgb_led_colors.h b/supervisor/shared/rgb_led_colors.h index 48994ad62c..c723fbab36 100644 --- a/supervisor/shared/rgb_led_colors.h +++ b/supervisor/shared/rgb_led_colors.h @@ -1,12 +1,18 @@ -#define BLACK 0x000000 -#define GREEN 0x003000 -#define BLUE 0x000030 -#define CYAN 0x003030 -#define RED 0x300000 -#define ORANGE 0x302000 -#define YELLOW 0x303000 -#define PURPLE 0x300030 -#define WHITE 0x303030 + +#define COLOR(r, g, b) (((r) << 16) | ((g) << 8) | (b)) +// For brightness == 255 (full). This will be adjusted downward for various different RGB indicators, +// which vary in brightness. +#define INTENSITY (0x30) + +#define BLACK COLOR(0, 0, 0) +#define GREEN COLOR(0, INTENSITY, 0) +#define BLUE COLOR(0, 0, INTENSITY) +#define CYAN COLOR(0, INTENSITY, INTENSITY) +#define RED COLOR(INTENSITY, 0, 0) +#define ORANGE COLOR(INTENSITY, INTENSITY*2/3, 0) +#define YELLOW COLOR(INTENSITY, INTENSITY, 0) +#define PURPLE COLOR(INTENSITY, 0, INTENSITY) +#define WHITE COLOR(INTENSITY, INTENSITY, INTENSITY) #define BOOT_RUNNING BLUE #define MAIN_RUNNING GREEN diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c index 4d93715161..05df4c628a 100644 --- a/supervisor/shared/rgb_led_status.c +++ b/supervisor/shared/rgb_led_status.c @@ -38,7 +38,7 @@ static digitalio_digitalinout_obj_t status_neopixel; #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) -uint8_t rgb_status_brightness = 255; +uint8_t rgb_status_brightness = 50; #define APA102_BUFFER_LENGTH 12 static uint8_t status_apa102_color[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff}; @@ -46,10 +46,18 @@ static uint8_t status_apa102_color[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, 0, #if CIRCUITPY_BITBANG_APA102 #include "shared-bindings/bitbangio/SPI.h" #include "shared-module/bitbangio/types.h" -static bitbangio_spi_obj_t status_apa102; +static bitbangio_spi_obj_t status_apa102 = { + .base = { + .type = &bitbangio_spi_type, + }, +}; #else #include "shared-bindings/busio/SPI.h" -busio_spi_obj_t status_apa102; +busio_spi_obj_t status_apa102 = { + .base = { + .type = &busio_spi_type, + }, +}; #endif #endif @@ -59,9 +67,21 @@ busio_spi_obj_t status_apa102; #include "shared-bindings/pulseio/PWMOut.h" #include "shared-bindings/microcontroller/Pin.h" -pulseio_pwmout_obj_t rgb_status_r; -pulseio_pwmout_obj_t rgb_status_g; -pulseio_pwmout_obj_t rgb_status_b; +pulseio_pwmout_obj_t rgb_status_r = { + .base = { + .type = &pulseio_pwmout_type, + }, +}; +pulseio_pwmout_obj_t rgb_status_g = { + .base = { + .type = &pulseio_pwmout_type, + }, +}; +pulseio_pwmout_obj_t rgb_status_b = { + .base = { + .type = &pulseio_pwmout_type, + }, +}; uint8_t rgb_status_brightness = 0xFF; @@ -74,8 +94,14 @@ uint16_t status_rgb_color[3] = { static uint32_t current_status_color = 0; #endif - +static bool rgb_led_status_init_in_progress = false; void rgb_led_status_init() { + if (rgb_led_status_init_in_progress) { + // Avoid recursion. + return; + } + rgb_led_status_init_in_progress = true; + #ifdef MICROPY_HW_NEOPIXEL common_hal_digitalio_digitalinout_construct(&status_neopixel, MICROPY_HW_NEOPIXEL); // Pretend we aren't using the pins. digitalio.DigitalInOut @@ -91,15 +117,15 @@ void rgb_led_status_init() { mp_const_none); #else if (!common_hal_busio_spi_deinited(&status_apa102)) { - // Don't use spi_deinit because that leads to infinite - // recursion because reset_pin_number may call - // rgb_led_status_init. - spi_m_sync_disable(&status_apa102.spi_desc); + // This may call us recursively if reset_pin_number() is called, + // The rgb_led_status_init_in_progress guard will prevent further recursion. + common_hal_busio_spi_deinit(&status_apa102); } common_hal_busio_spi_construct(&status_apa102, MICROPY_HW_APA102_SCK, MICROPY_HW_APA102_MOSI, mp_const_none); + common_hal_busio_spi_never_reset(&status_apa102); #endif // Pretend we aren't using the pins. bitbangio.SPI will // mark them as used. @@ -149,6 +175,8 @@ void rgb_led_status_init() { current_status_color = 0x1000000; // Not a valid color new_status_color(rgb); #endif + + rgb_led_status_init_in_progress = false; } void reset_status_led() {