diff options
Diffstat (limited to 'ports/atmel-samd')
52 files changed, 1779 insertions, 127 deletions
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 7a842b9c6..f77910f6a 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -76,6 +76,9 @@ BASE_CFLAGS = \ -ffunction-sections \ -fdata-sections \ -fshort-enums \ + -DCIRCUITPY_SOFTWARE_SAFE_MODE=0x0ADABEEF \ + -DCIRCUITPY_CANARY_WORD=0xADAF00 \ + -DCIRCUITPY_SAFE_RESTART_WORD=0xDEADBEEF \ --param max-inline-insns-single=500 # NDEBUG disables assert() statements. This reduces code size pretty dramatically, per tannewt. @@ -312,6 +315,7 @@ SRC_BINDINGS_ENUMS = \ digitalio/Direction.c \ digitalio/DriveMode.c \ digitalio/Pull.c \ + microcontroller/RunMode.c \ help.c \ math/__init__.c \ supervisor/__init__.c \ diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index 8648980c0..6b86a6890 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -10,16 +10,29 @@ #define SPI_FLASH_BAUDRATE (8000000) // On-board flash -#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_E -// Use default pinmux for the chip select since we manage it ourselves. -#define SPI_FLASH_PAD0_PINMUX PINMUX_PA16D_SERCOM3_PAD0 // MISO -#define SPI_FLASH_PAD1_PINMUX PINMUX_UNUSED // CS -#define SPI_FLASH_PAD2_PINMUX PINMUX_PA20D_SERCOM3_PAD2 // MOSI -#define SPI_FLASH_PAD3_PINMUX PINMUX_PA21D_SERCOM3_PAD3 // SCK - -#define SPI_FLASH_CS PIN_PB22 -#define SPI_FLASH_SERCOM SERCOM3 - +#define SPI_FLASH_MOSI_PIN PIN_PA20 +#define SPI_FLASH_MISO_PIN PIN_PA16 +#define SPI_FLASH_SCK_PIN PIN_PA21 +#define SPI_FLASH_CS_PIN PIN_PB22 + +#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA20D_SERCOM3_PAD2 +#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 +#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA21D_SERCOM3_PAD3 +#define SPI_FLASH_SERCOM SERCOM3 +#define SPI_FLASH_SERCOM_INDEX 5 +#define SPI_FLASH_MOSI_PAD 2 +#define SPI_FLASH_MISO_PAD 0 +#define SPI_FLASH_SCK_PAD 3 + +// <o> Transmit Data Pinout +// <0x0=>PAD[0,1]_DO_SCK +// <0x1=>PAD[2,3]_DO_SCK +// <0x2=>PAD[3,1]_DO_SCK +// <0x3=>PAD[0,3]_DO_SCK +#define SPI_FLASH_DOPO 1 +#define SPI_FLASH_DIPO 0 // same as MISO PAD + +// These are pins not to reset. // PA24 and PA25 are USB. #define MICROPY_PORT_A (PORT_PA16 | PORT_PA20 | PORT_PA21 | PORT_PA24 | PORT_PA25) #define MICROPY_PORT_B (PORT_PB22) @@ -27,8 +40,7 @@ #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "internal_flash.h" -//#include "spi_flash.h" +#include "spi_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk index 6e975fdc1..1834a0ebe 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk @@ -4,16 +4,13 @@ USB_PID = 0x8019 USB_PRODUCT = "CircuitPlayground Express" USB_MANUFACTURER = "Adafruit Industries LLC" -#SPI_FLASH_FILESYSTEM = 1 -INTERNAL_FLASH_FILESYSTEM = 1 +SPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 # Include these Python libraries in firmware. -### TODO(halbert): disable some of these frozen modules; they don't fit in 3.0.0 build while internalfs -### is in use -###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice -###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH -###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel -###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor diff --git a/ports/atmel-samd/boards/feather_m0_supersized/board.c b/ports/atmel-samd/boards/feather_m0_supersized/board.c new file mode 100644 index 000000000..c8e20206a --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/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/atmel-samd/boards/feather_m0_supersized/conf_access.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_access.h new file mode 100644 index 000000000..2326bfcdf --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"CircuitPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/ports/atmel-samd/boards/feather_m0_supersized/conf_board.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_board.h new file mode 100644 index 000000000..7b88c97fc --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/ports/atmel-samd/boards/feather_m0_supersized/conf_clocks.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_clocks.h new file mode 100644 index 000000000..d3f3e6496 --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_external_32k.h" diff --git a/ports/atmel-samd/boards/feather_m0_supersized/conf_usb.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_usb.h new file mode 100644 index 000000000..e5e59663c --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_usb.h @@ -0,0 +1,220 @@ + +#include <stdbool.h> +#include <stdint.h> + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Dave Astels" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "Hacked Feather M0 Express with 8Mbyte SPI flash" +#endif + +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h new file mode 100644 index 000000000..8eb59d9a0 --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -0,0 +1,34 @@ +/* Adafruit Feather M0 Express with an 8MB SPI flash instead of the usual 2MB */ + +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "Hacked Feather M0 Express with 8Mbyte SPI flash" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define MICROPY_HW_NEOPIXEL (&pin_PA06) + +// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. +#define SPI_FLASH_BAUDRATE (8000000) + +#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_C +#define SPI_FLASH_PAD0_PINMUX PINMUX_PA08D_SERCOM2_PAD0 // MOSI +// Use default pinmux for the chip select since we manage it ourselves. +#define SPI_FLASH_PAD1_PINMUX PINMUX_PA09D_SERCOM2_PAD1 // SCK +#define SPI_FLASH_PAD2_PINMUX PINMUX_PA14C_SERCOM2_PAD2 // MISO +#define SPI_FLASH_PAD3_PINMUX PINMUX_UNUSED // SCK +#define SPI_FLASH_SERCOM SERCOM2 + +#define SPI_FLASH_CS PIN_PA13 + +#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA14 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B ( 0 ) + +#include "spi_flash.h" + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code. +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#include "flash_S25FL064L.h" diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk new file mode 100644 index 000000000..340421f50 --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -0,0 +1,11 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash.ld +USB_VID = 0x239A +USB_PID = 0x8023 +USB_PRODUCT = "Feather M0 Supersized" +USB_MANUFACTURER = "Dave Astels" + +SPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21 + diff --git a/ports/atmel-samd/boards/feather_m0_supersized/pins.c b/ports/atmel-samd/boards/feather_m0_supersized/pins.c new file mode 100644 index 000000000..c5c70ee5d --- /dev/null +++ b/ports/atmel-samd/boards/feather_m0_supersized/pins.c @@ -0,0 +1,28 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA06) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/flash_S25FL064L.h b/ports/atmel-samd/boards/flash_S25FL064L.h new file mode 100644 index 000000000..40cfa4cf0 --- /dev/null +++ b/ports/atmel-samd/boards/flash_S25FL064L.h @@ -0,0 +1,55 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017 Dave Astels + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H + +// Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash. +// Datasheet: http://www.cypress.com/file/316661/download + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 23) // 8 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. +#ifndef SPI_FLASH_JEDEC_MANUFACTURER +#define SPI_FLASH_JEDEC_MANUFACTURER 0x01 +#define SPI_FLASH_SECTOR_PROTECTION false +#else +#define SPI_FLASH_JEDEC_MANUFACTURER_2 0x013 +#define SPI_FLASH_SECTOR_PROTECTION_2 false +#endif +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60 +#define SPI_FLASH_JEDEC_CAPACITY 0x17 + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H diff --git a/ports/atmel-samd/boards/flash_W25Q80DV.h b/ports/atmel-samd/boards/flash_W25Q80DV.h new file mode 100644 index 000000000..1e8003867 --- /dev/null +++ b/ports/atmel-samd/boards/flash_W25Q80DV.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H +#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H + +// The total flash size in bytes. +#define SPI_FLASH_TOTAL_SIZE (1 << 20) // 1 MiB + +// The size of the smallest erase unit thats erased with command 0x20. +#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB + +// The size of a page that is programmed with page program command 0x02. +#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes + +// These are the first three response bytes to the JEDEC ID command 0x9f that is +// used to confirm we're talking to the flash we expect. +#ifndef SPI_FLASH_JEDEC_MANUFACTURER +#define SPI_FLASH_JEDEC_MANUFACTURER 0xef +#define SPI_FLASH_SECTOR_PROTECTION false +#else +#define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef +#define SPI_FLASH_SECTOR_PROTECTION_2 false +#endif +#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40 +#define SPI_FLASH_JEDEC_CAPACITY 0x14 + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H diff --git a/ports/atmel-samd/boards/itsybitsy_m0/board.c b/ports/atmel-samd/boards/itsybitsy_m0/board.c new file mode 100644 index 000000000..d7e856d61 --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/board.c @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/itsybitsy_m0/conf_access.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_access.h new file mode 100644 index 000000000..25109b75c --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"MicroPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/ports/atmel-samd/boards/itsybitsy_m0/conf_board.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_board.h new file mode 100644 index 000000000..7b88c97fc --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/ports/atmel-samd/boards/itsybitsy_m0/conf_clocks.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_clocks.h new file mode 100644 index 000000000..9e4f7876b --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_crystalless.h" diff --git a/ports/atmel-samd/boards/itsybitsy_m0/conf_usb.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_usb.h new file mode 100644 index 000000000..5e8a61b88 --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_usb.h @@ -0,0 +1,221 @@ + +#include <stdbool.h> +#include <stdint.h> + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Adafruit Industries" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "ItsyBitsy M0" +#endif +// #define USB_DEVICE_SERIAL_NAME "12...EF" +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); + +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h new file mode 100644 index 000000000..e9fd08a5f --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h @@ -0,0 +1,36 @@ +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "Adafruit ItsyBitsy M0" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define CIRCUITPY_BITBANG_APA102 +#define MICROPY_HW_APA102_MOSI (&pin_PA01) +#define MICROPY_HW_APA102_SCK (&pin_PA00) + +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA27 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) + +// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz. +#define SPI_FLASH_BAUDRATE (8000000) + +#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F +#define SPI_FLASH_PAD2_PINMUX PINMUX_PB22D_SERCOM5_PAD2 // MOSI +// Use default pinmux for the chip select since we manage it ourselves. +#define SPI_FLASH_PAD3_PINMUX PINMUX_PB23D_SERCOM5_PAD3 // SCK +#define SPI_FLASH_PAD1_PINMUX PINMUX_PB03D_SERCOM5_PAD1 // MISO +#define SPI_FLASH_PAD0_PINMUX PINMUX_UNUSED // +#define SPI_FLASH_SERCOM SERCOM5 + +#define SPI_FLASH_CS PIN_PA27 + + +#include "spi_flash.h" + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code. +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +//#include "flash_S25FL216K.h" +#include "flash_W25Q80DV.h" +//#include "flash_GD25Q16C.h" diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk new file mode 100644 index 000000000..0fb0e38ed --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk @@ -0,0 +1,11 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld +USB_VID = 0x239A +USB_PID = 0x8012 +USB_PRODUCT = "Itsy Bitsy M0 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + +SPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21 + diff --git a/ports/atmel-samd/boards/itsybitsy_m0/pins.c b/ports/atmel-samd/boards/itsybitsy_m0/pins.c new file mode 100644 index 000000000..b70bb6a76 --- /dev/null +++ b/ports/atmel-samd/boards/itsybitsy_m0/pins.c @@ -0,0 +1,42 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PA17) }, // a.k.a D13 + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, + + { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA00) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld b/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld index 56ae5feb4..1d54bb88c 100644 --- a/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld +++ b/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld @@ -11,7 +11,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld index 1c0424747..81c1e8450 100644 --- a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld +++ b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld @@ -11,7 +11,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld index 4346c170c..8563ed3cb 100644 --- a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld +++ b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld @@ -10,7 +10,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd21x18-bootloader.ld b/ports/atmel-samd/boards/samd21x18-bootloader.ld index 13a3f75c1..4d2005518 100644 --- a/ports/atmel-samd/boards/samd21x18-bootloader.ld +++ b/ports/atmel-samd/boards/samd21x18-bootloader.ld @@ -11,7 +11,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd21x18-external-flash.ld b/ports/atmel-samd/boards/samd21x18-external-flash.ld index f5797cf6f..629e190b1 100644 --- a/ports/atmel-samd/boards/samd21x18-external-flash.ld +++ b/ports/atmel-samd/boards/samd21x18-external-flash.ld @@ -12,6 +12,7 @@ MEMORY /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_bootloader_dbl_tap = 0; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd21x18.ld b/ports/atmel-samd/boards/samd21x18.ld index a68094758..9e318e948 100644 --- a/ports/atmel-samd/boards/samd21x18.ld +++ b/ports/atmel-samd/boards/samd21x18.ld @@ -12,6 +12,7 @@ MEMORY /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_bootloader_dbl_tap = 0; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld index f4ad37c20..73012b200 100644 --- a/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld +++ b/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld @@ -10,7 +10,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld index 4e4e8b002..c9247ec73 100644 --- a/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld +++ b/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld @@ -10,7 +10,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd51x19-bootloader.ld b/ports/atmel-samd/boards/samd51x19-bootloader.ld index 63aada408..02f38f39f 100644 --- a/ports/atmel-samd/boards/samd51x19-bootloader.ld +++ b/ports/atmel-samd/boards/samd51x19-bootloader.ld @@ -10,7 +10,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld index 57bf299fb..bae25385a 100644 --- a/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld +++ b/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld @@ -10,7 +10,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd51x20-bootloader.ld b/ports/atmel-samd/boards/samd51x20-bootloader.ld index 3d6621a5a..ee0dcfd7a 100644 --- a/ports/atmel-samd/boards/samd51x20-bootloader.ld +++ b/ports/atmel-samd/boards/samd51x20-bootloader.ld @@ -10,7 +10,8 @@ MEMORY } /* top end of the stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - 4; +_bootloader_dbl_tap = _estack; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd51x20-external-flash.ld b/ports/atmel-samd/boards/samd51x20-external-flash.ld index b0a118507..4889700a4 100644 --- a/ports/atmel-samd/boards/samd51x20-external-flash.ld +++ b/ports/atmel-samd/boards/samd51x20-external-flash.ld @@ -11,6 +11,7 @@ MEMORY /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_bootloader_dbl_tap = 0; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/samd51x20.ld b/ports/atmel-samd/boards/samd51x20.ld index ed26425f3..a30f4525b 100644 --- a/ports/atmel-samd/boards/samd51x20.ld +++ b/ports/atmel-samd/boards/samd51x20.ld @@ -11,6 +11,7 @@ MEMORY /* top end of the stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_bootloader_dbl_tap = 0; /* define output sections */ SECTIONS diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk index 04dc9e401..a904b2837 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk @@ -4,8 +4,7 @@ USB_PID = 0x801F USB_PRODUCT="Trinket M0 Haxpress" USB_MANUFACTURER="Radomir Dopieralski" -#SPI_FLASH_FILESYSTEM = 1 -INTERNAL_FLASH_FILESYSTEM = 1 +SPI_FLASH_FILESYSTEM = 1 CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/ugame/board.c b/ports/atmel-samd/boards/ugame/board.c new file mode 100644 index 000000000..d7e856d61 --- /dev/null +++ b/ports/atmel-samd/boards/ugame/board.c @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "boards/board.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/ugame/conf_access.h b/ports/atmel-samd/boards/ugame/conf_access.h new file mode 100644 index 000000000..2326bfcdf --- /dev/null +++ b/ports/atmel-samd/boards/ugame/conf_access.h @@ -0,0 +1,115 @@ +/** + * \file + * + * \brief Memory access control configuration file. + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +/* + * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> + */ + +#ifndef _CONF_ACCESS_H_ +#define _CONF_ACCESS_H_ + +#include "compiler.h" +#include "board.h" + + +/*! \name Activation of Logical Unit Numbers + */ +//! @{ +#define LUN_0 ENABLE //!< On-Chip Virtual Memory. +#define LUN_1 DISABLE //!< AT45DBX Data Flash. +#define LUN_2 DISABLE //!< SD/MMC Card over SPI. +#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0. +#define LUN_4 DISABLE +#define LUN_5 DISABLE +#define LUN_6 DISABLE +#define LUN_7 DISABLE +#define LUN_USB DISABLE //!< Host Mass-Storage Memory. +//! @} + +/*! \name LUN 0 Definitions + */ +//! @{ +#define LUN_0_INCLUDE "access_vfs.h" +#define Lun_0_test_unit_ready vfs_test_unit_ready +#define Lun_0_read_capacity vfs_read_capacity +#define Lun_0_unload NULL +#define Lun_0_wr_protect vfs_wr_protect +#define Lun_0_removal vfs_removal +#define Lun_0_usb_read_10 vfs_usb_read_10 +#define Lun_0_usb_write_10 vfs_usb_write_10 +#define LUN_0_NAME "\"CircuitPython VFS[0]\"" +//! @} + +#define MEM_USB LUN_USB + +/*! \name Actions Associated with Memory Accesses + * + * Write here the action to associate with each memory access. + * + * \warning Be careful not to waste time in order not to disturb the functions. + */ +//! @{ +#define memory_start_read_action(nb_sectors) +#define memory_stop_read_action() +#define memory_start_write_action(nb_sectors) +#define memory_stop_write_action() +//! @} + +/*! \name Activation of Interface Features + */ +//! @{ +#define ACCESS_USB true //!< MEM <-> USB interface. +#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface. +#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface. +#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode. +#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface. +#define ACCESS_CODEC false //!< Codec interface. +//! @} + +/*! \name Specific Options for Access Control + */ +//! @{ +#define GLOBAL_WR_PROTECT false //!< Management of a global write protection. +//! @} + + +#endif // _CONF_ACCESS_H_ diff --git a/ports/atmel-samd/boards/ugame/conf_board.h b/ports/atmel-samd/boards/ugame/conf_board.h new file mode 100644 index 000000000..7b88c97fc --- /dev/null +++ b/ports/atmel-samd/boards/ugame/conf_board.h @@ -0,0 +1,14 @@ +/** + * \file + * + * \brief User board configuration template + * + */ +/* + * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> + */ + +#ifndef CONF_BOARD_H +#define CONF_BOARD_H + +#endif // CONF_BOARD_H diff --git a/ports/atmel-samd/boards/ugame/conf_clocks.h b/ports/atmel-samd/boards/ugame/conf_clocks.h new file mode 100644 index 000000000..9e4f7876b --- /dev/null +++ b/ports/atmel-samd/boards/ugame/conf_clocks.h @@ -0,0 +1 @@ +#include "conf_clocks_crystalless.h" diff --git a/ports/atmel-samd/boards/ugame/conf_usb.h b/ports/atmel-samd/boards/ugame/conf_usb.h new file mode 100644 index 000000000..b881ed149 --- /dev/null +++ b/ports/atmel-samd/boards/ugame/conf_usb.h @@ -0,0 +1,221 @@ + +#include <stdbool.h> +#include <stdint.h> + +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + +#ifndef CONF_USB_H_INCLUDED +#define CONF_USB_H_INCLUDED + +#define USB_DEVICE_MAJOR_VERSION 1 +#define USB_DEVICE_MINOR_VERSION 0 +#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) +#define USB_DEVICE_ATTR \ + (USB_CONFIG_ATTR_BUS_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED) +// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED) + +//! USB Device string definitions (Optional) +#ifndef USB_DEVICE_MANUFACTURE_NAME +# define USB_DEVICE_MANUFACTURE_NAME "Radomir Dopieralski" +#endif + +#ifndef USB_DEVICE_PRODUCT_NAME +# define USB_DEVICE_PRODUCT_NAME "uGame" +#endif +// #define USB_DEVICE_SERIAL_NAME "12...EF" +#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number +#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32 +extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; + +//! Control endpoint size +#define USB_DEVICE_EP_CTRL_SIZE 64 + +//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd) +#define USB_DEVICE_NB_INTERFACE 5 + +// (3 | USB_EP_DIR_IN) // CDC Notify endpoint +// (4 | USB_EP_DIR_IN) // CDC TX +// (5 | USB_EP_DIR_OUT) // CDC RX +// (1 | USB_EP_DIR_IN) // MSC IN +// (2 | USB_EP_DIR_OUT) // MSC OUT +// (6 | USB_EP_DIR_IN) // HID mouse report +// (7 | USB_EP_DIR_IN) // HID keyboard report +#define USB_DEVICE_MAX_EP 7 + +#define UDI_CDC_PORT_NB 1 +#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port) +extern bool mp_cdc_enable(uint8_t port); +#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port) +extern void mp_cdc_disable(uint8_t port); +#define UDI_CDC_LOW_RATE + +#define UDI_CDC_DEFAULT_RATE 115200 +#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1 +#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE +#define UDI_CDC_DEFAULT_DATABITS 8 + +#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() +void usb_rx_notify(void); + +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); +#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) +void usb_dtr_notify(uint8_t port, bool set); +#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) +void usb_rts_notify(uint8_t port, bool set); + +/** + * USB CDC low level configuration + * In standalone these configurations are defined by the CDC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition + +#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint +#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX +#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX + +//! Interface numbers +#define UDI_CDC_COMM_IFACE_NUMBER_0 0 +#define UDI_CDC_DATA_IFACE_NUMBER_0 1 + +/** + * Configuration of MSC interface + * @{ + */ +//! Vendor name and Product version of MSC interface +#define UDI_MSC_GLOBAL_VENDOR_ID \ + 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' ' +#define UDI_MSC_GLOBAL_PRODUCT_VERSION \ + '1', '.', '0', '0' + +//! Interface callback definition +#define UDI_MSC_ENABLE_EXT() mp_msc_enable() +extern bool mp_msc_enable(void); +#define UDI_MSC_DISABLE_EXT() mp_msc_disable() +extern void mp_msc_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_MSC_STRING_ID 5 + +/** + * USB MSC low level configuration + * In standalone these configurations are defined by the MSC module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN) +#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT) + +//! Interface number +#define UDI_MSC_IFACE_NUMBER 2 +/** + * Configuration of HID Mouse interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable() +extern bool mp_mouse_enable(void); +#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable() +extern void mp_mouse_disable(void); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_MOUSE_STRING_ID 6 + +/** + * USB HID Mouse low level configuration + * In standalone these configurations are defined by the HID Mouse module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_MOUSE_IFACE_NUMBER 3 +//@} +//@} + +/** + * Configuration of HID Keyboard interface + * @{ + */ +//! Interface callback definition +#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable() +extern bool mp_keyboard_enable(void); +#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable() +extern void mp_keyboard_disable(void); +#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value) +extern void mp_keyboard_led(uint8_t); + +//! Enable id string of interface to add an extra USB string +#define UDI_HID_KBD_STRING_ID 7 + +/** + * USB HID Keyboard low level configuration + * In standalone these configurations are defined by the HID Keyboard module. + * For composite device, these configuration must be defined here + * @{ + */ +//! Endpoint numbers definition +#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN) + +//! Interface number +#define UDI_HID_KBD_IFACE_NUMBER 4 + +/** + * Description of Composite Device + * @{ + */ +//! USB Interfaces descriptor structure +#define UDI_COMPOSITE_DESC_T \ + usb_iad_desc_t udi_cdc_iad; \ + udi_cdc_comm_desc_t udi_cdc_comm; \ + udi_cdc_data_desc_t udi_cdc_data; \ + udi_msc_desc_t udi_msc; \ + udi_hid_mouse_desc_t udi_hid_mouse; \ + udi_hid_kbd_desc_t udi_hid_kbd + +//! USB Interfaces descriptor value for Full Speed +#define UDI_COMPOSITE_DESC_FS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \ + .udi_msc = UDI_MSC_DESC_FS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interfaces descriptor value for High Speed +#define UDI_COMPOSITE_DESC_HS \ + .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \ + .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \ + .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \ + .udi_msc = UDI_MSC_DESC_HS, \ + .udi_hid_mouse = UDI_HID_MOUSE_DESC, \ + .udi_hid_kbd = UDI_HID_KBD_DESC + +//! USB Interface APIs +#define UDI_COMPOSITE_API \ + &udi_api_cdc_comm, \ + &udi_api_cdc_data, \ + &udi_api_msc, \ + &udi_api_hid_mouse, \ + &udi_api_hid_kbd +//@} + +/** + * USB Device Driver Configuration + * @{ + */ +//@} + +//! The includes of classes and other headers must be done at the end of this file to avoid compile error +#include "udi_cdc.h" +#include "udi_msc.h" +#include "udi_hid_mouse.h" +#include "udi_hid_kbd.h" + +#endif diff --git a/ports/atmel-samd/boards/ugame/mpconfigboard.h b/ports/atmel-samd/boards/ugame/mpconfigboard.h new file mode 100644 index 000000000..17baf9b0f --- /dev/null +++ b/ports/atmel-samd/boards/ugame/mpconfigboard.h @@ -0,0 +1,48 @@ +#define USB_REPL + +#define MICROPY_HW_BOARD_NAME "uGame" +#define MICROPY_HW_MCU_NAME "samd21e18" + +#if 1 +// Salae reads 12mhz which is the limit even though we set it to the +// safer 8mhz. +#define SPI_FLASH_BAUDRATE (8000000) + +#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_D +#define SPI_FLASH_PAD0_PINMUX PINMUX_PA16D_SERCOM3_PAD0 // MOSI +#define SPI_FLASH_PAD1_PINMUX PINMUX_PA17D_SERCOM3_PAD1 // SCK +#define SPI_FLASH_PAD2_PINMUX PINMUX_UNUSED // Use default pinmux for the chip + // select since we manage it + // ourselves. +#define SPI_FLASH_PAD3_PINMUX PINMUX_PA19D_SERCOM3_PAD3 // MISO +#define SPI_FLASH_SERCOM SERCOM3 + +#define SPI_FLASH_CS PIN_PA11 + +#define MICROPY_PORT_A (PORT_PA11 | PORT_PA16 |\ + PORT_PA17 | PORT_PA18 | PORT_PA19 | PORT_PA24 |\ + PORT_PA25) +#define MICROPY_PORT_B (0) + +#define CALIBRATE_CRYSTALLESS 1 + +#include "spi_flash.h" + +#define CIRCUITPY_INTERNAL_NVM_SIZE 256 +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +//#include "flash_W25Q32BV.h" +#include "flash_S25FL216K.h" + +#else + +#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_B (0) + +#include "internal_flash.h" + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#endif + diff --git a/ports/atmel-samd/boards/ugame/mpconfigboard.mk b/ports/atmel-samd/boards/ugame/mpconfigboard.mk new file mode 100644 index 000000000..40f1bc06f --- /dev/null +++ b/ports/atmel-samd/boards/ugame/mpconfigboard.mk @@ -0,0 +1,11 @@ +LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld +#LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0x239A +USB_PID = 0x801F +USB_PRODUCT = "UGame" +USB_MANUFACTURER = "Radomir Dopieralski" + +SPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD21E18A +CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/ugame/pins.c b/ports/atmel-samd/boards/ugame/pins.c new file mode 100644 index 000000000..b9c8f2386 --- /dev/null +++ b/ports/atmel-samd/boards/ugame/pins.c @@ -0,0 +1,18 @@ +#include "samd21_pins.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_X), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_O), MP_ROM_PTR(&pin_PA01) }, + + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) }, + + { MP_ROM_QSTR(MP_QSTR_UP), MP_ROM_PTR(&pin_PA03) }, + { MP_ROM_QSTR(MP_QSTR_LEFT), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_DOWN), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_RIGHT), MP_ROM_PTR(&pin_PA05) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_DC), MP_ROM_PTR(&pin_PA08) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/common-hal/analogio/AnalogIn.c b/ports/atmel-samd/common-hal/analogio/AnalogIn.c index 03c502dff..cbb9f5de5 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogIn.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogIn.c @@ -74,8 +74,10 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { config_adc.reference = ADC_REFERENCE_INTVCC1; config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2; config_adc.positive_input = self->pin->adc_input; - config_adc.resolution = ADC_RESOLUTION_16BIT; - config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128; + config_adc.resolution = ADC_RESOLUTION_12BIT; + // Default input clock is GCLK0 (48 MHz) + // 48Mhz / 32 = 1.5MHz. Max ADC clock is 2.1MHz + config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV32; struct adc_module adc_instance; // ADC must have been disabled before adc_init() is called. @@ -108,7 +110,8 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { } adc_disable(&adc_instance); - return data; + // Scale to 16 bits. In the future we might make this be this be under API control. + return data * 16; } float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) { diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c index db671f213..50d3b180c 100644 --- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -26,6 +26,7 @@ #include <stdint.h> #include <string.h> +#include <math.h> #include "py/gc.h" #include "py/mperrno.h" @@ -42,6 +43,12 @@ #include "shared_dma.h" #include "tick.h" +#define OVERSAMPLING 64 +#define SAMPLES_PER_BUFFER 32 + +// MEMS microphones must be clocked at at least 1MHz. +#define MIN_MIC_CLOCK 1000000 + void pdmin_reset(void) { while (I2S->SYNCBUSY.reg & I2S_SYNCBUSY_ENABLE) {} I2S->INTENCLR.reg = I2S_INTENCLR_MASK; @@ -96,8 +103,8 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self, mp_raise_RuntimeError("Unable to allocate audio DMA block counter."); } - if (!(bit_depth == 16 || bit_depth == 8) || !mono || oversample != 64) { - mp_raise_NotImplementedError("Only 8 or 16 bit mono with 64 oversample is supported."); + if (!(bit_depth == 16 || bit_depth == 8) || !mono || oversample != OVERSAMPLING) { + mp_raise_NotImplementedError("Only 8 or 16 bit mono with " MP_STRINGIFY(OVERSAMPLING) "x oversampling is supported."); } // TODO(tannewt): Use the DPLL to get a more precise sampling rate. @@ -112,12 +119,17 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self, config_clock_unit.clock.mck_out_enable = false; config_clock_unit.clock.sck_src = I2S_SERIAL_CLOCK_SOURCE_MCKDIV; - config_clock_unit.clock.sck_div = 8000000 / frequency / oversample; - self->frequency = 8000000 / config_clock_unit.clock.sck_div / oversample; + uint32_t clock_divisor = (uint32_t) roundf( 8000000.0f / frequency / oversample); + config_clock_unit.clock.sck_div = clock_divisor; + float mic_clock_freq = 8000000.0f / clock_divisor; + self->frequency = mic_clock_freq / oversample; + if (mic_clock_freq < MIN_MIC_CLOCK || clock_divisor == 0 || clock_divisor > 255) { + mp_raise_ValueError("sampling frequency out of range"); + } config_clock_unit.frame.number_slots = 2; config_clock_unit.frame.slot_size = I2S_SLOT_SIZE_16_BIT; - config_clock_unit.frame.data_delay = I2S_DATA_DELAY_1; + config_clock_unit.frame.data_delay = I2S_DATA_DELAY_0; config_clock_unit.frame.frame_sync.width = I2S_FRAME_SYNC_WIDTH_SLOT; @@ -141,6 +153,10 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self, i2s_serializer_set_config(&self->i2s_instance, self->serializer, &config_serializer); i2s_enable(&self->i2s_instance); + // Run the serializer all the time. This eliminates startup delay for the microphone. + i2s_clock_unit_enable(&self->i2s_instance, self->clock_unit); + i2s_serializer_enable(&self->i2s_instance, self->serializer); + self->bytes_per_sample = oversample >> 3; self->bit_depth = bit_depth; } @@ -154,6 +170,8 @@ void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t* self) { return; } i2s_disable(&self->i2s_instance); + i2s_serializer_disable(&self->i2s_instance, self->serializer); + i2s_clock_unit_disable(&self->i2s_instance, self->clock_unit); i2s_reset(&self->i2s_instance); reset_pin(self->clock_pin->pin); reset_pin(self->data_pin->pin); @@ -195,11 +213,15 @@ static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length, } dma_descriptor_create(audio_dma.descriptor, &descriptor_config); + // Do we need more values than will fit in the first buffer? + // If so, set up a second buffer chained to be filled after the first buffer. if (length * words_per_sample > words_per_buffer) { block_transfer_count = words_per_buffer; descriptor_config.next_descriptor_address = ((uint32_t)audio_dma.descriptor); if (length * words_per_sample < 2 * words_per_buffer) { - block_transfer_count = 2 * words_per_buffer - length * words_per_sample; + // Length needed is more than one buffer but less than two. + // Subtract off the size of the first buffer, and what remains is the count we need. + block_transfer_count = length * words_per_sample - words_per_buffer; descriptor_config.next_descriptor_address = 0; } descriptor_config.block_transfer_count = block_transfer_count; @@ -213,117 +235,150 @@ static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length, void start_dma(audiobusio_pdmin_obj_t* self) { dma_start_transfer_job(&audio_dma); tc_start_counter(MP_STATE_VM(audiodma_block_counter)); - i2s_clock_unit_enable(&self->i2s_instance, self->clock_unit); - i2s_serializer_enable(&self->i2s_instance, self->serializer); I2S->DATA[1].reg = I2S->DATA[1].reg; } void stop_dma(audiobusio_pdmin_obj_t* self) { - // Turn off the I2S clock and serializer. Peripheral is still enabled. - i2s_serializer_disable(&self->i2s_instance, self->serializer); - i2s_clock_unit_disable(&self->i2s_instance, self->clock_unit); - - // Shutdown the DMA + // Shutdown the DMA: serializer keeps running. tc_stop_counter(MP_STATE_VM(audiodma_block_counter)); dma_abort_job(&audio_dma); } -static const uint16_t sinc_filter[64] = { - 0, 1, 6, 16, 29, 49, 75, 108, - 149, 200, 261, 334, 418, 514, 622, 742, - 872, 1012, 1161, 1315, 1472, 1631, 1787, 1938, - 2081, 2212, 2329, 2429, 2509, 2568, 2604, 2616, - 2604, 2568, 2509, 2429, 2329, 2212, 2081, 1938, - 1787, 1631, 1472, 1315, 1161, 1012, 872, 742, - 622, 514, 418, 334, 261, 200, 149, 108, - 75, 49, 29, 16, 6, 1, 0, 0 +// a windowed sinc filter for 44 khz, 64 samples +// +// This filter is good enough to use for lower sample rates as +// well. It does not increase the noise enough to be a problem. +// +// In the long run we could use a fast filter like this to do the +// decimation and initial filtering in real time, filtering to a +// higher sample rate than specified. Then after the audio is +// recorded, a more expensive filter non-real-time filter could be +// used to down-sample and low-pass. +uint16_t sinc_filter [OVERSAMPLING] = { + 0, 2, 9, 21, 39, 63, 94, 132, + 179, 236, 302, 379, 467, 565, 674, 792, + 920, 1055, 1196, 1341, 1487, 1633, 1776, 1913, + 2042, 2159, 2263, 2352, 2422, 2474, 2506, 2516, + 2506, 2474, 2422, 2352, 2263, 2159, 2042, 1913, + 1776, 1633, 1487, 1341, 1196, 1055, 920, 792, + 674, 565, 467, 379, 302, 236, 179, 132, + 94, 63, 39, 21, 9, 2, 0, 0 }; +#define REPEAT_16_TIMES(X) X X X X X X X X X X X X X X X X + static uint16_t filter_sample(uint32_t pdm_samples[4]) { - uint16_t sample = 0; - for (uint8_t i = 0; i < 4; i++) { - uint16_t pdm = pdm_samples[i] & 0xffff; - for (uint8_t j = 0; j < 16; j++) { - if ((pdm & 0x8000) != 0) { - sample += sinc_filter[i * 16 + j]; + uint16_t running_sum = 0; + const uint16_t *filter_ptr = sinc_filter; + for (uint8_t i = 0; i < OVERSAMPLING/16; i++) { + // The sample is 16-bits right channel in the upper two bytes and 16-bits left channel + // in the lower two bytes. + // We just ignore the upper bits + uint32_t pdm_sample = pdm_samples[i]; + REPEAT_16_TIMES( { + if (pdm_sample & 0x8000) { + running_sum += *filter_ptr; + } + filter_ptr++; + pdm_sample <<= 1; } - pdm <<= 1; - } + ) } - return sample; + return running_sum; } +// output_buffer may be a byte buffer or a halfword buffer. +// output_buffer_length is the number of slots, not the number of bytes. uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self, - uint16_t* output_buffer, uint32_t length) { - // Write the wave file header. - - // We allocate two 256 byte buffers on the stack to use for double buffering. - // Our oversample rate is 64 (bits) so each buffer produces 32 samples. - // TODO(tannewt): Can the compiler optimize better if we fix the size of - // these buffers? - uint8_t samples_per_buffer = 32; + uint16_t* output_buffer, uint32_t output_buffer_length) { + // We allocate two buffers on the stack to use for double buffering. + const uint8_t samples_per_buffer = SAMPLES_PER_BUFFER; // For every word we record, we throw away 2 bytes of a phantom second channel. - uint8_t words_per_sample = self->bytes_per_sample / 2; - uint8_t words_per_buffer = samples_per_buffer * words_per_sample; + const uint8_t words_per_sample = self->bytes_per_sample / 2; + const uint8_t words_per_buffer = samples_per_buffer * words_per_sample; uint32_t first_buffer[words_per_buffer]; uint32_t second_buffer[words_per_buffer]; COMPILER_ALIGNED(16) DmacDescriptor second_descriptor; - setup_dma(self, length, &second_descriptor, words_per_buffer, + setup_dma(self, output_buffer_length, &second_descriptor, words_per_buffer, words_per_sample, first_buffer, second_buffer); start_dma(self); // Record uint32_t buffers_processed = 0; - uint32_t total_bytes = 0; + uint32_t values_output = 0; - uint64_t start_ticks = ticks_ms; - while (total_bytes < length) { + uint32_t remaining_samples_needed = output_buffer_length; + while (values_output < output_buffer_length) { // Wait for the next buffer to fill - while (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) == buffers_processed) { + uint32_t block_counter; + while ((block_counter = tc_get_count_value(MP_STATE_VM(audiodma_block_counter))) == buffers_processed) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif } - if (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) != (buffers_processed + 1)) { + if (block_counter != (buffers_processed + 1)) { + // Looks like we aren't keeping up. We shouldn't skip a buffer. break; } - // Throw away the first ~10ms of data because thats during mic start up. - if (ticks_ms - start_ticks < 10) { - buffers_processed++; - continue; - } - uint32_t* buffer = first_buffer; + + // The mic is running all the time, so we don't need to wait the usual 10msec or 100msec + // for it to start up. + + // Flip back and forth between processing the first and second buffers. + uint32_t *buffer = first_buffer; DmacDescriptor* descriptor = audio_dma.descriptor; if (buffers_processed % 2 == 1) { buffer = second_buffer; descriptor = &second_descriptor; } - // Decimate and filter the last buffer - int32_t samples_gathered = descriptor->BTCNT.reg / words_per_sample; - for (uint16_t i = 0; i < samples_gathered; i++) { + // Decimate and filter the buffer that was just filled. + uint32_t samples_gathered = descriptor->BTCNT.reg / words_per_sample; + // Don't run off the end of output buffer. Process only as many as needed. + uint32_t samples_to_process = min(remaining_samples_needed, samples_gathered); + for (uint32_t i = 0; i < samples_to_process; i++) { + // Call filter_sample just one place so it can be inlined. + uint16_t value = filter_sample(buffer + i * words_per_sample); if (self->bit_depth == 8) { - ((uint8_t*) output_buffer)[total_bytes] = filter_sample(buffer + i * words_per_sample) >> 8; - total_bytes += 1; - } else if (self->bit_depth == 16) { - output_buffer[total_bytes / 2] = filter_sample(buffer + i * words_per_sample); - total_bytes += 2; + // Truncate to 8 bits. + ((uint8_t*) output_buffer)[values_output] = value >> 8; + } else { + output_buffer[values_output] = value; } + values_output++; } + buffers_processed++; - if (length - total_bytes < samples_per_buffer) { - descriptor->BTCNT.reg = (length - total_bytes) * words_per_sample; - descriptor->DSTADDR.reg = ((uint32_t) buffer) + (length - total_bytes) * self->bytes_per_sample; + // Compute how many more samples we need, and if the last buffer is the last + // set of samples needed, adjust the DMA count to only fetch as necessary. + remaining_samples_needed = output_buffer_length - values_output; + if (remaining_samples_needed <= samples_per_buffer*2 && + remaining_samples_needed > samples_per_buffer) { + // Adjust the DMA settings for the current buffer, which will be processed + // after the other buffer, which is now receiving samples via DMA. + // We don't adjust the DMA in progress, but the one after that. + // Timeline: + // 1. current buffer (already processed) + // 2. alternate buffer (DMA in progress) + // 3. current buffer (last set of samples needed) + + // Set up to receive the last set of samples (don't include the alternate buffer, now in use). + uint32_t samples_needed_for_last_buffer = remaining_samples_needed - samples_per_buffer; + descriptor->BTCNT.reg = samples_needed_for_last_buffer * words_per_sample; + descriptor->DSTADDR.reg = ((uint32_t) buffer) + + samples_needed_for_last_buffer * words_per_sample * sizeof(buffer[0]); + + // Break chain to alternate buffer. descriptor->DESCADDR.reg = 0; } } stop_dma(self); - return total_bytes; + return values_output; } void common_hal_audiobusio_pdmin_record_to_file(audiobusio_pdmin_obj_t* self, uint8_t* buffer, uint32_t length) { diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index cb6a165de..4414d7ca9 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -262,3 +262,20 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, // } return status >= 0; // Status is number of chars read or an error code < 0. } + +bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) { + if (len == 0) { + return true; + } + int32_t status; +// if (len >= 16) { +// status = shared_dma_transfer(self->spi_master_instance.hw, data_out, data_in, len, 0 /*ignored*/); +// } else { + struct spi_xfer xfer; + xfer.txbuf = data_out; + xfer.rxbuf = data_in; + xfer.size = len; + status = spi_m_sync_transfer(&self->spi_desc, &xfer); +// } + return status >= 0; // Status is number of chars read or an error code < 0. +} diff --git a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c index c5fff4ba2..109f14b04 100644 --- a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c +++ b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c @@ -58,7 +58,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self } void common_hal_digitalio_digitalinout_switch_to_input( - digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) { + digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) { self->output = false; common_hal_digitalio_digitalinout_set_pull(self, pull); @@ -66,7 +66,7 @@ void common_hal_digitalio_digitalinout_switch_to_input( void common_hal_digitalio_digitalinout_switch_to_output( digitalio_digitalinout_obj_t* self, bool value, - enum digitalio_drive_mode_t drive_mode) { + digitalio_drive_mode_t drive_mode) { const uint8_t pin = self->pin->pin; gpio_set_pin_pull_mode(pin, GPIO_PULL_OFF); gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT); @@ -79,7 +79,7 @@ void common_hal_digitalio_digitalinout_switch_to_output( common_hal_digitalio_digitalinout_set_value(self, value); } -enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( +digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( digitalio_digitalinout_obj_t* self) { return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT; } @@ -115,7 +115,7 @@ bool common_hal_digitalio_digitalinout_get_value( void common_hal_digitalio_digitalinout_set_drive_mode( digitalio_digitalinout_obj_t* self, - enum digitalio_drive_mode_t drive_mode) { + digitalio_drive_mode_t drive_mode) { bool value = common_hal_digitalio_digitalinout_get_value(self); self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; // True is implemented differently between modes so reset the value to make @@ -125,7 +125,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode( } } -enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( +digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( digitalio_digitalinout_obj_t* self) { if (self->open_drain) { return DRIVE_MODE_OPEN_DRAIN; @@ -135,7 +135,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( } void common_hal_digitalio_digitalinout_set_pull( - digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) { + digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) { enum gpio_pull_mode asf_pull = GPIO_PULL_OFF; switch (pull) { case PULL_UP: @@ -151,7 +151,7 @@ void common_hal_digitalio_digitalinout_set_pull( gpio_set_pin_pull_mode(self->pin->pin, asf_pull); } -enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( +digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( digitalio_digitalinout_obj_t* self) { uint32_t pin = self->pin->pin; if (self->output) { diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index 5c119c439..614fac870 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -27,10 +27,13 @@ #include "py/mphal.h" #include "py/obj.h" #include "hal/include/hal_atomic.h" +#include "py/runtime.h" +#include "reset.h" #include "samd21_pins.h" #include "shared-bindings/nvm/ByteArray.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Processor.h" void common_hal_mcu_delay_us(uint32_t delay) { @@ -48,9 +51,32 @@ void common_hal_mcu_enable_interrupts(void) { atomic_leave_critical(&flags); } +extern uint32_t _ezero; + +void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { + // Set up the defaults. + _bootloader_dbl_tap = DBL_TAP_MAGIC; + _ezero = CIRCUITPY_CANARY_WORD; + + if (runmode == RUNMODE_BOOTLOADER) { + if (!bootloader_available()) { + mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present."); + } + // Pretend to be the first of the two reset presses needed to enter the + // bootloader. That way one reset will end in the bootloader. + _bootloader_dbl_tap = DBL_TAP_MAGIC; + } else if (runmode == RUNMODE_SAFE_MODE) { + _ezero = CIRCUITPY_SOFTWARE_SAFE_MODE; + } +} + +void common_hal_mcu_reset(void) { + reset(); +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. -mcu_processor_obj_t common_hal_mcu_processor_obj = { +const mcu_processor_obj_t common_hal_mcu_processor_obj = { .base = { .type = &mcu_processor_type, }, @@ -59,7 +85,7 @@ mcu_processor_obj_t common_hal_mcu_processor_obj = { // NVM is only available on Express boards for now. #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 // The singleton nvm.ByteArray object. -// nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { +// const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { // .base = { // .type = &nvm_bytearray_type, // }, diff --git a/ports/atmel-samd/reset.c b/ports/atmel-samd/reset.c index ab940285b..ba5bf9ba1 100644 --- a/ports/atmel-samd/reset.c +++ b/ports/atmel-samd/reset.c @@ -24,23 +24,22 @@ * THE SOFTWARE. */ -#include "reset.h" - #include "include/sam.h" -#include "supervisor/filesystem.h" -// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21 -#ifdef SAMD21 -#define DBL_TAP_PTR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4)) -#else - #ifdef SAMD51 - #define DBL_TAP_PTR ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4)) - #endif -#endif -#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set +#include "reset.h" +#include "supervisor/filesystem.h" -void reset_to_bootloader(void) { +void reset(void) { filesystem_flush(); - *DBL_TAP_PTR = DBL_TAP_MAGIC; NVIC_SystemReset(); } + +void reset_to_bootloader(void) { + _bootloader_dbl_tap = DBL_TAP_MAGIC; + reset(); +} + +extern uint32_t _srelocate; +bool bootloader_available(void) { + return &_bootloader_dbl_tap >= &_srelocate; +} diff --git a/ports/atmel-samd/reset.h b/ports/atmel-samd/reset.h index 88140f3b8..ea955c655 100644 --- a/ports/atmel-samd/reset.h +++ b/ports/atmel-samd/reset.h @@ -26,6 +26,16 @@ #ifndef MICROPY_INCLUDED_ATMEL_SAMD_RESET_H #define MICROPY_INCLUDED_ATMEL_SAMD_RESET_H +#include <stdbool.h> +#include <stdint.h> + +// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21 +#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set + +extern uint32_t _bootloader_dbl_tap; + void reset_to_bootloader(void); +void reset(void); +bool bootloader_available(void); #endif // MICROPY_INCLUDED_ATMEL_SAMD_RESET_H diff --git a/ports/atmel-samd/shared_dma.c b/ports/atmel-samd/shared_dma.c index f8cef0992..59fca30c8 100644 --- a/ports/atmel-samd/shared_dma.c +++ b/ports/atmel-samd/shared_dma.c @@ -106,7 +106,7 @@ int32_t shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length) } dma_configure(general_dma_tx.channel_id, sercom_index(sercom) * 2 + 2, false); - // Set up TX second. + // Set up TX. There is no RX job. struct dma_descriptor_config descriptor_config; dma_descriptor_get_config_defaults(&descriptor_config); descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; @@ -141,6 +141,11 @@ int32_t shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length) int32_t shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx) { if (general_dma_tx.job_status != ERR_NONE) { +} + +// Do write and read simultaneously. If buffer_out is NULL, write the tx byte over and over. +// If buffer_out is a real buffer, ignore tx. +enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx) { return general_dma_tx.job_status; } @@ -156,17 +161,19 @@ int32_t shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_ descriptor_config.block_transfer_count = length; // DATA register is consistently addressed across all SERCOM modes. descriptor_config.source_address = ((uint32_t)&sercom->SPI.DATA.reg); - descriptor_config.destination_address = ((uint32_t)buffer + length); + descriptor_config.destination_address = ((uint32_t)buffer_in + length); dma_descriptor_create(general_dma_rx.descriptor, &descriptor_config); - // Set up TX to retransmit the same byte over and over. + // Set up TX second. dma_descriptor_get_config_defaults(&descriptor_config); descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE; - descriptor_config.src_increment_enable = false; + // Increment write address only if we have a real buffer. + descriptor_config.src_increment_enable = buffer_out != NULL; descriptor_config.dst_increment_enable = false; descriptor_config.block_transfer_count = length; - descriptor_config.source_address = ((uint32_t)&tx); + // + descriptor_config.source_address = ((uint32_t) (buffer_out != NULL ? buffer_out + length : &tx)); // DATA register is consistently addressed across all SERCOM modes. descriptor_config.destination_address = ((uint32_t)&sercom->SPI.DATA.reg); diff --git a/ports/atmel-samd/shared_dma.h b/ports/atmel-samd/shared_dma.h index 1e9240338..2ddd81c4e 100644 --- a/ports/atmel-samd/shared_dma.h +++ b/ports/atmel-samd/shared_dma.h @@ -37,6 +37,7 @@ void init_shared_dma(void); enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length); enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx); +enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx); // Allocate a counter to track how far along we are in a DMA double buffer. bool allocate_block_counter(void); |
