merge from 2.2.0 + fix up board defs
This commit is contained in:
parent
ce81c8dda9
commit
065e82015f
|
@ -26,6 +26,9 @@
|
|||
[submodule "frozen/Adafruit_CircuitPython_BusDevice"]
|
||||
path = frozen/Adafruit_CircuitPython_BusDevice
|
||||
url = https://github.com/adafruit/Adafruit_CircuitPython_BusDevice.git
|
||||
[submodule "tools/python-semver"]
|
||||
path = tools/python-semver
|
||||
url = https://github.com/k-bx/python-semver.git
|
||||
[submodule "lib/stm32lib"]
|
||||
path = lib/stm32lib
|
||||
url = https://github.com/micropython/stm32lib
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
python:
|
||||
version: 3
|
|
@ -15,19 +15,29 @@ This often happens on Windows when the ``CIRCUITPY`` disk is not safely ejected
|
|||
before being reset by the button or being disconnected from USB. This can also
|
||||
happen on Linux and Mac OSX but its less likely.
|
||||
|
||||
.. caution:: Delete ``CIRCUITPY`` filesystem and reload CircuitPython.
|
||||
.. caution:: To erase and re-create ``CIRCUITPY`` (for example, to correct a corrupted filesystem),
|
||||
follow one of the procedures below. It's important to note that **any files stored on the**
|
||||
``CIRCUITPY`` **drive will be erased**.
|
||||
|
||||
To reload CircuitPython (for example, to correct a corrupted filesystem),
|
||||
follow the process below. It's important to note that **any files stored on the
|
||||
``CIRCUITPY`` drive will be erased**.
|
||||
**For boards with** ``CIRCUITPY`` **stored on a separate SPI flash chip,
|
||||
such as Feather M0 Express, Metro M0 Express and Circuit Playground Express:**
|
||||
|
||||
#. Download the appropriate flash erase uf2 from `here <https://github.com/adafruit/Adafruit_SPIFlash/tree/master/examples/flash_erase_express>`_.
|
||||
|
||||
#. Download the appropriate flash .erase uf2 from `here <https://github.com/adafruit/Adafruit_SPIFlash/tree/master/examples/flash_erase_express>`_.
|
||||
#. Double-click the reset button.
|
||||
#. Copy the appropriate .uf2 to the xxxBOOT drive.
|
||||
#. The on-board NeoPixel will turn blue, indicating the erase has started.
|
||||
#. After about 15 seconds, the NexoPixel will start flashing green. If it flashes red, the erase failed.
|
||||
#. Double-click again and load the appropriate `CircuitPython .uf2 <https://github.com/adafruit/circuitpython/releases/latest>`_.
|
||||
|
||||
**For boards without SPI flash, such as Feather M0 Proto, Gemma M0 and, Trinket M0:**
|
||||
|
||||
#. Download the appropriate erase .uf2 from `here <https://github.com/adafruit/Adafruit_Learning_System_Guides/tree/master/uf2_flash_erasers>`_.
|
||||
#. Double-click the reset button.
|
||||
#. Copy the appropriate .uf2 to the xxxBOOT drive.
|
||||
#. The boot LED will start pulsing again, and the xxxBOOT drive will appear again.
|
||||
#. Load the appropriate `CircuitPython .uf2 <https://github.com/adafruit/circuitpython/releases/latest>`_.
|
||||
|
||||
ValueError: Incompatible ``.mpy`` file.
|
||||
---------------------------------------
|
||||
|
||||
|
@ -35,9 +45,9 @@ This error occurs when importing a module that is stored as a ``mpy`` binary fil
|
|||
(rather than a ``py`` text file) that was generated by a different version of
|
||||
CircuitPython than the one its being loaded into. Most versions are compatible
|
||||
but, rarely they aren't. In particular, the ``mpy`` binary format changed between
|
||||
CircuitPython versions 1.x and 2.x.
|
||||
CircuitPython versions 1.x and 2.x, and will change again between 2.x and 3.x.
|
||||
|
||||
So, if you just upgraded to CircuitPython 2.x from 1.x you'll need to download a
|
||||
So, for instance, if you just upgraded to CircuitPython 2.x from 1.x you'll need to download a
|
||||
newer version of the library that triggered the error on ``import``. They are
|
||||
all available in the
|
||||
`Adafruit bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/latest>`_
|
||||
|
|
|
@ -18,7 +18,7 @@ float nearbyintf(float x)
|
|||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
if (y == 0)
|
||||
#pragma GCC diagnostic pop
|
||||
return s ? -0.0f : 0.0f;
|
||||
#pragma GCC diagnostic pop
|
||||
return y;
|
||||
}
|
||||
|
|
|
@ -255,7 +255,8 @@ STATIC int pyexec_friendly_repl_process_char(int c) {
|
|||
} else if (ret == CHAR_CTRL_B) {
|
||||
// reset friendly REPL
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
mp_hal_stdout_tx_str("Adafruit CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n");
|
||||
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
// mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n");
|
||||
goto input_restart;
|
||||
} else if (ret == CHAR_CTRL_C) {
|
||||
|
@ -394,7 +395,9 @@ int pyexec_friendly_repl(void) {
|
|||
#endif
|
||||
|
||||
friendly_repl_reset:
|
||||
mp_hal_stdout_tx_str("\r\nAdafruit CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n");
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO);
|
||||
mp_hal_stdout_tx_str("\r\n");
|
||||
// mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n");
|
||||
|
||||
// to test ctrl-C
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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_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_CS 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
}
|
|
@ -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_
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
#include "conf_clocks_external_32k.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
|
|
@ -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"
|
|
@ -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
|
||||
|
|
@ -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);
|
|
@ -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
|
|
@ -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
|
|
@ -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) {
|
||||
}
|
|
@ -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_
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
#include "conf_clocks_crystalless.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
|
|
@ -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"
|
|
@ -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
|
||||
|
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,6 +12,7 @@ MEMORY
|
|||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_bootloader_dbl_tap = 0;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
|
|
@ -12,6 +12,7 @@ MEMORY
|
|||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_bootloader_dbl_tap = 0;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,6 +11,7 @@ MEMORY
|
|||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_bootloader_dbl_tap = 0;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
|
|
@ -11,6 +11,7 @@ MEMORY
|
|||
|
||||
/* top end of the stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_bootloader_dbl_tap = 0;
|
||||
|
||||
/* define output sections */
|
||||
SECTIONS
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
}
|
|
@ -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_
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
#include "conf_clocks_crystalless.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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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);
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
pdm <<= 1;
|
||||
filter_ptr++;
|
||||
pdm_sample <<= 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) {
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
// },
|
||||
|
|
|
@ -24,23 +24,22 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "reset.h"
|
||||
|
||||
#include "include/sam.h"
|
||||
|
||||
#include "reset.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
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -130,6 +130,7 @@ SRC_BINDINGS_ENUMS = \
|
|||
digitalio/DriveMode.c \
|
||||
digitalio/Pull.c \
|
||||
math/__init__.c \
|
||||
microcontroller/RunMode.c \
|
||||
util.c
|
||||
|
||||
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
|
||||
|
|
|
@ -185,3 +185,23 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
|
||||
// Process data in chunks, let the pending tasks run in between
|
||||
size_t chunk_size = 1024; // TODO this should depend on baudrate
|
||||
size_t count = len / chunk_size;
|
||||
size_t i = 0;
|
||||
for (size_t j = 0; j < count; ++j) {
|
||||
for (size_t k = 0; k < chunk_size; ++k) {
|
||||
data_in[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out[i], 8, 0);
|
||||
++i;
|
||||
}
|
||||
ets_loop_iter();
|
||||
}
|
||||
while (i < len) {
|
||||
data_in[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out[i], 8, 0);
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
|
|
@ -59,7 +59,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;
|
||||
|
||||
if (self->pin->gpio_number == 16) {
|
||||
|
@ -75,7 +75,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) {
|
||||
self->output = true;
|
||||
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
|
||||
if (self->pin->gpio_number == 16) {
|
||||
|
@ -89,7 +89,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;
|
||||
}
|
||||
|
@ -136,7 +136,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
|
||||
|
@ -146,7 +146,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;
|
||||
|
@ -156,7 +156,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) {
|
||||
if (pull == PULL_DOWN) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"ESP8266 does not support pull down."));
|
||||
|
@ -174,7 +174,7 @@ void common_hal_digitalio_digitalinout_set_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) {
|
||||
if (self->pin->gpio_number < 16 &&
|
||||
(READ_PERI_REG(self->pin->peripheral) & PERIPHS_IO_MUX_PULLUP) != 0) {
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "common-hal/microcontroller/Processor.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/microcontroller/Processor.h"
|
||||
|
||||
|
@ -34,6 +37,7 @@
|
|||
#include "ets_alt_task.h"
|
||||
#include "etshal.h"
|
||||
#include "osapi.h"
|
||||
#include "user_interface.h"
|
||||
#include "xtirq.h"
|
||||
|
||||
#define ETS_LOOP_ITER_BIT (12)
|
||||
|
@ -54,9 +58,21 @@ void common_hal_mcu_enable_interrupts() {
|
|||
enable_irq(saved_interrupt_state & ~(1 << ETS_LOOP_ITER_BIT));
|
||||
}
|
||||
|
||||
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
|
||||
if (runmode == RUNMODE_BOOTLOADER) {
|
||||
mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present.");
|
||||
} else if (runmode == RUNMODE_SAFE_MODE) {
|
||||
mp_raise_ValueError("ESP8226 does not support safe mode.");
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_mcu_reset(void) {
|
||||
system_restart();
|
||||
}
|
||||
|
||||
// The singleton microcontroller.Processor object, returned by 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,
|
||||
},
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
# $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers.
|
||||
# This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h.
|
||||
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
|
||||
|
||||
INTERNAL_LIBM = (1)
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ def make_version_header(filename):
|
|||
#define MICROPY_VERSION_MINOR (%s)
|
||||
#define MICROPY_VERSION_MICRO (%s)
|
||||
#define MICROPY_VERSION_STRING "%s"
|
||||
#define MICROPY_FULL_VERSION_INFO ("Adafruit CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME)
|
||||
""" % (git_tag, git_hash, datetime.date.today().strftime("%Y-%m-%d"),
|
||||
ver[0].replace('v', ''), ver[1], ver[2], version_string)
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ endif
|
|||
MAKE_FROZEN = $(TOP)/tools/make-frozen.py
|
||||
MPY_CROSS = $(TOP)/mpy-cross/mpy-cross
|
||||
MPY_TOOL = $(TOP)/tools/mpy-tool.py
|
||||
PREPROCESS_FROZEN_MODULES = PYTHONPATH=$(TOP)/tools/python-semver $(TOP)/tools/preprocess_frozen_modules.py
|
||||
|
||||
all:
|
||||
.PHONY: all
|
||||
|
|
|
@ -114,13 +114,13 @@ $(MPY_CROSS): $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/ports/windows/fmod
|
|||
$(Q)$(MAKE) -C $(TOP)/mpy-cross
|
||||
|
||||
# Copy all the modules and single python files to freeze to a common area, omitting top-level dirs (the repo names).
|
||||
# Remove any conf.py (sphinx config) and setup.py (module install info) files, which are not meant to be frozen.
|
||||
# Do any preprocessing necessary: currently, this adds version information, removes examples, and
|
||||
# non-library .py files in the modules (setup.py and conf.py)
|
||||
# Then compile .mpy files from all the .py files, placing them in the same directories as the .py files.
|
||||
$(BUILD)/frozen_mpy: $(FROZEN_MPY_DIRS)
|
||||
$(ECHO) FREEZE $(FROZEN_MPY_DIRS)
|
||||
$(Q)$(MKDIR) -p $@
|
||||
$(Q)$(RSYNC) -rL --include="*/" --include='*.py' --exclude="*" $(addsuffix /*,$(FROZEN_MPY_DIRS)) $@
|
||||
$(Q)$(RM) -f $@/conf.py $@/setup.py
|
||||
$(Q)$(PREPROCESS_FROZEN_MODULES) -o $@ $(FROZEN_MPY_DIRS)
|
||||
$(Q)$(CD) $@ && \
|
||||
$(FIND) -L . -type f -name '*.py' | sed 's=^\./==' | \
|
||||
xargs -n1 $(abspath $(MPY_CROSS)) $(MPY_CROSS_FLAGS)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
# dummy file to work around readthedocs bug: https://github.com/rtfd/readthedocs.org/issues/2855
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <py/runtime.h>
|
||||
|
||||
#include "__init__.h"
|
||||
#include "Layer.h"
|
||||
|
||||
//| .. currentmodule:: _stage
|
||||
//|
|
||||
//| :class:`Layer` -- Keep information about a single layer of graphics
|
||||
//| ===================================================================
|
||||
//|
|
||||
//| .. class:: Layer(width, height, graphic, palette, [grid])
|
||||
//|
|
||||
//| Keep internal information about a layer of graphics (either a
|
||||
//| ``Grid`` or a ``Sprite``) in a format suitable for fast rendering
|
||||
//| with the ``render()`` function.
|
||||
//|
|
||||
//| :param int width: The width of the grid in tiles, or 1 for sprites.
|
||||
//| :param int height: The height of the grid in tiles, or 1 for sprites.
|
||||
//| :param bytearray graphic: The graphic data of the tiles.
|
||||
//| :param bytearray palette: The color palette to be used.
|
||||
//| :param bytearray grid: The contents of the grid map.
|
||||
//|
|
||||
//| This class is intended for internal use in the ``stage`` library and
|
||||
//| it shouldn't be used on its own.
|
||||
//|
|
||||
STATIC mp_obj_t layer_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 4, 5, false);
|
||||
|
||||
layer_obj_t *self = m_new_obj(layer_obj_t);
|
||||
self->base.type = type;
|
||||
|
||||
self->width = mp_obj_get_int(args[0]);
|
||||
self->height = mp_obj_get_int(args[1]);
|
||||
self->x = 0;
|
||||
self->y = 0;
|
||||
self->frame = 0;
|
||||
self->rotation = false;
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
|
||||
self->graphic = bufinfo.buf;
|
||||
if (bufinfo.len != 2048) {
|
||||
mp_raise_ValueError("graphic must be 2048 bytes long");
|
||||
}
|
||||
|
||||
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
|
||||
self->palette = bufinfo.buf;
|
||||
if (bufinfo.len != 32) {
|
||||
mp_raise_ValueError("palette must be 32 bytes long");
|
||||
}
|
||||
|
||||
if (n_args > 4) {
|
||||
mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ);
|
||||
self->map = bufinfo.buf;
|
||||
if (bufinfo.len < (self->width * self->height) / 2) {
|
||||
mp_raise_ValueError("map buffer too small");
|
||||
}
|
||||
} else {
|
||||
self-> map = NULL;
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| .. method:: move(x, y)
|
||||
//|
|
||||
//| Set the offset of the layer to the specified values.
|
||||
//|
|
||||
STATIC mp_obj_t layer_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
|
||||
layer_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
self->x = mp_obj_get_int(x_in);
|
||||
self->y = mp_obj_get_int(y_in);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(layer_move_obj, layer_move);
|
||||
|
||||
//| .. method:: frame(frame, rotation)
|
||||
//|
|
||||
//| Set the animation frame of the sprite, and optionally rotation its
|
||||
//| graphic.
|
||||
//|
|
||||
STATIC mp_obj_t layer_frame(mp_obj_t self_in, mp_obj_t frame_in,
|
||||
mp_obj_t rotation_in) {
|
||||
layer_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
self->frame = mp_obj_get_int(frame_in);
|
||||
self->rotation = mp_obj_get_int(rotation_in);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(layer_frame_obj, layer_frame);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t layer_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_move), MP_ROM_PTR(&layer_move_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_frame), MP_ROM_PTR(&layer_frame_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(layer_locals_dict, layer_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t mp_type_layer = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Layer,
|
||||
.make_new = layer_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&layer_locals_dict,
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED__STAGE_LAYER_H
|
||||
#define MICROPY_INCLUDED__STAGE_LAYER_H
|
||||
|
||||
#include "shared-module/_stage/Layer.h"
|
||||
|
||||
extern const mp_obj_type_t mp_type_layer;
|
||||
|
||||
#endif // MICROPY_INCLUDED__STAGE_LAYER
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <py/runtime.h>
|
||||
|
||||
#include "__init__.h"
|
||||
#include "Text.h"
|
||||
|
||||
//| .. currentmodule:: _stage
|
||||
//|
|
||||
//| :class:`Text` -- Keep information about a single text of text
|
||||
//| ==============================================================
|
||||
//|
|
||||
//| .. class:: Text(width, height, font, palette, chars)
|
||||
//|
|
||||
//| Keep internal information about a text of text
|
||||
//| in a format suitable for fast rendering
|
||||
//| with the ``render()`` function.
|
||||
//|
|
||||
//| :param int width: The width of the grid in tiles, or 1 for sprites.
|
||||
//| :param int height: The height of the grid in tiles, or 1 for sprites.
|
||||
//| :param bytearray font: The font data of the characters.
|
||||
//| :param bytearray palette: The color palette to be used.
|
||||
//| :param bytearray chars: The contents of the character grid.
|
||||
//|
|
||||
//| This class is intended for internal use in the ``stage`` library and
|
||||
//| it shouldn't be used on its own.
|
||||
//|
|
||||
STATIC mp_obj_t text_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 5, 5, false);
|
||||
|
||||
text_obj_t *self = m_new_obj(text_obj_t);
|
||||
self->base.type = type;
|
||||
|
||||
self->width = mp_obj_get_int(args[0]);
|
||||
self->height = mp_obj_get_int(args[1]);
|
||||
self->x = 0;
|
||||
self->y = 0;
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
|
||||
self->font = bufinfo.buf;
|
||||
if (bufinfo.len != 2048) {
|
||||
mp_raise_ValueError("font must be 2048 bytes long");
|
||||
}
|
||||
|
||||
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
|
||||
self->palette = bufinfo.buf;
|
||||
if (bufinfo.len != 32) {
|
||||
mp_raise_ValueError("palette must be 32 bytes long");
|
||||
}
|
||||
|
||||
mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ);
|
||||
self->chars = bufinfo.buf;
|
||||
if (bufinfo.len < self->width * self->height) {
|
||||
mp_raise_ValueError("chars buffer too small");
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| .. method:: move(x, y)
|
||||
//|
|
||||
//| Set the offset of the text to the specified values.
|
||||
//|
|
||||
STATIC mp_obj_t text_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) {
|
||||
text_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
self->x = mp_obj_get_int(x_in);
|
||||
self->y = mp_obj_get_int(y_in);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(text_move_obj, text_move);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t text_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_move), MP_ROM_PTR(&text_move_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(text_locals_dict, text_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t mp_type_text = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Text,
|
||||
.make_new = text_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&text_locals_dict,
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED__STAGE_TEXT_H
|
||||
#define MICROPY_INCLUDED__STAGE_TEXT_H
|
||||
|
||||
#include "shared-module/_stage/Text.h"
|
||||
|
||||
extern const mp_obj_type_t mp_type_text;
|
||||
|
||||
#endif // MICROPY_INCLUDED__STAGE_TEXT
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "__init__.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/busio/SPI.h"
|
||||
#include "shared-module/_stage/__init__.h"
|
||||
#include "Layer.h"
|
||||
#include "Text.h"
|
||||
|
||||
//| .. currentmodule:: _stage
|
||||
//|
|
||||
//| .. function:: render(x0, y0, x1, y1, layers, buffer, spi)
|
||||
//|
|
||||
//| Render and send to the display a fragment of the screen.
|
||||
//|
|
||||
//| :param int x0: Left edge of the fragment.
|
||||
//| :param int y0: Top edge of the fragment.
|
||||
//| :param int x1: Right edge of the fragment.
|
||||
//| :param int y1: Bottom edge of the fragment.
|
||||
//| :param list layers: A list of the `Layer` objects.
|
||||
//| :param bytearray buffer: A buffer to use for rendering.
|
||||
//| :param SPI spi: The SPI device to use.
|
||||
//|
|
||||
//| Note that this function only sends the raw pixel data. Setting up
|
||||
//| the display for receiving it and handling the chip-select and
|
||||
//| data-command pins has to be done outside of it.
|
||||
//| There are also no sanity checks, outside of the basic overflow
|
||||
//| checking. The caller is responsible for making the passed parameters
|
||||
//| valid.
|
||||
//|
|
||||
//| This function is intended for internal use in the ``stage`` library
|
||||
//| and all the necessary checks are performed there.
|
||||
STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) {
|
||||
uint8_t x0 = mp_obj_get_int(args[0]);
|
||||
uint8_t y0 = mp_obj_get_int(args[1]);
|
||||
uint8_t x1 = mp_obj_get_int(args[2]);
|
||||
uint8_t y1 = mp_obj_get_int(args[3]);
|
||||
|
||||
size_t layers_size = 0;
|
||||
mp_obj_t *layers;
|
||||
mp_obj_get_array(args[4], &layers_size, &layers);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[5], &bufinfo, MP_BUFFER_WRITE);
|
||||
uint16_t *buffer = bufinfo.buf;
|
||||
size_t buffer_size = bufinfo.len / 2; // 16-bit indexing
|
||||
|
||||
busio_spi_obj_t *spi = MP_OBJ_TO_PTR(args[6]);
|
||||
|
||||
if (!render_stage(x0, y0, x1, y1, layers, layers_size,
|
||||
buffer, buffer_size, spi)) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stage_render_obj, 7, 7, stage_render);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t stage_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__stage) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Layer), MP_ROM_PTR(&mp_type_layer) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Text), MP_ROM_PTR(&mp_type_text) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_render), MP_ROM_PTR(&stage_render_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(stage_module_globals, stage_module_globals_table);
|
||||
|
||||
const mp_obj_module_t stage_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&stage_module_globals,
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED__STAGE_H
|
||||
#define MICROPY_INCLUDED__STAGE_H
|
||||
|
||||
#include "shared-module/_stage/__init__.h"
|
||||
|
||||
#endif // MICROPY_INCLUDED__STAGE
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "lib/utils/context_manager_helpers.h"
|
||||
#include "py/binary.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
@ -41,7 +42,7 @@
|
|||
//|
|
||||
//| PDMIn can be used to record an input audio signal on a given set of pins.
|
||||
//|
|
||||
//| .. class:: PDMIn(clock_pin, data_pin, \*, frequency=8000, bit_depth=8, mono=True, oversample=64)
|
||||
//| .. class:: PDMIn(clock_pin, data_pin, \*, frequency=16000, bit_depth=8, mono=True, oversample=64, startup_delay=0.11)
|
||||
//|
|
||||
//| Create a PDMIn object associated with the given pins. This allows you to
|
||||
//| record audio signals from the given pins. Individual ports may put further
|
||||
|
@ -51,11 +52,16 @@
|
|||
//|
|
||||
//| :param ~microcontroller.Pin clock_pin: The pin to output the clock to
|
||||
//| :param ~microcontroller.Pin data_pin: The pin to read the data from
|
||||
//| :param int frequency: Target frequency in Hz of the resulting samples. Check `frequency` for real value
|
||||
//| :param int frequency: Target frequency of the resulting samples. Check `frequency` for actual value.
|
||||
//| Minimum frequency is about 16000 Hz.
|
||||
//| :param int bit_depth: Final number of bits per sample. Must be divisible by 8
|
||||
//| :param bool mono: True when capturing a single channel of audio, captures two channels otherwise
|
||||
//| :param int oversample: Number of single bit samples to decimate into a final sample. Must be divisible by 8
|
||||
//| :param float startup_delay: seconds to wait after starting microphone clock
|
||||
//| to allow microphone to turn on. Most require only 0.01s; some require 0.1s. Longer is safer.
|
||||
//| Must be in range 0.0-1.0 seconds.
|
||||
//|
|
||||
|
||||
//| Record 8-bit unsigned samples to buffer::
|
||||
//|
|
||||
//| import audiobusio
|
||||
|
@ -81,15 +87,19 @@
|
|||
//| mic.record(b, len(b))
|
||||
//|
|
||||
STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
|
||||
enum { ARG_frequency, ARG_bit_depth, ARG_mono, ARG_oversample };
|
||||
enum { ARG_frequency, ARG_bit_depth, ARG_mono, ARG_oversample, ARG_startup_delay };
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_frequency, MP_ARG_INT, {.u_int = 8000} },
|
||||
{ MP_QSTR_bit_depth, MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_mono, MP_ARG_BOOL,{.u_bool = true} },
|
||||
{ MP_QSTR_oversample, MP_ARG_INT, {.u_int = 64} },
|
||||
{ MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16000} },
|
||||
{ MP_QSTR_bit_depth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_mono, MP_ARG_KW_ONLY | MP_ARG_BOOL,{.u_bool = true} },
|
||||
{ MP_QSTR_oversample, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} },
|
||||
{ MP_QSTR_startup_delay, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
// Default microphone startup delay is 110msecs. Have seen mics that need 100 msecs plus a bit.
|
||||
static const float STARTUP_DELAY_DEFAULT = 0.110F;
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 2, pos_args + 2, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
|
@ -118,9 +128,19 @@ STATIC mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar
|
|||
}
|
||||
bool mono = args[ARG_mono].u_bool;
|
||||
|
||||
float startup_delay = (args[ARG_startup_delay].u_obj == MP_OBJ_NULL)
|
||||
? STARTUP_DELAY_DEFAULT
|
||||
: mp_obj_get_float(args[ARG_startup_delay].u_obj);
|
||||
if (startup_delay < 0.0 || startup_delay > 1.0) {
|
||||
mp_raise_ValueError("Microphone startup delay must be in range 0.0 to 1.0");
|
||||
}
|
||||
|
||||
common_hal_audiobusio_pdmin_construct(self, clock_pin, data_pin, frequency,
|
||||
bit_depth, mono, oversample);
|
||||
|
||||
// Wait for the microphone to start up. Some start in 10 msecs; some take as much as 100 msecs.
|
||||
mp_hal_delay_ms(startup_delay * 1000);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
|
@ -162,11 +182,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_pdmin___exit___obj, 4, 4,
|
|||
//| audio at the given rate. For internal flash, writing all 1s to the file
|
||||
//| before recording is recommended to speed up writes.
|
||||
//|
|
||||
//| :return: The number of samples recorded. If this is less than `destination_length`,
|
||||
//| some samples were missed due to processing time.
|
||||
//|
|
||||
STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destination, mp_obj_t destination_length) {
|
||||
audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_obj);
|
||||
raise_error_if_deinited(common_hal_audiobusio_pdmin_deinited(self));
|
||||
if (!MP_OBJ_IS_SMALL_INT(destination_length)) {
|
||||
mp_raise_TypeError("destination_length must be int");
|
||||
if (!MP_OBJ_IS_SMALL_INT(destination_length) || MP_OBJ_SMALL_INT_VALUE(destination_length) < 0) {
|
||||
mp_raise_TypeError("destination_length must be an int >= 0");
|
||||
}
|
||||
uint32_t length = MP_OBJ_SMALL_INT_VALUE(destination_length);
|
||||
|
||||
|
@ -174,8 +197,8 @@ STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat
|
|||
if (MP_OBJ_IS_TYPE(destination, &fatfs_type_fileio)) {
|
||||
mp_raise_NotImplementedError("");
|
||||
} else if (mp_get_buffer(destination, &bufinfo, MP_BUFFER_WRITE)) {
|
||||
if (bufinfo.len < length) {
|
||||
mp_raise_ValueError("Target buffer cannot hold destination_length bytes.");
|
||||
if (bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL) < length) {
|
||||
mp_raise_ValueError("Destination capacity is smaller than destination_length.");
|
||||
}
|
||||
uint8_t bit_depth = common_hal_audiobusio_pdmin_get_bit_depth(self);
|
||||
if (bufinfo.typecode != 'H' && bit_depth == 16) {
|
||||
|
@ -183,12 +206,10 @@ STATIC mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat
|
|||
} else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE && bit_depth == 8) {
|
||||
mp_raise_ValueError("destination buffer must be a bytearray or array of type 'B' for bit_depth = 8");
|
||||
}
|
||||
length *= bit_depth / 8;
|
||||
// length is the buffer length in slots, not bytes.
|
||||
uint32_t length_written =
|
||||
common_hal_audiobusio_pdmin_record_to_buffer(self, bufinfo.buf, length);
|
||||
if (length_written != length) {
|
||||
mp_printf(&mp_plat_print, "length mismatch %d %d\n", length_written, length);
|
||||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(length_written);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
|
|||
//|
|
||||
//| Read into ``buffer`` from the slave specified by ``address``.
|
||||
//| The number of bytes read will be the length of ``buffer``.
|
||||
//| At least one byte must be read.
|
||||
//|
|
||||
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
|
||||
//| as if ``buffer[start:end]``. This will not cause an allocation like
|
||||
|
@ -186,6 +187,9 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a
|
|||
int32_t start = args[ARG_start].u_int;
|
||||
uint32_t length = bufinfo.len;
|
||||
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
|
||||
if (length == 0) {
|
||||
mp_raise_ValueError("Buffer must be at least length 1");
|
||||
}
|
||||
uint8_t status = shared_module_bitbangio_i2c_read(self,
|
||||
args[ARG_address].u_int,
|
||||
((uint8_t*)bufinfo.buf) + start,
|
||||
|
@ -206,6 +210,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea
|
|||
//| as if ``buffer[start:end]``. This will not cause an allocation like
|
||||
//| ``buffer[start:end]`` will so it saves memory.
|
||||
//|
|
||||
//| Writing a buffer or slice of length zero is permitted, as it can be used
|
||||
//| to poll for the existence of a device.
|
||||
//|
|
||||
//| :param int address: 7-bit device address
|
||||
//| :param bytearray buffer: buffer containing the bytes to write
|
||||
//| :param int start: Index to start writing from
|
||||
|
|
|
@ -191,6 +191,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock);
|
|||
//| .. method:: SPI.write(buf)
|
||||
//|
|
||||
//| Write the data contained in ``buf``. Requires the SPI being locked.
|
||||
//| If the buffer is empty, nothing happens.
|
||||
//|
|
||||
// TODO(tannewt): Add support for start and end kwargs.
|
||||
STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) {
|
||||
|
@ -198,6 +199,9 @@ STATIC mp_obj_t bitbangio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) {
|
|||
raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
|
||||
mp_buffer_info_t src;
|
||||
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
|
||||
if (src.len == 0) {
|
||||
return mp_const_none;
|
||||
}
|
||||
check_lock(self);
|
||||
bool ok = shared_module_bitbangio_spi_write(self, src.buf, src.len);
|
||||
if (!ok) {
|
||||
|
@ -210,7 +214,9 @@ MP_DEFINE_CONST_FUN_OBJ_2(bitbangio_spi_write_obj, bitbangio_spi_write);
|
|||
|
||||
//| .. method:: SPI.readinto(buf)
|
||||
//|
|
||||
//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked.
|
||||
//| Read into the buffer specified by ``buf`` while writing zeroes.
|
||||
//| Requires the SPI being locked.
|
||||
//| If the number of bytes to read is 0, nothing happens.
|
||||
//|
|
||||
// TODO(tannewt): Add support for start and end kwargs.
|
||||
STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) {
|
||||
|
@ -218,6 +224,9 @@ STATIC mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *args) {
|
|||
raise_error_if_deinited(shared_module_bitbangio_spi_deinited(self));
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
|
||||
if (bufinfo.len == 0) {
|
||||
return mp_const_none;
|
||||
}
|
||||
check_lock(args[0]);
|
||||
bool ok = shared_module_bitbangio_spi_read(self, bufinfo.buf, bufinfo.len);
|
||||
if (!ok) {
|
||||
|
|
|
@ -171,6 +171,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
|
|||
//|
|
||||
//| Read into ``buffer`` from the slave specified by ``address``.
|
||||
//| The number of bytes read will be the length of ``buffer``.
|
||||
//| At least one byte must be read.
|
||||
//|
|
||||
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
|
||||
//| as if ``buffer[start:end]``. This will not cause an allocation like
|
||||
|
@ -201,6 +202,10 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args,
|
|||
int32_t start = args[ARG_start].u_int;
|
||||
uint32_t length = bufinfo.len;
|
||||
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
|
||||
if (length == 0) {
|
||||
mp_raise_ValueError("Buffer must be at least length 1");
|
||||
}
|
||||
|
||||
uint8_t status = common_hal_busio_i2c_read(self, args[ARG_address].u_int, ((uint8_t*)bufinfo.buf) + start, length);
|
||||
if (status != 0) {
|
||||
mp_raise_OSError(status);
|
||||
|
@ -219,6 +224,9 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 3, busio_i2c_readfrom_in
|
|||
//| as if ``buffer[start:end]``. This will not cause an allocation like
|
||||
//| ``buffer[start:end]`` will so it saves memory.
|
||||
//|
|
||||
//| Writing a buffer or slice of length zero is permitted, as it can be used
|
||||
//| to poll for the existence of a device.
|
||||
//|
|
||||
//| :param int address: 7-bit device address
|
||||
//| :param bytearray buffer: buffer containing the bytes to write
|
||||
//| :param int start: Index to start writing from
|
||||
|
|
|
@ -206,11 +206,12 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock);
|
|||
|
||||
//| .. method:: SPI.write(buffer, \*, start=0, end=len(buffer))
|
||||
//|
|
||||
//| Write the data contained in ``buf``. Requires the SPI being locked.
|
||||
//| Write the data contained in ``buffer``. The SPI object must be locked.
|
||||
//| If the buffer is empty, nothing happens.
|
||||
//|
|
||||
//| :param bytearray buffer: buffer containing the bytes to write
|
||||
//| :param int start: Index to start writing from
|
||||
//| :param int end: Index to read up to but not include
|
||||
//| :param bytearray buffer: Write out the data in this buffer
|
||||
//| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]``
|
||||
//| :param int end: End of the slice; this index is not included
|
||||
//|
|
||||
STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_buffer, ARG_start, ARG_end };
|
||||
|
@ -231,6 +232,10 @@ STATIC mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_
|
|||
uint32_t length = bufinfo.len;
|
||||
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
|
||||
|
||||
if (length == 0) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
bool ok = common_hal_busio_spi_write(self, ((uint8_t*)bufinfo.buf) + start, length);
|
||||
if (!ok) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
|
@ -242,12 +247,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 2, busio_spi_write);
|
|||
|
||||
//| .. method:: SPI.readinto(buffer, \*, start=0, end=len(buffer), write_value=0)
|
||||
//|
|
||||
//| Read into the buffer specified by ``buf`` while writing zeroes. Requires the SPI being locked.
|
||||
//| Read into ``buffer`` while writing ``write_value`` for each byte read.
|
||||
//| The SPI object must be locked.
|
||||
//| If the number of bytes to read is 0, nothing happens.
|
||||
//|
|
||||
//| :param bytearray buffer: buffer to write into
|
||||
//| :param int start: Index to start writing at
|
||||
//| :param int end: Index to write up to but not include
|
||||
//| :param int write_value: Value to write reading. (Usually ignored.)
|
||||
//| :param bytearray buffer: Read data into this buffer
|
||||
//| :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]``
|
||||
//| :param int end: End of the slice; this index is not included
|
||||
//| :param int write_value: Value to write while reading. (Usually ignored.)
|
||||
//|
|
||||
STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value };
|
||||
|
@ -269,6 +276,10 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
uint32_t length = bufinfo.len;
|
||||
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
|
||||
|
||||
if (length == 0) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
bool ok = common_hal_busio_spi_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int);
|
||||
if (!ok) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
|
@ -277,6 +288,68 @@ STATIC mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 2, busio_spi_readinto);
|
||||
|
||||
//| .. method:: SPI.write_readinto(buffer_out, buffer_in, \*, out_start=0, out_end=len(buffer_out), in_start=0, in_end=len(buffer_in))
|
||||
//|
|
||||
//| Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``.
|
||||
//| The SPI object must be locked.
|
||||
//| The lengths of the slices defined by ``buffer_out[out_start:out_end]`` and ``buffer_in[in_start:in_end]``
|
||||
//| must be equal.
|
||||
//| If buffer slice lengths are both 0, nothing happens.
|
||||
//|
|
||||
//| :param bytearray buffer_out: Write out the data in this buffer
|
||||
//| :param bytearray buffer_in: Read data into this buffer
|
||||
//| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]``
|
||||
//| :param int out_end: End of the slice; this index is not included
|
||||
//| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]``
|
||||
//| :param int in_end: End of the slice; this index is not included
|
||||
//|
|
||||
STATIC mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_buffer_out, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_buffer_in, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
|
||||
{ MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
|
||||
};
|
||||
busio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
raise_error_if_deinited(common_hal_busio_spi_deinited(self));
|
||||
check_lock(self);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_buffer_info_t buf_out_info;
|
||||
mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
|
||||
int32_t out_start = args[ARG_out_start].u_int;
|
||||
uint32_t out_length = buf_out_info.len;
|
||||
normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
|
||||
|
||||
mp_buffer_info_t buf_in_info;
|
||||
mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
|
||||
int32_t in_start = args[ARG_in_start].u_int;
|
||||
uint32_t in_length = buf_in_info.len;
|
||||
normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
|
||||
|
||||
if (out_length != in_length) {
|
||||
mp_raise_ValueError("buffer slices must be of equal length");
|
||||
}
|
||||
|
||||
if (out_length == 0) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
bool ok = common_hal_busio_spi_transfer(self,
|
||||
((uint8_t*)buf_out_info.buf) + out_start,
|
||||
((uint8_t*)buf_in_info.buf) + in_start,
|
||||
out_length);
|
||||
if (!ok) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 2, busio_spi_write_readinto);
|
||||
|
||||
STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_spi_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
|
||||
|
@ -288,6 +361,7 @@ STATIC const mp_rom_map_elem_t busio_spi_locals_dict_table[] = {
|
|||
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&busio_spi_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busio_spi_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table);
|
||||
|
||||
|
|
|
@ -55,4 +55,7 @@ extern bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *dat
|
|||
// Reads in len bytes while outputting zeroes.
|
||||
extern bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value);
|
||||
|
||||
// Reads and write len bytes simultaneously.
|
||||
extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H
|
||||
|
|
|
@ -124,7 +124,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_
|
|||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
enum digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
if (args[ARG_drive_mode].u_rom_obj == &digitalio_drive_mode_open_drain_obj) {
|
||||
drive_mode = DRIVE_MODE_OPEN_DRAIN;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o
|
|||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
enum digitalio_pull_t pull = PULL_NONE;
|
||||
digitalio_pull_t pull = PULL_NONE;
|
||||
if (args[ARG_pull].u_rom_obj == &digitalio_pull_up_obj) {
|
||||
pull = PULL_UP;
|
||||
}else if (args[ARG_pull].u_rom_obj == &digitalio_pull_down_obj) {
|
||||
|
@ -191,7 +191,7 @@ extern const digitalio_digitalio_direction_obj_t digitalio_digitalio_direction_o
|
|||
STATIC mp_obj_t digitalio_digitalinout_obj_get_direction(mp_obj_t self_in) {
|
||||
digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(self));
|
||||
enum digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self);
|
||||
digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self);
|
||||
if (direction == DIRECTION_INPUT) {
|
||||
return (mp_obj_t)&digitalio_direction_input_obj;
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) {
|
|||
mp_raise_AttributeError("Drive mode not used when direction is input.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self);
|
||||
digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self);
|
||||
if (drive_mode == DRIVE_MODE_PUSH_PULL) {
|
||||
return (mp_obj_t)&digitalio_drive_mode_push_pull_obj;
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_drive_mode(mp_obj_t self_in, mp_o
|
|||
mp_raise_AttributeError("Drive mode not used when direction is input.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL;
|
||||
if (drive_mode == &digitalio_drive_mode_open_drain_obj) {
|
||||
c_drive_mode = DRIVE_MODE_OPEN_DRAIN;
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_pull(mp_obj_t self_in) {
|
|||
mp_raise_AttributeError("Pull not used when direction is output.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self);
|
||||
digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self);
|
||||
if (pull == PULL_UP) {
|
||||
return (mp_obj_t)&digitalio_pull_up_obj;
|
||||
} else if (pull == PULL_DOWN) {
|
||||
|
@ -324,7 +324,7 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t p
|
|||
mp_raise_AttributeError("Pull not used when direction is output.");
|
||||
return mp_const_none;
|
||||
}
|
||||
enum digitalio_pull_t pull = PULL_NONE;
|
||||
digitalio_pull_t pull = PULL_NONE;
|
||||
if (pull_obj == &digitalio_pull_up_obj) {
|
||||
pull = PULL_UP;
|
||||
} else if (pull_obj == &digitalio_pull_down_obj) {
|
||||
|
|
|
@ -43,14 +43,14 @@ typedef enum {
|
|||
digitalinout_result_t common_hal_digitalio_digitalinout_construct(digitalio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin);
|
||||
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self);
|
||||
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull);
|
||||
void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, enum digitalio_drive_mode_t drive_mode);
|
||||
enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_switch_to_input(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
|
||||
void common_hal_digitalio_digitalinout_switch_to_output(digitalio_digitalinout_obj_t* self, bool value, digitalio_drive_mode_t drive_mode);
|
||||
digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_value(digitalio_digitalinout_obj_t* self, bool value);
|
||||
bool common_hal_digitalio_digitalinout_get_value(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, enum digitalio_drive_mode_t drive_mode);
|
||||
enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull);
|
||||
enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_drive_mode(digitalio_digitalinout_obj_t* self, digitalio_drive_mode_t drive_mode);
|
||||
digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(digitalio_digitalinout_obj_t* self);
|
||||
void common_hal_digitalio_digitalinout_set_pull(digitalio_digitalinout_obj_t* self, digitalio_pull_t pull);
|
||||
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalinout_obj_t* self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_DIGITALINOUT_H
|
||||
|
|
|
@ -29,10 +29,10 @@
|
|||
|
||||
#include "py/obj.h"
|
||||
|
||||
enum digitalio_direction_t {
|
||||
typedef enum {
|
||||
DIRECTION_INPUT,
|
||||
DIRECTION_OUTPUT
|
||||
};
|
||||
} digitalio_direction_t;
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} digitalio_direction_obj_t;
|
||||
|
|
|
@ -29,10 +29,10 @@
|
|||
|
||||
#include "py/obj.h"
|
||||
|
||||
enum digitalio_drive_mode_t {
|
||||
typedef enum {
|
||||
DRIVE_MODE_PUSH_PULL,
|
||||
DRIVE_MODE_OPEN_DRAIN
|
||||
};
|
||||
} digitalio_drive_mode_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
|
||||
#include "py/obj.h"
|
||||
|
||||
enum digitalio_pull_t {
|
||||
typedef enum _digitalio_pull_t {
|
||||
PULL_NONE,
|
||||
PULL_UP,
|
||||
PULL_DOWN
|
||||
};
|
||||
} digitalio_pull_t;
|
||||
|
||||
const mp_obj_type_t digitalio_pull_type;
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* This file is part of the Micro Python 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 "shared-bindings/microcontroller/RunMode.h"
|
||||
|
||||
//| .. currentmodule:: microcontroller
|
||||
//|
|
||||
//| :class:`RunMode` -- run state of the microcontroller
|
||||
//| =============================================================
|
||||
//|
|
||||
//| .. class:: microcontroller.RunMode
|
||||
//|
|
||||
//| Enum-like class to define the run mode of the microcontroller and
|
||||
//| CircuitPython.
|
||||
//|
|
||||
//| .. data:: NORMAL
|
||||
//|
|
||||
//| Run CircuitPython as normal.
|
||||
//|
|
||||
//| .. data:: SAFE_MODE
|
||||
//|
|
||||
//| Run CircuitPython in safe mode. User code will not be run and the
|
||||
//| file system will be writeable over USB.
|
||||
//|
|
||||
//| .. data:: BOOTLOADER
|
||||
//|
|
||||
//| Run the bootloader.
|
||||
//|
|
||||
const mp_obj_type_t mcu_runmode_type;
|
||||
|
||||
const mcu_runmode_obj_t mcu_runmode_normal_obj = {
|
||||
{ &mcu_runmode_type },
|
||||
};
|
||||
|
||||
const mcu_runmode_obj_t mcu_runmode_safe_mode_obj = {
|
||||
{ &mcu_runmode_type },
|
||||
};
|
||||
|
||||
const mcu_runmode_obj_t mcu_runmode_bootloader_obj = {
|
||||
{ &mcu_runmode_type },
|
||||
};
|
||||
|
||||
STATIC const mp_rom_map_elem_t mcu_runmode_locals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_PTR(&mcu_runmode_normal_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_SAFE_MODE), MP_ROM_PTR(&mcu_runmode_safe_mode_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_BOOTLOADER), MP_ROM_PTR(&mcu_runmode_bootloader_obj)},
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mcu_runmode_locals_dict, mcu_runmode_locals_dict_table);
|
||||
|
||||
STATIC void mcu_runmode_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
qstr runmode = MP_QSTR_NORMAL;
|
||||
if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_safe_mode_obj)) {
|
||||
runmode = MP_QSTR_SAFE_MODE;
|
||||
} else if (MP_OBJ_TO_PTR(self_in) ==
|
||||
MP_ROM_PTR(&mcu_runmode_bootloader_obj)) {
|
||||
runmode = MP_QSTR_SAFE_MODE;
|
||||
}
|
||||
mp_printf(print, "%q.%q.%q", MP_QSTR_microcontroller, MP_QSTR_RunMode,
|
||||
runmode);
|
||||
}
|
||||
|
||||
const mp_obj_type_t mcu_runmode_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_RunMode,
|
||||
.print = mcu_runmode_print,
|
||||
.locals_dict = (mp_obj_t)&mcu_runmode_locals_dict,
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* This file is part of the Micro Python 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_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
|
||||
#define MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef enum {
|
||||
RUNMODE_NORMAL,
|
||||
RUNMODE_SAFE_MODE,
|
||||
RUNMODE_BOOTLOADER
|
||||
} mcu_runmode_t;
|
||||
|
||||
const mp_obj_type_t mcu_runmode_type;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} mcu_runmode_obj_t;
|
||||
extern const mcu_runmode_obj_t mcu_runmode_normal_obj;
|
||||
extern const mcu_runmode_obj_t mcu_runmode_safe_mode_obj;
|
||||
extern const mcu_runmode_obj_t mcu_runmode_bootloader_obj;
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_RUNMODE_H
|
|
@ -106,6 +106,47 @@ STATIC mp_obj_t mcu_enable_interrupts(void) {
|
|||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupts);
|
||||
|
||||
//| .. method:: on_next_reset(run_mode)
|
||||
//|
|
||||
//| Configure the run mode used the next time the microcontroller is reset but
|
||||
//| not powered down.
|
||||
//|
|
||||
//| :param ~microcontroller.RunMode run_mode: The next run mode
|
||||
//|
|
||||
STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) {
|
||||
mcu_runmode_t run_mode;
|
||||
if (run_mode_obj == &mcu_runmode_normal_obj) {
|
||||
run_mode = RUNMODE_NORMAL;
|
||||
} else if (run_mode_obj == &mcu_runmode_safe_mode_obj) {
|
||||
run_mode = RUNMODE_SAFE_MODE;
|
||||
} else if (run_mode_obj == &mcu_runmode_bootloader_obj) {
|
||||
run_mode = RUNMODE_BOOTLOADER;
|
||||
} else {
|
||||
mp_raise_ValueError("Invalid run mode.");
|
||||
}
|
||||
|
||||
common_hal_mcu_on_next_reset(run_mode);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset);
|
||||
|
||||
//| .. method:: reset()
|
||||
//|
|
||||
//| Reset the microcontroller. After reset, the microcontroller will enter the
|
||||
//| run mode last set by `one_next_reset`.
|
||||
//|
|
||||
//| .. warning:: This may result in file system corruption when connected to a
|
||||
//| host computer. Be very careful when calling this! Make sure the device
|
||||
//| "Safely removed" on Windows or "ejected" on Mac OSX and Linux.
|
||||
//|
|
||||
STATIC mp_obj_t mcu_reset(void) {
|
||||
common_hal_mcu_reset();
|
||||
// We won't actually get here because we're resetting.
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset);
|
||||
|
||||
//| .. attribute:: nvm
|
||||
//|
|
||||
//| Available non-volatile memory.
|
||||
|
@ -132,11 +173,14 @@ STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_on_next_reset), MP_ROM_PTR(&mcu_on_next_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mcu_reset_obj) },
|
||||
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
|
||||
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&common_hal_mcu_nvm_obj) },
|
||||
#else
|
||||
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_RunMode), MP_ROM_PTR(&mcu_runmode_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Processor), MP_ROM_PTR(&mcu_processor_type) },
|
||||
|
|
|
@ -33,11 +33,16 @@
|
|||
|
||||
#include "common-hal/microcontroller/Processor.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/RunMode.h"
|
||||
|
||||
extern void common_hal_mcu_delay_us(uint32_t);
|
||||
|
||||
extern void common_hal_mcu_disable_interrupts(void);
|
||||
extern void common_hal_mcu_enable_interrupts(void);
|
||||
|
||||
extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode);
|
||||
extern void common_hal_mcu_reset(void);
|
||||
|
||||
extern const mp_obj_dict_t mcu_pin_globals;
|
||||
|
||||
extern const mcu_processor_obj_t common_hal_mcu_processor_obj;
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Layer.h"
|
||||
#include "__init__.h"
|
||||
|
||||
|
||||
// Get the color of the pixel on the layer.
|
||||
uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y) {
|
||||
|
||||
// Shift by the layer's position offset.
|
||||
x -= layer->x;
|
||||
y -= layer->y;
|
||||
|
||||
// Bounds check.
|
||||
if ((x < 0) || (x >= layer->width << 4) ||
|
||||
(y < 0) || (y >= layer->height << 4)) {
|
||||
return TRANSPARENT;
|
||||
}
|
||||
|
||||
// Get the tile from the grid location or from sprite frame.
|
||||
uint8_t frame = layer->frame;
|
||||
if (layer->map) {
|
||||
uint8_t tx = x >> 4;
|
||||
uint8_t ty = y >> 4;
|
||||
|
||||
frame = layer->map[(ty * layer->width + tx) >> 1];
|
||||
if (tx & 0x01) {
|
||||
frame &= 0x0f;
|
||||
} else {
|
||||
frame >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the position within the tile.
|
||||
x &= 0x0f;
|
||||
y &= 0x0f;
|
||||
|
||||
// Rotate the image.
|
||||
uint8_t ty = y; // Temporary variable for swapping.
|
||||
switch (layer->rotation) {
|
||||
case 1: // 90 degrees clockwise
|
||||
y = 15 - x;
|
||||
x = ty;
|
||||
break;
|
||||
case 2: // 180 degrees
|
||||
y = 15 - ty;
|
||||
x = 15 - x;
|
||||
break;
|
||||
case 3: // 90 degrees counter-clockwise
|
||||
y = x;
|
||||
x = 15 - ty;
|
||||
break;
|
||||
case 4: // 0 degrees, mirrored
|
||||
x = 15 - x;
|
||||
break;
|
||||
case 5: // 90 degrees clockwise, mirrored
|
||||
y = x;
|
||||
x = ty;
|
||||
break;
|
||||
case 6: // 180 degrees, mirrored
|
||||
y = 15 - ty;
|
||||
break;
|
||||
case 7: // 90 degrees counter-clockwise, mirrored
|
||||
y = 15 - x;
|
||||
x = 15 - ty;
|
||||
break;
|
||||
default: // 0 degrees
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the value of the pixel.
|
||||
uint8_t pixel = layer->graphic[(frame << 7) + (y << 3) + (x >> 1)];
|
||||
if (x & 0x01) {
|
||||
pixel &= 0x0f;
|
||||
} else {
|
||||
pixel >>= 4;
|
||||
}
|
||||
|
||||
// Convert to 16-bit color using the palette.
|
||||
return layer->palette[pixel << 1] | layer->palette[(pixel << 1) + 1] << 8;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_SHARED_MODULE__STAGE_LAYER_H
|
||||
#define MICROPY_INCLUDED_SHARED_MODULE__STAGE_LAYER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
uint8_t *map;
|
||||
uint8_t *graphic;
|
||||
uint8_t *palette;
|
||||
int16_t x, y;
|
||||
uint8_t width, height;
|
||||
uint8_t frame;
|
||||
uint8_t rotation;
|
||||
} layer_obj_t;
|
||||
|
||||
uint16_t get_layer_pixel(layer_obj_t *layer, int16_t x, uint16_t y);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE_LAYER
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Text.h"
|
||||
#include "__init__.h"
|
||||
|
||||
|
||||
// Get the color of the pixel on the text.
|
||||
uint16_t get_text_pixel(text_obj_t *text, int16_t x, uint16_t y) {
|
||||
|
||||
// Shift by the text's position offset.
|
||||
x -= text->x;
|
||||
y -= text->y;
|
||||
|
||||
// Bounds check.
|
||||
if ((x < 0) || (x >= text->width << 3) ||
|
||||
(y < 0) || (y >= text->height << 3)) {
|
||||
return TRANSPARENT;
|
||||
}
|
||||
|
||||
// Get the tile from the grid location or from sprite frame.
|
||||
uint8_t tx = x >> 3;
|
||||
uint8_t ty = y >> 3;
|
||||
uint8_t c = text->chars[ty * text->width + tx];
|
||||
uint8_t color_offset = 0;
|
||||
if (c & 0x80) {
|
||||
color_offset = 4;
|
||||
}
|
||||
c &= 0x7f;
|
||||
if (!c) {
|
||||
return TRANSPARENT;
|
||||
}
|
||||
|
||||
// Get the position within the char.
|
||||
x &= 0x07;
|
||||
y &= 0x07;
|
||||
|
||||
// Get the value of the pixel.
|
||||
uint8_t pixel = text->font[(c << 4) + (y << 1) + (x >> 2)];
|
||||
pixel = ((pixel >> ((x & 0x03) << 1)) & 0x03) + color_offset;
|
||||
|
||||
// Convert to 16-bit color using the palette.
|
||||
return text->palette[pixel << 1] | text->palette[(pixel << 1) + 1] << 8;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_SHARED_MODULE__STAGE_TEXT_H
|
||||
#define MICROPY_INCLUDED_SHARED_MODULE__STAGE_TEXT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
uint8_t *chars;
|
||||
uint8_t *font;
|
||||
uint8_t *palette;
|
||||
int16_t x, y;
|
||||
uint8_t width, height;
|
||||
} text_obj_t;
|
||||
|
||||
uint16_t get_text_pixel(text_obj_t *text, int16_t x, uint16_t y);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE_TEXT
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Layer.h"
|
||||
#include "Text.h"
|
||||
#include "__init__.h"
|
||||
#include "shared-bindings/_stage/Layer.h"
|
||||
#include "shared-bindings/_stage/Text.h"
|
||||
|
||||
|
||||
bool render_stage(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
||||
mp_obj_t *layers, size_t layers_size,
|
||||
uint16_t *buffer, size_t buffer_size,
|
||||
busio_spi_obj_t *spi) {
|
||||
|
||||
// TODO(deshipu): Do a collision check of each layer with the
|
||||
// rectangle, and only process the layers that overlap with it.
|
||||
|
||||
size_t index = 0;
|
||||
for (uint8_t y = y0; y < y1; ++y) {
|
||||
for (uint8_t x = x0; x < x1; ++x) {
|
||||
for (size_t layer = 0; layer < layers_size; ++layer) {
|
||||
uint16_t c = TRANSPARENT;
|
||||
layer_obj_t *obj = MP_OBJ_TO_PTR(layers[layer]);
|
||||
if (obj->base.type == &mp_type_layer) {
|
||||
c = get_layer_pixel(obj, x, y);
|
||||
} else if (obj->base.type == &mp_type_text) {
|
||||
c = get_text_pixel((text_obj_t *)obj, x, y);
|
||||
}
|
||||
if (c != TRANSPARENT) {
|
||||
buffer[index] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
index += 1;
|
||||
// The buffer is full, send it.
|
||||
if (index >= buffer_size) {
|
||||
if (!common_hal_busio_spi_write(spi,
|
||||
((uint8_t*)buffer), buffer_size * 2)) {
|
||||
return false;
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Send the remaining data.
|
||||
if (index) {
|
||||
if (!common_hal_busio_spi_write(spi, ((uint8_t*)buffer), index * 2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Radomir Dopieralski
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_SHARED_MODULE__STAGE_H
|
||||
#define MICROPY_INCLUDED_SHARED_MODULE__STAGE_H
|
||||
|
||||
#include "shared-bindings/busio/SPI.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "py/obj.h"
|
||||
|
||||
#define TRANSPARENT (0x1ff8)
|
||||
|
||||
bool render_stage(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
||||
mp_obj_t *layers, size_t layers_size,
|
||||
uint16_t *buffer, size_t buffer_size,
|
||||
busio_spi_obj_t *spi);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE__STAGE
|
|
@ -2,7 +2,7 @@ rm -rf ports/atmel-samd/build*
|
|||
rm -rf ports/esp8266/build*
|
||||
rm -rf ports/nrf/build*
|
||||
|
||||
ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger feather_m0_express metro_m0_express metro_m4_express trinket_m0 gemma_m0 feather52"
|
||||
ATMEL_BOARDS="arduino_zero circuitplayground_express feather_m0_basic feather_m0_adalogger itsybitsy_m0 feather_m0_express metro_m0_express metro_m4_express trinket_m0 gemma_m0 feather52"
|
||||
ROSIE_SETUPS="rosie-ci"
|
||||
|
||||
PARALLEL="-j 5"
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import os
|
||||
import os.path
|
||||
from pathlib import Path
|
||||
import semver
|
||||
import subprocess
|
||||
|
||||
# Compatible with Python 3.4 due to travis using trusty as default.
|
||||
|
||||
def version_string(path=None, *, valid_semver=False):
|
||||
version = None
|
||||
try:
|
||||
tag = subprocess.check_output('git describe --tags --exact-match', shell=True, cwd=path)
|
||||
version = tag.strip().decode("utf-8", "strict")
|
||||
except subprocess.CalledProcessError:
|
||||
describe = subprocess.check_output("git describe --tags", shell=True, cwd=path)
|
||||
tag, additional_commits, commitish = describe.strip().decode("utf-8", "strict").rsplit("-", maxsplit=2)
|
||||
commitish = commitish[1:]
|
||||
if valid_semver:
|
||||
version_info = semver.parse_version_info(tag)
|
||||
if not version_info.prerelease:
|
||||
version = semver.bump_patch(tag) + "-alpha.0.plus." + additional_commits + "+" + commitish
|
||||
else:
|
||||
version = tag + ".plus." + additional_commits + "+" + commitish
|
||||
else:
|
||||
version = commitish
|
||||
return version
|
||||
|
||||
# Visit all the .py files in topdir. Replace any __version__ = "0.0.0-auto.0" type of info
|
||||
# with actual version info derived from git.
|
||||
def copy_and_process(in_dir, out_dir):
|
||||
for root, subdirs, files in os.walk(in_dir):
|
||||
|
||||
# Skip library examples directories.
|
||||
if Path(root).name == 'examples':
|
||||
continue
|
||||
|
||||
for file in files:
|
||||
# Skip top-level setup.py (module install info) and conf.py (sphinx config),
|
||||
# which are not part of the library
|
||||
if (root == in_dir) and file in ('conf.py', 'setup.py'):
|
||||
continue
|
||||
|
||||
input_file_path = Path(root, file)
|
||||
output_file_path = Path(out_dir, input_file_path.relative_to(in_dir))
|
||||
|
||||
if file.endswith(".py"):
|
||||
if not output_file_path.parent.exists():
|
||||
output_file_path.parent.mkdir(parents=True)
|
||||
with input_file_path.open("r") as input, output_file_path.open("w") as output:
|
||||
for line in input:
|
||||
if line.startswith("__version__"):
|
||||
module_version = version_string(root, valid_semver=True)
|
||||
line = line.replace("0.0.0-auto.0", module_version)
|
||||
output.write(line)
|
||||
|
||||
if __name__ == '__main__':
|
||||
argparser = argparse.ArgumentParser(description="""\
|
||||
Copy and pre-process .py files into output directory, before freezing.
|
||||
1. Remove top-level repo directory.
|
||||
2. Update __version__ info.
|
||||
3. Remove examples.
|
||||
4. Remove non-library setup.py and conf.py""")
|
||||
argparser.add_argument("in_dirs", metavar="input-dir", nargs="+",
|
||||
help="top-level code dirs (may be git repo dirs)")
|
||||
argparser.add_argument("-o", "--out_dir", help="output directory")
|
||||
args = argparser.parse_args()
|
||||
|
||||
for in_dir in args.in_dirs:
|
||||
copy_and_process(in_dir, args.out_dir)
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 2001c62d1a0361c44acc7076d8ce91e1d1c66141
|
Loading…
Reference in New Issue