summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <thach@tinyusb.org>2018-06-07 13:50:04 +0700
committerhathach <thach@tinyusb.org>2018-06-07 13:50:04 +0700
commit9bb4ded5fa4e7d4aed179037d0cbcf5986df11a8 (patch)
tree2ad3519d31b3511db9d21a01896b4132f26be6a7
parent52ebfd07a51749d996e149eccc104a2cc0fd294e (diff)
parent44721cba3d5bb92d0226ec9451a0aaa95379b9f1 (diff)
Merge remote-tracking branch 'upstream/master'
-rw-r--r--.gitmodules12
-rw-r--r--.travis.yml8
-rw-r--r--CONTRIBUTING.md23
-rw-r--r--README.rst11
-rw-r--r--conf.py1
-rw-r--r--docs/c2rst.py1
-rw-r--r--docs/design_guide.rst4
-rw-r--r--docs/library/array.rst2
-rw-r--r--docs/library/builtins.rst22
-rw-r--r--docs/library/gc.rst6
-rw-r--r--docs/library/index.rst57
-rw-r--r--docs/library/sys.rst20
-rw-r--r--docs/library/ustruct.rst44
-rw-r--r--docs/templates/unsupported_in_circuitpython.inc9
m---------frozen/Adafruit_CircuitPython_BusDevice0
m---------frozen/Adafruit_CircuitPython_CircuitPlayground0
m---------frozen/Adafruit_CircuitPython_DotStar0
m---------frozen/Adafruit_CircuitPython_HID0
m---------frozen/Adafruit_CircuitPython_IRRemote0
m---------frozen/Adafruit_CircuitPython_LIS3DH0
m---------frozen/Adafruit_CircuitPython_Motor0
m---------frozen/Adafruit_CircuitPython_seesaw0
-rw-r--r--main.c78
-rw-r--r--ports/atmel-samd/Makefile49
-rw-r--r--ports/atmel-samd/audio_dma.c6
-rw-r--r--ports/atmel-samd/bindings/samd/Clock.c3
-rw-r--r--ports/atmel-samd/board_busses.c113
-rw-r--r--ports/atmel-samd/board_busses.h39
-rw-r--r--ports/atmel-samd/boards/arduino_zero/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/arduino_zero/pins.c5
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/board.c1
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/pins.c7
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/board.c65
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h73
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk21
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/pins.c65
-rw-r--r--ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_adalogger/pins.c7
-rw-r--r--ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_basic/pins.c7
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/pins.c7
-rw-r--r--ports/atmel-samd/boards/feather_m0_express_crickit/board.c (renamed from ports/atmel-samd/boards/metro_m4_express_revb/board.c)12
-rw-r--r--ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h60
-rw-r--r--ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk17
-rw-r--r--ports/atmel-samd/boards/feather_m0_express_crickit/pins.c33
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm69/pins.c7
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm9x/pins.c7
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/pins.c7
-rw-r--r--ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h28
-rw-r--r--ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/feather_m4_express/pins.c35
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.h51
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/gemma_m0/pins.c7
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0_express/pins.c7
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/pins.c9
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/pins.c7
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h12
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/pins.c9
-rw-r--r--ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h62
-rw-r--r--ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/metro_m4_express_revb/pins.c44
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h56
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/pins.c7
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.h52
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/trinket_m0/pins.c7
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h10
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/pins.c7
-rw-r--r--ports/atmel-samd/boards/ugame10/mpconfigboard.h5
-rw-r--r--ports/atmel-samd/boards/ugame10/mpconfigboard.mk4
-rw-r--r--ports/atmel-samd/boards/ugame10/pins.c7
-rw-r--r--ports/atmel-samd/common-hal/analogio/AnalogIn.c2
-rw-r--r--ports/atmel-samd/common-hal/analogio/AnalogOut.c6
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/I2SOut.c13
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/PDMIn.c11
-rw-r--r--ports/atmel-samd/common-hal/audioio/AudioOut.c11
-rw-r--r--ports/atmel-samd/common-hal/busio/I2C.c9
-rw-r--r--ports/atmel-samd/common-hal/busio/SPI.c5
-rw-r--r--ports/atmel-samd/common-hal/busio/UART.c3
-rw-r--r--ports/atmel-samd/common-hal/microcontroller/Pin.c7
-rw-r--r--ports/atmel-samd/common-hal/microcontroller/Pin.h2
-rw-r--r--ports/atmel-samd/common-hal/microcontroller/Processor.c2
-rw-r--r--ports/atmel-samd/common-hal/microcontroller/__init__.c130
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PWMOut.c4
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseIn.c242
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseIn.h4
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseOut.c4
-rw-r--r--ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c157
-rw-r--r--ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.h48
-rw-r--r--ports/atmel-samd/common-hal/rotaryio/__init__.c1
-rw-r--r--ports/atmel-samd/common-hal/touchio/TouchIn.c45
-rw-r--r--ports/atmel-samd/external_flash/external_flash.c3
-rw-r--r--ports/atmel-samd/external_flash/qspi_flash.c4
-rw-r--r--ports/atmel-samd/external_flash/spi_flash.c4
m---------ports/atmel-samd/freetouch0
-rw-r--r--ports/atmel-samd/mpconfigport.h69
-rw-r--r--ports/atmel-samd/mpconfigport.mk10
-rw-r--r--ports/atmel-samd/mphalport.c2
-rw-r--r--ports/atmel-samd/peripherals/adc.h (renamed from ports/atmel-samd/samd21_peripherals.h)9
-rw-r--r--ports/atmel-samd/peripherals/cache.h (renamed from ports/atmel-samd/samd51_peripherals.h)8
-rw-r--r--ports/atmel-samd/peripherals/clocks.c (renamed from ports/atmel-samd/clocks.c)51
-rw-r--r--ports/atmel-samd/peripherals/clocks.h (renamed from ports/atmel-samd/clocks.h)2
-rw-r--r--ports/atmel-samd/peripherals/dma.c (renamed from ports/atmel-samd/shared_dma.c)164
-rw-r--r--ports/atmel-samd/peripherals/dma.h (renamed from ports/atmel-samd/shared_dma.h)9
-rw-r--r--ports/atmel-samd/peripherals/events.c59
-rw-r--r--ports/atmel-samd/peripherals/events.h (renamed from ports/atmel-samd/events.h)2
-rw-r--r--ports/atmel-samd/peripherals/external_interrupts.c105
-rw-r--r--ports/atmel-samd/peripherals/external_interrupts.h54
-rw-r--r--ports/atmel-samd/peripherals/i2s.c46
-rw-r--r--ports/atmel-samd/peripherals/i2s.h (renamed from ports/atmel-samd/i2s.h)0
-rw-r--r--ports/atmel-samd/peripherals/pins.h42
-rw-r--r--ports/atmel-samd/peripherals/samd21/adc.c47
-rw-r--r--ports/atmel-samd/peripherals/samd21/cache.c (renamed from ports/atmel-samd/pins.h)19
-rw-r--r--ports/atmel-samd/peripherals/samd21/clocks.c (renamed from ports/atmel-samd/samd21_clocks.c)108
-rw-r--r--ports/atmel-samd/peripherals/samd21/dma.c118
-rw-r--r--ports/atmel-samd/peripherals/samd21/events.c (renamed from ports/atmel-samd/events.c)119
-rw-r--r--ports/atmel-samd/peripherals/samd21/external_interrupts.c86
-rw-r--r--ports/atmel-samd/peripherals/samd21/i2s.c46
-rw-r--r--ports/atmel-samd/peripherals/samd21/pins.c (renamed from ports/atmel-samd/samd21_pins.c)106
-rw-r--r--ports/atmel-samd/peripherals/samd21/pins.h (renamed from ports/atmel-samd/samd21_pins.h)11
-rw-r--r--ports/atmel-samd/peripherals/samd21/sercom.c (renamed from ports/atmel-samd/samd21_peripherals.c)20
-rw-r--r--ports/atmel-samd/peripherals/samd21/timers.c75
-rw-r--r--ports/atmel-samd/peripherals/samd51/adc.c61
-rw-r--r--ports/atmel-samd/peripherals/samd51/cache.c39
-rw-r--r--ports/atmel-samd/peripherals/samd51/clocks.c480
-rw-r--r--ports/atmel-samd/peripherals/samd51/dma.c94
-rw-r--r--ports/atmel-samd/peripherals/samd51/events.c88
-rw-r--r--ports/atmel-samd/peripherals/samd51/external_interrupts.c132
-rw-r--r--ports/atmel-samd/peripherals/samd51/i2s.c (renamed from ports/atmel-samd/i2s.c)36
-rw-r--r--ports/atmel-samd/peripherals/samd51/pins.c (renamed from ports/atmel-samd/samd51_pins.c)2
-rw-r--r--ports/atmel-samd/peripherals/samd51/pins.h (renamed from ports/atmel-samd/samd51_pins.h)5
-rw-r--r--ports/atmel-samd/peripherals/samd51/sercom.c (renamed from ports/atmel-samd/samd51_peripherals.c)44
-rw-r--r--ports/atmel-samd/peripherals/samd51/timers.c (renamed from ports/atmel-samd/timers.c)166
-rw-r--r--ports/atmel-samd/peripherals/sercom.c (renamed from ports/atmel-samd/peripherals.c)2
-rw-r--r--ports/atmel-samd/peripherals/sercom.h (renamed from ports/atmel-samd/peripherals.h)17
-rw-r--r--ports/atmel-samd/peripherals/timers.c147
-rw-r--r--ports/atmel-samd/peripherals/timers.h (renamed from ports/atmel-samd/timers.h)0
-rw-r--r--ports/atmel-samd/samd51_clocks.c86
-rw-r--r--ports/atmel-samd/supervisor/filesystem.c7
-rw-r--r--ports/atmel-samd/supervisor/port.c113
-rw-r--r--ports/atmel-samd/tick.c28
-rw-r--r--ports/esp8266/mpconfigport.h2
-rw-r--r--ports/nrf/common-hal/busio/I2C.c2
-rw-r--r--ports/nrf/mpconfigport.h3
-rw-r--r--py/modbuiltins.c1
-rw-r--r--py/moduerrno.c29
-rw-r--r--py/mperrno.h6
-rw-r--r--py/mpstate.h3
-rw-r--r--py/obj.h1
-rw-r--r--py/objexcept.c7
-rw-r--r--py/py.mk1
-rw-r--r--py/reload.c16
-rw-r--r--py/reload.h10
-rw-r--r--py/runtime.c6
-rw-r--r--shared-bindings/audioio/AudioOut.c3
-rw-r--r--shared-bindings/bitbangio/I2C.c7
-rw-r--r--shared-bindings/bitbangio/I2C.h3
-rw-r--r--shared-bindings/board/__init__.h2
-rw-r--r--shared-bindings/busio/I2C.c6
-rw-r--r--shared-bindings/busio/I2C.h3
-rw-r--r--shared-bindings/gamepad/GamePad.c34
-rw-r--r--shared-bindings/index.rst4
-rw-r--r--shared-bindings/rotaryio/IncrementalEncoder.c168
-rw-r--r--shared-bindings/rotaryio/IncrementalEncoder.h43
-rw-r--r--shared-bindings/rotaryio/__init__.c75
-rw-r--r--shared-bindings/rotaryio/__init__.h34
-rw-r--r--shared-bindings/supervisor/__init__.c18
-rw-r--r--shared-bindings/time/__init__.c35
-rw-r--r--shared-module/bitbangio/I2C.c15
-rw-r--r--shared-module/bitbangio/types.h1
-rw-r--r--shared-module/busio/I2C.c4
-rw-r--r--shared-module/gamepad/GamePad.c18
-rw-r--r--shared-module/gamepad/GamePad.h3
-rw-r--r--shared-module/gamepad/__init__.c15
-rw-r--r--supervisor/shared/autoreload.c14
-rw-r--r--supervisor/shared/autoreload.h2
-rw-r--r--supervisor/shared/rgb_led_status.c1
-rw-r--r--tests/basics/errno1.py5
-rw-r--r--tests/basics/errno1.py.exp3
l---------tests/pyboard.py2
-rwxr-xr-xtools/build_adafruit_bins.sh2
-rw-r--r--tools/cpboard.py684
205 files changed, 4822 insertions, 1601 deletions
diff --git a/.gitmodules b/.gitmodules
index 59048d6c0..d0f3fd565 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -55,3 +55,15 @@
[submodule "frozen/Adafruit_CircuitPython_HID"]
path = frozen/Adafruit_CircuitPython_HID
url = https://github.com/adafruit/Adafruit_CircuitPython_HID.git
+[submodule "ports/atmel-samd/Adafruit_CircuitPython_Motor"]
+ path = frozen/Adafruit_CircuitPython_Motor
+ url = https://github.com/adafruit/Adafruit_CircuitPython_Motor.git
+[submodule "ports/atmel-samd/Adafruit_CircuitPython_seesaw"]
+ path = frozen/Adafruit_CircuitPython_seesaw
+ url = https://github.com/adafruit/Adafruit_CircuitPython_seesaw.git
+[submodule "frozen/Adafruit_CircuitPython_IRRemote"]
+ path = frozen/Adafruit_CircuitPython_IRRemote
+ url = https://github.com/adafruit/Adafruit_CircuitPython_IRRemote.git
+[submodule "frozen/Adafruit_CircuitPython_DotStar"]
+ path = frozen/Adafruit_CircuitPython_DotStar
+ url = https://github.com/adafruit/Adafruit_CircuitPython_DotStar.git
diff --git a/.travis.yml b/.travis.yml
index 1e18640c8..986e32cc4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,11 +6,13 @@ compiler:
env:
- TRAVIS_BOARD=arduino_zero
- TRAVIS_BOARD=circuitplayground_express
+ - TRAVIS_BOARD=circuitplayground_express_crickit
- TRAVIS_BOARD=feather_m0_basic
- TRAVIS_BOARD=feather_m0_adalogger
- TRAVIS_BOARD=feather_m0_rfm69
- TRAVIS_BOARD=feather_m0_rfm9x
- TRAVIS_BOARD=feather_m0_express
+ - TRAVIS_BOARD=feather_m0_express_crickit
- TRAVIS_BOARD=feather_m4_express
- TRAVIS_BOARD=itsybitsy_m0_express
- TRAVIS_BOARD=itsybitsy_m4_express
@@ -42,7 +44,11 @@ notifications:
before_script:
- sudo dpkg --add-architecture i386
- - sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system
+ - |
+ sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system ||
+ sleep 30 ||
+ sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system
+
- ([[ -z "$TRAVIS_TEST" ]] || sudo apt-get install -y qemu-system)
- ([[ -z "$TRAVIS_BOARD" ]] || (wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2017q4-1~trusty3_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb))
- ([[ $TRAVIS_TEST != "qemu" ]] || (wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2017q4-1~trusty3_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb))
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2eb0214da..6feed085c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,12 +5,6 @@ By participating in this project you agree to abide by its terms. Participation
covers any forum used to converse about CircuitPython including unofficial and official spaces. Failure to do
so will result in corrective actions such as time out or ban from the project.
-## Developer contact
-[@tannewt](https://github.com/tannewt) is the main developer of CircuitPython
-and is sponsored by [Adafruit Industries LLC](https://adafruit.com). He is
-reachable on [Discord](https://adafru.it/discord) as tannewt during US West Coast
-working hours. He also checks GitHub issues and the [Adafruit support forum](https://forums.adafruit.com/viewforum.php?f=60).
-
## Licensing
By contributing to this repository you are certifying that you have all necessary
permissions to license the code under an MIT License. You still retain the
@@ -20,6 +14,23 @@ If you have an employment contract with your employer please make sure that they
don't automatically own your work product. Make sure to get any necessary approvals
before contributing. Another term for this contribution off-hours is moonlighting.
+## Getting started
+CircuitPython developer Dan Halbert (@dhalbert) has written up build instructions using native build
+tools [here](https://learn.adafruit.com/building-circuitpython).
+
+For SAMD21 debugging workflow tips check out [this learn guide](https://learn.adafruit.com/debugging-the-samd21-with-gdb) from Scott (@tannewt).
+
+## Developer contacts
+Scott Shawcroft ([@tannewt](https://github.com/tannewt)) is the lead developer of CircuitPython
+and is sponsored by [Adafruit Industries LLC](https://adafruit.com). Scott is usually available
+during US West Coast working hours. Dan Halbert ([@dhalbert](https://github.com/dhalbert)) and
+Kattni Rembor ([@kattni](https://github.com/kattni)) are also sponsored by [Adafruit Industries
+ LLC](https://adafruit.com) and are usually available during US East Coast daytime hours including
+some weekends.
+
+They are all reachable on [Discord](https://adafru.it/discord), GitHub issues and the [Adafruit
+support forum](https://forums.adafruit.com/viewforum.php?f=60).
+
## Code guidelines
We aim to keep our code and commit style compatible with MicroPython upstream.
Please review their
diff --git a/README.rst b/README.rst
index 6017be207..a1b90fa02 100644
--- a/README.rst
+++ b/README.rst
@@ -103,10 +103,15 @@ Differences from `MicroPython <https://github.com/micropython/micropython>`__
CircuitPython:
-- includes a port for Atmel SAMD21 (Commonly known as M0 in Adafruit
- product names.)
-- supports only Atmel SAMD21 and ESP8266 ports.
+- includes a ports for MicroChip SAMD21 (Commonly known as M0 in Adafruit
+ product names and SAMD51 (M4).
+- supports only SAMD21, SAMD51, and ESP8266 ports. An nRF port is under
+ development.
- tracks MicroPython's releases (not master).
+- Longints (arbitrary-length integers) are enabled for most M0
+ Express boards (those boards with SPI flash chips external
+ to the microcontroller), and for all M4 builds.
+ Longints are disabled on other boards due to lack of flash space.
Behavior
~~~~~~~~
diff --git a/conf.py b/conf.py
index eb4b1490f..03d100f12 100644
--- a/conf.py
+++ b/conf.py
@@ -101,6 +101,7 @@ exclude_patterns = ["**/build*",
"ports/atmel-samd/asf4_conf",
"ports/atmel-samd/external_flash",
"ports/atmel-samd/freetouch",
+ "ports/atmel-samd/peripherals",
"ports/atmel-samd/QTouch",
"ports/atmel-samd/tools",
"ports/bare-arm",
diff --git a/docs/c2rst.py b/docs/c2rst.py
index 9ca8bc1bb..904fb7408 100644
--- a/docs/c2rst.py
+++ b/docs/c2rst.py
@@ -7,6 +7,7 @@ class CStrip(sphinx.parsers.Parser):
def parse(self, inputstring, document):
# This setting is missing starting with Sphinx 1.7.1 so we set it ourself.
document.settings.tab_width = 4
+ document.settings.character_level_inline_markup = False
stripped = []
for line in inputstring.split("\n"):
line = line.strip()
diff --git a/docs/design_guide.rst b/docs/design_guide.rst
index a1524eaa2..e7b3832bc 100644
--- a/docs/design_guide.rst
+++ b/docs/design_guide.rst
@@ -441,10 +441,10 @@ buffers.
Examples
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-ustruct.pack
+struct.pack
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Use `ustruct.pack_into` instead of `ustruct.pack`.
+Use `struct.pack_into` instead of `struct.pack`.
Sensor properties and units
--------------------------------------------------------------------------------
diff --git a/docs/library/array.rst b/docs/library/array.rst
index dfaef0ff6..0f1310b68 100644
--- a/docs/library/array.rst
+++ b/docs/library/array.rst
@@ -1,8 +1,6 @@
:mod:`array` -- arrays of numeric data
======================================
-.. include:: ../templates/unsupported_in_circuitpython.inc
-
.. module:: array
:synopsis: efficient arrays of numeric data
diff --git a/docs/library/builtins.rst b/docs/library/builtins.rst
index b45b6fe38..36a84bc0c 100644
--- a/docs/library/builtins.rst
+++ b/docs/library/builtins.rst
@@ -1,18 +1,14 @@
Builtin functions and exceptions
================================
-.. warning::
-
- These builtins are inherited from MicroPython and may not work in CircuitPython
- as documented or at all! If work differently from CPython, then their behavior
- may change.
-
All builtin functions and exceptions are described here. They are also
available via ``builtins`` module.
Functions and types
-------------------
+Not all of these functions and types are turned on in all CircuitPython ports, for space reasons.
+
.. function:: abs()
.. function:: all()
@@ -62,6 +58,8 @@ Functions and types
.. class:: frozenset()
+`frozenset()` is not enabled on non-Express CircuitPython boards.
+
.. function:: getattr()
.. function:: globals()
@@ -80,12 +78,12 @@ Functions and types
.. classmethod:: from_bytes(bytes, byteorder)
- In MicroPython, `byteorder` parameter must be positional (this is
+ In CircuitPython, `byteorder` parameter must be positional (this is
compatible with CPython).
.. method:: to_bytes(size, byteorder)
- In MicroPython, `byteorder` parameter must be positional (this is
+ In CircuitPython, `byteorder` parameter must be positional (this is
compatible with CPython).
.. function:: isinstance()
@@ -130,6 +128,8 @@ Functions and types
.. function:: reversed()
+`reversed()` is not enabled on non-Express CircuitPython boards.
+
.. function:: round()
.. class:: set()
@@ -182,12 +182,16 @@ Exceptions
.. exception:: OSError
- |see_cpython| `OSError`. MicroPython doesn't implement ``errno``
+ |see_cpython| `OSError`. CircuitPython doesn't implement the ``errno``
attribute, instead use the standard way to access exception arguments:
``exc.args[0]``.
.. exception:: RuntimeError
+.. exception:: ReloadException
+
+ `ReloadException` is used internally to deal with soft restarts.
+
.. exception:: StopIteration
.. exception:: SyntaxError
diff --git a/docs/library/gc.rst b/docs/library/gc.rst
index 01bd925e9..1a6c3d68c 100644
--- a/docs/library/gc.rst
+++ b/docs/library/gc.rst
@@ -31,7 +31,7 @@ Functions
.. admonition:: Difference to CPython
:class: attention
- This function is MicroPython extension.
+ This function is a MicroPython extension.
.. function:: mem_free()
@@ -41,7 +41,7 @@ Functions
.. admonition:: Difference to CPython
:class: attention
- This function is MicroPython extension.
+ This function is a MicroPython extension.
.. function:: threshold([amount])
@@ -63,6 +63,6 @@ Functions
.. admonition:: Difference to CPython
:class: attention
- This function is a MicroPython extension. CPython has a similar
+ This function is a a MicroPython extension. CPython has a similar
function - ``set_threshold()``, but due to different GC
implementations, its signature and semantics are different.
diff --git a/docs/library/index.rst b/docs/library/index.rst
index c7b6879aa..6c2e576e7 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -3,43 +3,74 @@
MicroPython libraries
=====================
+Python standard libraries and micro-libraries
+---------------------------------------------
+
+These libraries are inherited from MicroPython.
+They are similar to the standard Python libraries with the same name
+or with the "u" prefix dropped.
+They implement a subset of or a variant of the corresponding
+standard Python library.
+
.. warning::
- These modules are inherited from MicroPython and may not work in CircuitPython
- as documented or at all! If they do work, they may change at any time.
+ Though these MicroPython-based libraries are available in CircuitPython,
+ their functionality may change in the future, perhaps significantly.
+ As CircuitPython continues to develop, new versions of these libraries will
+ be created that are more compliant with the standard Python libraries.
+ You may need to change your code later if you rely
+ on any non-standard functionality they currently provide.
+CircuitPython's goal long-term goalis that code written in CircuitPython
+using Python standard libraries will be runnable on CPython without changes.
-Python standard libraries and micro-libraries
----------------------------------------------
+Some libraries below are not enabled on CircuitPython builds with
+limited flash memory, usually on non-Express builds:
+``uerrno``, ``ure``.
+
+Some libraries are not currently enabled in any CircuitPython build, but may be in the future:
+``uio``, ``ujson``, ``uzlib``.
+Some libraries are only enabled only WiFi-capable ports (ESP8266, nRF)
+because they are typically used for network software:
+``binascii``, ``hashlib``, ``uheapq``, ``uselect``, ``ussl``.
+Not all of these are enabled on all WiFi-capable ports.
.. toctree::
:maxdepth: 1
builtins.rst
+ uheapq.rst
array.rst
- gc.rst
- sys.rst
binascii.rst
collections.rst
- uerrno.rst
+ gc.rst
hashlib.rst
- uheapq.rst
+ sys.rst
+ uerrno.rst
uio.rst
ujson.rst
ure.rst
uselect.rst
usocket.rst
ussl.rst
- ustruct.rst
uzlib.rst
+Omitted functions in the ``string`` library
+-------------------------------------------
+
+A few string operations are not enabled on CircuitPython
+M0 non-Express builds, due to limited flash memory:
+``string.center()``, ``string.partition()``, ``string.splitlines()``,
+``string.reversed()``.
+
-MicroPython-specific libraries
-------------------------------
+CircuitPython/MicroPython-specific libraries
+--------------------------------------------
-Functionality specific to the MicroPython implementation is available in
-the following libraries.
+Functionality specific to the CircuitPython/MicroPython implementation is available in
+the following libraries. These libraries may change signficantly or be removed in future
+versions of CircuitPtyon.
.. toctree::
:maxdepth: 1
diff --git a/docs/library/sys.rst b/docs/library/sys.rst
index de2ec2dcd..bb92850b8 100644
--- a/docs/library/sys.rst
+++ b/docs/library/sys.rst
@@ -45,12 +45,12 @@ Constants
.. data:: implementation
Object with information about the current Python implementation. For
- MicroPython, it has following attributes:
+ CircuitPython, it has following attributes:
- * *name* - string "micropython"
+ * *name* - string "circuitpython"
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
- This object is the recommended way to distinguish MicroPython from other
+ This object is the recommended way to distinguish CircuitPython from other
Python implementations (note that it still may not exist in the very
minimal ports).
@@ -58,13 +58,13 @@ Constants
:class: attention
CPython mandates more attributes for this object, but the actual useful
- bare minimum is implemented in MicroPython.
+ bare minimum is implemented in CircuitPython.
.. data:: maxsize
Maximum value which a native integer type can hold on the current platform,
- or maximum value representable by MicroPython integer type, if it's smaller
- than platform max value (that is the case for MicroPython ports without
+ or maximum value representable by CircuitPython integer type, if it's smaller
+ than platform max value (that is the case for CircuitPython ports without
long int support).
This attribute is useful for detecting "bitness" of a platform (32-bit vs
@@ -96,11 +96,11 @@ Constants
.. data:: platform
- The platform that MicroPython is running on. For OS/RTOS ports, this is
+ The platform that CircuitPython is running on. For OS/RTOS ports, this is
usually an identifier of the OS, e.g. ``"linux"``. For baremetal ports it
- is an identifier of a board, e.g. ``"pyboard"`` for the original MicroPython
- reference board. It thus can be used to distinguish one board from another.
- If you need to check whether your program runs on MicroPython (vs other
+ is an identifier of the chip on a board, e.g. ``"MicroChip SAMD51"``.
+ It thus can be used to distinguish one board from another.
+ If you need to check whether your program runs on CircuitPython (vs other
Python implementation), use `sys.implementation` instead.
.. data:: stderr
diff --git a/docs/library/ustruct.rst b/docs/library/ustruct.rst
deleted file mode 100644
index c378a94bb..000000000
--- a/docs/library/ustruct.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-:mod:`ustruct` -- pack and unpack primitive data types
-======================================================
-
-.. include:: ../templates/unsupported_in_circuitpython.inc
-
-.. module:: ustruct
- :synopsis: pack and unpack primitive data types
-
-|see_cpython_module| :mod:`cpython:struct`.
-
-Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``.
-
-Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
-``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending
-on the floating-point support).
-
-Functions
----------
-
-.. function:: calcsize(fmt)
-
- Return the number of bytes needed to store the given *fmt*.
-
-.. function:: pack(fmt, v1, v2, ...)
-
- Pack the values *v1*, *v2*, ... according to the format string *fmt*.
- The return value is a bytes object encoding the values.
-
-.. function:: pack_into(fmt, buffer, offset, v1, v2, ...)
-
- Pack the values *v1*, *v2*, ... according to the format string *fmt*
- into a *buffer* starting at *offset*. *offset* may be negative to count
- from the end of *buffer*.
-
-.. function:: unpack(fmt, data)
-
- Unpack from the *data* according to the format string *fmt*.
- The return value is a tuple of the unpacked values.
-
-.. function:: unpack_from(fmt, data, offset=0)
-
- Unpack from the *data* starting at *offset* according to the format string
- *fmt*. *offset* may be negative to count from the end of *buffer*. The return
- value is a tuple of the unpacked values.
diff --git a/docs/templates/unsupported_in_circuitpython.inc b/docs/templates/unsupported_in_circuitpython.inc
index 18c9215a8..1ed605d50 100644
--- a/docs/templates/unsupported_in_circuitpython.inc
+++ b/docs/templates/unsupported_in_circuitpython.inc
@@ -1,5 +1,8 @@
.. warning::
- This module is inherited from MicroPython and may not work in CircuitPython
- as documented or at all! If they do work, they may change at any time. It is
- unsupported.
+ Though this MicroPython-based library is available for use in CircuitPython,
+ its functionality may change in the future, perhaps significantly.
+ As CircuitPython continues to develop, it may be changed
+ to comply more closely with the corresponding standard Python library.
+ You may need to change your code later if you rely
+ on any non-standard functionality it currently provides.
diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice
-Subproject de2d0d33cace54532467e411128521dfc8d253c
+Subproject 376a80e62acb3ba8b9a1e5c11bb75d36352f219
diff --git a/frozen/Adafruit_CircuitPython_CircuitPlayground b/frozen/Adafruit_CircuitPython_CircuitPlayground
-Subproject a669915237545638c64f89400f368a91c408cd5
+Subproject d0022de9d5e9b4c3d4998a5d708e59ee147f0a2
diff --git a/frozen/Adafruit_CircuitPython_DotStar b/frozen/Adafruit_CircuitPython_DotStar
new file mode 160000
+Subproject af25424ee7dbebea3e5d77390c017018ffa52d3
diff --git a/frozen/Adafruit_CircuitPython_HID b/frozen/Adafruit_CircuitPython_HID
-Subproject 90e4ca931a991718985e655bdcd527c1b0543f5
+Subproject 1da880cee3c2d64e2e7e4ca5082f3a74c4a37a5
diff --git a/frozen/Adafruit_CircuitPython_IRRemote b/frozen/Adafruit_CircuitPython_IRRemote
new file mode 160000
+Subproject c29e10b590efbdf06163897b49cd0c2bea82ad6
diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH
-Subproject d5491cded0d12716ceb1111ca4c4431111a22df
+Subproject c4152a0d87a04903ae0e612eb381af440c9e28b
diff --git a/frozen/Adafruit_CircuitPython_Motor b/frozen/Adafruit_CircuitPython_Motor
new file mode 160000
+Subproject 6da5d14b98ac3d929662731f73ce03c0c958b52
diff --git a/frozen/Adafruit_CircuitPython_seesaw b/frozen/Adafruit_CircuitPython_seesaw
new file mode 160000
+Subproject 498f59bf926477b3a8fb8eb157ca05eb12c3e29
diff --git a/main.c b/main.c
index bc37fa871..fb1a9e90f 100644
--- a/main.c
+++ b/main.c
@@ -168,7 +168,7 @@ bool start_mp(safe_mode_t safe_mode) {
reset_status_led();
if (result.return_code & PYEXEC_FORCED_EXIT) {
- return reload_next_character;
+ return reload_requested;
}
}
@@ -180,7 +180,7 @@ bool start_mp(safe_mode_t safe_mode) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
- if (reload_next_character) {
+ if (reload_requested) {
return true;
}
@@ -233,40 +233,7 @@ bool start_mp(safe_mode_t safe_mode) {
}
}
-int __attribute__((used)) main(void) {
- // initialise the cpu and peripherals
- safe_mode_t safe_mode = port_init();
-
- rgb_led_status_init();
-
- // Stack limit should be less than real stack size, so we have a chance
- // to recover from limit hit. (Limit is measured in bytes.)
- mp_stack_ctrl_init();
- mp_stack_set_limit((char*)&_estack - (char*)&_ebss - 1024);
-
-#if MICROPY_MAX_STACK_USAGE
- // _ezero (same as _ebss) is an int, so start 4 bytes above it.
- mp_stack_set_bottom(&_ezero + 1);
- mp_stack_fill_with_sentinel();
-#endif
-
- // Create a new filesystem only if we're not in a safe mode.
- // A power brownout here could make it appear as if there's
- // no SPI flash filesystem, and we might erase the existing one.
- filesystem_init(safe_mode == NO_SAFE_MODE, false);
-
- // Reset everything and prep MicroPython to run boot.py.
- reset_port();
- reset_board();
- reset_mp();
-
- // Turn on autoreload by default but before boot.py in case it wants to change it.
- autoreload_enable();
-
- // By default our internal flash is readonly to local python code and
- // writable over USB. Set it here so that boot.py can change it.
- filesystem_writable_by_python(false);
-
+void run_boot_py(safe_mode_t safe_mode) {
// If not in safe mode, run boot before initing USB and capture output in a
// file.
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
@@ -329,8 +296,8 @@ int __attribute__((used)) main(void) {
if (!skip_boot_output) {
f_close(boot_output_file);
filesystem_flush();
- boot_output_file = NULL;
}
+ boot_output_file = NULL;
#endif
// Reset to remove any state that boot.py setup. It should only be used to
@@ -338,6 +305,43 @@ int __attribute__((used)) main(void) {
reset_port();
reset_mp();
}
+}
+
+int __attribute__((used)) main(void) {
+ // initialise the cpu and peripherals
+ safe_mode_t safe_mode = port_init();
+
+ rgb_led_status_init();
+
+ // Stack limit should be less than real stack size, so we have a chance
+ // to recover from limit hit. (Limit is measured in bytes.)
+ mp_stack_set_top((char*)&_estack);
+ mp_stack_set_limit((char*)&_estack - (char*)&_ebss - 1024);
+
+#if MICROPY_MAX_STACK_USAGE
+ // _ezero (same as _ebss) is an int, so start 4 bytes above it.
+ mp_stack_set_bottom(&_ezero + 1);
+ mp_stack_fill_with_sentinel();
+#endif
+
+ // Create a new filesystem only if we're not in a safe mode.
+ // A power brownout here could make it appear as if there's
+ // no SPI flash filesystem, and we might erase the existing one.
+ filesystem_init(safe_mode == NO_SAFE_MODE, false);
+
+ // Reset everything and prep MicroPython to run boot.py.
+ reset_port();
+ reset_board();
+ reset_mp();
+
+ // Turn on autoreload by default but before boot.py in case it wants to change it.
+ autoreload_enable();
+
+ // By default our internal flash is readonly to local python code and
+ // writable over USB. Set it here so that boot.py can change it.
+ filesystem_writable_by_python(false);
+
+ run_boot_py(safe_mode);
// Start serial and HID after giving boot.py a chance to tweak behavior.
serial_init();
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index e85a11b57..1a406c1d0 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -112,8 +112,7 @@ else
# -finline-limit=80 or so is similar to not having it on.
# There is no simple default value, though.
ifdef INTERNAL_FLASH_FILESYSTEM
- ## Not currently needed
- ## CFLAGS += -finline-limit=50
+ CFLAGS += -finline-limit=60
endif
CFLAGS += -flto
endif
@@ -165,6 +164,20 @@ ifndef INTERNAL_LIBM
LIBS += -lm
endif
+# Propagate longint choice from .mk to C. There's no easy string comparison
+# in cpp coniditionals, so we #define separate names for each.
+ifeq ($(LONGINT_IMPL),NONE)
+CFLAGS += -DLONGINT_IMPL_NONE
+endif
+
+ifeq ($(LONGINT_IMPL),MPZ)
+CFLAGS += -DLONGINT_IMPL_MPZ
+endif
+
+ifeq ($(LONGINT_IMPL),LONGLONG)
+CFLAGS += -DLONGINT_IMPL_LONGLONG
+endif
+
ifeq ($(CHIP_FAMILY), samd21)
LDFLAGS += -mthumb -mcpu=cortex-m0plus -Lasf/thirdparty/CMSIS/Lib/GCC/
BOOTLOADER_SIZE := 0x2000
@@ -227,20 +240,28 @@ SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF))
SRC_C = \
audio_dma.c \
+ board_busses.c \
background.c \
- clocks.c \
- $(CHIP_FAMILY)_clocks.c \
- events.c \
fatfs_port.c \
flash_api.c \
mphalport.c \
reset.c \
- $(CHIP_FAMILY)_peripherals.c \
- peripherals.c \
- $(CHIP_FAMILY)_pins.c \
- shared_dma.c \
+ peripherals/clocks.c \
+ peripherals/dma.c \
+ peripherals/events.c \
+ peripherals/external_interrupts.c \
+ peripherals/sercom.c \
+ peripherals/timers.c \
+ peripherals/$(CHIP_FAMILY)/adc.c \
+ peripherals/$(CHIP_FAMILY)/cache.c \
+ peripherals/$(CHIP_FAMILY)/clocks.c \
+ peripherals/$(CHIP_FAMILY)/dma.c \
+ peripherals/$(CHIP_FAMILY)/events.c \
+ peripherals/$(CHIP_FAMILY)/external_interrupts.c \
+ peripherals/$(CHIP_FAMILY)/pins.c \
+ peripherals/$(CHIP_FAMILY)/sercom.c \
+ peripherals/$(CHIP_FAMILY)/timers.c \
tick.c \
- timers.c \
usb.c \
usb_mass_storage.c \
bindings/samd/__init__.c \
@@ -259,7 +280,7 @@ SRC_C = \
lib/libc/string0.c \
lib/mp-readline/readline.c \
$(BUILD)/autogen_usb_descriptor.c \
- # freetouch/adafruit_ptc.c
+ freetouch/adafruit_ptc.c
# Choose which flash filesystem impl to use.
# (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive.
@@ -287,6 +308,8 @@ SRC_COMMON_HAL = \
microcontroller/Processor.c \
neopixel_write/__init__.c \
os/__init__.c \
+ rotaryio/__init__.c \
+ rotaryio/IncrementalEncoder.c \
rtc/__init__.c \
rtc/RTC.c \
storage/__init__.c \
@@ -306,7 +329,7 @@ SRC_COMMON_HAL = \
usb_hid/Device.c \
audioio/__init__.c \
audioio/AudioOut.c \
-# touchio/__init__.c \
+ touchio/__init__.c \
touchio/TouchIn.c \
ifeq ($(INTERNAL_LIBM),1)
@@ -377,7 +400,7 @@ ifneq ($(CHIP_VARIANT),SAMD51G18A)
audiobusio/__init__.c \
audiobusio/I2SOut.c \
audiobusio/PDMIn.c
- SRC_C += i2s.c
+ SRC_C += peripherals/i2s.c peripherals/$(CHIP_FAMILY)/i2s.c
endif
endif
diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c
index e8dbdc61d..5a572e9d1 100644
--- a/ports/atmel-samd/audio_dma.c
+++ b/ports/atmel-samd/audio_dma.c
@@ -25,9 +25,9 @@
*/
#include "audio_dma.h"
-#include "clocks.h"
-#include "events.h"
-#include "shared_dma.h"
+#include "peripherals/clocks.h"
+#include "peripherals/events.h"
+#include "peripherals/dma.h"
#include "shared-bindings/audioio/RawSample.h"
#include "shared-bindings/audioio/WaveFile.h"
diff --git a/ports/atmel-samd/bindings/samd/Clock.c b/ports/atmel-samd/bindings/samd/Clock.c
index 81e8fb1ce..3c87177a4 100644
--- a/ports/atmel-samd/bindings/samd/Clock.c
+++ b/ports/atmel-samd/bindings/samd/Clock.c
@@ -24,9 +24,8 @@
* THE SOFTWARE.
*/
-#include "clocks.h"
#include "bindings/samd/Clock.h"
-
+#include "peripherals/clocks.h"
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/runtime.h"
diff --git a/ports/atmel-samd/board_busses.c b/ports/atmel-samd/board_busses.c
new file mode 100644
index 000000000..008391bf0
--- /dev/null
+++ b/ports/atmel-samd/board_busses.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "shared-bindings/busio/I2C.h"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/busio/UART.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "mpconfigboard.h"
+#include "peripherals/pins.h"
+#include "py/runtime.h"
+
+#if !defined(DEFAULT_I2C_BUS_SDA) || !defined(DEFAULT_I2C_BUS_SCL)
+ STATIC mp_obj_t board_i2c(void) {
+ mp_raise_NotImplementedError("No default I2C bus");
+ return NULL;
+ }
+#else
+ STATIC mp_obj_t i2c_singleton = NULL;
+
+ STATIC mp_obj_t board_i2c(void) {
+
+ if (i2c_singleton == NULL) {
+ busio_i2c_obj_t *self = m_new_obj(busio_i2c_obj_t);
+ self->base.type = &busio_i2c_type;
+
+ assert_pin_free(DEFAULT_I2C_BUS_SDA);
+ assert_pin_free(DEFAULT_I2C_BUS_SCL);
+ common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 400000, 0);
+ i2c_singleton = (mp_obj_t)self;
+ }
+ return i2c_singleton;
+
+ }
+#endif
+MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c);
+
+#if !defined(DEFAULT_SPI_BUS_SCK) || !defined(DEFAULT_SPI_BUS_MISO) || !defined(DEFAULT_SPI_BUS_MOSI)
+ STATIC mp_obj_t board_spi(void) {
+ mp_raise_NotImplementedError("No default SPI bus");
+ return NULL;
+ }
+#else
+ STATIC mp_obj_t spi_singleton = NULL;
+
+ STATIC mp_obj_t board_spi(void) {
+
+ if (spi_singleton == NULL) {
+ busio_spi_obj_t *self = m_new_obj(busio_spi_obj_t);
+ self->base.type = &busio_spi_type;
+ assert_pin_free(DEFAULT_SPI_BUS_SCK);
+ assert_pin_free(DEFAULT_SPI_BUS_MOSI);
+ assert_pin_free(DEFAULT_SPI_BUS_MISO);
+ const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_SCK);
+ const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MOSI);
+ const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(DEFAULT_SPI_BUS_MISO);
+ common_hal_busio_spi_construct(self, clock, mosi, miso);
+ spi_singleton = (mp_obj_t)self;
+ }
+ return spi_singleton;
+ }
+#endif
+MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi);
+
+#if !defined(DEFAULT_UART_BUS_RX) || !defined(DEFAULT_UART_BUS_TX)
+ STATIC mp_obj_t board_uart(void) {
+ mp_raise_NotImplementedError("No default UART bus");
+ return NULL;
+ }
+#else
+ STATIC mp_obj_t uart_singleton = NULL;
+
+ STATIC mp_obj_t board_uart(void) {
+ if (uart_singleton == NULL) {
+ busio_uart_obj_t *self = m_new_obj(busio_uart_obj_t);
+ self->base.type = &busio_uart_type;
+
+ assert_pin_free(DEFAULT_UART_BUS_RX);
+ assert_pin_free(DEFAULT_UART_BUS_TX);
+
+ const mcu_pin_obj_t* rx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_RX);
+ const mcu_pin_obj_t* tx = MP_OBJ_TO_PTR(DEFAULT_UART_BUS_TX);
+
+ common_hal_busio_uart_construct(self, tx, rx, 9600, 8, PARITY_NONE, 1, 1000, 64);
+ uart_singleton = (mp_obj_t)self;
+ }
+ return uart_singleton;
+ }
+#endif
+MP_DEFINE_CONST_FUN_OBJ_0(board_uart_obj, board_uart);
diff --git a/ports/atmel-samd/board_busses.h b/ports/atmel-samd/board_busses.h
new file mode 100644
index 000000000..a368885a5
--- /dev/null
+++ b/ports/atmel-samd/board_busses.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_BUSSES_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_BUSSES_H
+
+void board_i2c(void);
+extern mp_obj_fun_builtin_fixed_t board_i2c_obj;
+
+void board_spi(void);
+extern mp_obj_fun_builtin_fixed_t board_spi_obj;
+
+void board_uart(void);
+extern mp_obj_fun_builtin_fixed_t board_uart_obj;
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_BUSSES_H
diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h
index 6eeddb36c..a32f128f5 100644
--- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h
+++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h
@@ -14,3 +14,13 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
index b24cc9c64..017e66ddf 100644
--- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Arduino Zero"
USB_MANUFACTURER = "Arduino"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/arduino_zero/pins.c b/ports/atmel-samd/boards/arduino_zero/pins.c
index 8b28c0fc2..8a7ff70e6 100644
--- a/ports/atmel-samd/boards/arduino_zero/pins.c
+++ b/ports/atmel-samd/boards/arduino_zero/pins.c
@@ -1,6 +1,6 @@
#include "shared-bindings/board/__init__.h"
-#include "samd21_pins.h"
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -30,5 +30,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ 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_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/circuitplayground_express/board.c b/ports/atmel-samd/boards/circuitplayground_express/board.c
index eb7ffab4a..5c5e9f7fa 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/board.c
+++ b/ports/atmel-samd/boards/circuitplayground_express/board.c
@@ -31,7 +31,6 @@
#include "hal/include/hal_gpio.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/neopixel_write/__init__.h"
-#include "samd21_pins.h"
void board_init(void)
{
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
index 73d45f2cf..3d97e2cb1 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
@@ -58,3 +58,13 @@
// Explanation of how a user got into safe mode.
#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PB03)
+#define DEFAULT_I2C_BUS_SDA (&pin_PB02)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA05)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA07)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA06)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB09)
+#define DEFAULT_UART_BUS_TX (&pin_PB08)
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
index 4d6e32eb7..831106adc 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "CircuitPlayground Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/circuitplayground_express/pins.c b/ports/atmel-samd/boards/circuitplayground_express/pins.c
index aecd7f416..14ae89c55 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/pins.c
+++ b/ports/atmel-samd/boards/circuitplayground_express/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -56,5 +58,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA05) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA07) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/board.c b/ports/atmel-samd/boards/circuitplayground_express_crickit/board.c
new file mode 100644
index 000000000..5c5e9f7fa
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/board.c
@@ -0,0 +1,65 @@
+/*
+ * 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 <string.h>
+
+#include "boards/board.h"
+#include "common-hal/microcontroller/Pin.h"
+#include "hal/include/hal_gpio.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/neopixel_write/__init__.h"
+
+void board_init(void)
+{
+}
+
+// Check the status of the two buttons on CircuitPlayground Express. If both are
+// pressed, then boot into user safe mode.
+bool board_requests_safe_mode(void) {
+ gpio_set_pin_function(PIN_PA14, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(PIN_PA14, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(PIN_PA14, GPIO_PULL_DOWN);
+
+ gpio_set_pin_function(PIN_PA28, GPIO_PIN_FUNCTION_OFF);
+ gpio_set_pin_direction(PIN_PA28, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(PIN_PA28, GPIO_PULL_DOWN);
+ bool safe_mode = gpio_get_pin_level(PIN_PA14) &&
+ gpio_get_pin_level(PIN_PA28);
+ reset_pin(PIN_PA14);
+ reset_pin(PIN_PA28);
+ return safe_mode;
+}
+
+void reset_board(void) {
+ uint8_t empty[30];
+ memset(empty, 0, 30);
+ digitalio_digitalinout_obj_t neopixel_pin;
+ common_hal_digitalio_digitalinout_construct(&neopixel_pin, &pin_PB23);
+ common_hal_digitalio_digitalinout_switch_to_output(&neopixel_pin, false,
+ DRIVE_MODE_PUSH_PULL);
+ common_hal_neopixel_write(&neopixel_pin, empty, 30);
+ common_hal_digitalio_digitalinout_deinit(&neopixel_pin);
+}
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h
new file mode 100644
index 000000000..83cc19d9f
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h
@@ -0,0 +1,73 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit CircuitPlayground Express with Crickit libraries"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+// No framebuf on CRICKit version to save space.
+#define MICROPY_PY_FRAMEBUF (0)
+
+// Don't allow touch on A0 (PA02), because it's connected to the speaker.
+#define PA02_NO_TOUCH (true)
+
+// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
+#define SPI_FLASH_BAUDRATE (8000000)
+
+// On-board flash
+#define SPI_FLASH_MOSI_PIN PIN_PA20
+#define SPI_FLASH_MISO_PIN PIN_PA16
+#define SPI_FLASH_SCK_PIN PIN_PA21
+#define SPI_FLASH_CS_PIN PIN_PB22
+
+#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA20D_SERCOM3_PAD2
+#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0
+#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA21D_SERCOM3_PAD3
+#define SPI_FLASH_SERCOM SERCOM3
+#define SPI_FLASH_SERCOM_INDEX 3
+#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)
+#define MICROPY_PORT_C (0)
+
+#define SPEAKER_ENABLE_PIN (&pin_PA30)
+
+#include "external_flash/devices.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 "external_flash/devices.h"
+
+#define EXTERNAL_FLASH_DEVICE_COUNT 2
+#define EXTERNAL_FLASH_DEVICES S25FL216K, \
+ GD25Q16C
+
+#include "external_flash/external_flash.h"
+
+#define CALIBRATE_CRYSTALLESS 1
+
+// Explanation of how a user got into safe mode.
+#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PB03)
+#define DEFAULT_I2C_BUS_SDA (&pin_PB02)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA05)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA07)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA06)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB09)
+#define DEFAULT_UART_BUS_TX (&pin_PB08)
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
new file mode 100644
index 000000000..0145bf785
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
@@ -0,0 +1,21 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld
+USB_VID = 0x239A
+USB_PID = 0x8019
+USB_PRODUCT = "CircuitPlayground Express with Crickit libraries"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+SPI_FLASH_FILESYSTEM = 1
+# Turn off longints for Crickit build to make room for additional frozen libs.
+LONGINT_IMPL = NONE
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
+# Include these Python libraries in firmware.
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_CircuitPlayground
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_seesaw
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/pins.c b/ports/atmel-samd/boards/circuitplayground_express_crickit/pins.c
new file mode 100644
index 000000000..14ae89c55
--- /dev/null
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/pins.c
@@ -0,0 +1,65 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.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_D12), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_TEMPERATURE), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_PA09) },
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_PA28) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA28) },
+ { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_SLIDE_SWITCH), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PB23) },
+
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) },
+
+ { MP_ROM_QSTR(MP_QSTR_REMOTEIN), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_IR_RX), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_REMOTEOUT), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_IR_TX), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_IR_PROXIMITY), MP_ROM_PTR(&pin_PA04) },
+
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_PA08) },
+
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_INTERRUPT), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SDA), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_ACCELEROMETER_SCL), MP_ROM_PTR(&pin_PA01) },
+
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_PA30) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h
index 8802d39d9..94caa7d04 100644
--- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h
@@ -12,3 +12,13 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA22)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA23)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
index debd3d775..4f2855d73 100644
--- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 Adalogger"
USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/pins.c b/ports/atmel-samd/boards/feather_m0_adalogger/pins.c
index a229b6bab..0754617dd 100644
--- a/ports/atmel-samd/boards/feather_m0_adalogger/pins.c
+++ b/ports/atmel-samd/boards/feather_m0_adalogger/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -30,5 +32,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ 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_RED_LED), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h
index 04cbc4ff8..34de8e166 100644
--- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h
@@ -13,3 +13,13 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
index 641611176..a77da91f2 100644
--- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m0_basic/pins.c b/ports/atmel-samd/boards/feather_m0_basic/pins.c
index c9119e77b..4486d27ab 100644
--- a/ports/atmel-samd/boards/feather_m0_basic/pins.c
+++ b/ports/atmel-samd/boards/feather_m0_basic/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -23,5 +25,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ 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_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h
index c85f553ba..bfa8c642a 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h
@@ -48,3 +48,13 @@
#include "external_flash/external_flash.h"
#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
index 909922dbe..d4725fdf4 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m0_express/pins.c b/ports/atmel-samd/boards/feather_m0_express/pins.c
index c5c70ee5d..68666c273 100644
--- a/ports/atmel-samd/boards/feather_m0_express/pins.c
+++ b/ports/atmel-samd/boards/feather_m0_express/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -24,5 +26,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ 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_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/board.c b/ports/atmel-samd/boards/feather_m0_express_crickit/board.c
index a98385d29..c8e20206a 100644
--- a/ports/atmel-samd/boards/metro_m4_express_revb/board.c
+++ b/ports/atmel-samd/boards/feather_m0_express_crickit/board.c
@@ -25,17 +25,9 @@
*/
#include "boards/board.h"
-#include "mpconfigboard.h"
-#include "hal/include/hal_gpio.h"
-void board_init(void) {
- gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF);
- gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT);
- gpio_set_pin_level(MICROPY_HW_LED_TX, true);
-
- gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF);
- gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT);
- gpio_set_pin_level(MICROPY_HW_LED_RX, true);
+void board_init(void)
+{
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h
new file mode 100644
index 000000000..756462013
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h
@@ -0,0 +1,60 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Express with Crickit libraries"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define MICROPY_HW_NEOPIXEL (&pin_PA06)
+
+// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz.
+#define SPI_FLASH_BAUDRATE (8000000)
+
+#define SPI_FLASH_MOSI_PIN PIN_PA08
+#define SPI_FLASH_MISO_PIN PIN_PA14
+#define SPI_FLASH_SCK_PIN PIN_PA09
+#define SPI_FLASH_CS_PIN PIN_PA13
+#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0
+#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2
+#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1
+#define SPI_FLASH_SERCOM SERCOM2
+#define SPI_FLASH_SERCOM_INDEX 2
+#define SPI_FLASH_MOSI_PAD 0
+#define SPI_FLASH_MISO_PAD 2
+#define SPI_FLASH_SCK_PAD 1
+// <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 0
+#define SPI_FLASH_DIPO 2 // same as MISO pad
+
+// These are pins not to reset.
+#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25)
+#define MICROPY_PORT_B ( 0 )
+#define MICROPY_PORT_C ( 0 )
+
+#include "external_flash/external_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 "external_flash/devices.h"
+
+#define EXTERNAL_FLASH_DEVICE_COUNT 2
+#define EXTERNAL_FLASH_DEVICES S25FL216K, \
+ GD25Q16C
+
+#include "external_flash/external_flash.h"
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
new file mode 100644
index 000000000..4096560c2
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
@@ -0,0 +1,17 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x8023
+USB_PRODUCT = "Feather M0 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
+# Include these Python libraries in firmware.
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_seesaw
diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c b/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c
new file mode 100644
index 000000000..68666c273
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c
@@ -0,0 +1,33 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.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_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h
index 33445940e..4f4ea2ffe 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h
@@ -13,3 +13,13 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
index bf4f567af..bd1a96479 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 RFM69"
USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/pins.c b/ports/atmel-samd/boards/feather_m0_rfm69/pins.c
index eb5f531e3..6055f8a1b 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm69/pins.c
+++ b/ports/atmel-samd/boards/feather_m0_rfm69/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -26,5 +28,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_RFM69_D0), MP_ROM_PTR(&pin_PA09) },
{ MP_ROM_QSTR(MP_QSTR_RFM69_RST), MP_ROM_PTR(&pin_PA08) },
{ MP_ROM_QSTR(MP_QSTR_RFM69_CS), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h
index a2563cc9f..a9d586c2e 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h
@@ -13,3 +13,13 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
index fbc422eef..fedd8d072 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M0 RFM9x"
USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c b/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c
index 2e5d0a8e6..7395c6e2f 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c
+++ b/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -26,5 +28,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_RFM9X_D0), MP_ROM_PTR(&pin_PA09) },
{ MP_ROM_QSTR(MP_QSTR_RFM9X_RST), MP_ROM_PTR(&pin_PA08) },
{ MP_ROM_QSTR(MP_QSTR_RFM9X_CS), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h
index 5bc74d5a7..c8118e48b 100644
--- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h
@@ -47,3 +47,13 @@
#define EXTERNAL_FLASH_DEVICES S25FL064L
#include "external_flash/external_flash.h"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
index 340421f50..79bf2d34a 100644
--- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
@@ -5,7 +5,7 @@ USB_PRODUCT = "Feather M0 Supersized"
USB_MANUFACTURER = "Dave Astels"
SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
-
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/pins.c b/ports/atmel-samd/boards/feather_m0_supersized/pins.c
index c5c70ee5d..68666c273 100644
--- a/ports/atmel-samd/boards/feather_m0_supersized/pins.c
+++ b/ports/atmel-samd/boards/feather_m0_supersized/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -24,5 +26,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ 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_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h
index 6e1022256..b5af61ba6 100644
--- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h
@@ -3,15 +3,15 @@
#define CIRCUITPY_MCU_FAMILY samd51
-// This is for Rev C which is green
+// Rev E
-#define MICROPY_HW_NEOPIXEL (&pin_PB23)
+#define MICROPY_HW_NEOPIXEL (&pin_PB03)
// These are pins not to reset.
-// QSPI Data pins and TX LED
-#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09)
-// RX LED, QSPI CS, QSPI SCK and NeoPixel pin
-#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB23 )
+// QSPI Data pins
+#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
+// QSPI CS, QSPI SCK and NeoPixel pin
+#define MICROPY_PORT_B (PORT_PB03 | PORT_PB10 | PORT_PB11)
#define MICROPY_PORT_C (0)
#define MICROPY_PORT_D (0)
@@ -25,9 +25,21 @@
#include "external_flash/devices.h"
-#define EXTERNAL_FLASH_DEVICE_COUNT 2
-#define EXTERNAL_FLASH_DEVICES W25Q16FW, GD25Q16C
+#define EXTERNAL_FLASH_DEVICE_COUNT 1
+#define EXTERNAL_FLASH_DEVICES GD25Q16C
#define EXTERNAL_FLASH_QSPI_DUAL
#include "external_flash/external_flash.h"
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA13)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA12)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA17)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB23)
+#define DEFAULT_SPI_BUS_MISO (&pin_PB22)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB17)
+#define DEFAULT_UART_BUS_TX (&pin_PB16)
diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
index 2bfd0f3a0..e19a27b88 100644
--- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Feather M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
QSPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
-CHIP_VARIANT = SAMD51G19A
+CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/feather_m4_express/pins.c b/ports/atmel-samd/boards/feather_m4_express/pins.c
index c161e736e..b9b04e0ac 100644
--- a/ports/atmel-samd/boards/feather_m4_express/pins.c
+++ b/ports/atmel-samd/boards/feather_m4_express/pins.c
@@ -1,30 +1,35 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.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_PA05) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB08) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PB09) },
- { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA06) },
- { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA10) },
- { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_PA03) },
-
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA06) },
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) },
- { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA19) },
- { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA18) },
- { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA07) },
- { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA07) },
- { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA04) },
- { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB22) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB17) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB17) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB16) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB16) },
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA12) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA13) },
- { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA14) },
- { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA15) },
- { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA19) },
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA20) },
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA21) },
{ MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA22) },
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA23) },
- { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB23) },
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PB01) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h
index 6457d481f..53e802f17 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h
@@ -12,6 +12,57 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
+#define DEFAULT_I2C_BUS_SCL (&pin_PA05)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA04)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA05)
+#define DEFAULT_UART_BUS_TX (&pin_PA04)
+
#include "internal_flash.h"
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define IGNORE_PIN_PA03 1
+#define IGNORE_PIN_PA06 1
+#define IGNORE_PIN_PA07 1
+#define IGNORE_PIN_PA08 1
+#define IGNORE_PIN_PA09 1
+#define IGNORE_PIN_PA10 1
+#define IGNORE_PIN_PA11 1
+#define IGNORE_PIN_PA12 1
+#define IGNORE_PIN_PA13 1
+#define IGNORE_PIN_PA14 1
+#define IGNORE_PIN_PA15 1
+#define IGNORE_PIN_PA16 1
+#define IGNORE_PIN_PA17 1
+#define IGNORE_PIN_PA18 1
+#define IGNORE_PIN_PA19 1
+#define IGNORE_PIN_PA20 1
+#define IGNORE_PIN_PA21 1
+#define IGNORE_PIN_PA22 1
+#define IGNORE_PIN_PA27 1
+#define IGNORE_PIN_PA28 1
+#define IGNORE_PIN_PA30 1
+#define IGNORE_PIN_PA31 1
+#define IGNORE_PIN_PB01 1
+#define IGNORE_PIN_PB02 1
+#define IGNORE_PIN_PB03 1
+#define IGNORE_PIN_PB04 1
+#define IGNORE_PIN_PB05 1
+#define IGNORE_PIN_PB06 1
+#define IGNORE_PIN_PB07 1
+#define IGNORE_PIN_PB08 1
+#define IGNORE_PIN_PB09 1
+#define IGNORE_PIN_PB10 1
+#define IGNORE_PIN_PB11 1
+#define IGNORE_PIN_PB12 1
+#define IGNORE_PIN_PB13 1
+#define IGNORE_PIN_PB14 1
+#define IGNORE_PIN_PB15 1
+#define IGNORE_PIN_PB16 1
+#define IGNORE_PIN_PB17 1
+#define IGNORE_PIN_PB22 1
+#define IGNORE_PIN_PB23 1
+#define IGNORE_PIN_PB30 1
+#define IGNORE_PIN_PB31 1
+#define IGNORE_PIN_PB00 1
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
index a406e8f58..ddc4287c3 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Gemma M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/gemma_m0/pins.c b/ports/atmel-samd/boards/gemma_m0/pins.c
index 5d3bedca0..196e438e0 100644
--- a/ports/atmel-samd/boards/gemma_m0/pins.c
+++ b/ports/atmel-samd/boards/gemma_m0/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) }, // pad 1
@@ -19,5 +21,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) },
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h
index a7ecd27ea..be59bc5d4 100644
--- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h
@@ -46,3 +46,13 @@
GD25Q16C
#include "external_flash/external_flash.h"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
index 0fb0e38ed..66586b611 100644
--- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
@@ -5,7 +5,7 @@ USB_PRODUCT = "Itsy Bitsy M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
-
diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c b/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c
index b70bb6a76..25407bc14 100644
--- a/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c
+++ b/ports/atmel-samd/boards/itsybitsy_m0_express/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) },
@@ -38,5 +40,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ 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_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h
index 95c542a43..faa0d6e75 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h
@@ -31,3 +31,13 @@
#define EXTERNAL_FLASH_DEVICES GD25Q16C
#include "external_flash/external_flash.h"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA13)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA12)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA01)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA00)
+#define DEFAULT_SPI_BUS_MISO (&pin_PB23)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA16)
+#define DEFAULT_UART_BUS_TX (&pin_PA17)
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
index f96661327..27f5ea2b8 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "ItsyBitsy M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
QSPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c b/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c
index 11aeda9c6..3997ecda4 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/pins.c
@@ -1,4 +1,6 @@
-#include "samd51_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
// This mapping only includes functional names because pins broken
// out on connectors are labeled with their MCU name available from
@@ -27,13 +29,14 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA12) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA13) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_PA03) },
-
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA01) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA00) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB23) },
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PB03) },
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h
index e635acd59..f798c5d36 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h
@@ -49,3 +49,13 @@
#include "external_flash/external_flash.h"
#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA23)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA22)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB10)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA12)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA11)
+#define DEFAULT_UART_BUS_TX (&pin_PA10)
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index 79d60380d..0388a408b 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Metro M0 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/metro_m0_express/pins.c b/ports/atmel-samd/boards/metro_m0_express/pins.c
index 58510faab..13f0eb0ba 100644
--- a/ports/atmel-samd/boards/metro_m0_express/pins.c
+++ b/ports/atmel-samd/boards/metro_m0_express/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
@@ -29,5 +31,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ 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_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h
index 701203771..7aef929f7 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h
@@ -32,3 +32,15 @@
#define EXTERNAL_FLASH_DEVICES S25FL116K, S25FL216K, GD25Q16C
#include "external_flash/external_flash.h"
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PB03)
+#define DEFAULT_I2C_BUS_SDA (&pin_PB02)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA13)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA12)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA14)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA23)
+#define DEFAULT_UART_BUS_TX (&pin_PA22)
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
index 1d59ed966..38e8a12d7 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Metro M4 Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
QSPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD51J19A
CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/metro_m4_express/pins.c b/ports/atmel-samd/boards/metro_m4_express/pins.c
index 32ecdf492..0e66817f7 100644
--- a/ports/atmel-samd/boards/metro_m4_express/pins.c
+++ b/ports/atmel-samd/boards/metro_m4_express/pins.c
@@ -1,4 +1,6 @@
-#include "samd51_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
// This mapping only includes functional names because pins broken
// out on connectors are labeled with their MCU name available from
@@ -31,8 +33,6 @@ STATIC const mp_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PB02 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_AREF), (mp_obj_t)&pin_PA03 },
-
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB22 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA13 },
@@ -41,5 +41,8 @@ STATIC const mp_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_LED_RX), (mp_obj_t)&pin_PB06 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h
deleted file mode 100644
index 206d85465..000000000
--- a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// This is for Rev B which a larger run was done and sent to Adafruit community
-// members.
-
-#define MICROPY_HW_BOARD_NAME "Metro M4 Express Rev B (Black)"
-#define MICROPY_HW_MCU_NAME "samd51j19"
-
-#define CIRCUITPY_MCU_FAMILY samd51
-
-#define MICROPY_HW_LED_TX PIN_PA27
-#define MICROPY_HW_LED_RX PIN_PB06
-
-#define MICROPY_HW_NEOPIXEL (&pin_PB17)
-
-#define SPI_FLASH_BAUDRATE (60000000)
-
-// Rev B: single channel SPI
-// Rev C will be QSPI
-#define SPI_FLASH_MOSI_PIN PIN_PB08
-#define SPI_FLASH_MISO_PIN PIN_PB11
-#define SPI_FLASH_SCK_PIN PIN_PB09
-#define SPI_FLASH_CS_PIN PIN_PB10
-#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB08D_SERCOM4_PAD0
-#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3
-#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB09D_SERCOM4_PAD1
-#define SPI_FLASH_SERCOM SERCOM4
-#define SPI_FLASH_SERCOM_INDEX 4
-#define SPI_FLASH_MOSI_PAD 0
-#define SPI_FLASH_MISO_PAD 3
-#define SPI_FLASH_SCK_PAD 1
-// <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 0
-#define SPI_FLASH_DIPO 3 // same as MISO pad
-
-// These are pins not to reset.
-// Pin for TX LED
-#define MICROPY_PORT_A (PORT_PA27)
-// Pins for RX LED, SPI flash and neopixel
-#define MICROPY_PORT_B (PORT_PB06 | PORT_PB08 | PORT_PB09 | PORT_PB10 | PORT_PB11 | PORT_PB17)
-#define MICROPY_PORT_C (0)
-#define MICROPY_PORT_D (0)
-
-#define AUTORESET_DELAY_MS 500
-
-#include "external_flash/external_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 8192
-
-#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
-
-#include "external_flash/devices.h"
-
-#define EXTERNAL_FLASH_DEVICE_COUNT 2
-#define EXTERNAL_FLASH_DEVICES S25FL216K, \
- GD25Q16C
-
-#include "external_flash/external_flash.h"
diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk
deleted file mode 100644
index a3d6e2522..000000000
--- a/ports/atmel-samd/boards/metro_m4_express_revb/mpconfigboard.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-LD_FILE = boards/samd51x19-bootloader-external-flash.ld
-USB_VID = 0x239A
-USB_PID = 0x8021
-USB_PRODUCT = "Metro M4 Express Rev B (Black)"
-USB_MANUFACTURER = "Adafruit Industries LLC"
-
-SPI_FLASH_FILESYSTEM = 1
-
-CHIP_VARIANT = SAMD51J19A
-CHIP_FAMILY = samd51
diff --git a/ports/atmel-samd/boards/metro_m4_express_revb/pins.c b/ports/atmel-samd/boards/metro_m4_express_revb/pins.c
deleted file mode 100644
index a18906f73..000000000
--- a/ports/atmel-samd/boards/metro_m4_express_revb/pins.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "samd51_pins.h"
-
-// This mapping only includes functional names because pins broken
-// out on connectors are labeled with their MCU name available from
-// microcontroller.pin.
-STATIC const mp_map_elem_t board_global_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PA05 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PA06 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PA11 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PA07 },
-
-
- { MP_OBJ_NEW_QSTR(MP_QSTR_D0), (mp_obj_t)&pin_PA23 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_PA23 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D1), (mp_obj_t)&pin_PA22 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_PA22 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA08 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PA10 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PB12 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PB14 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PB15 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D7), (mp_obj_t)&pin_PA14 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA16 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA17 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D10), (mp_obj_t)&pin_PA18 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA19 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA20 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA21 },
-
- { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PB02 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PB03 },
-
- { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), (mp_obj_t)&pin_PB17 },
-
- { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA13 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PA12 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA15 },
-
- { MP_OBJ_NEW_QSTR(MP_QSTR_LED_RX), (mp_obj_t)&pin_PB06 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_LED_TX), (mp_obj_t)&pin_PA27 },
-};
-MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h
index a26fd7fdd..15979ae77 100644
--- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h
+++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h
@@ -1,8 +1,8 @@
#define MICROPY_HW_BOARD_NAME "Adafruit pIRKey M0"
#define MICROPY_HW_MCU_NAME "samd21e18"
-// #define MICROPY_HW_APA102_MOSI (&pin_PA00)
-// #define MICROPY_HW_APA102_SCK (&pin_PA01)
+#define MICROPY_HW_APA102_MOSI (&pin_PA00)
+#define MICROPY_HW_APA102_SCK (&pin_PA01)
// #define CIRCUITPY_BITBANG_APA102
@@ -12,6 +12,58 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
+// A number of modules are removed for pIRKey to make room for frozen libraries.
+#define PIRKEY_M0 (1)
+
#include "internal_flash.h"
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define IGNORE_PIN_PA02 1
+#define IGNORE_PIN_PA03 1
+#define IGNORE_PIN_PA04 1
+#define IGNORE_PIN_PA05 1
+#define IGNORE_PIN_PA06 1
+#define IGNORE_PIN_PA07 1
+#define IGNORE_PIN_PA08 1
+#define IGNORE_PIN_PA09 1
+#define IGNORE_PIN_PA10 1
+#define IGNORE_PIN_PA11 1
+#define IGNORE_PIN_PA12 1
+#define IGNORE_PIN_PA13 1
+#define IGNORE_PIN_PA14 1
+#define IGNORE_PIN_PA15 1
+#define IGNORE_PIN_PA16 1
+#define IGNORE_PIN_PA17 1
+#define IGNORE_PIN_PA18 1
+#define IGNORE_PIN_PA19 1
+#define IGNORE_PIN_PA20 1
+#define IGNORE_PIN_PA21 1
+#define IGNORE_PIN_PA22 1
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
+#define IGNORE_PIN_PA27 1
+#define IGNORE_PIN_PA30 1
+#define IGNORE_PIN_PA31 1
+#define IGNORE_PIN_PB00 1
+#define IGNORE_PIN_PB01 1
+#define IGNORE_PIN_PB02 1
+#define IGNORE_PIN_PB03 1
+#define IGNORE_PIN_PB04 1
+#define IGNORE_PIN_PB05 1
+#define IGNORE_PIN_PB06 1
+#define IGNORE_PIN_PB07 1
+#define IGNORE_PIN_PB08 1
+#define IGNORE_PIN_PB09 1
+#define IGNORE_PIN_PB10 1
+#define IGNORE_PIN_PB11 1
+#define IGNORE_PIN_PB12 1
+#define IGNORE_PIN_PB13 1
+#define IGNORE_PIN_PB14 1
+#define IGNORE_PIN_PB15 1
+#define IGNORE_PIN_PB16 1
+#define IGNORE_PIN_PB17 1
+#define IGNORE_PIN_PB22 1
+#define IGNORE_PIN_PB23 1
+#define IGNORE_PIN_PB30 1
+#define IGNORE_PIN_PB31 1
diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
index 52dfc1430..0f8d0f9ca 100644
--- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
@@ -5,6 +5,12 @@ USB_PRODUCT = "pIRKey M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
+
+# Include these Python libraries in firmware.
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_IRRemote
diff --git a/ports/atmel-samd/boards/pirkey_m0/pins.c b/ports/atmel-samd/boards/pirkey_m0/pins.c
index a1b7db85c..e08302f14 100644
--- a/ports/atmel-samd/boards/pirkey_m0/pins.c
+++ b/ports/atmel-samd/boards/pirkey_m0/pins.c
@@ -1,9 +1,14 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_REMOTEIN), MP_ROM_PTR(&pin_PA28) },
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) },
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h
index 05033ad38..d561947e3 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h
@@ -14,3 +14,55 @@
#define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#define IGNORE_PIN_PA03 1
+#define IGNORE_PIN_PA04 1
+#define IGNORE_PIN_PA11 1
+#define IGNORE_PIN_PA12 1
+#define IGNORE_PIN_PA13 1
+#define IGNORE_PIN_PA14 1
+#define IGNORE_PIN_PA15 1
+#define IGNORE_PIN_PA16 1
+#define IGNORE_PIN_PA17 1
+#define IGNORE_PIN_PA18 1
+#define IGNORE_PIN_PA19 1
+#define IGNORE_PIN_PA20 1
+#define IGNORE_PIN_PA21 1
+#define IGNORE_PIN_PA22 1
+#define IGNORE_PIN_PA23 1
+#define IGNORE_PIN_PA27 1
+#define IGNORE_PIN_PA28 1
+#define IGNORE_PIN_PA30 1
+#define IGNORE_PIN_PA31 1
+#define IGNORE_PIN_PB01 1
+#define IGNORE_PIN_PB02 1
+#define IGNORE_PIN_PB03 1
+#define IGNORE_PIN_PB04 1
+#define IGNORE_PIN_PB05 1
+#define IGNORE_PIN_PB06 1
+#define IGNORE_PIN_PB07 1
+#define IGNORE_PIN_PB08 1
+#define IGNORE_PIN_PB09 1
+#define IGNORE_PIN_PB10 1
+#define IGNORE_PIN_PB11 1
+#define IGNORE_PIN_PB12 1
+#define IGNORE_PIN_PB13 1
+#define IGNORE_PIN_PB14 1
+#define IGNORE_PIN_PB15 1
+#define IGNORE_PIN_PB16 1
+#define IGNORE_PIN_PB17 1
+#define IGNORE_PIN_PB22 1
+#define IGNORE_PIN_PB23 1
+#define IGNORE_PIN_PB30 1
+#define IGNORE_PIN_PB31 1
+#define IGNORE_PIN_PB00 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA09)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA08)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA07)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA06)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA09)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA07)
+#define DEFAULT_UART_BUS_TX (&pin_PA06)
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index 43d07eb5f..c9c45152b 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT = "Trinket M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/trinket_m0/pins.c b/ports/atmel-samd/boards/trinket_m0/pins.c
index ac5898600..633017024 100644
--- a/ports/atmel-samd/boards/trinket_m0/pins.c
+++ b/ports/atmel-samd/boards/trinket_m0/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA08) },
@@ -27,5 +29,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) },
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h
index ea45c1f8b..3377d1b7e 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h
@@ -54,3 +54,13 @@
#define EXTERNAL_FLASH_DEVICES W25Q32BV
#include "external_flash/external_flash.h"
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA09)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA08)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PA07)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PA06)
+#define DEFAULT_SPI_BUS_MISO (&pin_PA09)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA07)
+#define DEFAULT_UART_BUS_TX (&pin_PA06)
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
index a904b2837..d97aa08ab 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
@@ -5,6 +5,7 @@ USB_PRODUCT="Trinket M0 Haxpress"
USB_MANUFACTURER="Radomir Dopieralski"
SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c b/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c
index ac5898600..633017024 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA08) },
@@ -27,5 +29,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA00) },
{ MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h
index 1652314ed..4e5e88569 100644
--- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h
+++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h
@@ -47,3 +47,8 @@
#define EXTERNAL_FLASH_DEVICES S25FL216K
#include "external_flash/external_flash.h"
+
+#define EXTRA_BUILTIN_MODULES \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module }
diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
index 343115fbb..2386531f9 100644
--- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
@@ -6,6 +6,10 @@ USB_PRODUCT = "uGame10"
USB_MANUFACTURER = "Radomir Dopieralski"
SPI_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
+
+
+FROZEN_MPY_DIRS += $(TOP)/frozen/ugame10
diff --git a/ports/atmel-samd/boards/ugame10/pins.c b/ports/atmel-samd/boards/ugame10/pins.c
index af516a401..87ace5e96 100644
--- a/ports/atmel-samd/boards/ugame10/pins.c
+++ b/ports/atmel-samd/boards/ugame10/pins.c
@@ -1,4 +1,6 @@
-#include "samd21_pins.h"
+#include "shared-bindings/board/__init__.h"
+
+#include "board_busses.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_X), MP_ROM_PTR(&pin_PA00) },
@@ -23,5 +25,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_B), MP_ROM_PTR(&pin_PA14) },
{ MP_ROM_QSTR(MP_QSTR_C), MP_ROM_PTR(&pin_PA15) },
{ MP_ROM_QSTR(MP_QSTR_D), MP_ROM_PTR(&pin_PA28) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/common-hal/analogio/AnalogIn.c b/ports/atmel-samd/common-hal/analogio/AnalogIn.c
index 02613ae07..e452eb030 100644
--- a/ports/atmel-samd/common-hal/analogio/AnalogIn.c
+++ b/ports/atmel-samd/common-hal/analogio/AnalogIn.c
@@ -34,7 +34,7 @@
#include "py/binary.h"
#include "py/mphal.h"
-#include "peripherals.h"
+#include "peripherals/adc.h"
#include "shared-bindings/analogio/AnalogIn.h"
#include "atmel_start_pins.h"
diff --git a/ports/atmel-samd/common-hal/analogio/AnalogOut.c b/ports/atmel-samd/common-hal/analogio/AnalogOut.c
index 97299a863..9ceca3868 100644
--- a/ports/atmel-samd/common-hal/analogio/AnalogOut.c
+++ b/ports/atmel-samd/common-hal/analogio/AnalogOut.c
@@ -42,10 +42,6 @@
#include "hpl/pm/hpl_pm_base.h"
#endif
-#ifdef SAMD51
-#include "samd51_pins.h"
-#endif
-
void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self,
const mcu_pin_obj_t *pin) {
if (pin->pin != PIN_PA02
@@ -73,7 +69,7 @@ void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self,
#endif
// SAMD21: This clock should be <= 12 MHz, per datasheet section 47.6.3.
- // SAMD51: This clock should be <= 350kHz, per datasheet table 37-6.
+ // SAMD51: This clock should be <= 350kHz, per datasheet table 37-6.
_gclk_enable_channel(DAC_GCLK_ID, CONF_GCLK_DAC_SRC);
// Don't double init the DAC on the SAMD51 when both outputs are in use. We use the free state
diff --git a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
index f4a8eb52e..27a7b9ee0 100644
--- a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
+++ b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
@@ -45,13 +45,14 @@
#include "hpl/pm/hpl_pm_base.h"
#endif
+#include "peripherals/clocks.h"
+#include "peripherals/dma.h"
+#include "peripherals/events.h"
+#include "peripherals/i2s.h"
+#include "peripherals/pins.h"
+#include "peripherals/timers.h"
+
#include "audio_dma.h"
-#include "clocks.h"
-#include "events.h"
-#include "i2s.h"
-#include "pins.h"
-#include "shared_dma.h"
-#include "timers.h"
#ifdef SAMD21
#define SERCTRL(name) I2S_SERCTRL_ ## name
diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
index 44129eed1..5502fcd81 100644
--- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
+++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
@@ -41,12 +41,13 @@
#include "hal/include/hal_gpio.h"
#include "hal/utils/include/utils.h"
+#include "peripherals/clocks.h"
+#include "peripherals/events.h"
+#include "peripherals/i2s.h"
+#include "peripherals/pins.h"
+#include "peripherals/dma.h"
+
#include "audio_dma.h"
-#include "clocks.h"
-#include "events.h"
-#include "i2s.h"
-#include "pins.h"
-#include "shared_dma.h"
#include "tick.h"
#define OVERSAMPLING 64
diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c
index 6971c020b..fc5c75673 100644
--- a/ports/atmel-samd/common-hal/audioio/AudioOut.c
+++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c
@@ -45,10 +45,11 @@
#endif
#include "audio_dma.h"
-#include "events.h"
-#include "samd21_pins.h"
-#include "shared_dma.h"
-#include "timers.h"
+
+#include "peripherals/dma.h"
+#include "peripherals/events.h"
+#include "peripherals/pins.h"
+#include "peripherals/timers.h"
void audioout_reset(void) {
}
@@ -240,6 +241,8 @@ void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self) {
disable_event_channel(self->tc_to_dac_event_channel);
+ tc_set_enable(tc_insts[self->tc_index], false);
+
reset_pin(self->left_channel->pin);
self->left_channel = mp_const_none;
#ifdef SAMD51
diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c
index 77676b535..c14b2d68f 100644
--- a/ports/atmel-samd/common-hal/busio/I2C.c
+++ b/ports/atmel-samd/common-hal/busio/I2C.c
@@ -32,8 +32,7 @@
#include "hal/include/hal_i2c_m_sync.h"
#include "hal/include/hpl_i2c_m_sync.h"
-#include "peripherals.h"
-#include "pins.h"
+#include "peripherals/sercom.h"
#include "shared-bindings/microcontroller/__init__.h"
@@ -41,7 +40,11 @@
#define ATTEMPTS 2
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
- const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency) {
+ const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout) {
+ #ifdef PIRKEY_M0
+ mp_raise_NotImplementedError("Not enough pins available");
+ return;
+ #endif
Sercom* sercom = NULL;
uint8_t sercom_index;
uint32_t sda_pinmux = 0;
diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c
index a2bf30f05..a9bd55903 100644
--- a/ports/atmel-samd/common-hal/busio/SPI.c
+++ b/ports/atmel-samd/common-hal/busio/SPI.c
@@ -36,9 +36,8 @@
#include "hal/include/hpl_spi_m_sync.h"
#include "supervisor/shared/rgb_led_status.h"
-#include "peripherals.h"
-#include "pins.h"
-#include "shared_dma.h"
+#include "peripherals/dma.h"
+#include "peripherals/sercom.h"
void common_hal_busio_spi_construct(busio_spi_obj_t *self,
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c
index 537677520..a95ccf3ac 100644
--- a/ports/atmel-samd/common-hal/busio/UART.c
+++ b/ports/atmel-samd/common-hal/busio/UART.c
@@ -42,8 +42,7 @@
#include "hal/include/hal_usart_async.h"
#include "hal/include/hpl_usart_async.h"
-#include "peripherals.h"
-#include "pins.h"
+#include "peripherals/sercom.h"
// Do-nothing callback needed so that usart_async code will enable rx interrupts.
// See comment below re usart_async_register_callback()
diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c
index e1ca5d622..ad97581e1 100644
--- a/ports/atmel-samd/common-hal/microcontroller/Pin.c
+++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c
@@ -29,13 +29,8 @@
#include "atmel_start_pins.h"
#include "hal/include/hal_gpio.h"
+#include "peripherals/pins.h"
#include "supervisor/shared/rgb_led_status.h"
-#ifdef SAMD21
-#include "samd21_pins.h"
-#endif
-#ifdef SAMD51
-#include "samd51_pins.h"
-#endif
#ifdef MICROPY_HW_NEOPIXEL
bool neopixel_in_use;
diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h
index 4e21a14cd..4230246a5 100644
--- a/ports/atmel-samd/common-hal/microcontroller/Pin.h
+++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h
@@ -81,4 +81,6 @@ void reset_all_pins(void);
void reset_pin(uint8_t pin);
void claim_pin(const mcu_pin_obj_t* pin);
+#include "peripherals/pins.h"
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PIN_H
diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c
index e7f758cd1..a76ee2e78 100644
--- a/ports/atmel-samd/common-hal/microcontroller/Processor.c
+++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c
@@ -63,7 +63,7 @@
#include "common-hal/microcontroller/Processor.h"
-#include "peripherals.h"
+#include "peripherals/adc.h"
#include "peripheral_clk_config.h"
diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c
index 4b8c33182..c57b6939c 100644
--- a/ports/atmel-samd/common-hal/microcontroller/__init__.c
+++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c
@@ -30,10 +30,10 @@
#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/Pin.h"
#include "shared-bindings/microcontroller/Processor.h"
void common_hal_mcu_delay_us(uint32_t delay) {
@@ -42,13 +42,31 @@ void common_hal_mcu_delay_us(uint32_t delay) {
// Interrupt flags that will be saved and restored during disable/Enable
// interrupt functions below.
-volatile hal_atomic_t flags;
+
+// ASF4's interrupt disable doesn't handle duplicate calls
+volatile uint32_t interrupt_flags;
+volatile uint32_t nesting_count = 0;
void common_hal_mcu_disable_interrupts(void) {
- atomic_enter_critical(&flags);
+ if (nesting_count == 0) {
+ interrupt_flags = __get_PRIMASK();
+ __disable_irq();
+ __DMB();
+ }
+ nesting_count++;
}
void common_hal_mcu_enable_interrupts(void) {
- atomic_leave_critical(&flags);
+ if (nesting_count == 0) {
+ // This is very very bad because it means there was mismatched disable/enables so we
+ // "HardFault".
+ HardFault_Handler();
+ }
+ nesting_count--;
+ if (nesting_count > 0) {
+ return;
+ }
+ __DMB();
+ __set_PRIMASK(interrupt_flags);
}
extern uint32_t _ezero;
@@ -97,162 +115,162 @@ const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
// This maps MCU pin names to pin objects.
STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = {
// Pins in datasheet order.
-#ifdef PIN_PA00
+#if defined(PIN_PA00) && !defined(IGNORE_PIN_PA00)
{ MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) },
#endif
-#ifdef PIN_PA01
+#if defined(PIN_PA01) && !defined(IGNORE_PIN_PA01)
{ MP_ROM_QSTR(MP_QSTR_PA01), MP_ROM_PTR(&pin_PA01) },
#endif
-#ifdef PIN_PA02
+#if defined(PIN_PA02) && !defined(IGNORE_PIN_PA02)
{ MP_ROM_QSTR(MP_QSTR_PA02), MP_ROM_PTR(&pin_PA02) },
#endif
-#ifdef PIN_PA03
+#if defined(PIN_PA03) && !defined(IGNORE_PIN_PA03)
{ MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) },
#endif
-#ifdef PIN_PB04
+#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04)
{ MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) },
#endif
-#ifdef PIN_PB05
+#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05)
{ MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) },
#endif
-#ifdef PIN_PB06
+#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06)
{ MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) },
#endif
-#ifdef PIN_PB07
+#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07)
{ MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) },
#endif
-#ifdef PIN_PB08
+#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08)
{ MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) },
#endif
-#ifdef PIN_PB09
+#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09)
{ MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) },
#endif
-#ifdef PIN_PA04
+#if defined(PIN_PA04) && !defined(IGNORE_PIN_PA04)
{ MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) },
#endif
-#ifdef PIN_PA05
+#if defined(PIN_PA05) && !defined(IGNORE_PIN_PA05)
{ MP_ROM_QSTR(MP_QSTR_PA05), MP_ROM_PTR(&pin_PA05) },
#endif
-#ifdef PIN_PA06
+#if defined(PIN_PA06) && !defined(IGNORE_PIN_PA06)
{ MP_ROM_QSTR(MP_QSTR_PA06), MP_ROM_PTR(&pin_PA06) },
#endif
-#ifdef PIN_PA07
+#if defined(PIN_PA07) && !defined(IGNORE_PIN_PA07)
{ MP_ROM_QSTR(MP_QSTR_PA07), MP_ROM_PTR(&pin_PA07) },
#endif
-#ifdef PIN_PA08
+#if defined(PIN_PA08) && !defined(IGNORE_PIN_PA08)
{ MP_ROM_QSTR(MP_QSTR_PA08), MP_ROM_PTR(&pin_PA08) },
#endif
-#ifdef PIN_PA09
+#if defined(PIN_PA09) && !defined(IGNORE_PIN_PA09)
{ MP_ROM_QSTR(MP_QSTR_PA09), MP_ROM_PTR(&pin_PA09) },
#endif
-#ifdef PIN_PA10
+#if defined(PIN_PA10) && !defined(IGNORE_PIN_PA10)
{ MP_ROM_QSTR(MP_QSTR_PA10), MP_ROM_PTR(&pin_PA10) },
#endif
-#ifdef PIN_PA11
+#if defined(PIN_PA11) && !defined(IGNORE_PIN_PA11)
{ MP_ROM_QSTR(MP_QSTR_PA11), MP_ROM_PTR(&pin_PA11) },
#endif
-#ifdef PIN_PB10
+#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10)
{ MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) },
#endif
-#ifdef PIN_PB11
+#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11)
{ MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) },
#endif
-#ifdef PIN_PB12
+#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12)
{ MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) },
#endif
-#ifdef PIN_PB13
+#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13)
{ MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) },
#endif
-#ifdef PIN_PB14
+#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14)
{ MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) },
#endif
// Second page.
-#ifdef PIN_PB15
+#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15)
{ MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) },
#endif
-#ifdef PIN_PA12
+#if defined(PIN_PA12) && !defined(IGNORE_PIN_PA12)
{ MP_ROM_QSTR(MP_QSTR_PA12), MP_ROM_PTR(&pin_PA12) },
#endif
-#ifdef PIN_PA13
+#if defined(PIN_PA13) && !defined(IGNORE_PIN_PA13)
{ MP_ROM_QSTR(MP_QSTR_PA13), MP_ROM_PTR(&pin_PA13) },
#endif
-#ifdef PIN_PA14
+#if defined(PIN_PA14) && !defined(IGNORE_PIN_PA14)
{ MP_ROM_QSTR(MP_QSTR_PA14), MP_ROM_PTR(&pin_PA14) },
#endif
-#ifdef PIN_PA15
+#if defined(PIN_PA15) && !defined(IGNORE_PIN_PA15)
{ MP_ROM_QSTR(MP_QSTR_PA15), MP_ROM_PTR(&pin_PA15) },
#endif
-#ifdef PIN_PA16
+#if defined(PIN_PA16) && !defined(IGNORE_PIN_PA16)
{ MP_ROM_QSTR(MP_QSTR_PA16), MP_ROM_PTR(&pin_PA16) },
#endif
-#ifdef PIN_PA17
+#if defined(PIN_PA17) && !defined(IGNORE_PIN_PA17)
{ MP_ROM_QSTR(MP_QSTR_PA17), MP_ROM_PTR(&pin_PA17) },
#endif
-#ifdef PIN_PA18
+#if defined(PIN_PA18) && !defined(IGNORE_PIN_PA18)
{ MP_ROM_QSTR(MP_QSTR_PA18), MP_ROM_PTR(&pin_PA18) },
#endif
-#ifdef PIN_PA19
+#if defined(PIN_PA19) && !defined(IGNORE_PIN_PA19)
{ MP_ROM_QSTR(MP_QSTR_PA19), MP_ROM_PTR(&pin_PA19) },
#endif
-#ifdef PIN_PB16
+#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16)
{ MP_ROM_QSTR(MP_QSTR_PB16), MP_ROM_PTR(&pin_PB16) },
#endif
-#ifdef PIN_PB17
+#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17)
{ MP_ROM_QSTR(MP_QSTR_PB17), MP_ROM_PTR(&pin_PB17) },
#endif
-#ifdef PIN_PA20
+#if defined(PIN_PA20) && !defined(IGNORE_PIN_PA20)
{ MP_ROM_QSTR(MP_QSTR_PA20), MP_ROM_PTR(&pin_PA20) },
#endif
-#ifdef PIN_PA21
+#if defined(PIN_PA21) && !defined(IGNORE_PIN_PA21)
{ MP_ROM_QSTR(MP_QSTR_PA21), MP_ROM_PTR(&pin_PA21) },
#endif
-#ifdef PIN_PA22
+#if defined(PIN_PA22) && !defined(IGNORE_PIN_PA22)
{ MP_ROM_QSTR(MP_QSTR_PA22), MP_ROM_PTR(&pin_PA22) },
#endif
-#ifdef PIN_PA23
+#if defined(PIN_PA23) && !defined(IGNORE_PIN_PA23)
{ MP_ROM_QSTR(MP_QSTR_PA23), MP_ROM_PTR(&pin_PA23) },
#endif
-#ifdef PIN_PA24
+#if defined(PIN_PA24) && !defined(IGNORE_PIN_PA24)
{ MP_ROM_QSTR(MP_QSTR_PA24), MP_ROM_PTR(&pin_PA24) },
#endif
-#ifdef PIN_PA25
+#if defined(PIN_PA25) && !defined(IGNORE_PIN_PA25)
{ MP_ROM_QSTR(MP_QSTR_PA25), MP_ROM_PTR(&pin_PA25) },
#endif
-#ifdef PIN_PB22
+#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22)
{ MP_ROM_QSTR(MP_QSTR_PB22), MP_ROM_PTR(&pin_PB22) },
#endif
-#ifdef PIN_PB23
+#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23)
{ MP_ROM_QSTR(MP_QSTR_PB23), MP_ROM_PTR(&pin_PB23) },
#endif
-#ifdef PIN_PA27
+#if defined(PIN_PA27) && !defined(IGNORE_PIN_PA27)
{ MP_ROM_QSTR(MP_QSTR_PA27), MP_ROM_PTR(&pin_PA27) },
#endif
-#ifdef PIN_PA28
+#if defined(PIN_PA28) && !defined(IGNORE_PIN_PA28)
{ MP_ROM_QSTR(MP_QSTR_PA28), MP_ROM_PTR(&pin_PA28) },
#endif
-#ifdef PIN_PA30
+#if defined(PIN_PA30) && !defined(IGNORE_PIN_PA30)
{ MP_ROM_QSTR(MP_QSTR_PA30), MP_ROM_PTR(&pin_PA30) },
#endif
-#ifdef PIN_PA31
+#if defined(PIN_PA31) && !defined(IGNORE_PIN_PA31)
{ MP_ROM_QSTR(MP_QSTR_PA31), MP_ROM_PTR(&pin_PA31) },
#endif
-#ifdef PIN_PB30
+#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30)
{ MP_ROM_QSTR(MP_QSTR_PB30), MP_ROM_PTR(&pin_PB30) },
#endif
-#ifdef PIN_PB31
+#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31)
{ MP_ROM_QSTR(MP_QSTR_PB31), MP_ROM_PTR(&pin_PB31) },
#endif
-#ifdef PIN_PB00
+#if defined(PIN_PB00) && !defined(IGNORE_PIN_PB00)
{ MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) },
#endif
-#ifdef PIN_PB01
+#if defined(PIN_PB01) && !defined(IGNORE_PIN_PB01)
{ MP_ROM_QSTR(MP_QSTR_PB01), MP_ROM_PTR(&pin_PB01) },
#endif
-#ifdef PIN_PB02
+#if defined(PIN_PB02) && !defined(IGNORE_PIN_PB02)
{ MP_ROM_QSTR(MP_QSTR_PB02), MP_ROM_PTR(&pin_PB02) },
#endif
-#ifdef PIN_PB03
+#if defined(PIN_PB03) && !defined(IGNORE_PIN_PB03)
{ MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) }
#endif
};
diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c
index 24cd154c2..18d896686 100644
--- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c
@@ -34,9 +34,9 @@
#include "atmel_start_pins.h"
#include "hal/utils/include/utils_repeat_macro.h"
-#include "timers.h"
+#include "peripherals/timers.h"
-#include "samd21_pins.h"
+#include "peripherals/pins.h"
#undef ENABLE
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c
index 6e3aa3abb..99a60a829 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c
+++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2017-2018 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -34,90 +34,28 @@
#include "mpconfigport.h"
#include "py/gc.h"
#include "py/runtime.h"
-#include "samd21_pins.h"
+#include "peripherals/external_interrupts.h"
+#include "peripherals/pins.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/pulseio/PulseIn.h"
-#ifdef SAMD21
-#include "hpl/gclk/hpl_gclk_base.h"
-#endif
-
#include "tick.h"
-static pulseio_pulsein_obj_t *active_pulseins[EIC_EXTINT_NUM];
-static uint64_t last_ms[EIC_EXTINT_NUM];
-static uint16_t last_us[EIC_EXTINT_NUM];
-
-bool eic_get_enable(void) {
- #ifdef SAMD51
- return EIC->CTRLA.bit.ENABLE;
- #endif
- #ifdef SAMD21
- return EIC->CTRL.bit.ENABLE;
- #endif
-}
-
-void eic_set_enable(bool value) {
- #ifdef SAMD51
- EIC->CTRLA.bit.ENABLE = value;
- while (EIC->SYNCBUSY.bit.ENABLE != 0) {}
- // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first
- // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us.
- #endif
- #ifdef SAMD21
- EIC->CTRL.bit.ENABLE = value;
- while (EIC->STATUS.bit.SYNCBUSY != 0) {}
- #endif
-}
-
-void eic_reset(void) {
- #ifdef SAMD51
- EIC->CTRLA.bit.SWRST = true;
- while (EIC->SYNCBUSY.bit.SWRST != 0) {}
- // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first
- // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us.
- #endif
- #ifdef SAMD21
- EIC->CTRL.bit.SWRST = true;
- while (EIC->STATUS.bit.SYNCBUSY != 0) {}
- #endif
-}
-
-void pulsein_reset(void) {
- for (int i = 0; i < EIC_EXTINT_NUM; i++) {
- active_pulseins[i] = NULL;
- last_ms[i] = 0;
- last_us[i] = 0;
- #ifdef SAMD51
- NVIC_DisableIRQ(EIC_0_IRQn + i);
- NVIC_ClearPendingIRQ(EIC_0_IRQn + i);
- #endif
- }
- eic_reset();
- #ifdef SAMD21
- NVIC_DisableIRQ(EIC_IRQn);
- NVIC_ClearPendingIRQ(EIC_IRQn);
- #endif
-}
-
static void pulsein_set_config(pulseio_pulsein_obj_t* self, bool first_edge) {
- uint8_t sense_setting = EIC_CONFIG_FILTEN0;
+ uint32_t sense_setting;
if (!first_edge) {
- sense_setting |= EIC_CONFIG_SENSE0_BOTH_Val;
+ sense_setting = EIC_CONFIG_SENSE0_BOTH_Val;
+ configure_eic_channel(self->channel, sense_setting);
+ return;
} else if (self->idle_state) {
- sense_setting |= EIC_CONFIG_SENSE0_FALL_Val;
+ sense_setting = EIC_CONFIG_SENSE0_FALL_Val;
} else {
- sense_setting |= EIC_CONFIG_SENSE0_RISE_Val;
+ sense_setting = EIC_CONFIG_SENSE0_RISE_Val;
}
- eic_set_enable(false);
- uint8_t config_index = self->channel / 8;
- uint8_t position = (self->channel % 8) * 4;
- uint32_t masked_value = EIC->CONFIG[config_index].reg & ~(0xf << position);
- EIC->CONFIG[config_index].reg = masked_value | (sense_setting << position);
- eic_set_enable(true);
+ turn_on_eic_channel(self->channel, sense_setting, EIC_HANDLER_PULSEIN);
}
-static void pulsein_interrupt_handler(uint8_t channel) {
+void pulsein_interrupt_handler(uint8_t channel) {
// Grab the current time first.
uint32_t current_us;
uint64_t current_ms;
@@ -125,16 +63,16 @@ static void pulsein_interrupt_handler(uint8_t channel) {
// current_tick gives us the remaining us until the next tick but we want the number since the
// last ms.
current_us = 1000 - current_us;
- pulseio_pulsein_obj_t* self = active_pulseins[channel];
+ pulseio_pulsein_obj_t* self = get_eic_channel_data(channel);
if (self->first_edge) {
self->first_edge = false;
pulsein_set_config(self, false);
} else {
- uint32_t ms_diff = current_ms - last_ms[self->channel];
- uint16_t us_diff = current_us - last_us[self->channel];
+ uint32_t ms_diff = current_ms - self->last_ms;
+ uint16_t us_diff = current_us - self->last_us;
uint32_t total_diff = us_diff;
- if (last_us[self->channel] > current_us) {
- total_diff = 1000 + current_us - last_us[self->channel];
+ if (self->last_us > current_us) {
+ total_diff = 1000 + current_us - self->last_us;
if (ms_diff > 1) {
total_diff += (ms_diff - 1) * 1000;
}
@@ -154,8 +92,8 @@ static void pulsein_interrupt_handler(uint8_t channel) {
self->start++;
}
}
- last_ms[self->channel] = current_ms;
- last_us[self->channel] = current_us;
+ self->last_ms = current_ms;
+ self->last_us = current_us;
}
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
@@ -163,17 +101,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
if (!pin->has_extint) {
mp_raise_RuntimeError("No hardware support on pin");
}
- uint32_t mask = 1 << pin->extint_channel;
- if (active_pulseins[pin->extint_channel] != NULL ||
- (eic_get_enable() == 1 &&
-#ifdef SAMD51
- ((EIC->INTENSET.bit.EXTINT & mask) != 0 ||
- (EIC->EVCTRL.bit.EXTINTEO & mask) != 0))) {
-#endif
-#ifdef SAMD21
- ((EIC->INTENSET.vec.EXTINT & mask) != 0 ||
- (EIC->EVCTRL.vec.EXTINTEO & mask) != 0))) {
-#endif
+ if (eic_get_enable() && !eic_channel_free(pin->extint_channel)) {
mp_raise_RuntimeError("EXTINT channel already in use");
}
@@ -188,42 +116,22 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
self->start = 0;
self->len = 0;
self->first_edge = true;
+ self->last_us = 0;
+ self->last_ms = 0;
- active_pulseins[pin->extint_channel] = self;
+ set_eic_channel_data(pin->extint_channel, (void*) self);
// Check to see if the EIC is enabled and start it up if its not.'
- // SAMD51 EIC can only be clocked up to 100mhz so we use the 48mhz clock.
if (eic_get_enable() == 0) {
- #ifdef SAMD51
- MCLK->APBAMASK.bit.EIC_ = true;
- hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID,
- GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
- #endif
-
- #ifdef SAMD21
- PM->APBAMASK.bit.EIC_ = true;
- _gclk_enable_channel(EIC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
- #endif
-
-
- #ifdef SAMD21
- NVIC_DisableIRQ(EIC_IRQn);
- NVIC_ClearPendingIRQ(EIC_IRQn);
- NVIC_EnableIRQ(EIC_IRQn);
- #endif
+ turn_on_external_interrupt_controller();
}
gpio_set_pin_function(pin->pin, GPIO_PIN_FUNCTION_A);
- #ifdef SAMD51
- NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
- NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
- NVIC_EnableIRQ(EIC_0_IRQn + self->channel);
- #endif
+ turn_on_cpu_interrupt(self->channel);
// Set config will enable the EIC.
pulsein_set_config(self, true);
- EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos;
}
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
@@ -234,39 +142,9 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
if (common_hal_pulseio_pulsein_deinited(self)) {
return;
}
- uint32_t mask = 1 << self->channel;
- EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos;
- #ifdef SAMD51
- NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
- NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
- #endif
- active_pulseins[self->channel] = NULL;
+ turn_off_eic_channel(self->channel);
reset_pin(self->pin);
self->pin = NO_PIN;
-
- bool all_null = true;
- for (uint8_t i = 0; all_null && i < 16; i++) {
- all_null = all_null && active_pulseins[i] == NULL;
- }
- #ifdef SAMD21
- if (all_null && EIC->INTENSET.reg == 0) {
- NVIC_DisableIRQ(EIC_IRQn);
- NVIC_ClearPendingIRQ(EIC_IRQn);
- }
- #endif
- // Test if all channels are null and deinit everything if they are.
- if (all_null && EIC->EVCTRL.reg == 0 && EIC->INTENSET.reg == 0) {
- eic_set_enable(false);
- #ifdef SAMD51
- MCLK->APBAMASK.bit.EIC_ = false;
- hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, 0);
- #endif
-
- #ifdef SAMD21
- PM->APBAMASK.bit.EIC_ = false;
- hri_gclk_write_CLKCTRL_reg(GCLK, GCLK_CLKCTRL_ID(EIC_GCLK_ID));
- #endif
- }
}
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
@@ -289,9 +167,9 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self,
}
// Reconfigure the pin and make sure its set to detect the first edge.
- last_ms[self->channel] = 0;
- last_us[self->channel] = 0;
self->first_edge = true;
+ self->last_ms = 0;
+ self->last_us = 0;
gpio_set_pin_function(self->pin, GPIO_PIN_FUNCTION_A);
uint32_t mask = 1 << self->channel;
// Clear previous interrupt state and re-enable it.
@@ -343,69 +221,3 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self,
common_hal_mcu_enable_interrupts();
return value;
}
-
-void external_interrupt_handler(uint8_t channel) {
- pulsein_interrupt_handler(channel);
- EIC->INTFLAG.reg = (1 << channel) << EIC_INTFLAG_EXTINT_Pos;
-}
-
-#ifdef SAMD21
-void EIC_Handler(void) {
- for (uint8_t i = 0; i < 16; i++) {
- if ((EIC->INTFLAG.vec.EXTINT & (1 << i)) != 0) {
- external_interrupt_handler(i);
- }
- }
-}
-#endif
-
-#ifdef SAMD51
-void EIC_0_Handler(void) {
- external_interrupt_handler(0);
-}
-void EIC_1_Handler(void) {
- external_interrupt_handler(1);
-}
-void EIC_2_Handler(void) {
- external_interrupt_handler(2);
-}
-void EIC_3_Handler(void) {
- external_interrupt_handler(3);
-}
-void EIC_4_Handler(void) {
- external_interrupt_handler(4);
-}
-void EIC_5_Handler(void) {
- external_interrupt_handler(5);
-}
-void EIC_6_Handler(void) {
- external_interrupt_handler(6);
-}
-void EIC_7_Handler(void) {
- external_interrupt_handler(7);
-}
-void EIC_8_Handler(void) {
- external_interrupt_handler(8);
-}
-void EIC_9_Handler(void) {
- external_interrupt_handler(9);
-}
-void EIC_10_Handler(void) {
- external_interrupt_handler(10);
-}
-void EIC_11_Handler(void) {
- external_interrupt_handler(11);
-}
-void EIC_12_Handler(void) {
- external_interrupt_handler(12);
-}
-void EIC_13_Handler(void) {
- external_interrupt_handler(13);
-}
-void EIC_14_Handler(void) {
- external_interrupt_handler(14);
-}
-void EIC_15_Handler(void) {
- external_interrupt_handler(15);
-}
-#endif
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.h b/ports/atmel-samd/common-hal/pulseio/PulseIn.h
index e3af42e0a..3d79b50c3 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseIn.h
+++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.h
@@ -41,8 +41,12 @@ typedef struct {
volatile uint16_t start;
volatile uint16_t len;
volatile bool first_edge;
+ volatile uint64_t last_ms;
+ volatile uint16_t last_us;
} pulseio_pulsein_obj_t;
void pulsein_reset(void);
+void pulsein_interrupt_handler(uint8_t channel);
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PULSEIO_PULSEIN_H
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
index 95b0bbee0..8e715d410 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
@@ -31,11 +31,11 @@
#include "hal/include/hal_gpio.h"
#include "mpconfigport.h"
+#include "peripherals/pins.h"
+#include "peripherals/timers.h"
#include "py/gc.h"
#include "py/runtime.h"
-#include "samd21_pins.h"
#include "shared-bindings/pulseio/PulseOut.h"
-#include "timers.h"
// This timer is shared amongst all PulseOut objects under the assumption that
// the code is single threaded.
diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
new file mode 100644
index 000000000..ddc545295
--- /dev/null
+++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
@@ -0,0 +1,157 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/rotaryio/IncrementalEncoder.h"
+
+#include "atmel_start_pins.h"
+
+#include "peripherals/external_interrupts.h"
+#include "py/runtime.h"
+
+void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t* self,
+ const mcu_pin_obj_t* pin_a, const mcu_pin_obj_t* pin_b) {
+ if (!pin_a->has_extint || !pin_a->has_extint) {
+ mp_raise_RuntimeError("Both pins must support hardware interrupts");
+ }
+
+ // TODO: The SAMD51 has a peripheral dedicated to quadrature encoder debugging. Use it instead
+ // of the external interrupt.
+
+ if (eic_get_enable()) {
+ if (!eic_channel_free(pin_a->extint_channel) || !eic_channel_free(pin_b->extint_channel)) {
+ mp_raise_RuntimeError("A hardware interrupt channel is already in use");
+ }
+ } else {
+ turn_on_external_interrupt_controller();
+ }
+
+ // These default settings apply when the EIC isn't yet enabled.
+ self->eic_channel_a = pin_a->extint_channel;
+ self->eic_channel_b = pin_b->extint_channel;
+ self->pin_a = pin_a->pin;
+ self->pin_b = pin_b->pin;
+
+ gpio_set_pin_function(self->pin_a, GPIO_PIN_FUNCTION_A);
+ gpio_set_pin_pull_mode(self->pin_a, GPIO_PULL_UP);
+
+ gpio_set_pin_function(self->pin_b, GPIO_PIN_FUNCTION_A);
+ gpio_set_pin_pull_mode(self->pin_b, GPIO_PULL_UP);
+
+ set_eic_channel_data(self->eic_channel_a, (void*) self);
+ set_eic_channel_data(self->eic_channel_b, (void*) self);
+
+ self->position = 0;
+ self->quarter_count = 0;
+
+ // Top two bits of self->last_state don't matter, because they'll be gone as soon as
+ // interrupt handler is called.
+ self->last_state =
+ ((uint8_t) gpio_get_pin_level(self->pin_a) << 1) |
+ (uint8_t) gpio_get_pin_level(self->pin_b);
+
+ turn_on_eic_channel(self->eic_channel_a, EIC_CONFIG_SENSE0_BOTH_Val, EIC_HANDLER_INCREMENTAL_ENCODER);
+ turn_on_eic_channel(self->eic_channel_b, EIC_CONFIG_SENSE0_BOTH_Val, EIC_HANDLER_INCREMENTAL_ENCODER);
+}
+
+bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t* self) {
+ return self->pin_a == NO_PIN;
+}
+
+void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t* self) {
+ if (common_hal_rotaryio_incrementalencoder_deinited(self)) {
+ return;
+ }
+ turn_off_eic_channel(self->eic_channel_a);
+ turn_off_eic_channel(self->eic_channel_b);
+ reset_pin(self->pin_a);
+ self->pin_a = NO_PIN;
+ reset_pin(self->pin_b);
+ self->pin_b = NO_PIN;
+}
+
+mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t* self) {
+ return self->position;
+}
+
+void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t* self,
+ mp_int_t new_position) {
+ self->position = new_position;
+}
+
+void incrementalencoder_interrupt_handler(uint8_t channel) {
+ rotaryio_incrementalencoder_obj_t* self = get_eic_channel_data(channel);
+
+ // This table also works for detent both at 11 and 00
+ // For 11 at detent:
+ // Turning cw: 11->01->00->10->11
+ // Turning ccw: 11->10->00->01->11
+ // For 00 at detent:
+ // Turning cw: 00->10->11->10->00
+ // Turning ccw: 00->01->11->10->00
+
+ // index table by state <oldA><oldB><newA><newB>
+ #define BAD 7
+ static const int8_t transitions[16] = {
+ 0, // 00 -> 00 no movement
+ -1, // 00 -> 01 3/4 ccw (11 detent) or 1/4 ccw (00 at detent)
+ +1, // 00 -> 10 3/4 cw or 1/4 cw
+ BAD, // 00 -> 11 non-Gray-code transition
+ +1, // 01 -> 00 2/4 or 4/4 cw
+ 0, // 01 -> 01 no movement
+ BAD, // 01 -> 10 non-Gray-code transition
+ -1, // 01 -> 11 4/4 or 2/4 ccw
+ -1, // 10 -> 00 2/4 or 4/4 ccw
+ BAD, // 10 -> 01 non-Gray-code transition
+ 0, // 10 -> 10 no movement
+ +1, // 10 -> 11 4/4 or 2/4 cw
+ BAD, // 11 -> 00 non-Gray-code transition
+ +1, // 11 -> 01 1/4 or 3/4 cw
+ -1, // 11 -> 10 1/4 or 3/4 ccw
+ 0, // 11 -> 11 no movement
+ };
+
+ // Shift the old AB bits to the "old" position, and set the new AB bits.
+ // TODO(tannewt): If we need more speed then read the pin directly. gpio_get_pin_level has
+ // smarts to compensate for pin direction we don't need.
+ self->last_state = (self->last_state & 0x3) << 2 |
+ ((uint8_t) gpio_get_pin_level(self->pin_a) << 1) |
+ (uint8_t) gpio_get_pin_level(self->pin_b);
+
+ int8_t quarter_incr = transitions[self->last_state];
+ if (quarter_incr == BAD) {
+ // Missed a transition. We don't know which way we're going, so do nothing.
+ return;
+ }
+
+ self->quarter_count += quarter_incr;
+ if (self->quarter_count >= 4) {
+ self->position += 1;
+ self->quarter_count = 0;
+ } else if (self->quarter_count <= -4) {
+ self->position -= 1;
+ self->quarter_count = 0;
+ }
+}
diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.h b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.h
new file mode 100644
index 000000000..e07cc84d5
--- /dev/null
+++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t pin_a;
+ uint8_t pin_b;
+ uint8_t eic_channel_a:4;
+ uint8_t eic_channel_b:4;
+ uint8_t last_state:4; // <old A><old B><new A><new B>
+ int8_t quarter_count:4; // count intermediate transitions between detents
+ mp_int_t position;
+} rotaryio_incrementalencoder_obj_t;
+
+
+void incrementalencoder_interrupt_handler(uint8_t channel);
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H
diff --git a/ports/atmel-samd/common-hal/rotaryio/__init__.c b/ports/atmel-samd/common-hal/rotaryio/__init__.c
new file mode 100644
index 000000000..0aae79c26
--- /dev/null
+++ b/ports/atmel-samd/common-hal/rotaryio/__init__.c
@@ -0,0 +1 @@
+// No rotaryio module functions.
diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.c b/ports/atmel-samd/common-hal/touchio/TouchIn.c
index 6bb96ff00..e39a091d7 100644
--- a/ports/atmel-samd/common-hal/touchio/TouchIn.c
+++ b/ports/atmel-samd/common-hal/touchio/TouchIn.c
@@ -33,11 +33,18 @@
#include "py/mphal.h"
#include "shared-bindings/touchio/TouchIn.h"
-#include "samd21_pins.h"
-#include "tick.h"
+#ifdef SAMD21
+#include "hpl/pm/hpl_pm_base.h"
+#endif
+
+#include "peripherals/clocks.h"
+#include "peripherals/pins.h"
+#include "tick.h"
#include "adafruit_ptc.h"
+bool touch_enabled = false;
+
static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
adafruit_ptc_start_conversion(PTC, &self->config);
@@ -58,13 +65,21 @@ void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self,
}
claim_pin(pin);
- /* Setup and enable generic clock source for PTC module. */
- struct system_gclk_chan_config gclk_chan_conf;
- system_gclk_chan_get_config_defaults(&gclk_chan_conf);
- gclk_chan_conf.source_generator = GCLK_GENERATOR_3;
- system_gclk_chan_set_config(PTC_GCLK_ID, &gclk_chan_conf);
- system_gclk_chan_enable(PTC_GCLK_ID);
- system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_PTC);
+ // Turn on the PTC if its not in use. We won't turn it off until reset.
+ #ifdef SAMD21
+ if ((( Ptc *) PTC)->CTRLA.bit.ENABLE == 0) {
+ // We run the PTC at 8mhz so divide the 48mhz clock by 6.
+ uint8_t gclk = find_free_gclk(6);
+ if (gclk > GCLK_GEN_NUM) {
+ mp_raise_RuntimeError("No free GCLKs");
+ }
+ enable_clock_generator(gclk, CLOCK_48MHZ, 6);
+
+ /* Setup and enable generic clock source for PTC module. */
+ connect_gclk_to_peripheral(gclk, PTC_GCLK_ID);
+
+ _pm_enable_bus_clock(PM_BUS_APBC, PTC);
+ }
adafruit_ptc_get_config_default(&self->config);
self->config.pin = pin->pin;
@@ -80,6 +95,7 @@ void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self,
// but for touches using fruit or other objects, the difference is much less.
self->threshold = get_raw_reading(self) + 100;
+ #endif
}
bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t* self) {
@@ -91,12 +107,21 @@ void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t* self) {
if (common_hal_touchio_touchin_deinited(self)) {
return;
}
+ // We leave the clocks running because they may be in use by others.
+
reset_pin(self->config.pin);
self->config.pin = NO_PIN;
}
void touchin_reset() {
- // TODO(tannewt): Reset the PTC.
+ Ptc* ptc = ((Ptc *) PTC);
+ if (ptc->CTRLA.bit.ENABLE == 1) {
+ ptc->CTRLA.bit.ENABLE = 0;
+ while (ptc->CTRLA.bit.ENABLE == 1) {}
+
+ ptc->CTRLA.bit.SWRESET = 1;
+ while (ptc->CTRLA.bit.SWRESET == 1) {}
+ }
}
bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self) {
diff --git a/ports/atmel-samd/external_flash/external_flash.c b/ports/atmel-samd/external_flash/external_flash.c
index ccc47e5b1..e6c407e73 100644
--- a/ports/atmel-samd/external_flash/external_flash.c
+++ b/ports/atmel-samd/external_flash/external_flash.c
@@ -36,12 +36,9 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "lib/oofatfs/ff.h"
-#include "peripherals.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/shared/rgb_led_status.h"
-//#include "shared_dma.h"
-
#include "hal_gpio.h"
#include "hal_spi_m_sync.h"
diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/external_flash/qspi_flash.c
index 3fc9d31be..ec91c21e2 100644
--- a/ports/atmel-samd/external_flash/qspi_flash.c
+++ b/ports/atmel-samd/external_flash/qspi_flash.c
@@ -32,8 +32,8 @@
#include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL
#include "external_flash/common_commands.h"
-#include "peripherals.h"
-#include "shared_dma.h"
+#include "peripherals/cache.h"
+#include "peripherals/dma.h"
#include "atmel_start_pins.h"
#include "hal_gpio.h"
diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/ports/atmel-samd/external_flash/spi_flash.c
index 8a8cbaef8..faad8d9e0 100644
--- a/ports/atmel-samd/external_flash/spi_flash.c
+++ b/ports/atmel-samd/external_flash/spi_flash.c
@@ -29,8 +29,8 @@
#include <string.h>
#include "external_flash/common_commands.h"
-#include "peripherals.h"
-#include "shared_dma.h"
+#include "peripherals/sercom.h"
+#include "py/mpconfig.h"
#include "hal_gpio.h"
#include "hal_spi_m_sync.h"
diff --git a/ports/atmel-samd/freetouch b/ports/atmel-samd/freetouch
-Subproject c3deba11eb4be397ec719cfbfba1abcaecda2c0
+Subproject b6859a349efb79e2008d6f6a34e406e93a8e19c
diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h
index e6c3a201f..276ffafe3 100644
--- a/ports/atmel-samd/mpconfigport.h
+++ b/ports/atmel-samd/mpconfigport.h
@@ -140,19 +140,27 @@ typedef long mp_off_t;
#define CIRCUITPY_MCU_FAMILY samd21
#define MICROPY_PY_SYS_PLATFORM "Atmel SAMD21"
#define PORT_HEAP_SIZE (16384 + 4096)
-// If you change MICROPY_LONGINT_IMPL, also change MPY_TOOL_LONGINT_IMPL in mpconfigport.mk.
-#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#endif
#ifdef SAMD51
#define CIRCUITPY_MCU_FAMILY samd51
#define MICROPY_PY_SYS_PLATFORM "MicroChip SAMD51"
#define PORT_HEAP_SIZE (0x20000) // 128KiB
-// If you change MICROPY_LONGINT_IMPL, also change MPY_TOOL_LONGINT_IMPL in mpconfigport.mk.
-#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
+#endif
+
+#ifdef LONGINT_IMPL_NONE
+#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
+#endif
+
+#ifdef LONGINT_IMPL_MPZ
+#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MP_SSIZE_MAX (0x7fffffff)
#endif
+#ifdef LONGINT_IMPL_LONGLONG
+#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
+#endif
+
// extra built in modules to add to the list of known ones
extern const struct _mp_obj_module_t microcontroller_module;
extern const struct _mp_obj_module_t bitbangio_module;
@@ -166,6 +174,7 @@ extern const struct _mp_obj_module_t board_module;
extern const struct _mp_obj_module_t math_module;
extern const struct _mp_obj_module_t os_module;
extern const struct _mp_obj_module_t random_module;
+extern const struct _mp_obj_module_t rotaryio_module;
extern const struct _mp_obj_module_t rtc_module;
extern const struct _mp_obj_module_t samd_module;
extern const struct _mp_obj_module_t storage_module;
@@ -188,9 +197,13 @@ extern const struct _mp_obj_module_t usb_hid_module;
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
#define MICROPY_PY_BUILTINS_REVERSED (1)
+ #define MICROPY_PY_UERRNO (1)
+ #define MICROPY_PY_UERRNO_ERRORCODE (0)
#define MICROPY_PY_URE (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
- #define MICROPY_PY_FRAMEBUF (1)
+ #ifndef MICROPY_PY_FRAMEBUF
+ #define MICROPY_PY_FRAMEBUF (1)
+ #endif
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
@@ -203,18 +216,23 @@ extern const struct _mp_obj_module_t usb_hid_module;
#define AUDIOBUSIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_audiobusio), (mp_obj_t)&audiobusio_module },
#endif
+ #ifndef EXTRA_BUILTIN_MODULES
#define EXTRA_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module }, \
AUDIOBUSIO_MODULE \
{ MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rotaryio), (mp_obj_t)&rotaryio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }
+ #endif
#define EXPRESS_BOARD
#else
#define MICROPY_PY_BUILTINS_REVERSED (0)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
#define MICROPY_PY_FRAMEBUF (0)
+ #ifndef EXTRA_BUILTIN_MODULES
#define EXTRA_BUILTIN_MODULES
+ #endif
#define MICROPY_PY_BUILTINS_COMPLEX (0)
@@ -222,10 +240,32 @@ extern const struct _mp_obj_module_t usb_hid_module;
#endif
// Disabled for now.
-// { MP_OBJ_NEW_QSTR(MP_QSTR_touchio), (mp_obj_t)&touchio_module },
// { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module },
+#ifdef SAMD21
+#define TOUCHIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_touchio), (mp_obj_t)&touchio_module },
+#endif
+#ifdef SAMD51
+#define TOUCHIO_MODULE
+#endif
+// A pIRKey has minimal I/O needs. Remove unneeded modules to make room
+// for frozen modules. math is very large and is also removed.
+#ifdef PIRKEY_M0
+#define MICROPY_PORT_BUILTIN_MODULES \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)&microcontroller_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module },
+#else
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
@@ -244,12 +284,26 @@ extern const struct _mp_obj_module_t usb_hid_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, \
+ TOUCHIO_MODULE \
EXTRA_BUILTIN_MODULES
+#endif
#define MICROPY_PORT_BUILTIN_DEBUG_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uheap),(mp_obj_t)&uheap_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ustack),(mp_obj_t)&ustack_module }
+#define MICROPY_PY_UERRNO_LIST \
+ X(EPERM) \
+ X(ENOENT) \
+ X(EIO) \
+ X(EAGAIN) \
+ X(ENOMEM) \
+ X(EACCES) \
+ X(EEXIST) \
+ X(ENODEV) \
+ X(EISDIR) \
+ X(EINVAL) \
+
// We need to provide a declaration/definition of alloca()
#include <alloca.h>
@@ -264,7 +318,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
#define MP_STATE_PORT MP_STATE_VM
-#include "shared_dma.h"
+#include "peripherals/dma.h"
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8]; \
@@ -272,6 +326,7 @@ extern const struct _mp_obj_module_t usb_hid_module;
mp_obj_t playing_audio[AUDIO_DMA_CHANNEL_COUNT]; \
mp_obj_t rtc_time_source; \
FLASH_ROOT_POINTERS \
+ mp_obj_t gamepad_singleton; \
void run_background_tasks(void);
#define MICROPY_VM_HOOK_LOOP run_background_tasks();
diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk
index 0f3f399e2..c2eedfdc3 100644
--- a/ports/atmel-samd/mpconfigport.mk
+++ b/ports/atmel-samd/mpconfigport.mk
@@ -1,12 +1,18 @@
# Define an equivalent for MICROPY_LONGINT_IMPL, to pass to $(MPY-TOOL) in py/mkrules.mk
# $(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.
-ifeq ($(CHIP_FAMILY), samd21)
+
+ifeq ($(LONGINT_IMPL),NONE)
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=none
endif
-ifeq ($(CHIP_FAMILY), samd51)
+ifeq ($(LONGINT_IMPL),MPZ)
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
endif
+ifeq ($(LONGINT_IMPL),LONGLONG)
+MPY_TOOL_LONGINT_IMPL = -mlongint-impl=longlong
+endif
+
+
INTERNAL_LIBM = 1
diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c
index cdf27fe02..c1b8ce550 100644
--- a/ports/atmel-samd/mphalport.c
+++ b/ports/atmel-samd/mphalport.c
@@ -28,7 +28,7 @@ int mp_hal_stdin_rx_chr(void) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
- // if (reload_next_character) {
+ // if (reload_requested) {
// return CHAR_CTRL_D;
// }
if (usb_bytes_available()) {
diff --git a/ports/atmel-samd/samd21_peripherals.h b/ports/atmel-samd/peripherals/adc.h
index 805717695..6530b1dcd 100644
--- a/ports/atmel-samd/samd21_peripherals.h
+++ b/ports/atmel-samd/peripherals/adc.h
@@ -24,15 +24,12 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
-#define MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_ADC_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_ADC_H
#include "include/sam.h"
#include "hal/include/hal_adc_sync.h"
-void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
-uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
-bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance);
-#endif // MICROPY_INCLUDED_ATMEL_SAMD_SAMD21_PERIPHERALS_H
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_ADC_H
diff --git a/ports/atmel-samd/samd51_peripherals.h b/ports/atmel-samd/peripherals/cache.h
index 6643379a5..b260568a3 100644
--- a/ports/atmel-samd/samd51_peripherals.h
+++ b/ports/atmel-samd/peripherals/cache.h
@@ -27,14 +27,6 @@
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PERIPHERALS_H
#define MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PERIPHERALS_H
-#include "sam.h"
-#include "hal/include/hal_adc_sync.h"
-
-void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
-uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
-bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
-void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance);
-
void samd_peripherals_disable_and_clear_cache(void);
void samd_peripherals_enable_cache(void);
diff --git a/ports/atmel-samd/clocks.c b/ports/atmel-samd/peripherals/clocks.c
index a890210bf..bfcca4547 100644
--- a/ports/atmel-samd/clocks.c
+++ b/ports/atmel-samd/peripherals/clocks.c
@@ -56,41 +56,20 @@ uint8_t find_free_gclk(uint16_t divisor) {
return 0xff;
}
+static uint8_t last_static_clock = 0;
+
+void init_dynamic_clocks(void) {
+ // Find the last statically initialized clock and save it. Everything after will be reset with
+ // the VM via reset_gclks.
+ for (uint8_t i = 0; i < GCLK_GEN_NUM; i++) {
+ if (gclk_enabled(i)) {
+ last_static_clock = i;
+ }
+ }
+}
+
void reset_gclks(void) {
- // Never reset GCLK0 because its used for the core
- #if CONF_GCLK_GEN_1_GENEN == 0
- disable_gclk(1);
- #endif
- #if CONF_GCLK_GEN_2_GENEN == 0
- disable_gclk(2);
- #endif
- #if CONF_GCLK_GEN_3_GENEN == 0
- disable_gclk(3);
- #endif
- #if CONF_GCLK_GEN_4_GENEN == 0
- disable_gclk(4);
- #endif
- #if CONF_GCLK_GEN_5_GENEN == 0
- disable_gclk(5);
- #endif
- #if CONF_GCLK_GEN_6_GENEN == 0
- disable_gclk(6);
- #endif
- #if CONF_GCLK_GEN_7_GENEN == 0
- disable_gclk(7);
- #endif
- #ifdef SAMD51
- #if CONF_GCLK_GEN_8_GENEN == 0
- disable_gclk(8);
- #endif
- #if CONF_GCLK_GEN_9_GENEN == 0
- disable_gclk(9);
- #endif
- #if CONF_GCLK_GEN_10_GENEN == 0
- disable_gclk(10);
- #endif
- #if CONF_GCLK_GEN_11_GENEN == 0
- disable_gclk(11);
- #endif
- #endif
+ for (uint8_t i = last_static_clock + 1; i < GCLK_GEN_NUM; i++) {
+ disable_gclk(i);
+ }
}
diff --git a/ports/atmel-samd/clocks.h b/ports/atmel-samd/peripherals/clocks.h
index 6b7cfedce..22c166d3e 100644
--- a/ports/atmel-samd/clocks.h
+++ b/ports/atmel-samd/peripherals/clocks.h
@@ -63,11 +63,13 @@ static inline bool board_has_crystal(void) {
}
void clock_init(void);
+void init_dynamic_clocks(void);
bool clock_get_enabled(uint8_t type, uint8_t index);
bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index);
uint32_t clock_get_frequency(uint8_t type, uint8_t index);
uint32_t clock_get_calibration(uint8_t type, uint8_t index);
int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val);
+void save_usb_clock_calibration(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_CLOCKS_H
diff --git a/ports/atmel-samd/shared_dma.c b/ports/atmel-samd/peripherals/dma.c
index edc2d0f1a..664c6aea8 100644
--- a/ports/atmel-samd/shared_dma.c
+++ b/ports/atmel-samd/peripherals/dma.c
@@ -23,7 +23,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "shared_dma.h"
+#include "peripherals/dma.h"
#include <string.h>
@@ -48,164 +48,6 @@ COMPILER_ALIGNED(16) static DmacDescriptor write_back_descriptors[DMA_CHANNEL_CO
#define FIRST_SERCOM_TX_TRIGSRC 0x05
#endif
-static uint8_t sercom_index(Sercom* sercom) {
- #ifdef SAMD21
- return ((uint32_t) sercom - (uint32_t) SERCOM0) / 0x400;
- #else
- const Sercom* sercoms[SERCOM_INST_NUM] = SERCOM_INSTS;
- for (uint8_t i = 0; i < SERCOM_INST_NUM; i++) {
- if (sercoms[i] == sercom) {
- return i;
- }
- }
- return 0;
- #endif
-}
-
-void dma_configure(uint8_t channel_number, uint8_t trigsrc, bool output_event) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- /** Select the DMA channel and clear software trigger */
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
- DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;
- DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << channel_number));
- uint32_t event_output_enable = 0;
- if (output_event) {
- event_output_enable = DMAC_CHCTRLB_EVOE;
- }
- DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL_LVL0 |
- DMAC_CHCTRLB_TRIGSRC(trigsrc) |
- DMAC_CHCTRLB_TRIGACT_BEAT |
- event_output_enable;
- common_hal_mcu_enable_interrupts();
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- channel->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
- channel->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;
- if (output_event) {
- channel->CHEVCTRL.reg = DMAC_CHEVCTRL_EVOE;
- }
- channel->CHCTRLA.reg = DMAC_CHCTRLA_TRIGSRC(trigsrc) |
- DMAC_CHCTRLA_TRIGACT_BURST |
- DMAC_CHCTRLA_BURSTLEN_SINGLE;
- #endif
-}
-
-void dma_enable_channel(uint8_t channel_number) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- /** Select the DMA channel and clear software trigger */
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- // Clear any previous interrupts.
- DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK;
- DMAC->CHCTRLA.bit.ENABLE = true;
- common_hal_mcu_enable_interrupts();
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- channel->CHCTRLA.bit.ENABLE = true;
- // Clear any previous interrupts.
- channel->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK;
- #endif
-}
-
-void dma_disable_channel(uint8_t channel_number) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- /** Select the DMA channel and clear software trigger */
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- DMAC->CHCTRLA.bit.ENABLE = false;
- common_hal_mcu_enable_interrupts();
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- channel->CHCTRLA.bit.ENABLE = false;
- #endif
-}
-
-void dma_suspend_channel(uint8_t channel_number) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- /** Select the DMA channel and clear software trigger */
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_SUSPEND_Val;
- common_hal_mcu_enable_interrupts();
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_SUSPEND;
- #endif
-}
-
-void dma_resume_channel(uint8_t channel_number) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- /** Select the DMA channel and clear software trigger */
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_RESUME_Val;
- DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_SUSP;
- common_hal_mcu_enable_interrupts();
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_RESUME;
- #endif
-}
-
-bool dma_channel_enabled(uint8_t channel_number) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- /** Select the DMA channel and clear software trigger */
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- bool enabled = DMAC->CHCTRLA.bit.ENABLE;
- common_hal_mcu_enable_interrupts();
- return enabled;
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- return channel->CHCTRLA.bit.ENABLE;
- #endif
-}
-
-uint8_t dma_transfer_status(uint8_t channel_number) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- /** Select the DMA channel and clear software trigger */
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- uint8_t status = DMAC->CHINTFLAG.reg;
- common_hal_mcu_enable_interrupts();
- return status;
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- return channel->CHINTFLAG.reg;
- #endif
-}
-
-static bool channel_free(uint8_t channel_number) {
- #ifdef SAMD21
- common_hal_mcu_disable_interrupts();
- DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
- bool channel_free = DMAC->CHSTATUS.reg == 0;
- common_hal_mcu_enable_interrupts();
- return channel_free;
- #endif
-
- #ifdef SAMD51
- DmacChannel* channel = &DMAC->Channel[channel_number];
- return channel->CHSTATUS.reg == 0;
- #endif
-}
-
void init_shared_dma(void) {
// Turn on the clocks
#ifdef SAMD51
@@ -237,8 +79,8 @@ static int32_t shared_dma_transfer(void* peripheral,
const uint8_t* buffer_out, volatile uint32_t* dest,
volatile uint32_t* src, uint8_t* buffer_in,
uint32_t length, uint8_t tx) {
- if (!channel_free(SHARED_TX_CHANNEL) ||
- (buffer_in != NULL && !channel_free(SHARED_RX_CHANNEL))) {
+ if (!dma_channel_free(SHARED_TX_CHANNEL) ||
+ (buffer_in != NULL && !dma_channel_free(SHARED_RX_CHANNEL))) {
return -1;
}
diff --git a/ports/atmel-samd/shared_dma.h b/ports/atmel-samd/peripherals/dma.h
index 03e5b276c..cf256b962 100644
--- a/ports/atmel-samd/shared_dma.h
+++ b/ports/atmel-samd/peripherals/dma.h
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H
-#define MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_DMA_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_DMA_H
#include <stdbool.h>
#include <stdint.h>
@@ -49,6 +49,8 @@ int32_t qspi_dma_write(uint32_t address, const uint8_t* buffer, uint32_t length)
int32_t qspi_dma_read(uint32_t address, uint8_t* buffer, uint32_t length);
#endif
+uint8_t sercom_index(Sercom* sercom);
+
int32_t sercom_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length);
int32_t sercom_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx);
int32_t sercom_dma_transfer(Sercom* sercom, const uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length);
@@ -58,8 +60,9 @@ void dma_enable_channel(uint8_t channel_number);
void dma_disable_channel(uint8_t channel_number);
void dma_suspend_channel(uint8_t channel_number);
void dma_resume_channel(uint8_t channel_number);
+bool dma_channel_free(uint8_t channel_number);
bool dma_channel_enabled(uint8_t channel_number);
uint8_t dma_transfer_status(uint8_t channel_number);
DmacDescriptor* dma_descriptor(uint8_t channel_number);
-#endif // MICROPY_INCLUDED_ATMEL_SAMD_SHARED_DMA_H
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_DMA_H
diff --git a/ports/atmel-samd/peripherals/events.c b/ports/atmel-samd/peripherals/events.c
new file mode 100644
index 000000000..2f6aea716
--- /dev/null
+++ b/ports/atmel-samd/peripherals/events.c
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "peripherals/events.h"
+#include "py/runtime.h"
+
+uint8_t find_async_event_channel(void) {
+ int8_t channel;
+ for (channel = EVSYS_CHANNELS - 1; channel > 0; channel--) {
+ if (event_channel_free(channel)) {
+ break;
+ }
+ }
+ if (channel < 0) {
+ mp_raise_RuntimeError("All event channels in use");
+ }
+ return channel;
+}
+
+#ifdef SAMD21
+#define EVSYS_SYNCH_NUM EVSYS_CHANNELS
+#endif
+uint8_t find_sync_event_channel(void) {
+ uint8_t channel;
+ for (channel = 0; channel < EVSYS_SYNCH_NUM; channel++) {
+ if (event_channel_free(channel)) {
+ break;
+ }
+ }
+ if (channel >= EVSYS_SYNCH_NUM) {
+ mp_raise_RuntimeError("All sync event channels in use");
+ }
+ return channel;
+}
diff --git a/ports/atmel-samd/events.h b/ports/atmel-samd/peripherals/events.h
index 64093c0ab..0073142f1 100644
--- a/ports/atmel-samd/events.h
+++ b/ports/atmel-samd/peripherals/events.h
@@ -44,4 +44,6 @@ void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generat
bool event_interrupt_active(uint8_t channel);
bool event_interrupt_overflow(uint8_t channel);
+bool event_channel_free(uint8_t channel);
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_EVENTS_H
diff --git a/ports/atmel-samd/peripherals/external_interrupts.c b/ports/atmel-samd/peripherals/external_interrupts.c
new file mode 100644
index 000000000..dfec6c998
--- /dev/null
+++ b/ports/atmel-samd/peripherals/external_interrupts.c
@@ -0,0 +1,105 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/pulseio/PulseIn.h"
+#include "common-hal/rotaryio/IncrementalEncoder.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "peripherals/external_interrupts.h"
+
+#include "sam.h"
+
+// This structure is used to share per-channel storage amongst all users of external interrupts.
+// Without this there would be multiple arrays even though they are disjoint because each channel
+// has one user.
+static void *channel_data[EIC_EXTINT_NUM];
+static uint8_t channel_handler[EIC_EXTINT_NUM];
+
+void external_interrupt_handler(uint8_t channel) {
+ uint8_t handler = channel_handler[channel];
+ if (handler == EIC_HANDLER_PULSEIN) {
+ pulsein_interrupt_handler(channel);
+ } else if (handler == EIC_HANDLER_INCREMENTAL_ENCODER) {
+ incrementalencoder_interrupt_handler(channel);
+ }
+ EIC->INTFLAG.reg = (1 << channel) << EIC_INTFLAG_EXTINT_Pos;
+}
+
+void configure_eic_channel(uint8_t eic_channel, uint32_t sense_setting) {
+ uint8_t config_index = eic_channel / 8;
+ uint8_t position = (eic_channel % 8) * 4;
+ #ifdef SAMD51
+ eic_set_enable(false);
+ #endif
+ common_hal_mcu_disable_interrupts();
+ uint32_t masked_value = EIC->CONFIG[config_index].reg & ~(0xf << position);
+ EIC->CONFIG[config_index].reg = masked_value | (sense_setting << position);
+ common_hal_mcu_enable_interrupts();
+ #ifdef SAMD51
+ eic_set_enable(true);
+ #endif
+}
+
+void turn_on_eic_channel(uint8_t eic_channel, uint32_t sense_setting,
+ uint8_t channel_interrupt_handler) {
+ // We do very light filtering using majority voting.
+ sense_setting |= EIC_CONFIG_FILTEN0;
+ configure_eic_channel(eic_channel, sense_setting);
+ uint32_t mask = 1 << eic_channel;
+ EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos;
+ if (channel_interrupt_handler != EIC_HANDLER_NO_INTERRUPT) {
+ channel_handler[eic_channel] = channel_interrupt_handler;
+ turn_on_cpu_interrupt(eic_channel);
+ }
+}
+
+void turn_off_eic_channel(uint8_t eic_channel) {
+ uint32_t mask = 1 << eic_channel;
+ EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos;
+ #ifdef SAMD51
+ NVIC_DisableIRQ(EIC_0_IRQn + eic_channel);
+ NVIC_ClearPendingIRQ(EIC_0_IRQn + eic_channel);
+ #endif
+ channel_data[eic_channel] = NULL;
+
+ #ifdef SAMD21
+ if (EIC->INTENSET.reg == 0) {
+ NVIC_DisableIRQ(EIC_IRQn);
+ NVIC_ClearPendingIRQ(EIC_IRQn);
+ }
+ #endif
+ // Test if all channels are null and deinit everything if they are.
+ if (EIC->EVCTRL.reg == 0 && EIC->INTENSET.reg == 0) {
+ turn_off_external_interrupt_controller();
+ }
+}
+
+void* get_eic_channel_data(uint8_t eic_channel) {
+ return channel_data[eic_channel];
+}
+
+void set_eic_channel_data(uint8_t eic_channel, void* data) {
+ channel_data[eic_channel] = data;
+}
diff --git a/ports/atmel-samd/peripherals/external_interrupts.h b/ports/atmel-samd/peripherals/external_interrupts.h
new file mode 100644
index 000000000..12d820677
--- /dev/null
+++ b/ports/atmel-samd/peripherals/external_interrupts.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_EXTERNAL_INTERRUPTS_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_EXTERNAL_INTERRUPTS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define EIC_HANDLER_NO_INTERRUPT 0x0
+#define EIC_HANDLER_PULSEIN 0x1
+#define EIC_HANDLER_INCREMENTAL_ENCODER 0x2
+
+void turn_on_external_interrupt_controller(void);
+void turn_off_external_interrupt_controller(void);
+void turn_on_cpu_interrupt(uint8_t eic_channel);
+void turn_on_eic_channel(uint8_t eic_channel, uint32_t sense_setting,
+ uint8_t channel_interrupt_handler);
+void configure_eic_channel(uint8_t eic_channel, uint32_t sense_setting);
+void turn_off_eic_channel(uint8_t eic_channel);
+bool eic_channel_free(uint8_t eic_channel);
+bool eic_get_enable(void);
+void eic_set_enable(bool value);
+void eic_reset(void);
+
+void* get_eic_channel_data(uint8_t eic_channel);
+void set_eic_channel_data(uint8_t eic_channel, void* data);
+
+void external_interrupt_handler(uint8_t channel);
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_EXTERNAL_INTERRUPTS_H
diff --git a/ports/atmel-samd/peripherals/i2s.c b/ports/atmel-samd/peripherals/i2s.c
new file mode 100644
index 000000000..4d99e7b5b
--- /dev/null
+++ b/ports/atmel-samd/peripherals/i2s.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "i2s.h"
+
+#include "clocks.h"
+
+#include "hpl/gclk/hpl_gclk_base.h"
+#ifdef SAMD21
+#include "hpl/pm/hpl_pm_base.h"
+#endif
+
+void i2s_set_enable(bool enable) {
+ while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
+ I2S->CTRLA.bit.ENABLE = enable;
+ while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
+}
+
+void i2s_set_clock_unit_enable(uint8_t clock_unit, bool enable) {
+ while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {}
+ I2S->CTRLA.vec.CKEN = 1 << clock_unit;
+ while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {}
+}
diff --git a/ports/atmel-samd/i2s.h b/ports/atmel-samd/peripherals/i2s.h
index 7df667b2a..7df667b2a 100644
--- a/ports/atmel-samd/i2s.h
+++ b/ports/atmel-samd/peripherals/i2s.h
diff --git a/ports/atmel-samd/peripherals/pins.h b/ports/atmel-samd/peripherals/pins.h
new file mode 100644
index 000000000..1ddbf3329
--- /dev/null
+++ b/ports/atmel-samd/peripherals/pins.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure
+// that all necessary includes are already included.
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_PINS_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_PINS_H
+
+#include "mpconfigport.h"
+
+#ifdef SAMD21
+#include "peripherals/samd21/pins.h"
+#endif
+#ifdef SAMD51
+#include "peripherals/samd51/pins.h"
+#endif
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_PINS_H
diff --git a/ports/atmel-samd/peripherals/samd21/adc.c b/ports/atmel-samd/peripherals/samd21/adc.c
new file mode 100644
index 000000000..3a7f1e811
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd21/adc.c
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Dan Halbert 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 "hal/include/hal_adc_sync.h"
+#include "hpl/gclk/hpl_gclk_base.h"
+#include "hpl/pm/hpl_pm_base.h"
+
+// Do initialization and calibration setup needed for any use of the ADC.
+// The reference and resolution should be set by the caller.
+void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) {
+ // Turn the clocks on.
+ _pm_enable_bus_clock(PM_BUS_APBC, ADC);
+ _gclk_enable_channel(ADC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
+
+ adc_sync_init(adc, instance, (void *)NULL);
+
+ // Load the factory calibration
+ hri_adc_write_CALIB_BIAS_CAL_bf(ADC, (*((uint32_t*) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos);
+ // Bits 7:5
+ uint16_t linearity = ((*((uint32_t*) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
+ // Bits 4:0
+ linearity |= (*((uint32_t*) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
+ hri_adc_write_CALIB_LINEARITY_CAL_bf(ADC, linearity);
+}
diff --git a/ports/atmel-samd/pins.h b/ports/atmel-samd/peripherals/samd21/cache.c
index 1842efbc0..641b5e115 100644
--- a/ports/atmel-samd/pins.h
+++ b/ports/atmel-samd/peripherals/samd21/cache.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2017 Dan Halbert 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
@@ -24,16 +24,9 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PINS_H
-#define MICROPY_INCLUDED_ATMEL_SAMD_PINS_H
+// The SAMD21 doesn't have a cache so we have nothing to do.
+void samd_peripherals_disable_and_clear_cache(void) {
+}
-#include "mpconfigport.h"
-
-#ifdef SAMD21
-#include "samd21_pins.h"
-#endif
-#ifdef SAMD51
-#include "samd51_pins.h"
-#endif
-
-#endif // MICROPY_INCLUDED_ATMEL_SAMD_PINS_H
+void samd_peripherals_enable_cache(void) {
+}
diff --git a/ports/atmel-samd/samd21_clocks.c b/ports/atmel-samd/peripherals/samd21/clocks.c
index 0fc4d63e5..51b7ad993 100644
--- a/ports/atmel-samd/samd21_clocks.c
+++ b/ports/atmel-samd/peripherals/samd21/clocks.c
@@ -24,15 +24,24 @@
* THE SOFTWARE.
*/
-#include "clocks.h"
+#include <string.h>
+#include <stdlib.h>
-#include "hpl_gclk_config.h"
+#include "peripherals/clocks.h"
+
+#include "hal/include/hal_flash.h"
#include "bindings/samd/Clock.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "py/runtime.h"
+#ifdef EXPRESS_BOARD
+#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - NVMCTRL_ROW_SIZE - CIRCUITPY_INTERNAL_NVM_SIZE)
+#else
+#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x010000 - NVMCTRL_ROW_SIZE - CIRCUITPY_INTERNAL_NVM_SIZE)
+#endif
+
bool gclk_enabled(uint8_t gclk) {
common_hal_mcu_disable_interrupts();
// Explicitly do a byte write so the peripheral knows we're just wanting to read the channel
@@ -102,17 +111,48 @@ static void init_clock_source_xosc32k(void) {
while (!SYSCTRL->PCLKSR.bit.XOSC32KRDY) {}
}
-static void init_clock_source_dfll48m(void) {
+static void init_clock_source_dfll48m_xosc(void) {
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
+ while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {}
+ SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(0x1f / 4) |
+ SYSCTRL_DFLLMUL_FSTEP(0xff / 4) |
+ SYSCTRL_DFLLMUL_MUL(48000000 / 32768);
+ uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos;
+ if (coarse == 0x3f) {
+ coarse = 0x1f;
+ }
+ SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) |
+ SYSCTRL_DFLLVAL_FINE(512);
+
+ SYSCTRL->DFLLCTRL.reg = 0;
+ while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {}
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_MODE |
+ SYSCTRL_DFLLCTRL_ENABLE;
+ while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {}
+ while (GCLK->STATUS.bit.SYNCBUSY) {}
+}
+
+static void init_clock_source_dfll48m_usb(void) {
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {}
SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) |
SYSCTRL_DFLLMUL_FSTEP(1) |
SYSCTRL_DFLLMUL_MUL(48000);
uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos;
- if (coarse == 0x3f)
+ if (coarse == 0x3f) {
coarse = 0x1f;
+ }
+ uint32_t fine = 512;
+ #ifdef CALIBRATE_CRYSTALLESS
+ // This is stored in an NVM page after the text and data storage but before
+ // the optional file system. The first 16 bytes are the identifier for the
+ // section.
+ if (strcmp((char*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, "CIRCUITPYTHON1") == 0) {
+ fine = ((uint16_t *) INTERNAL_CIRCUITPY_CONFIG_START_ADDR)[8];
+ }
+ #endif
SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) |
- SYSCTRL_DFLLVAL_FINE(512);
+ SYSCTRL_DFLLVAL_FINE(fine);
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS |
SYSCTRL_DFLLCTRL_USBCRM |
SYSCTRL_DFLLCTRL_MODE |
@@ -124,17 +164,30 @@ static void init_clock_source_dfll48m(void) {
void clock_init(void)
{
init_clock_source_osc8m();
- if (board_has_crystal())
+ if (board_has_crystal()) {
init_clock_source_xosc32k();
- else
+ } else {
init_clock_source_osc32k();
+ }
+
+ if (board_has_crystal()) {
+ enable_clock_generator(3, GCLK_GENCTRL_SRC_XOSC32K_Val, 1);
+ connect_gclk_to_peripheral(3, GCLK_CLKCTRL_ID_DFLL48_Val);
+ init_clock_source_dfll48m_xosc();
+ } else {
+ init_clock_source_dfll48m_usb();
+ }
+
enable_clock_generator(0, GCLK_GENCTRL_SRC_DFLL48M_Val, 1);
enable_clock_generator(1, GCLK_GENCTRL_SRC_DFLL48M_Val, 150);
- init_clock_source_dfll48m();
- if (board_has_crystal())
+ if (board_has_crystal()) {
enable_clock_generator(2, GCLK_GENCTRL_SRC_XOSC32K_Val, 32);
- else
+ } else {
enable_clock_generator(2, GCLK_GENCTRL_SRC_OSC32K_Val, 32);
+ }
+
+ // Do this after all static clock init so that they aren't used dynamically.
+ init_dynamic_clocks();
}
static bool clk_enabled(uint8_t clk) {
@@ -310,6 +363,41 @@ int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) {
return -2; // calibration is read only
}
+void save_usb_clock_calibration(void) {
+ #ifndef CALIBRATE_CRYSTALLESS
+ return;
+ #endif
+ // If we are on USB lets double check our fine calibration for the clock and
+ // save the new value if its different enough.
+ SYSCTRL->DFLLSYNC.bit.READREQ = 1;
+ uint16_t saved_calibration = 0x1ff;
+ if (strcmp((char*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, "CIRCUITPYTHON1") == 0) {
+ saved_calibration = ((uint16_t *) INTERNAL_CIRCUITPY_CONFIG_START_ADDR)[8];
+ }
+ while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) {
+ // TODO(tannewt): Run the mass storage stuff if this takes a while.
+ }
+ int16_t current_calibration = SYSCTRL->DFLLVAL.bit.FINE;
+ if (abs(current_calibration - saved_calibration) > 10) {
+ // Copy the full internal config page to memory.
+ uint8_t page_buffer[NVMCTRL_ROW_SIZE];
+ memcpy(page_buffer, (uint8_t*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, NVMCTRL_ROW_SIZE);
+
+ // Modify it.
+ memcpy(page_buffer, "CIRCUITPYTHON1", 15);
+ // First 16 bytes (0-15) are ID. Little endian!
+ page_buffer[16] = current_calibration & 0xff;
+ page_buffer[17] = current_calibration >> 8;
+
+ // Write it back.
+ // We don't use features that use any advanced NVMCTRL features so we can fake the descriptor
+ // whenever we need it instead of storing it long term.
+ struct flash_descriptor desc;
+ desc.dev.hw = NVMCTRL;
+ flash_write(&desc, (uint32_t) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, page_buffer, NVMCTRL_ROW_SIZE);
+ }
+}
+
#ifdef SAMD21_EXPOSE_ALL_CLOCKS
CLOCK_SOURCE(XOSC);
CLOCK_SOURCE(GCLKIN);
diff --git a/ports/atmel-samd/peripherals/samd21/dma.c b/ports/atmel-samd/peripherals/samd21/dma.c
new file mode 100644
index 000000000..3a399745a
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd21/dma.c
@@ -0,0 +1,118 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017-2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "peripherals/dma.h"
+
+#include <string.h>
+
+#include "py/gc.h"
+#include "py/mpstate.h"
+
+#include "hal/utils/include/utils.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+
+uint8_t sercom_index(Sercom* sercom) {
+ return ((uint32_t) sercom - (uint32_t) SERCOM0) / 0x400;
+}
+
+void dma_configure(uint8_t channel_number, uint8_t trigsrc, bool output_event) {
+ common_hal_mcu_disable_interrupts();
+ /** Select the DMA channel and clear software trigger */
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
+ DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;
+ DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << channel_number));
+ uint32_t event_output_enable = 0;
+ if (output_event) {
+ event_output_enable = DMAC_CHCTRLB_EVOE;
+ }
+ DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL_LVL0 |
+ DMAC_CHCTRLB_TRIGSRC(trigsrc) |
+ DMAC_CHCTRLB_TRIGACT_BEAT |
+ event_output_enable;
+ common_hal_mcu_enable_interrupts();
+}
+
+void dma_enable_channel(uint8_t channel_number) {
+ common_hal_mcu_disable_interrupts();
+ /** Select the DMA channel and clear software trigger */
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ // Clear any previous interrupts.
+ DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK;
+ DMAC->CHCTRLA.bit.ENABLE = true;
+ common_hal_mcu_enable_interrupts();
+}
+
+void dma_disable_channel(uint8_t channel_number) {
+ common_hal_mcu_disable_interrupts();
+ /** Select the DMA channel and clear software trigger */
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ DMAC->CHCTRLA.bit.ENABLE = false;
+ common_hal_mcu_enable_interrupts();
+}
+
+void dma_suspend_channel(uint8_t channel_number) {
+ common_hal_mcu_disable_interrupts();
+ /** Select the DMA channel and clear software trigger */
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_SUSPEND_Val;
+ common_hal_mcu_enable_interrupts();
+}
+
+void dma_resume_channel(uint8_t channel_number) {
+ common_hal_mcu_disable_interrupts();
+ /** Select the DMA channel and clear software trigger */
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ DMAC->CHCTRLB.bit.CMD = DMAC_CHCTRLB_CMD_RESUME_Val;
+ DMAC->CHINTFLAG.reg = DMAC_CHINTFLAG_SUSP;
+ common_hal_mcu_enable_interrupts();
+}
+
+bool dma_channel_enabled(uint8_t channel_number) {
+ common_hal_mcu_disable_interrupts();
+ /** Select the DMA channel and clear software trigger */
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ bool enabled = DMAC->CHCTRLA.bit.ENABLE;
+ common_hal_mcu_enable_interrupts();
+ return enabled;
+}
+
+uint8_t dma_transfer_status(uint8_t channel_number) {
+ common_hal_mcu_disable_interrupts();
+ /** Select the DMA channel and clear software trigger */
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ uint8_t status = DMAC->CHINTFLAG.reg;
+ common_hal_mcu_enable_interrupts();
+ return status;
+}
+
+bool dma_channel_free(uint8_t channel_number) {
+ common_hal_mcu_disable_interrupts();
+ DMAC->CHID.reg = DMAC_CHID_ID(channel_number);
+ bool channel_free = DMAC->CHSTATUS.reg == 0;
+ common_hal_mcu_enable_interrupts();
+ return channel_free;
+}
diff --git a/ports/atmel-samd/events.c b/ports/atmel-samd/peripherals/samd21/events.c
index 05a2ae8a7..08b82c91f 100644
--- a/ports/atmel-samd/events.c
+++ b/ports/atmel-samd/peripherals/samd21/events.c
@@ -24,137 +24,58 @@
* THE SOFTWARE.
*/
-#include "events.h"
+#include "peripherals/events.h"
-#include "clocks.h"
+#include "peripherals/clocks.h"
#include "py/runtime.h"
-#ifdef SAMD21
#include "hpl/pm/hpl_pm_base.h"
-#endif
-
-#ifdef SAMD51
-#include "hri/hri_mclk_d51.h"
-#endif
void turn_on_event_system(void) {
- #ifdef SAMD51
- hri_mclk_set_APBBMASK_EVSYS_bit(MCLK);
- #endif
-
- #ifdef SAMD21
_pm_enable_bus_clock(PM_BUS_APBC, EVSYS);
- #endif
}
void reset_event_system(void) {
- #ifdef SAMD51
- EVSYS->CTRLA.bit.SWRST = true;
- hri_mclk_clear_APBBMASK_EVSYS_bit(MCLK);
- #endif
-
- #ifdef SAMD21
EVSYS->CTRL.bit.SWRST = true;
_pm_disable_bus_clock(PM_BUS_APBC, EVSYS);
- #endif
}
-static bool channel_free(int8_t channel) {
+bool event_channel_free(uint8_t channel) {
uint8_t generator;
- #ifdef SAMD51
- generator = EVSYS->Channel[channel].CHANNEL.bit.EVGEN;
- #endif
- #ifdef SAMD21
// Explicitly do a byte write so the peripheral knows we're just wanting to read the channel
// rather than write to it.
*((uint8_t*) &EVSYS->CHANNEL.reg) = channel;
generator = (EVSYS->CHANNEL.reg & EVSYS_CHANNEL_EVGEN_Msk) >> EVSYS_CHANNEL_EVGEN_Pos;
- #endif
return generator == 0;
}
-uint8_t find_async_event_channel(void) {
- int8_t channel;
- for (channel = EVSYS_CHANNELS - 1; channel > 0; channel--) {
- if (channel_free(channel)) {
- break;
- }
- }
- if (channel < 0) {
- mp_raise_RuntimeError("All event channels in use");
- }
- return channel;
-}
-
-#ifdef SAMD21
-#define EVSYS_SYNCH_NUM EVSYS_CHANNELS
-#endif
-uint8_t find_sync_event_channel(void) {
- uint8_t channel;
- for (channel = 0; channel < EVSYS_SYNCH_NUM; channel++) {
- if (channel_free(channel)) {
- break;
- }
- }
- if (channel >= EVSYS_SYNCH_NUM) {
- mp_raise_RuntimeError("All sync event channels in use");
- }
- return channel;
-}
-
void disable_event_channel(uint8_t channel_number) {
- #ifdef SAMD51
- EVSYS->Channel[channel_number].CHANNEL.reg = 0;
- #endif
- #ifdef SAMD21
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel_number);
- #endif
}
void disable_event_user(uint8_t user_number) {
- #ifdef SAMD51
- EVSYS->USER[user_number].reg = 0;
- #endif
- #ifdef SAMD21
EVSYS->USER.reg = EVSYS_USER_USER(user_number);
- #endif
}
void connect_event_user_to_channel(uint8_t user, uint8_t channel) {
- #ifdef SAMD51
- EVSYS->USER[user].reg = channel + 1;
- #endif
- #ifdef SAMD21
EVSYS->USER.reg = EVSYS_USER_USER(user) | EVSYS_USER_CHANNEL(channel + 1);
- #endif
}
void init_async_event_channel(uint8_t channel, uint8_t generator) {
- #ifdef SAMD51
- EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) | EVSYS_CHANNEL_PATH_ASYNCHRONOUS;
- #endif
- #ifdef SAMD21
- EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel) | EVSYS_CHANNEL_EVGEN(generator) | EVSYS_CHANNEL_PATH_ASYNCHRONOUS;
- #endif
+ EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel) |
+ EVSYS_CHANNEL_EVGEN(generator) |
+ EVSYS_CHANNEL_PATH_ASYNCHRONOUS;
}
void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generator) {
connect_gclk_to_peripheral(gclk, EVSYS_GCLK_ID_0 + channel);
- #ifdef SAMD51
- EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) |
- EVSYS_CHANNEL_PATH_SYNCHRONOUS |
- EVSYS_CHANNEL_EDGSEL_RISING_EDGE;
- EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR;
- EVSYS->Channel[channel].CHINTENSET.reg = EVSYS_CHINTENSET_EVD | EVSYS_CHINTENSET_OVR;
- #endif
- #ifdef SAMD21
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(channel) |
EVSYS_CHANNEL_EVGEN(generator) |
EVSYS_CHANNEL_PATH_RESYNCHRONIZED |
EVSYS_CHANNEL_EDGSEL_RISING_EDGE;
- if (channel > 7) {
- uint8_t value = 1 << (channel - 7);
+ if (channel >= 8) {
+ uint8_t value = 1 << (channel - 8);
EVSYS->INTFLAG.reg = EVSYS_INTFLAG_EVDp8(value) | EVSYS_INTFLAG_OVRp8(value);
EVSYS->INTENSET.reg = EVSYS_INTENSET_EVDp8(value) | EVSYS_INTENSET_OVRp8(value);
} else {
@@ -162,14 +83,12 @@ void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generat
EVSYS->INTFLAG.reg = EVSYS_INTFLAG_EVD(value) | EVSYS_INTFLAG_OVR(value);
EVSYS->INTENSET.reg = EVSYS_INTENSET_EVD(value) | EVSYS_INTENSET_OVR(value);
}
- #endif
}
bool event_interrupt_active(uint8_t channel) {
bool active = false;
- #ifdef SAMD21
- if (channel > 7) {
- uint8_t value = 1 << (channel - 7);
+ if (channel >= 8) {
+ uint8_t value = 1 << (channel - 8);
active = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_EVDp8(value)) != 0;
// Only clear if we know its active, otherwise there is the possibility it becomes active
// after we check but before we clear.
@@ -183,31 +102,17 @@ bool event_interrupt_active(uint8_t channel) {
EVSYS->INTFLAG.reg = EVSYS_INTFLAG_EVD(value) | EVSYS_INTFLAG_OVR(value);
}
}
- #endif
- #ifdef SAMD51
- active = EVSYS->Channel[channel].CHINTFLAG.bit.EVD;
- // Only clear if we know its active, otherwise there is the possibility it becomes after we
- // check but before we clear.
- if (active) {
- EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR;
- }
- #endif
return active;
}
bool event_interrupt_overflow(uint8_t channel) {
bool overflow = false;
- #ifdef SAMD21
- if (channel > 7) {
- uint8_t value = 1 << (channel - 7);
+ if (channel >= 8) {
+ uint8_t value = 1 << (channel - 8);
overflow = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_OVRp8(value)) != 0;
} else {
uint8_t value = 1 << channel;
overflow = (EVSYS->INTFLAG.reg & EVSYS_INTFLAG_OVR(value)) != 0;
}
- #endif
- #ifdef SAMD51
- overflow = EVSYS->Channel[channel].CHINTFLAG.bit.OVR;
- #endif
return overflow;
}
diff --git a/ports/atmel-samd/peripherals/samd21/external_interrupts.c b/ports/atmel-samd/peripherals/samd21/external_interrupts.c
new file mode 100644
index 000000000..209c439c0
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd21/external_interrupts.c
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "peripherals/external_interrupts.h"
+
+#include "hpl/gclk/hpl_gclk_base.h"
+#include "peripherals/clocks.h"
+#include "sam.h"
+
+void turn_on_external_interrupt_controller(void) {
+ PM->APBAMASK.bit.EIC_ = true;
+ _gclk_enable_channel(EIC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
+ eic_set_enable(true);
+}
+
+void turn_off_external_interrupt_controller(void) {
+ eic_set_enable(false);
+ PM->APBAMASK.bit.EIC_ = false;
+ hri_gclk_write_CLKCTRL_reg(GCLK, GCLK_CLKCTRL_ID(EIC_GCLK_ID));
+}
+
+void turn_on_cpu_interrupt(uint8_t eic_channel) {
+ // Ignore the channel since the CPU interrupt line is shared.
+ (void) eic_channel;
+
+ NVIC_DisableIRQ(EIC_IRQn);
+ NVIC_ClearPendingIRQ(EIC_IRQn);
+ NVIC_EnableIRQ(EIC_IRQn);
+}
+
+bool eic_get_enable(void) {
+ return EIC->CTRL.bit.ENABLE;
+}
+
+void eic_set_enable(bool value) {
+ EIC->CTRL.bit.ENABLE = value;
+ while (EIC->STATUS.bit.SYNCBUSY != 0) {}
+}
+
+void eic_reset(void) {
+ EIC->CTRL.bit.SWRST = true;
+ while (EIC->STATUS.bit.SYNCBUSY != 0) {}
+ for (int i = 0; i < EIC_EXTINT_NUM; i++) {
+ set_eic_channel_data(i, NULL);
+ }
+ NVIC_DisableIRQ(EIC_IRQn);
+ NVIC_ClearPendingIRQ(EIC_IRQn);
+}
+
+bool eic_channel_free(uint8_t eic_channel) {
+ uint32_t mask = 1 << eic_channel;
+ return get_eic_channel_data(eic_channel) == NULL &&
+ (EIC->INTENSET.vec.EXTINT & mask) == 0 &&
+ (EIC->EVCTRL.vec.EXTINTEO & mask) == 0;
+}
+
+void EIC_Handler(void) {
+ for (uint8_t i = 0; i < 16; i++) {
+ if ((EIC->INTFLAG.vec.EXTINT & (1 << i)) != 0) {
+ external_interrupt_handler(i);
+ }
+ }
+}
diff --git a/ports/atmel-samd/peripherals/samd21/i2s.c b/ports/atmel-samd/peripherals/samd21/i2s.c
new file mode 100644
index 000000000..7df401601
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd21/i2s.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "peripherals/i2s.h"
+
+#include "peripherals/clocks.h"
+
+#include "hpl/gclk/hpl_gclk_base.h"
+#include "hpl/pm/hpl_pm_base.h"
+
+void turn_on_i2s(void) {
+ _pm_enable_bus_clock(PM_BUS_APBC, I2S);
+}
+
+void i2s_set_serializer_enable(uint8_t serializer, bool enable) {
+ while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {}
+ if (enable) {
+ I2S->CTRLA.vec.SEREN = 1 << serializer;
+ } else {
+ I2S->CTRLA.vec.SEREN &= ~(1 << serializer);
+ }
+ while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {}
+}
diff --git a/ports/atmel-samd/samd21_pins.c b/ports/atmel-samd/peripherals/samd21/pins.c
index eafc4b5fb..bbb023a54 100644
--- a/ports/atmel-samd/samd21_pins.c
+++ b/ports/atmel-samd/peripherals/samd21/pins.c
@@ -26,8 +26,6 @@
#include "shared-bindings/microcontroller/Pin.h"
-#include "samd21_pins.h"
-
#define SERCOM(sercom_index, p_pad) \
{ \
.index = sercom_index, \
@@ -93,21 +91,21 @@ const mcu_pin_obj_t pin_## p_name = { \
// Pins in datasheet order.
// NOTE(tannewt): TC wave out 0 is commented out because the first channel is
// used to vary the 16 bit timer's frequency.
-#ifdef PIN_PA00
+#if defined(PIN_PA00) && !defined(IGNORE_PIN_PA00)
PIN(PA00, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(1, 0),
TCC(2, 0),
NO_TIMER);
#endif
-#ifdef PIN_PA01
+#if defined(PIN_PA01) && !defined(IGNORE_PIN_PA01)
PIN(PA01, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(1, 1),
TCC(2, 1),
NO_TIMER);
#endif
-#ifdef PIN_PA02
+#if defined(PIN_PA02) && !defined(IGNORE_PIN_PA02)
// Touch is not allowed on A0 (PA02) on Circuit Playground Express.
PIN(PA02, EXTINT_CHANNEL(2), ADC_INPUT(0),
#ifdef PA02_NO_TOUCH
@@ -120,140 +118,140 @@ PIN(PA02, EXTINT_CHANNEL(2), ADC_INPUT(0),
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PA03
+#if defined(PIN_PA03) && !defined(IGNORE_PIN_PA03)
PIN(PA03, EXTINT_CHANNEL(3), ADC_INPUT(1), TOUCH(1),
NO_SERCOM,
NO_SERCOM,
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PB04
+#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04)
PIN(PB04, EXTINT_CHANNEL(4), ADC_INPUT(12), TOUCH(10),
NO_SERCOM,
NO_SERCOM,
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PB05
+#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05)
PIN(PB05, EXTINT_CHANNEL(5), ADC_INPUT(13), TOUCH(11),
NO_SERCOM,
NO_SERCOM,
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PB06
+#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06)
PIN(PB06, EXTINT_CHANNEL(6), ADC_INPUT(14), TOUCH(12),
NO_SERCOM,
NO_SERCOM,
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PB07
+#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07)
PIN(PB07, EXTINT_CHANNEL(7), ADC_INPUT(15), TOUCH(13),
NO_SERCOM,
NO_SERCOM,
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PB08
+#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08)
PIN(PB08, EXTINT_CHANNEL(8), ADC_INPUT(2), TOUCH(14),
NO_SERCOM,
SERCOM(4, 0),
TC(4, 0),
NO_TIMER);
#endif
-#ifdef PIN_PB09
+#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09)
PIN(PB09, EXTINT_CHANNEL(9), ADC_INPUT(3), TOUCH(15),
NO_SERCOM,
SERCOM(4, 1),
TC(4, 1),
NO_TIMER);
#endif
-#ifdef PIN_PA04
+#if defined(PIN_PA04) && !defined(IGNORE_PIN_PA04)
PIN(PA04, EXTINT_CHANNEL(4), ADC_INPUT(4), TOUCH(2),
NO_SERCOM,
SERCOM(0, 0),
TCC(0, 0),
NO_TIMER);
#endif
-#ifdef PIN_PA05
+#if defined(PIN_PA05) && !defined(IGNORE_PIN_PA05)
PIN(PA05, EXTINT_CHANNEL(5), ADC_INPUT(5), TOUCH(3),
NO_SERCOM,
SERCOM(0, 1),
TCC(0, 1),
NO_TIMER);
#endif
-#ifdef PIN_PA06
+#if defined(PIN_PA06) && !defined(IGNORE_PIN_PA06)
PIN(PA06, EXTINT_CHANNEL(6), ADC_INPUT(6), TOUCH(4),
NO_SERCOM,
SERCOM(0, 2),
TCC(1, 0),
NO_TIMER);
#endif
-#ifdef PIN_PA07
+#if defined(PIN_PA07) && !defined(IGNORE_PIN_PA07)
PIN(PA07, EXTINT_CHANNEL(7), ADC_INPUT(7), TOUCH(5),
NO_SERCOM,
SERCOM(0, 3),
TCC(1, 1),
NO_TIMER);
#endif
-#ifdef PIN_PA08
+#if defined(PIN_PA08) && !defined(IGNORE_PIN_PA08)
PIN(PA08, NO_EXTINT, ADC_INPUT(16), NO_TOUCH,
SERCOM(0, 0),
SERCOM(2, 0),
TCC(0, 0),
TCC(1, 2));
#endif
-#ifdef PIN_PA09
+#if defined(PIN_PA09) && !defined(IGNORE_PIN_PA09)
PIN(PA09, EXTINT_CHANNEL(9), ADC_INPUT(17), NO_TOUCH,
SERCOM(0, 1),
SERCOM(2, 1),
TCC(0, 1),
TCC(1, 3));
#endif
-#ifdef PIN_PA10
+#if defined(PIN_PA10) && !defined(IGNORE_PIN_PA10)
PIN(PA10, EXTINT_CHANNEL(10), ADC_INPUT(18), NO_TOUCH,
SERCOM(0, 2),
SERCOM(2, 2),
TCC(1, 0),
TCC(0, 2));
#endif
-#ifdef PIN_PA11
+#if defined(PIN_PA11) && !defined(IGNORE_PIN_PA11)
PIN(PA11, EXTINT_CHANNEL(11), ADC_INPUT(19), NO_TOUCH,
SERCOM(0, 3),
SERCOM(2, 3),
TCC(1, 1),
TCC(0, 3));
#endif
-#ifdef PIN_PB10
+#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10)
PIN(PB10, EXTINT_CHANNEL(10), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(4, 2),
TC(5, 0),
TCC(0, 4));
#endif
-#ifdef PIN_PB11
+#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11)
PIN(PB11, EXTINT_CHANNEL(11), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(4, 3),
TC(5, 1),
TCC(0, 5));
#endif
-#ifdef PIN_PB12
+#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12)
PIN(PB12, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH,
SERCOM(4, 0),
NO_SERCOM,
TC(4, 0),
TCC(0, 6));
#endif
-#ifdef PIN_PB13
+#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13)
PIN(PB13, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH,
SERCOM(4, 1),
NO_SERCOM,
TC(4, 1),
TCC(0, 7));
#endif
-#ifdef PIN_PB14
+#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14)
PIN(PB14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH,
SERCOM(4, 2),
NO_SERCOM,
@@ -262,28 +260,28 @@ PIN(PB14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH,
#endif
// Second page.
-#ifdef PIN_PB15
+#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15)
PIN(PB15, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH,
SERCOM(4, 3),
NO_SERCOM,
TC(5, 1),
NO_TIMER);
#endif
-#ifdef PIN_PA12
+#if defined(PIN_PA12) && !defined(IGNORE_PIN_PA12)
PIN(PA12, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH,
SERCOM(2, 0),
SERCOM(4, 0),
TCC(2, 0),
TCC(0, 6));
#endif
-#ifdef PIN_PA13
+#if defined(PIN_PA13) && !defined(IGNORE_PIN_PA13)
PIN(PA13, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH,
SERCOM(2, 1),
SERCOM(4, 1),
TCC(2, 1),
TCC(0, 7));
#endif
-#ifdef PIN_PA14
+#if defined(PIN_PA14) && !defined(IGNORE_PIN_PA14)
PIN(PA14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH,
SERCOM(2, 2),
#ifdef SERCOM4
@@ -294,7 +292,7 @@ PIN(PA14, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH,
TC(3, 0),
TCC(0, 4));
#endif
-#ifdef PIN_PA15
+#if defined(PIN_PA15) && !defined(IGNORE_PIN_PA15)
PIN(PA15, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH,
SERCOM(2, 3),
#ifdef SERCOM4
@@ -305,35 +303,35 @@ PIN(PA15, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH,
TC(3, 1),
TCC(0, 5));
#endif
-#ifdef PIN_PA16
+#if defined(PIN_PA16) && !defined(IGNORE_PIN_PA16)
PIN(PA16, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH,
SERCOM(1, 0),
SERCOM(3, 0),
TCC(2, 0),
TCC(0, 6));
#endif
-#ifdef PIN_PA17
+#if defined(PIN_PA17) && !defined(IGNORE_PIN_PA17)
PIN(PA17, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH,
SERCOM(1, 1),
SERCOM(3, 1),
TCC(2, 1),
TCC(0, 7));
#endif
-#ifdef PIN_PA18
+#if defined(PIN_PA18) && !defined(IGNORE_PIN_PA18)
PIN(PA18, EXTINT_CHANNEL(2), NO_ADC, NO_TOUCH,
SERCOM(1, 2),
SERCOM(3, 2),
TC(3, 0),
TCC(0, 2));
#endif
-#ifdef PIN_PA19
+#if defined(PIN_PA19) && !defined(IGNORE_PIN_PA19)
PIN(PA19, EXTINT_CHANNEL(3), NO_ADC, NO_TOUCH,
SERCOM(1, 3),
SERCOM(3, 3),
TC(3, 1),
TCC(0, 3));
#endif
-#ifdef PIN_PB16
+#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16)
PIN(PB16, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH,
SERCOM(5, 0),
NO_SERCOM,
@@ -344,7 +342,7 @@ PIN(PB16, EXTINT_CHANNEL(0), NO_ADC, NO_TOUCH,
#endif
TCC(0, 4));
#endif
-#ifdef PIN_PB17
+#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17)
PIN(PB17, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH,
SERCOM(5, 1),
NO_SERCOM,
@@ -355,7 +353,7 @@ PIN(PB17, EXTINT_CHANNEL(1), NO_ADC, NO_TOUCH,
#endif
TCC(0, 5));
#endif
-#ifdef PIN_PA20
+#if defined(PIN_PA20) && !defined(IGNORE_PIN_PA20)
PIN(PA20, EXTINT_CHANNEL(4), NO_ADC, NO_TOUCH,
SERCOM(5, 2),
SERCOM(3, 2),
@@ -366,7 +364,7 @@ PIN(PA20, EXTINT_CHANNEL(4), NO_ADC, NO_TOUCH,
#endif
TCC(0, 6));
#endif
-#ifdef PIN_PA21
+#if defined(PIN_PA21) && !defined(IGNORE_PIN_PA21)
PIN(PA21, EXTINT_CHANNEL(5), NO_ADC, NO_TOUCH,
SERCOM(5, 3),
SERCOM(3, 3),
@@ -377,7 +375,7 @@ PIN(PA21, EXTINT_CHANNEL(5), NO_ADC, NO_TOUCH,
#endif
TCC(0, 7));
#endif
-#ifdef PIN_PA22
+#if defined(PIN_PA22) && !defined(IGNORE_PIN_PA22)
PIN(PA22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH,
SERCOM(3, 0),
#ifdef SERCOM5
@@ -388,7 +386,7 @@ PIN(PA22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH,
TC(4, 0),
TCC(0, 4));
#endif
-#ifdef PIN_PA23
+#if defined(PIN_PA23) && !defined(IGNORE_PIN_PA23)
PIN(PA23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH,
SERCOM(3, 1),
#ifdef SERCOM5
@@ -399,7 +397,7 @@ PIN(PA23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH,
TC(4, 1),
TCC(0, 5));
#endif
-#ifdef PIN_PA24
+#if defined(PIN_PA24) && !defined(IGNORE_PIN_PA24)
PIN(PA24, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH,
SERCOM(3, 2),
#ifdef SERCOM5
@@ -410,7 +408,7 @@ PIN(PA24, EXTINT_CHANNEL(12), NO_ADC, NO_TOUCH,
TC(5, 0),
TCC(0, 2));
#endif
-#ifdef PIN_PA25
+#if defined(PIN_PA25) && !defined(IGNORE_PIN_PA25)
PIN(PA25, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH,
SERCOM(3, 3),
#ifdef SERCOM5
@@ -421,7 +419,7 @@ PIN(PA25, EXTINT_CHANNEL(13), NO_ADC, NO_TOUCH,
TC(5, 1),
TCC(1, 3));
#endif
-#ifdef PIN_PB22
+#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22)
PIN(PB22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(5, 2),
@@ -432,7 +430,7 @@ PIN(PB22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH,
#endif
NO_TIMER);
#endif
-#ifdef PIN_PB23
+#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23)
PIN(PB23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(5, 3),
@@ -443,49 +441,49 @@ PIN(PB23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH,
#endif
NO_TIMER);
#endif
-#ifdef PIN_PA27
+#if defined(PIN_PA27) && !defined(IGNORE_PIN_PA27)
PIN(PA27, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH,
NO_SERCOM,
NO_SERCOM,
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PA28
+#if defined(PIN_PA28) && !defined(IGNORE_PIN_PA28)
PIN(PA28, EXTINT_CHANNEL(8), NO_ADC, NO_TOUCH,
NO_SERCOM,
NO_SERCOM,
NO_TIMER,
NO_TIMER);
#endif
-#ifdef PIN_PA30
+#if defined(PIN_PA30) && !defined(IGNORE_PIN_PA30)
PIN(PA30, EXTINT_CHANNEL(10), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(1, 2),
TCC(1, 0),
NO_TIMER);
#endif
-#ifdef PIN_PA31
+#if defined(PIN_PA31) && !defined(IGNORE_PIN_PA31)
PIN(PA31, EXTINT_CHANNEL(11), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(1, 3),
TCC(1, 1),
NO_TIMER);
#endif
-#ifdef PIN_PB30
+#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30)
PIN(PB30, EXTINT_CHANNEL(14), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(5, 0),
TCC(0, 0),
TCC(1, 2));
#endif
-#ifdef PIN_PB31
+#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31)
PIN(PB31, EXTINT_CHANNEL(15), NO_ADC, NO_TOUCH,
NO_SERCOM,
SERCOM(5, 1),
TCC(0, 1),
TCC(1, 3));
#endif
-#ifdef PIN_PB00
+#if defined(PIN_PB00) && !defined(IGNORE_PIN_PB00)
PIN(PB00, EXTINT_CHANNEL(0), ADC_INPUT(8), TOUCH(6),
NO_SERCOM,
SERCOM(5, 2),
@@ -496,7 +494,7 @@ PIN(PB00, EXTINT_CHANNEL(0), ADC_INPUT(8), TOUCH(6),
#endif
NO_TIMER);
#endif
-#ifdef PIN_PB01
+#if defined(PIN_PB01) && !defined(IGNORE_PIN_PB01)
PIN(PB01, EXTINT_CHANNEL(1), ADC_INPUT(9), TOUCH(7),
NO_SERCOM,
SERCOM(5, 3)),
@@ -507,7 +505,7 @@ PIN(PB01, EXTINT_CHANNEL(1), ADC_INPUT(9), TOUCH(7),
#endif
NO_TIMER;
#endif
-#ifdef PIN_PB02
+#if defined(PIN_PB02) && !defined(IGNORE_PIN_PB02)
PIN(PB02, EXTINT_CHANNEL(2), ADC_INPUT(10), TOUCH(8),
NO_SERCOM,
SERCOM(5, 0),
@@ -518,7 +516,7 @@ PIN(PB02, EXTINT_CHANNEL(2), ADC_INPUT(10), TOUCH(8),
#endif
NO_TIMER);
#endif
-#ifdef PIN_PB03
+#if defined(PIN_PB03) && !defined(IGNORE_PIN_PB03)
PIN(PB03, EXTINT_CHANNEL(3), ADC_INPUT(11), TOUCH(9),
NO_SERCOM,
SERCOM(5, 1),
diff --git a/ports/atmel-samd/samd21_pins.h b/ports/atmel-samd/peripherals/samd21/pins.h
index 522563ef1..0b99ce9b3 100644
--- a/ports/atmel-samd/samd21_pins.h
+++ b/ports/atmel-samd/peripherals/samd21/pins.h
@@ -24,12 +24,13 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H
-#define MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H
+// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure
+// that all necessary includes are already included.
-#include "include/sam.h"
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SAMD21_PINS_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SAMD21_PINS_H
-#include "common-hal/microcontroller/Pin.h"
+#include "include/sam.h"
void reset_pin(uint8_t pin);
@@ -201,4 +202,4 @@ extern const mcu_pin_obj_t pin_PB02;
extern const mcu_pin_obj_t pin_PB03;
#endif
-#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SAMD21_PINS_H
diff --git a/ports/atmel-samd/samd21_peripherals.c b/ports/atmel-samd/peripherals/samd21/sercom.c
index 5bbac2965..a27e49e0e 100644
--- a/ports/atmel-samd/samd21_peripherals.c
+++ b/ports/atmel-samd/peripherals/samd21/sercom.c
@@ -24,11 +24,9 @@
* THE SOFTWARE.
*/
-#include "hal/include/hal_adc_sync.h"
#include "hpl/gclk/hpl_gclk_base.h"
#include "hpl/pm/hpl_pm_base.h"
-
// The clock initializer values are rather random, so we need to put them in
// tables for lookup. We can't compute them.
@@ -93,21 +91,3 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) {
return clock_pad == 1 || clock_pad == 3;
}
-
-// Do initialization and calibration setup needed for any use of the ADC.
-// The reference and resolution should be set by the caller.
-void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) {
- // Turn the clocks on.
- _pm_enable_bus_clock(PM_BUS_APBC, ADC);
- _gclk_enable_channel(ADC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
-
- adc_sync_init(adc, instance, (void *)NULL);
-
- // Load the factory calibration
- hri_adc_write_CALIB_BIAS_CAL_bf(ADC, (*((uint32_t*) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos);
- // Bits 7:5
- uint16_t linearity = ((*((uint32_t*) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
- // Bits 4:0
- linearity |= (*((uint32_t*) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
- hri_adc_write_CALIB_LINEARITY_CAL_bf(ADC, linearity);
-}
diff --git a/ports/atmel-samd/peripherals/samd21/timers.c b/ports/atmel-samd/peripherals/samd21/timers.c
new file mode 100644
index 000000000..c93a71086
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd21/timers.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "peripherals/timers.h"
+
+//#include "common-hal/pulseio/PulseOut.h"
+
+#include "hpl/gclk/hpl_gclk_base.h"
+
+const uint8_t tcc_cc_num[3] = {4, 2, 2};
+const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC3_GCLK_ID,
+ TC4_GCLK_ID,
+ TC5_GCLK_ID,
+#ifdef TC6_GCLK_ID
+ TC6_GCLK_ID,
+#endif
+#ifdef TC7_GCLK_ID
+ TC7_GCLK_ID,
+#endif
+ };
+const uint8_t tcc_gclk_ids[3] = {TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID};
+
+void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) {
+ uint8_t gclk_id;
+ if (is_tc) {
+ gclk_id = tc_gclk_ids[index];
+ } else {
+ gclk_id = tcc_gclk_ids[index];
+ }
+ // Determine the clock slot on the APBC bus. TCC0 is the first and 8 slots in.
+ uint8_t clock_slot = 8 + index;
+ // We index TCs starting at zero but in memory they begin at three so we have to add three.
+ if (is_tc) {
+ clock_slot += 3;
+ }
+ PM->APBCMASK.reg |= 1 << clock_slot;
+ _gclk_enable_channel(gclk_id, gclk_index);
+}
+
+void tc_set_enable(Tc* tc, bool enable) {
+ tc->COUNT16.CTRLA.bit.ENABLE = enable;
+ while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {
+ /* Wait for sync */
+ }
+}
+
+void tc_wait_for_sync(Tc* tc) {
+ while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {}
+}
diff --git a/ports/atmel-samd/peripherals/samd51/adc.c b/ports/atmel-samd/peripherals/samd51/adc.c
new file mode 100644
index 000000000..af6333a94
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd51/adc.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Dan Halbert 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 "hal/include/hal_adc_sync.h"
+#include "hpl/gclk/hpl_gclk_base.h"
+#include "hri/hri_mclk_d51.h"
+
+// Do initialization and calibration setup needed for any use of the ADC.
+// The reference and resolution should be set by the caller.
+void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) {
+ // Turn the clocks on.
+ if (instance == ADC0) {
+ hri_mclk_set_APBDMASK_ADC0_bit(MCLK);
+ hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
+ } else if (instance == ADC1) {
+ hri_mclk_set_APBDMASK_ADC1_bit(MCLK);
+ hri_gclk_write_PCHCTRL_reg(GCLK, ADC1_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
+ }
+
+ adc_sync_init(adc, instance, (void *)NULL);
+
+ // SAMD51 has a CALIB register but doesn't have documented fuses for them.
+ uint8_t biasrefbuf;
+ uint8_t biasr2r;
+ uint8_t biascomp;
+ if (instance == ADC0) {
+ biasrefbuf = ((*(uint32_t*) ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
+ biasr2r = ((*(uint32_t*) ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
+ biascomp = ((*(uint32_t*) ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
+ } else {
+ biasrefbuf = ((*(uint32_t*) ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
+ biasr2r = ((*(uint32_t*) ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
+ biascomp = ((*(uint32_t*) ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
+ }
+ hri_adc_write_CALIB_BIASREFBUF_bf(instance, biasrefbuf);
+ hri_adc_write_CALIB_BIASR2R_bf(instance, biasr2r);
+ hri_adc_write_CALIB_BIASCOMP_bf(instance, biascomp);
+}
diff --git a/ports/atmel-samd/peripherals/samd51/cache.c b/ports/atmel-samd/peripherals/samd51/cache.c
new file mode 100644
index 000000000..f94dd830c
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd51/cache.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Dan Halbert 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 "sam.h"
+
+// Turn off cache and invalidate all data in it.
+void samd_peripherals_disable_and_clear_cache(void) {
+ CMCC->CTRL.bit.CEN = 0;
+ while (CMCC->SR.bit.CSTS) {}
+ CMCC->MAINT0.bit.INVALL = 1;
+}
+
+// Enable cache
+void samd_peripherals_enable_cache(void) {
+ CMCC->CTRL.bit.CEN = 1;
+}
diff --git a/ports/atmel-samd/peripherals/samd51/clocks.c b/ports/atmel-samd/peripherals/samd51/clocks.c
new file mode 100644
index 000000000..37468a3f7
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd51/clocks.c
@@ -0,0 +1,480 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "peripherals/clocks.h"
+
+#include "hpl_gclk_config.h"
+
+#include "bindings/samd/Clock.h"
+#include "shared-bindings/microcontroller/__init__.h"
+
+#include "py/runtime.h"
+
+bool gclk_enabled(uint8_t gclk) {
+ return GCLK->GENCTRL[gclk].bit.GENEN;
+}
+
+void disable_gclk(uint8_t gclk) {
+ while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
+ GCLK->GENCTRL[gclk].bit.GENEN = false;
+ while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
+}
+
+void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral) {
+ GCLK->PCHCTRL[peripheral].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk);
+ while(GCLK->SYNCBUSY.reg != 0) {}
+}
+
+void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral) {
+ GCLK->PCHCTRL[peripheral].reg = 0;
+}
+
+static void enable_clock_generator_sync(uint8_t gclk, uint32_t source, uint16_t divisor, bool sync) {
+ uint32_t divsel = 0;
+ // The datasheet says 8 bits and max value of 512, how is that possible?
+ if (divisor > 255) { // Generator 1 has 16 bits
+ divsel = GCLK_GENCTRL_DIVSEL;
+ for (int i = 15; i > 0; i--) {
+ if (divisor & (1 << i)) {
+ divisor = i - 1;
+ break;
+ }
+ }
+ }
+
+ GCLK->GENCTRL[gclk].reg = GCLK_GENCTRL_SRC(source) | GCLK_GENCTRL_DIV(divisor) | divsel | GCLK_GENCTRL_OE | GCLK_GENCTRL_GENEN;
+ if (sync)
+ while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
+}
+
+void enable_clock_generator(uint8_t gclk, uint32_t source, uint16_t divisor) {
+ enable_clock_generator_sync(gclk, source, divisor, true);
+}
+
+void disable_clock_generator(uint8_t gclk) {
+ GCLK->GENCTRL[gclk].reg = 0;
+ while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
+}
+
+static void init_clock_source_osculp32k(void) {
+ // Calibration value is loaded at startup
+ OSC32KCTRL->OSCULP32K.bit.EN1K = 1;
+ OSC32KCTRL->OSCULP32K.bit.EN32K = 0;
+}
+
+static void init_clock_source_xosc32k(void) {
+ OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ONDEMAND |
+ OSC32KCTRL_XOSC32K_EN1K |
+ OSC32KCTRL_XOSC32K_XTALEN |
+ OSC32KCTRL_XOSC32K_ENABLE |
+ OSC32KCTRL_XOSC32K_CGM(1);
+}
+
+static void init_clock_source_dpll0(void)
+{
+ GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(5);
+ OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(59);
+ OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0);
+ OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
+
+ while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY)) {}
+}
+
+void clock_init(void) {
+ // DFLL48M is enabled by default
+
+ init_clock_source_osculp32k();
+
+ if (board_has_crystal()) {
+ init_clock_source_xosc32k();
+ OSC32KCTRL->RTCCTRL.bit.RTCSEL = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K_Val;
+ } else {
+ OSC32KCTRL->RTCCTRL.bit.RTCSEL = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K_Val;
+ }
+
+ MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV(1);
+
+ enable_clock_generator_sync(0, GCLK_GENCTRL_SRC_DPLL0_Val, 1, false);
+ enable_clock_generator_sync(1, GCLK_GENCTRL_SRC_DFLL_Val, 1, false);
+ enable_clock_generator_sync(4, GCLK_GENCTRL_SRC_DPLL0_Val, 1, false);
+ enable_clock_generator_sync(5, GCLK_GENCTRL_SRC_DFLL_Val, 24, false);
+
+ init_clock_source_dpll0();
+
+ // Do this after all static clock init so that they aren't used dynamically.
+ init_dynamic_clocks();
+}
+
+static bool clk_enabled(uint8_t clk) {
+ return GCLK->PCHCTRL[clk].bit.CHEN;
+}
+
+static uint8_t clk_get_generator(uint8_t clk) {
+ return GCLK->PCHCTRL[clk].bit.GEN;
+}
+
+static uint8_t generator_get_source(uint8_t gen) {
+ return GCLK->GENCTRL[gen].bit.SRC;
+}
+
+static bool osc_enabled(uint8_t index) {
+ switch (index) {
+ case GCLK_SOURCE_XOSC0:
+ return OSCCTRL->XOSCCTRL[0].bit.ENABLE;
+ case GCLK_SOURCE_XOSC1:
+ return OSCCTRL->XOSCCTRL[1].bit.ENABLE;
+ case GCLK_SOURCE_OSCULP32K:
+ return true;
+ case GCLK_SOURCE_XOSC32K:
+ return OSC32KCTRL->XOSC32K.bit.ENABLE;
+ case GCLK_SOURCE_DFLL:
+ return OSCCTRL->DFLLCTRLA.bit.ENABLE;
+ case GCLK_SOURCE_DPLL0:
+ return OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE;
+ case GCLK_SOURCE_DPLL1:
+ return OSCCTRL->Dpll[1].DPLLCTRLA.bit.ENABLE;
+ };
+ return false;
+}
+
+static uint32_t osc_get_source(uint8_t index) {
+ uint8_t dpll_index = index - GCLK_SOURCE_DPLL0;
+ uint32_t refclk = OSCCTRL->Dpll[dpll_index].DPLLCTRLB.bit.REFCLK;
+ switch (refclk) {
+ case 0x0:
+ return generator_get_source(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + dpll_index].bit.GEN);
+ case 0x1:
+ return GCLK_SOURCE_XOSC32K;
+ case 0x2:
+ return GCLK_SOURCE_XOSC0;
+ case 0x3:
+ return GCLK_SOURCE_XOSC1;
+ }
+ return 0;
+}
+
+static uint32_t osc_get_frequency(uint8_t index);
+
+static uint32_t generator_get_frequency(uint8_t gen) {
+ uint8_t src = GCLK->GENCTRL[gen].bit.SRC;
+ uint32_t div;
+ if (GCLK->GENCTRL[gen].bit.DIVSEL) {
+ div = 1 << (GCLK->GENCTRL[gen].bit.DIV + 1);
+ } else {
+ div = GCLK->GENCTRL[gen].bit.DIV;
+ if (!div)
+ div = 1;
+ }
+
+ return osc_get_frequency(src) / div;
+}
+
+static uint32_t dpll_get_frequency(uint8_t index) {
+ uint8_t dpll_index = index - GCLK_SOURCE_DPLL0;
+ uint32_t refclk = OSCCTRL->Dpll[dpll_index].DPLLCTRLB.bit.REFCLK;
+ uint32_t freq;
+
+ switch (refclk) {
+ case 0x0: // GCLK
+ freq = generator_get_frequency(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + dpll_index].bit.GEN);
+ break;
+ case 0x1: // XOSC32
+ freq = 32768;
+ break;
+ case 0x2: // XOSC0
+ case 0x3: // XOSC1
+ default:
+ return 0; // unknown
+ }
+
+ return (freq * (OSCCTRL->Dpll[dpll_index].DPLLRATIO.bit.LDR + 1)) +
+ (freq * OSCCTRL->Dpll[dpll_index].DPLLRATIO.bit.LDRFRAC / 32);
+}
+
+static uint32_t osc_get_frequency(uint8_t index) {
+ switch (index) {
+ case GCLK_SOURCE_XOSC0:
+ case GCLK_SOURCE_XOSC1:
+ return 0; // unknown
+ case GCLK_SOURCE_OSCULP32K:
+ case GCLK_SOURCE_XOSC32K:
+ return 32768;
+ case GCLK_SOURCE_DFLL:
+ return 48000000;
+ case GCLK_SOURCE_DPLL0:
+ case GCLK_SOURCE_DPLL1:
+ return dpll_get_frequency(index);
+ }
+ return 0;
+}
+
+bool clock_get_enabled(uint8_t type, uint8_t index) {
+ if (type == 0)
+ return osc_enabled(index);
+ if (type == 1)
+ return clk_enabled(index);
+ if (type == 2)
+ return SysTick->CTRL & SysTick_CTRL_ENABLE_Msk;
+ return false;
+}
+
+bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) {
+ if (type == 0 && osc_enabled(index)) {
+ if (index == GCLK_SOURCE_DPLL0 || index == GCLK_SOURCE_DPLL1) {
+ *p_type = 0;
+ *p_index = osc_get_source(index);
+ return true;
+ }
+ return false;
+ }
+ if (type == 1 && index <= 47 && clk_enabled(index)) {
+ *p_type = 0;
+ *p_index = generator_get_source(clk_get_generator(index));
+ return true;
+ }
+ if (type == 2) {
+ switch (index) {
+ case 0:
+ case 1:
+ *p_type = 0;
+ *p_index = generator_get_source(0);
+ return true;
+ case 2:
+ *p_type = 0;
+ switch (OSC32KCTRL->RTCCTRL.bit.RTCSEL) {
+ case 0:
+ case 1:
+ *p_index = GCLK_SOURCE_OSCULP32K;
+ return true;
+ case 4:
+ case 5:
+ *p_index = GCLK_SOURCE_XOSC32K;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+}
+
+uint32_t clock_get_frequency(uint8_t type, uint8_t index) {
+ if (type == 0) {
+ return osc_get_frequency(index);
+ }
+ if (type == 1 && index <= 47 && clk_enabled(index)) {
+ return generator_get_frequency(clk_get_generator(index));
+ }
+ if (type == 2) {
+ switch (index) {
+ case 0:
+ return clock_get_frequency(0, generator_get_source(0)) / SysTick->LOAD;
+ case 1:
+ return clock_get_frequency(0, generator_get_source(0)) / MCLK->CPUDIV.bit.DIV;
+ case 2:
+ switch (OSC32KCTRL->RTCCTRL.bit.RTCSEL) {
+ case 0:
+ case 4:
+ return 1024;
+ case 1:
+ case 5:
+ return 32768;
+ }
+ }
+ }
+ return 0;
+}
+
+uint32_t clock_get_calibration(uint8_t type, uint8_t index) {
+ if (type == 0) {
+ switch (index) {
+ case GCLK_SOURCE_OSCULP32K:
+ return OSC32KCTRL->OSCULP32K.bit.CALIB;
+ };
+ }
+ if (type == 2 && index == 0) {
+ return SysTick->LOAD + 1;
+ }
+ return 0;
+}
+
+int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) {
+ if (type == 0) {
+ switch (index) {
+ case GCLK_SOURCE_OSCULP32K:
+ if (val > 0x3f)
+ return -1;
+ OSC32KCTRL->OSCULP32K.bit.CALIB = val;
+ return 0;
+ };
+ }
+ if (type == 2 && index == 0) {
+ if (val < 0x1000 || val > 0x1000000)
+ return -1;
+ SysTick->LOAD = val - 1;
+ return 0;
+ }
+ return -2;
+}
+
+
+void save_usb_clock_calibration(void) {
+}
+
+#include <instance/can0.h>
+#include <instance/can1.h>
+#include <instance/i2s.h>
+#include <instance/sdhc1.h>
+#include <instance/sercom6.h>
+#include <instance/sercom7.h>
+#include <instance/tcc4.h>
+
+CLOCK_SOURCE(XOSC0);
+CLOCK_SOURCE(XOSC1);
+CLOCK_SOURCE(GCLKIN);
+CLOCK_SOURCE(GCLKGEN1);
+CLOCK_SOURCE(OSCULP32K);
+CLOCK_SOURCE(XOSC32K);
+CLOCK_SOURCE(DFLL);
+CLOCK_SOURCE(DPLL0);
+CLOCK_SOURCE(DPLL1);
+
+CLOCK_GCLK_(OSCCTRL, DFLL48);
+CLOCK_GCLK_(OSCCTRL, FDPLL0);
+CLOCK_GCLK_(OSCCTRL, FDPLL1);
+CLOCK_GCLK_(OSCCTRL, FDPLL032K); // GCLK_OSCCTRL_FDPLL1_32K, GCLK_SDHC0_SLOW, GCLK_SDHC1_SLOW, GCLK_SERCOM[0..7]_SLOW
+CLOCK_GCLK(EIC);
+CLOCK_GCLK_(FREQM, MSR);
+// 6: GCLK_FREQM_REF
+CLOCK_GCLK_(SERCOM0, CORE);
+CLOCK_GCLK_(SERCOM1, CORE);
+CLOCK(TC0_TC1, 1, 9);
+CLOCK_GCLK(USB);
+CLOCK_GCLK_(EVSYS, 0);
+CLOCK_GCLK_(EVSYS, 1);
+CLOCK_GCLK_(EVSYS, 2);
+CLOCK_GCLK_(EVSYS, 3);
+CLOCK_GCLK_(EVSYS, 4);
+CLOCK_GCLK_(EVSYS, 5);
+CLOCK_GCLK_(EVSYS, 6);
+CLOCK_GCLK_(EVSYS, 7);
+CLOCK_GCLK_(EVSYS, 8);
+CLOCK_GCLK_(EVSYS, 9);
+CLOCK_GCLK_(EVSYS, 10);
+CLOCK_GCLK_(EVSYS, 11);
+CLOCK_GCLK_(SERCOM2, CORE);
+CLOCK_GCLK_(SERCOM3, CORE);
+CLOCK(TCC0_TCC1, 1, 25);
+CLOCK(TC2_TC3, 1, 26);
+CLOCK_GCLK(CAN0);
+CLOCK_GCLK(CAN1);
+CLOCK(TCC2_TCC3, 1, 29);
+CLOCK(TC4_TC5, 1, 30);
+CLOCK_GCLK(PDEC);
+CLOCK_GCLK(AC);
+CLOCK_GCLK(CCL);
+CLOCK_GCLK_(SERCOM4, CORE);
+CLOCK_GCLK_(SERCOM5, CORE);
+CLOCK_GCLK_(SERCOM6, CORE);
+CLOCK_GCLK_(SERCOM7, CORE);
+CLOCK_GCLK(TCC4);
+CLOCK(TC6_TC7, 1, 39);
+CLOCK_GCLK(ADC0);
+CLOCK_GCLK(ADC1);
+CLOCK_GCLK(DAC);
+CLOCK_GCLK_(I2S, 0);
+CLOCK_GCLK_(I2S, 1);
+CLOCK_GCLK(SDHC0);
+CLOCK_GCLK(SDHC1);
+// 47: GCLK_CM4_TRACE
+
+CLOCK(SYSTICK, 2, 0);
+CLOCK(CPU, 2, 1);
+CLOCK(RTC, 2, 2);
+
+
+STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = {
+ CLOCK_ENTRY(XOSC0),
+ CLOCK_ENTRY(XOSC1),
+ CLOCK_ENTRY(GCLKIN),
+ CLOCK_ENTRY(GCLKGEN1),
+ CLOCK_ENTRY(OSCULP32K),
+ CLOCK_ENTRY(XOSC32K),
+ CLOCK_ENTRY(DFLL),
+ CLOCK_ENTRY(DPLL0),
+ CLOCK_ENTRY(DPLL1),
+
+ CLOCK_ENTRY_(OSCCTRL, DFLL48),
+ CLOCK_ENTRY_(OSCCTRL, FDPLL0),
+ CLOCK_ENTRY_(OSCCTRL, FDPLL1),
+ CLOCK_ENTRY_(OSCCTRL, FDPLL032K),
+ CLOCK_ENTRY(EIC),
+ CLOCK_ENTRY_(FREQM, MSR),
+ CLOCK_ENTRY_(SERCOM0, CORE),
+ CLOCK_ENTRY_(SERCOM1, CORE),
+ CLOCK_ENTRY(TC0_TC1),
+ CLOCK_ENTRY(USB),
+ CLOCK_ENTRY_(EVSYS, 0),
+ CLOCK_ENTRY_(EVSYS, 1),
+ CLOCK_ENTRY_(EVSYS, 2),
+ CLOCK_ENTRY_(EVSYS, 3),
+ CLOCK_ENTRY_(EVSYS, 4),
+ CLOCK_ENTRY_(EVSYS, 5),
+ CLOCK_ENTRY_(EVSYS, 6),
+ CLOCK_ENTRY_(EVSYS, 7),
+ CLOCK_ENTRY_(EVSYS, 8),
+ CLOCK_ENTRY_(EVSYS, 9),
+ CLOCK_ENTRY_(EVSYS, 10),
+ CLOCK_ENTRY_(EVSYS, 11),
+ CLOCK_ENTRY_(SERCOM2, CORE),
+ CLOCK_ENTRY_(SERCOM3, CORE),
+ CLOCK_ENTRY(TCC0_TCC1),
+ CLOCK_ENTRY(TC2_TC3),
+ CLOCK_ENTRY(CAN0),
+ CLOCK_ENTRY(CAN1),
+ CLOCK_ENTRY(TCC2_TCC3),
+ CLOCK_ENTRY(TC4_TC5),
+ CLOCK_ENTRY(PDEC),
+ CLOCK_ENTRY(AC),
+ CLOCK_ENTRY(CCL),
+ CLOCK_ENTRY_(SERCOM4, CORE),
+ CLOCK_ENTRY_(SERCOM5, CORE),
+ CLOCK_ENTRY_(SERCOM6, CORE),
+ CLOCK_ENTRY_(SERCOM7, CORE),
+ CLOCK_ENTRY(TCC4),
+ CLOCK_ENTRY(TC6_TC7),
+ CLOCK_ENTRY(ADC0),
+ CLOCK_ENTRY(ADC1),
+ CLOCK_ENTRY(DAC),
+ CLOCK_ENTRY_(I2S, 0),
+ CLOCK_ENTRY_(I2S, 1),
+ CLOCK_ENTRY(SDHC0),
+ CLOCK_ENTRY(SDHC1),
+
+ CLOCK_ENTRY(SYSTICK),
+ CLOCK_ENTRY(CPU),
+ CLOCK_ENTRY(RTC),
+};
+MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table);
diff --git a/ports/atmel-samd/peripherals/samd51/dma.c b/ports/atmel-samd/peripherals/samd51/dma.c
new file mode 100644
index 000000000..ccb35aaf6
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd51/dma.c
@@ -0,0 +1,94 @@
+/*
+ * 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 "peripherals/dma.h"
+
+#include <string.h>
+
+#include "py/gc.h"
+#include "py/mpstate.h"
+
+#include "hal/utils/include/utils.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+
+uint8_t sercom_index(Sercom* sercom) {
+ const Sercom* sercoms[SERCOM_INST_NUM] = SERCOM_INSTS;
+ for (uint8_t i = 0; i < SERCOM_INST_NUM; i++) {
+ if (sercoms[i] == sercom) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+void dma_configure(uint8_t channel_number, uint8_t trigsrc, bool output_event) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ channel->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
+ channel->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;
+ if (output_event) {
+ channel->CHEVCTRL.reg = DMAC_CHEVCTRL_EVOE;
+ }
+ channel->CHCTRLA.reg = DMAC_CHCTRLA_TRIGSRC(trigsrc) |
+ DMAC_CHCTRLA_TRIGACT_BURST |
+ DMAC_CHCTRLA_BURSTLEN_SINGLE;
+}
+
+void dma_enable_channel(uint8_t channel_number) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ channel->CHCTRLA.bit.ENABLE = true;
+ // Clear any previous interrupts.
+ channel->CHINTFLAG.reg = DMAC_CHINTFLAG_MASK;
+}
+
+void dma_disable_channel(uint8_t channel_number) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ channel->CHCTRLA.bit.ENABLE = false;
+}
+
+void dma_suspend_channel(uint8_t channel_number) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_SUSPEND;
+}
+
+void dma_resume_channel(uint8_t channel_number) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ channel->CHCTRLB.reg = DMAC_CHCTRLB_CMD_RESUME;
+}
+
+bool dma_channel_enabled(uint8_t channel_number) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ return channel->CHCTRLA.bit.ENABLE;
+}
+
+uint8_t dma_transfer_status(uint8_t channel_number) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ return channel->CHINTFLAG.reg;
+}
+
+bool dma_channel_free(uint8_t channel_number) {
+ DmacChannel* channel = &DMAC->Channel[channel_number];
+ return channel->CHSTATUS.reg == 0;
+}
diff --git a/ports/atmel-samd/peripherals/samd51/events.c b/ports/atmel-samd/peripherals/samd51/events.c
new file mode 100644
index 000000000..5ea2c87e6
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd51/events.c
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "peripherals/events.h"
+
+#include "peripherals/clocks.h"
+
+#include "py/runtime.h"
+
+#include "hri/hri_mclk_d51.h"
+
+void turn_on_event_system(void) {
+ hri_mclk_set_APBBMASK_EVSYS_bit(MCLK);
+}
+
+void reset_event_system(void) {
+ EVSYS->CTRLA.bit.SWRST = true;
+ hri_mclk_clear_APBBMASK_EVSYS_bit(MCLK);
+}
+
+bool event_channel_free(uint8_t channel) {
+ uint8_t generator;
+ generator = EVSYS->Channel[channel].CHANNEL.bit.EVGEN;
+ return generator == 0;
+}
+
+void disable_event_channel(uint8_t channel_number) {
+ EVSYS->Channel[channel_number].CHANNEL.reg = 0;
+}
+
+void disable_event_user(uint8_t user_number) {
+ EVSYS->USER[user_number].reg = 0;
+}
+
+void connect_event_user_to_channel(uint8_t user, uint8_t channel) {
+ EVSYS->USER[user].reg = channel + 1;
+}
+
+void init_async_event_channel(uint8_t channel, uint8_t generator) {
+ EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) | EVSYS_CHANNEL_PATH_ASYNCHRONOUS;
+}
+
+void init_event_channel_interrupt(uint8_t channel, uint8_t gclk, uint8_t generator) {
+ connect_gclk_to_peripheral(gclk, EVSYS_GCLK_ID_0 + channel);
+ EVSYS->Channel[channel].CHANNEL.reg = EVSYS_CHANNEL_EVGEN(generator) |
+ EVSYS_CHANNEL_PATH_SYNCHRONOUS |
+ EVSYS_CHANNEL_EDGSEL_RISING_EDGE;
+ EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR;
+ EVSYS->Channel[channel].CHINTENSET.reg = EVSYS_CHINTENSET_EVD | EVSYS_CHINTENSET_OVR;
+}
+
+bool event_interrupt_active(uint8_t channel) {
+ bool active = false;
+ active = EVSYS->Channel[channel].CHINTFLAG.bit.EVD;
+ // Only clear if we know its active, otherwise there is the possibility it becomes after we
+ // check but before we clear.
+ if (active) {
+ EVSYS->Channel[channel].CHINTFLAG.reg = EVSYS_CHINTFLAG_EVD | EVSYS_CHINTFLAG_OVR;
+ }
+ return active;
+}
+
+bool event_interrupt_overflow(uint8_t channel) {
+ return EVSYS->Channel[channel].CHINTFLAG.bit.OVR;
+}
diff --git a/ports/atmel-samd/peripherals/samd51/external_interrupts.c b/ports/atmel-samd/peripherals/samd51/external_interrupts.c
new file mode 100644
index 000000000..6006d480e
--- /dev/null
+++ b/ports/atmel-samd/peripherals/samd51/external_interrupts.c
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "peripherals/external_interrupts.h"
+
+#include "peripherals/clocks.h"
+#include "sam.h"
+
+void turn_on_external_interrupt_controller(void) {
+ MCLK->APBAMASK.bit.EIC_ = true;
+
+ // We use the 48mhz clock to lightly filter the incoming pulse to reduce spurious interrupts.
+ connect_gclk_to_peripheral(GCLK_PCHCTRL_GEN_GCLK1_Val, EIC_GCLK_ID);
+ eic_set_enable(true);
+}
+
+void turn_off_external_interrupt_controller(void) {
+ eic_set_enable(false);
+ MCLK->APBAMASK.bit.EIC_ = false;
+ disconnect_gclk_from_peripheral(GCLK_PCHCTRL_GEN_GCLK1_Val, EIC_GCLK_ID);
+}
+
+void turn_on_cpu_interrupt(uint8_t eic_channel) {
+ // Ignore the channel since the CPU interrupt line is shared.
+ (void) eic_channel;
+
+ NVIC_DisableIRQ(EIC_0_IRQn + eic_channel);
+ NVIC_ClearPendingIRQ(EIC_0_IRQn + eic_channel);
+ NVIC_EnableIRQ(EIC_0_IRQn + eic_channel);
+}
+
+bool eic_get_enable(void) {
+ return EIC->CTRLA.bit.ENABLE;
+}
+
+void eic_set_enable(bool value) {
+ EIC->CTRLA.bit.ENABLE = value;
+ while (EIC->SYNCBUSY.bit.ENABLE != 0) {}
+ // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first
+ // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us.
+}
+
+void eic_reset(void) {
+ EIC->CTRLA.bit.SWRST = true;
+ while (EIC->SYNCBUSY.bit.SWRST != 0) {}
+ // This won't actually block long enough in Rev A of SAMD51 and will miss edges in the first
+ // three cycles of the peripheral clock. See the errata for details. It shouldn't impact us.
+ for (int i = 0; i < EIC_EXTINT_NUM; i++) {
+ set_eic_channel_data(i, NULL);
+ NVIC_DisableIRQ(EIC_0_IRQn + i);
+ NVIC_ClearPendingIRQ(EIC_0_IRQn + i);
+ }
+}
+
+bool eic_channel_free(uint8_t eic_channel) {
+ uint32_t mask = 1 << eic_channel;
+ return get_eic_channel_data(eic_channel) == NULL &&
+ (EIC->INTENSET.bit.EXTINT & mask) == 0 &&
+ (EIC->EVCTRL.bit.EXTINTEO & mask) == 0;
+}
+
+void EIC_0_Handler(void) {
+ external_interrupt_handler(0);
+}
+void EIC_1_Handler(void) {
+ external_interrupt_handler(1);
+}
+void EIC_2_Handler(void) {
+ external_interrupt_handler(2);
+}
+void EIC_3_Handler(void) {
+ external_interrupt_handler(3);
+}
+void EIC_4_Handler(void) {
+ external_interrupt_handler(4);
+}
+void EIC_5_Handler(void) {
+ external_interrupt_handler(5);
+}
+void EIC_6_Handler(void) {
+ external_interrupt_handler(6);
+}
+void EIC_7_Handler(void) {
+ external_interrupt_handler(7);
+}
+void EIC_8_Handler(void) {
+ external_interrupt_handler(8);
+}
+void EIC_9_Handler(void) {
+ external_interrupt_handler(9);
+}
+void EIC_10_Handler(void) {
+ external_interrupt_handler(10);
+}
+void EIC_11_Handler(void) {
+ external_interrupt_handler(11);
+}
+void EIC_12_Handler(void) {
+ external_interrupt_handler(12);
+}
+void EIC_13_Handler(void) {
+ external_interrupt_handler(13);
+}
+void EIC_14_Handler(void) {
+ external_interrupt_handler(14);
+}
+void EIC_15_Handler(void) {
+ external_interrupt_handler(15);
+}
diff --git a/ports/atmel-samd/i2s.c b/ports/atmel-samd/peripherals/samd51/i2s.c
index 663ecdd1d..97ce13f7d 100644
--- a/ports/atmel-samd/i2s.c
+++ b/ports/atmel-samd/peripherals/samd51/i2s.c
@@ -24,53 +24,22 @@
* THE SOFTWARE.
*/
-#include "i2s.h"
+#include "peripherals/i2s.h"
-#include "clocks.h"
+#include "peripherals/clocks.h"
#include "hpl/gclk/hpl_gclk_base.h"
-#ifdef SAMD21
-#include "hpl/pm/hpl_pm_base.h"
-#endif
void turn_on_i2s(void) {
// Make sure the I2S peripheral is running so we can see if the resources we need are free.
- #ifdef SAMD51
hri_mclk_set_APBDMASK_I2S_bit(MCLK);
// Connect the clock units to the 2mhz clock by default. They can't reset without it.
connect_gclk_to_peripheral(5, I2S_GCLK_ID_0);
connect_gclk_to_peripheral(5, I2S_GCLK_ID_1);
- #endif
-
- #ifdef SAMD21
- _pm_enable_bus_clock(PM_BUS_APBC, I2S);
- #endif
-}
-
-void i2s_set_enable(bool enable) {
- while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
- I2S->CTRLA.bit.ENABLE = enable;
- while (I2S->SYNCBUSY.bit.ENABLE == 1) {}
-}
-
-void i2s_set_clock_unit_enable(uint8_t clock_unit, bool enable) {
- while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {}
- I2S->CTRLA.vec.CKEN = 1 << clock_unit;
- while ((I2S->SYNCBUSY.vec.CKEN & (1 << clock_unit)) != 0) {}
}
void i2s_set_serializer_enable(uint8_t serializer, bool enable) {
- #ifdef SAMD21
- while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {}
- if (enable) {
- I2S->CTRLA.vec.SEREN = 1 << serializer;
- } else {
- I2S->CTRLA.vec.SEREN &= ~(1 << serializer);
- }
- while ((I2S->SYNCBUSY.vec.SEREN & (1 << serializer)) != 0) {}
- #endif
- #ifdef SAMD51
if (serializer == 0) {
while (I2S->SYNCBUSY.bit.TXEN == 1) {}
I2S->CTRLA.bit.TXEN = enable;
@@ -80,5 +49,4 @@ void i2s_set_serializer_enable(uint8_t serializer, bool enable) {
I2S->CTRLA.bit.RXEN = enable;
while (I2S->SYNCBUSY.bit.RXEN == 1) {}
}
- #endif
}
diff --git a/ports/atmel-samd/samd51_pins.c b/ports/atmel-samd/peripherals/samd51/pins.c
index 6d597b6e1..1c52d35a2 100644
--- a/ports/atmel-samd/samd51_pins.c
+++ b/ports/atmel-samd/peripherals/samd51/pins.c
@@ -26,8 +26,6 @@
#include "shared-bindings/microcontroller/Pin.h"
-#include "samd51_pins.h"
-
#define SERCOM(sercom_index, p_pad) \
{ \
.index = sercom_index, \
diff --git a/ports/atmel-samd/samd51_pins.h b/ports/atmel-samd/peripherals/samd51/pins.h
index c9ffacc24..b9a05a345 100644
--- a/ports/atmel-samd/samd51_pins.h
+++ b/ports/atmel-samd/peripherals/samd51/pins.h
@@ -24,13 +24,14 @@
* THE SOFTWARE.
*/
+// DO NOT include this file directly. Use shared-bindings/microcontroller/Pin.h instead to ensure
+// that all necessary includes are already included.
+
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PINS_H
#define MICROPY_INCLUDED_ATMEL_SAMD_SAMD51_PINS_H
#include "include/sam.h"
-#include "common-hal/microcontroller/Pin.h"
-
void reset_pin(uint8_t pin);
#define MUX_C 2
diff --git a/ports/atmel-samd/samd51_peripherals.c b/ports/atmel-samd/peripherals/samd51/sercom.c
index 5772b8e0a..6d0a02fbd 100644
--- a/ports/atmel-samd/samd51_peripherals.c
+++ b/ports/atmel-samd/peripherals/samd51/sercom.c
@@ -131,47 +131,3 @@ uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad) {
bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad) {
return clock_pad == 1;
}
-
-// Do initialization and calibration setup needed for any use of the ADC.
-// The reference and resolution should be set by the caller.
-void samd_peripherals_adc_setup(struct adc_sync_descriptor *adc, Adc *instance) {
- // Turn the clocks on.
- if (instance == ADC0) {
- hri_mclk_set_APBDMASK_ADC0_bit(MCLK);
- hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
- } else if (instance == ADC1) {
- hri_mclk_set_APBDMASK_ADC1_bit(MCLK);
- hri_gclk_write_PCHCTRL_reg(GCLK, ADC1_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
- }
-
- adc_sync_init(adc, instance, (void *)NULL);
-
- // SAMD51 has a CALIB register but doesn't have documented fuses for them.
- uint8_t biasrefbuf;
- uint8_t biasr2r;
- uint8_t biascomp;
- if (instance == ADC0) {
- biasrefbuf = ((*(uint32_t*) ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
- biasr2r = ((*(uint32_t*) ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
- biascomp = ((*(uint32_t*) ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
- } else {
- biasrefbuf = ((*(uint32_t*) ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
- biasr2r = ((*(uint32_t*) ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
- biascomp = ((*(uint32_t*) ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
- }
- hri_adc_write_CALIB_BIASREFBUF_bf(instance, biasrefbuf);
- hri_adc_write_CALIB_BIASR2R_bf(instance, biasr2r);
- hri_adc_write_CALIB_BIASCOMP_bf(instance, biascomp);
-}
-
-// Turn off cache and invalidate all data in it.
-void samd_peripherals_disable_and_clear_cache(void) {
- CMCC->CTRL.bit.CEN = 0;
- while (CMCC->SR.bit.CSTS) {}
- CMCC->MAINT0.bit.INVALL = 1;
-}
-
-// Enable cache
-void samd_peripherals_enable_cache(void) {
- CMCC->CTRL.bit.CEN = 1;
-}
diff --git a/ports/atmel-samd/timers.c b/ports/atmel-samd/peripherals/samd51/timers.c
index 33518b782..f25dbc0e4 100644
--- a/ports/atmel-samd/timers.c
+++ b/ports/atmel-samd/peripherals/samd51/timers.c
@@ -27,36 +27,10 @@
#include <stdbool.h>
#include <stdint.h>
-#include "timers.h"
+#include "peripherals/timers.h"
-#include "common-hal/pulseio/PulseOut.h"
-
-#ifdef SAMD21
-#include "hpl/gclk/hpl_gclk_base.h"
-#endif
-
-#ifdef SAMD51
#include "hri/hri_gclk_d51.h"
-#endif
-const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024};
-
-// This bitmask keeps track of which channels of a TCC are currently claimed.
-#ifdef SAMD21
-const uint8_t tcc_cc_num[3] = {4, 2, 2};
-const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC3_GCLK_ID,
- TC4_GCLK_ID,
- TC5_GCLK_ID,
-#ifdef TC6_GCLK_ID
- TC6_GCLK_ID,
-#endif
-#ifdef TC7_GCLK_ID
- TC7_GCLK_ID,
-#endif
- };
-const uint8_t tcc_gclk_ids[3] = {TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID};
-#endif
-#ifdef SAMD51
const uint8_t tcc_cc_num[5] = {6, 4, 3, 2, 2};
const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC0_GCLK_ID,
TC1_GCLK_ID,
@@ -85,36 +59,6 @@ const uint8_t tcc_gclk_ids[TCC_INST_NUM] = {TCC0_GCLK_ID,
TCC4_GCLK_ID
#endif
};
-#endif
-Tc* const tc_insts[TC_INST_NUM] = TC_INSTS;
-Tcc* const tcc_insts[TCC_INST_NUM] = TCC_INSTS;
-
-IRQn_Type const tc_irq[TC_INST_NUM] = {
-#ifdef TC0
- TC0_IRQn,
-#endif
-#ifdef TC1
- TC1_IRQn,
-#endif
-#ifdef TC2
- TC2_IRQn,
-#endif
-#ifdef TC3
- TC3_IRQn,
-#endif
-#ifdef TC4
- TC4_IRQn,
-#endif
-#ifdef TC5
- TC5_IRQn,
-#endif
-#ifdef TC6
- TC6_IRQn,
-#endif
-#ifdef TC7
- TC7_IRQn,
-#endif
-};
void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) {
uint8_t gclk_id;
@@ -124,7 +68,6 @@ void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) {
gclk_id = tcc_gclk_ids[index];
}
// Turn on the clocks for the peripherals.
- #ifdef SAMD51
if (is_tc) {
switch (index) {
case 0:
@@ -180,122 +123,15 @@ void turn_on_clocks(bool is_tc, uint8_t index, uint32_t gclk_index) {
hri_gclk_write_PCHCTRL_reg(GCLK, gclk_id,
gclk_index | (1 << GCLK_PCHCTRL_CHEN_Pos));
- #endif
-
- #ifdef SAMD21
- // Determine the clock slot on the APBC bus. TCC0 is the first and 8 slots in.
- uint8_t clock_slot = 8 + index;
- // We index TCs starting at zero but in memory they begin at three so we have to add three.
- if (is_tc) {
- clock_slot += 3;
- }
- PM->APBCMASK.reg |= 1 << clock_slot;
- _gclk_enable_channel(gclk_id, gclk_index);
- #endif
}
void tc_set_enable(Tc* tc, bool enable) {
tc->COUNT16.CTRLA.bit.ENABLE = enable;
- #ifdef SAMD21
- while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {
- /* Wait for sync */
- }
- #endif
- #ifdef SAMD51
while (tc->COUNT16.SYNCBUSY.bit.ENABLE != 0) {
/* Wait for sync */
}
- #endif
-}
-
-void tc_enable_interrupts(uint8_t tc_index) {
- NVIC_DisableIRQ(tc_irq[tc_index]);
- NVIC_ClearPendingIRQ(tc_irq[tc_index]);
- NVIC_EnableIRQ(tc_irq[tc_index]);
-}
-
-void tc_disable_interrupts(uint8_t tc_index) {
- NVIC_DisableIRQ(tc_irq[tc_index]);
- NVIC_ClearPendingIRQ(tc_irq[tc_index]);
-}
-
-void tcc_set_enable(Tcc* tcc, bool enable) {
- tcc->CTRLA.bit.ENABLE = enable;
- while (tcc->SYNCBUSY.bit.ENABLE != 0) {
- /* Wait for sync */
- }
}
void tc_wait_for_sync(Tc* tc) {
- #ifdef SAMD21
- while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {}
- #endif
- #ifdef SAMD51
while (tc->COUNT16.SYNCBUSY.reg != 0) {}
- #endif
-}
-
-void tc_reset(Tc* tc) {
- tc->COUNT16.CTRLA.bit.SWRST = 1;
- while (tc->COUNT16.CTRLA.bit.SWRST == 1) {
- }
-}
-
-void shared_timer_handler(bool is_tc, uint8_t index) {
- // Add calls to interrupt handlers for specific functionality here.
- if (is_tc) {
- pulseout_interrupt_handler(index);
- }
-}
-
-#ifdef SAMD51
-#define TC_OFFSET 0
-#endif
-#ifdef SAMD21
-#define TC_OFFSET 3
-#endif
-
-void TCC0_Handler(void) {
- shared_timer_handler(false, 0);
}
-void TCC1_Handler(void) {
- shared_timer_handler(false, 1);
-}
-void TCC2_Handler(void) {
- shared_timer_handler(false, 2);
-}
-// TC0 - TC2 only exist on the SAMD51
-#ifdef TC0
-void TC0_Handler(void) {
- shared_timer_handler(true, 0);
-}
-#endif
-#ifdef TC1
-void TC1_Handler(void) {
- shared_timer_handler(true, 1);
-}
-#endif
-#ifdef TC2
-void TC2_Handler(void) {
- shared_timer_handler(true, 2);
-}
-#endif
-void TC3_Handler(void) {
- shared_timer_handler(true, 3 - TC_OFFSET);
-}
-void TC4_Handler(void) {
- shared_timer_handler(true, 4 - TC_OFFSET);
-}
-void TC5_Handler(void) {
- shared_timer_handler(true, 5 - TC_OFFSET);
-}
-#ifdef TC6
-void TC6_Handler(void) {
- shared_timer_handler(true, 6 - TC_OFFSET);
-}
-#endif
-#ifdef TC7
-void TC7_Handler(void) {
- shared_timer_handler(true, 7 - TC_OFFSET);
-}
-#endif
diff --git a/ports/atmel-samd/peripherals.c b/ports/atmel-samd/peripherals/sercom.c
index c75a1f43b..04c1fd008 100644
--- a/ports/atmel-samd/peripherals.c
+++ b/ports/atmel-samd/peripherals/sercom.c
@@ -24,7 +24,7 @@
* THE SOFTWARE.
*/
-#include "peripherals.h"
+#include "peripherals/sercom.h"
#include "hpl_sercom_config.h"
diff --git a/ports/atmel-samd/peripherals.h b/ports/atmel-samd/peripherals/sercom.h
index 8a07c0045..66ad1a403 100644
--- a/ports/atmel-samd/peripherals.h
+++ b/ports/atmel-samd/peripherals/sercom.h
@@ -24,24 +24,19 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H
-#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SPI_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SPI_H
#include <stdint.h>
#include "mpconfigport.h"
-// Routines common across chip families.
+void samd_peripherals_sercom_clock_init(Sercom* sercom, uint8_t sercom_index);
+uint8_t samd_peripherals_get_spi_dopo(uint8_t clock_pad, uint8_t mosi_pad);
uint8_t samd_peripherals_spi_baudrate_to_baud_reg_value(const uint32_t baudrate);
uint32_t samd_peripherals_spi_baud_reg_value_to_baudrate(const uint8_t baud_reg_value);
+bool samd_peripherals_valid_spi_clock_pad(uint8_t clock_pad);
Sercom* sercom_insts[SERCOM_INST_NUM];
-#ifdef SAMD21
-#include "samd21_peripherals.h"
-#endif
-#ifdef SAMD51
-#include "samd51_peripherals.h"
-#endif
-
-#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_H
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_PERIPHERALS_SPI_H
diff --git a/ports/atmel-samd/peripherals/timers.c b/ports/atmel-samd/peripherals/timers.c
new file mode 100644
index 000000000..cdcb92ac8
--- /dev/null
+++ b/ports/atmel-samd/peripherals/timers.c
@@ -0,0 +1,147 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "timers.h"
+
+#include "common-hal/pulseio/PulseOut.h"
+
+const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024};
+
+Tc* const tc_insts[TC_INST_NUM] = TC_INSTS;
+Tcc* const tcc_insts[TCC_INST_NUM] = TCC_INSTS;
+
+IRQn_Type const tc_irq[TC_INST_NUM] = {
+#ifdef TC0
+ TC0_IRQn,
+#endif
+#ifdef TC1
+ TC1_IRQn,
+#endif
+#ifdef TC2
+ TC2_IRQn,
+#endif
+#ifdef TC3
+ TC3_IRQn,
+#endif
+#ifdef TC4
+ TC4_IRQn,
+#endif
+#ifdef TC5
+ TC5_IRQn,
+#endif
+#ifdef TC6
+ TC6_IRQn,
+#endif
+#ifdef TC7
+ TC7_IRQn,
+#endif
+};
+
+void tc_enable_interrupts(uint8_t tc_index) {
+ NVIC_DisableIRQ(tc_irq[tc_index]);
+ NVIC_ClearPendingIRQ(tc_irq[tc_index]);
+ NVIC_EnableIRQ(tc_irq[tc_index]);
+}
+
+void tc_disable_interrupts(uint8_t tc_index) {
+ NVIC_DisableIRQ(tc_irq[tc_index]);
+ NVIC_ClearPendingIRQ(tc_irq[tc_index]);
+}
+
+void tcc_set_enable(Tcc* tcc, bool enable) {
+ tcc->CTRLA.bit.ENABLE = enable;
+ while (tcc->SYNCBUSY.bit.ENABLE != 0) {
+ /* Wait for sync */
+ }
+}
+
+void tc_reset(Tc* tc) {
+ tc->COUNT16.CTRLA.bit.SWRST = 1;
+ while (tc->COUNT16.CTRLA.bit.SWRST == 1) {
+ }
+}
+
+void shared_timer_handler(bool is_tc, uint8_t index) {
+ // Add calls to interrupt handlers for specific functionality here.
+ if (is_tc) {
+ pulseout_interrupt_handler(index);
+ }
+}
+
+#ifdef SAMD51
+#define TC_OFFSET 0
+#endif
+#ifdef SAMD21
+#define TC_OFFSET 3
+#endif
+
+void TCC0_Handler(void) {
+ shared_timer_handler(false, 0);
+}
+void TCC1_Handler(void) {
+ shared_timer_handler(false, 1);
+}
+void TCC2_Handler(void) {
+ shared_timer_handler(false, 2);
+}
+// TC0 - TC2 only exist on the SAMD51
+#ifdef TC0
+void TC0_Handler(void) {
+ shared_timer_handler(true, 0);
+}
+#endif
+#ifdef TC1
+void TC1_Handler(void) {
+ shared_timer_handler(true, 1);
+}
+#endif
+#ifdef TC2
+void TC2_Handler(void) {
+ shared_timer_handler(true, 2);
+}
+#endif
+void TC3_Handler(void) {
+ shared_timer_handler(true, 3 - TC_OFFSET);
+}
+void TC4_Handler(void) {
+ shared_timer_handler(true, 4 - TC_OFFSET);
+}
+void TC5_Handler(void) {
+ shared_timer_handler(true, 5 - TC_OFFSET);
+}
+#ifdef TC6
+void TC6_Handler(void) {
+ shared_timer_handler(true, 6 - TC_OFFSET);
+}
+#endif
+#ifdef TC7
+void TC7_Handler(void) {
+ shared_timer_handler(true, 7 - TC_OFFSET);
+}
+#endif
diff --git a/ports/atmel-samd/timers.h b/ports/atmel-samd/peripherals/timers.h
index fa8965784..fa8965784 100644
--- a/ports/atmel-samd/timers.h
+++ b/ports/atmel-samd/peripherals/timers.h
diff --git a/ports/atmel-samd/samd51_clocks.c b/ports/atmel-samd/samd51_clocks.c
deleted file mode 100644
index cc3dd7917..000000000
--- a/ports/atmel-samd/samd51_clocks.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "clocks.h"
-
-#include "hpl_gclk_config.h"
-
-#include "shared-bindings/microcontroller/__init__.h"
-
-#include "py/runtime.h"
-
-bool gclk_enabled(uint8_t gclk) {
- return GCLK->GENCTRL[gclk].bit.GENEN;
-}
-
-void disable_gclk(uint8_t gclk) {
- while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
- GCLK->GENCTRL[gclk].bit.GENEN = false;
- while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
-}
-
-void connect_gclk_to_peripheral(uint8_t gclk, uint8_t peripheral) {
- GCLK->PCHCTRL[peripheral].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk);
- while(GCLK->SYNCBUSY.reg != 0) {}
-}
-
-void disconnect_gclk_from_peripheral(uint8_t gclk, uint8_t peripheral) {
- GCLK->PCHCTRL[peripheral].reg = 0;
-}
-
-void enable_clock_generator(uint8_t gclk, uint32_t source, uint16_t divisor) {
- GCLK->GENCTRL[gclk].reg = GCLK_GENCTRL_SRC(source) | GCLK_GENCTRL_DIV(divisor) | GCLK_GENCTRL_GENEN;
- while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
-}
-
-void disable_clock_generator(uint8_t gclk) {
- GCLK->GENCTRL[gclk].reg = 0;
- while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
-}
-
-bool clock_get_enabled(uint8_t type, uint8_t index) {
- return false;
-}
-
-bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) {
- return false;
-}
-
-uint32_t clock_get_frequency(uint8_t type, uint8_t index) {
- return 0;
-}
-
-uint32_t clock_get_calibration(uint8_t type, uint8_t index) {
- return 0;
-}
-
-int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) {
- return -2;
-}
-
-STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = {
-};
-MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table);
diff --git a/ports/atmel-samd/supervisor/filesystem.c b/ports/atmel-samd/supervisor/filesystem.c
index 2ba29f279..8a6010951 100644
--- a/ports/atmel-samd/supervisor/filesystem.c
+++ b/ports/atmel-samd/supervisor/filesystem.c
@@ -32,13 +32,6 @@
#include "flash_api.h"
-#ifdef EXPRESS_BOARD
-// #include "common-hal/touchio/TouchIn.h"
-#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x100 - CIRCUITPY_INTERNAL_NVM_SIZE)
-#else
-#define INTERNAL_CIRCUITPY_CONFIG_START_ADDR (0x00040000 - 0x010000 - 0x100 - CIRCUITPY_INTERNAL_NVM_SIZE)
-#endif
-
fs_user_mount_t fs_user_mount_flash;
mp_vfs_mount_t mp_vfs_mount_flash;
diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c
index 8e6f2b185..3e8d5bcc7 100644
--- a/ports/atmel-samd/supervisor/port.c
+++ b/ports/atmel-samd/supervisor/port.c
@@ -53,13 +53,16 @@
#include "common-hal/pulseio/PulseOut.h"
#include "common-hal/pulseio/PWMOut.h"
#include "common-hal/rtc/RTC.h"
+#include "common-hal/touchio/TouchIn.h"
#include "common-hal/usb_hid/Device.h"
+#include "peripherals/cache.h"
+#include "peripherals/clocks.h"
+#include "peripherals/events.h"
+#include "peripherals/external_interrupts.h"
+#include "peripherals/dma.h"
#include "shared-bindings/rtc/__init__.h"
-#include "clocks.h"
-#include "events.h"
-#include "peripherals.h"
-#include "shared_dma.h"
#include "tick.h"
+#include "usb.h"
#ifdef CIRCUITPY_GAMEPAD_TICKS
#include "shared-module/gamepad/__init__.h"
@@ -180,22 +183,17 @@ safe_mode_t port_init(void) {
#ifdef SAMD21
hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2);
_pm_init();
- clock_init();
-#endif
-#ifdef SAMD51
- init_mcu();
#endif
+ clock_init();
+
board_init();
// Configure millisecond timer initialization.
tick_init();
- rtc_init();
- // Init the nvm controller.
- // struct nvm_config config_nvm;
- // nvm_get_config_defaults(&config_nvm);
- // config_nvm.manual_page_write = false;
- // nvm_set_config(&config_nvm);
+#ifndef PIRKEY_M0
+ rtc_init();
+#endif
init_shared_dma();
#ifdef CIRCUITPY_CANARY_WORD
@@ -205,9 +203,16 @@ safe_mode_t port_init(void) {
}
#endif
- // if (PM->RCAUSE.bit.BOD33 == 1 || PM->RCAUSE.bit.BOD12 == 1) {
- // return BROWNOUT;
- // }
+ #ifdef SAMD21
+ if (PM->RCAUSE.bit.BOD33 == 1 || PM->RCAUSE.bit.BOD12 == 1) {
+ return BROWNOUT;
+ }
+ #endif
+ #ifdef SAMD51
+ if (RSTC->RCAUSE.bit.BODVDD == 1 || RSTC->RCAUSE.bit.BODCORE == 1) {
+ return BROWNOUT;
+ }
+ #endif
if (board_requests_safe_mode()) {
return USER_SAFE_MODE;
@@ -240,38 +245,31 @@ void reset_port(void) {
i2sout_reset();
#endif
audio_dma_reset();
-// touchin_reset();
//pdmin_reset();
#endif
- pulsein_reset();
+#ifdef SAMD21
+ touchin_reset();
+#endif
+ eic_reset();
pulseout_reset();
pwmout_reset();
+
+#ifndef PIRKEY_M0
+ analogin_reset();
+ analogout_reset();
rtc_reset();
+#endif
reset_gclks();
- analogin_reset();
-
#ifdef CIRCUITPY_GAMEPAD_TICKS
gamepad_reset();
#endif
- analogout_reset();
-
reset_event_system();
reset_all_pins();
- // Set up debugging pins after reset_all_pins().
-
- // Uncomment to init PIN_PA17 for debugging.
- // struct port_config pin_conf;
- // port_get_config_defaults(&pin_conf);
- //
- // pin_conf.direction = PORT_PIN_DIR_OUTPUT;
- // port_pin_set_config(MICROPY_HW_LED1, &pin_conf);
- // port_pin_set_output_level(MICROPY_HW_LED1, false);
-
// Output clocks for debugging.
// not supported by SAMD51G; uncomment for SAMD51J or update for 51G
// #ifdef SAMD51
@@ -283,52 +281,9 @@ void reset_port(void) {
usb_hid_reset();
-// #ifdef CALIBRATE_CRYSTALLESS
-// // If we are on USB lets double check our fine calibration for the clock and
-// // save the new value if its different enough.
-// if (mp_msc_enabled) {
-// SYSCTRL->DFLLSYNC.bit.READREQ = 1;
-// uint16_t saved_calibration = 0x1ff;
-// if (strcmp((char*) INTERNAL_CIRCUITPY_CONFIG_START_ADDR, "CIRCUITPYTHON1") == 0) {
-// saved_calibration = ((uint16_t *) INTERNAL_CIRCUITPY_CONFIG_START_ADDR)[8];
-// }
-// while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) {
-// // TODO(tannewt): Run the mass storage stuff if this takes a while.
-// }
-// int16_t current_calibration = SYSCTRL->DFLLVAL.bit.FINE;
-// if (abs(current_calibration - saved_calibration) > 10) {
-// enum status_code error_code;
-// uint8_t page_buffer[NVMCTRL_ROW_SIZE];
-// for (int i = 0; i < NVMCTRL_ROW_PAGES; i++) {
-// do
-// {
-// error_code = nvm_read_buffer(INTERNAL_CIRCUITPY_CONFIG_START_ADDR + i * NVMCTRL_PAGE_SIZE,
-// page_buffer + i * NVMCTRL_PAGE_SIZE,
-// NVMCTRL_PAGE_SIZE);
-// } while (error_code == STATUS_BUSY);
-// }
-// // If this is the first write, include the header.
-// if (strcmp((char*) page_buffer, "CIRCUITPYTHON1") != 0) {
-// memcpy(page_buffer, "CIRCUITPYTHON1", 15);
-// }
-// // First 16 bytes (0-15) are ID. Little endian!
-// page_buffer[16] = current_calibration & 0xff;
-// page_buffer[17] = current_calibration >> 8;
-// do
-// {
-// error_code = nvm_erase_row(INTERNAL_CIRCUITPY_CONFIG_START_ADDR);
-// } while (error_code == STATUS_BUSY);
-// for (int i = 0; i < NVMCTRL_ROW_PAGES; i++) {
-// do
-// {
-// error_code = nvm_write_buffer(INTERNAL_CIRCUITPY_CONFIG_START_ADDR + i * NVMCTRL_PAGE_SIZE,
-// page_buffer + i * NVMCTRL_PAGE_SIZE,
-// NVMCTRL_PAGE_SIZE);
-// } while (error_code == STATUS_BUSY);
-// }
-// }
-// }
-// #endif
+ if (usb_connected()) {
+ save_usb_clock_calibration();
+ }
}
/**
diff --git a/ports/atmel-samd/tick.c b/ports/atmel-samd/tick.c
index 27b5f05b4..6cd7c7833 100644
--- a/ports/atmel-samd/tick.c
+++ b/ports/atmel-samd/tick.c
@@ -30,6 +30,7 @@
#include "supervisor/shared/autoreload.h"
#include "shared-module/gamepad/__init__.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
// Global millisecond tick count
@@ -38,8 +39,13 @@ volatile uint64_t ticks_ms = 0;
void SysTick_Handler(void) {
// SysTick interrupt handler called when the SysTick timer reaches zero
// (every millisecond).
+ common_hal_mcu_disable_interrupts();
ticks_ms += 1;
+ // Read the control register to reset the COUNTFLAG.
+ (void) SysTick->CTRL;
+ common_hal_mcu_enable_interrupts();
+
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
@@ -61,7 +67,7 @@ void tick_delay(uint32_t us) {
uint32_t us_until_next_tick = SysTick->VAL / ticks_per_us;
uint32_t start_tick;
while (us >= us_until_next_tick) {
- start_tick=SysTick->VAL; // wait for SysTick->VAL to RESET
+ start_tick = SysTick->VAL; // wait for SysTick->VAL to RESET
while (SysTick->VAL < start_tick) {}
us -= us_until_next_tick;
us_until_next_tick = 1000;
@@ -72,11 +78,25 @@ void tick_delay(uint32_t us) {
// us counts down!
void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
- *ms = ticks_ms;
- *us_until_ms = SysTick->VAL / ticks_per_us;
+
+ // We disable interrupts to prevent ticks_ms from changing while we grab it.
+ common_hal_mcu_disable_interrupts();
+ uint32_t tick_status = SysTick->CTRL;
+ uint32_t current_us = SysTick->VAL;
+ uint32_t tick_status2 = SysTick->CTRL;
+ uint64_t current_ms = ticks_ms;
+ // The second clause ensures our value actually rolled over. Its possible it hit zero between
+ // the VAL read and CTRL read.
+ if ((tick_status & SysTick_CTRL_COUNTFLAG_Msk) != 0 ||
+ ((tick_status2 & SysTick_CTRL_COUNTFLAG_Msk) != 0 && current_us > ticks_per_us)) {
+ current_ms++;
+ }
+ common_hal_mcu_enable_interrupts();
+ *ms = current_ms;
+ *us_until_ms = current_us / ticks_per_us;
}
void wait_until(uint64_t ms, uint32_t us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
- while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
+ while (ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}
diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h
index 616e9875c..907a4cbdf 100644
--- a/ports/esp8266/mpconfigport.h
+++ b/ports/esp8266/mpconfigport.h
@@ -28,7 +28,7 @@
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
-#define MICROPY_USE_INTERNAL_ERRNO (1)
+#define MICROPY_USE_INTERNAL_ERRNO (0)
#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_BUILTINS_COMPLEX (0)
diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c
index 07b067a2c..7e92a84ff 100644
--- a/ports/nrf/common-hal/busio/I2C.c
+++ b/ports/nrf/common-hal/busio/I2C.c
@@ -32,7 +32,7 @@
#include "pins.h"
#include "nrf.h"
-void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency) {
+void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout ) {
if (scl->pin == sda->pin) {
mp_raise_ValueError("Invalid pins");
}
diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h
index ac5741f77..62e950430 100644
--- a/ports/nrf/mpconfigport.h
+++ b/ports/nrf/mpconfigport.h
@@ -82,7 +82,7 @@
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
-#define MICROPY_USE_INTERNAL_ERRNO (1)
+#define MICROPY_USE_INTERNAL_ERRNO (0)
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_STR_CENTER (0)
@@ -323,6 +323,7 @@ extern const struct _mp_obj_module_t ble_module;
struct _music_data_t *music_data; \
const struct _pwm_events *pwm_active_events; \
const struct _pwm_events *pwm_pending_events; \
+ mp_obj_t gamepad_singleton; \
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 5e11b8d18..cea87b181 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -700,6 +700,7 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_IndentationError), MP_ROM_PTR(&mp_type_IndentationError) },
{ MP_ROM_QSTR(MP_QSTR_IndexError), MP_ROM_PTR(&mp_type_IndexError) },
{ MP_ROM_QSTR(MP_QSTR_KeyboardInterrupt), MP_ROM_PTR(&mp_type_KeyboardInterrupt) },
+ { MP_ROM_QSTR(MP_QSTR_ReloadException), MP_ROM_PTR(&mp_type_ReloadException) },
{ MP_ROM_QSTR(MP_QSTR_KeyError), MP_ROM_PTR(&mp_type_KeyError) },
{ MP_ROM_QSTR(MP_QSTR_LookupError), MP_ROM_PTR(&mp_type_LookupError) },
{ MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_MemoryError) },
diff --git a/py/moduerrno.c b/py/moduerrno.c
index de66c941b..660fca07a 100644
--- a/py/moduerrno.c
+++ b/py/moduerrno.c
@@ -30,8 +30,6 @@
#include "py/obj.h"
#include "py/mperrno.h"
-#if MICROPY_PY_UERRNO
-
// This list can be defined per port in mpconfigport.h to tailor it to a
// specific port's needs. If it's not defined then we provide a default.
#ifndef MICROPY_PY_UERRNO_LIST
@@ -61,6 +59,8 @@
#endif
+#if MICROPY_PY_UERRNO
+
#if MICROPY_PY_UERRNO_ERRORCODE
STATIC const mp_rom_map_elem_t errorcode_table[] = {
#define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) },
@@ -100,6 +100,20 @@ const mp_obj_module_t mp_module_uerrno = {
};
qstr mp_errno_to_str(mp_obj_t errno_val) {
+ // For commonly encountered errors, return human readable strings
+ if (MP_OBJ_IS_SMALL_INT(errno_val)) {
+ switch (MP_OBJ_SMALL_INT_VALUE(errno_val)) {
+ case EPERM: return MP_QSTR_Permission_space_denied;
+ case ENOENT: return MP_QSTR_No_space_such_space_file_slash_directory;
+ case EIO: return MP_QSTR_Input_slash_output_space_error;
+ case EACCES: return MP_QSTR_Permission_space_denied;
+ case EEXIST: return MP_QSTR_File_space_exists;
+ case ENODEV: return MP_QSTR_Unsupported_space_operation;
+ case EINVAL: return MP_QSTR_Invalid_space_argument;
+ }
+ }
+
+ // Otherwise, return the Exxxx string for that error code
#if MICROPY_PY_UERRNO_ERRORCODE
// We have the errorcode dict so can do a lookup using the hash map
mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP);
@@ -119,4 +133,15 @@ qstr mp_errno_to_str(mp_obj_t errno_val) {
#endif
}
+#else //MICROPY_PY_UERRNO
+
+qstr mp_errno_to_str(mp_obj_t errno_val) {
+ int v = MP_OBJ_SMALL_INT_VALUE(errno_val);
+ #define X(e) if (v == e) return (MP_QSTR_ ## e);
+ MICROPY_PY_UERRNO_LIST
+ #undef X
+
+ return MP_QSTR_;
+}
+
#endif //MICROPY_PY_UERRNO
diff --git a/py/mperrno.h b/py/mperrno.h
index caac116ab..a028157ba 100644
--- a/py/mperrno.h
+++ b/py/mperrno.h
@@ -142,12 +142,6 @@
#endif
-#if MICROPY_PY_UERRNO
-
-#include "py/obj.h"
-
qstr mp_errno_to_str(mp_obj_t errno_val);
-#endif
-
#endif // MICROPY_INCLUDED_PY_MPERRNO_H
diff --git a/py/mpstate.h b/py/mpstate.h
index 19a5d711e..c50947066 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -136,6 +136,9 @@ typedef struct _mp_state_vm_t {
mp_obj_exception_t mp_kbd_exception;
#endif
+ // exception object of type ReloadException
+ mp_obj_exception_t mp_reload_exception;
+
// dictionary with loaded modules (may be exposed as sys.modules)
mp_obj_dict_t mp_loaded_modules_dict;
diff --git a/py/obj.h b/py/obj.h
index e4d950b97..d086d3c14 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -590,6 +590,7 @@ extern const mp_obj_type_t mp_type_ImportError;
extern const mp_obj_type_t mp_type_IndentationError;
extern const mp_obj_type_t mp_type_IndexError;
extern const mp_obj_type_t mp_type_KeyboardInterrupt;
+extern const mp_obj_type_t mp_type_ReloadException;
extern const mp_obj_type_t mp_type_KeyError;
extern const mp_obj_type_t mp_type_LookupError;
extern const mp_obj_type_t mp_type_MemoryError;
diff --git a/py/objexcept.c b/py/objexcept.c
index 4844c7f92..f0874df77 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -113,7 +113,6 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr
mp_print_str(print, "");
return;
} else if (o->args->len == 1) {
- #if MICROPY_PY_UERRNO
// try to provide a nice OSError error message
if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) {
qstr qst = mp_errno_to_str(o->args->items[0]);
@@ -122,7 +121,6 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr
return;
}
}
- #endif
mp_obj_print_helper(print, o->args->items[0], PRINT_STR);
return;
}
@@ -249,6 +247,7 @@ const mp_obj_type_t mp_type_ ## exc_name = { \
// http://docs.python.org/3/library/exceptions.html
MP_DEFINE_EXCEPTION(SystemExit, BaseException)
MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
+MP_DEFINE_EXCEPTION(ReloadException, BaseException)
MP_DEFINE_EXCEPTION(GeneratorExit, BaseException)
MP_DEFINE_EXCEPTION(Exception, BaseException)
#if MICROPY_PY_ASYNC_AWAIT
@@ -275,9 +274,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(UnboundLocalError, NameError)
*/
MP_DEFINE_EXCEPTION(OSError, Exception)
-#if MICROPY_PY_BUILTINS_TIMEOUTERROR
- MP_DEFINE_EXCEPTION(TimeoutError, OSError)
-#endif
+ MP_DEFINE_EXCEPTION(TimeoutError, OSError)
/*
MP_DEFINE_EXCEPTION(BlockingIOError, OSError)
MP_DEFINE_EXCEPTION(ChildProcessError, OSError)
diff --git a/py/py.mk b/py/py.mk
index 21f81c35d..e934c3a83 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -188,6 +188,7 @@ PY_O_BASENAME = \
objtype.o \
objzip.o \
opmethods.o \
+ reload.o \
sequence.o \
stream.o \
binary.o \
diff --git a/py/reload.c b/py/reload.c
new file mode 100644
index 000000000..95305f2c9
--- /dev/null
+++ b/py/reload.c
@@ -0,0 +1,16 @@
+//
+// Created by Roy Hooper on 2018-05-14.
+//
+
+#include "reload.h"
+#include "py/mpstate.h"
+
+void mp_raise_reload_exception(void) {
+ MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception));
+#if MICROPY_ENABLE_SCHEDULER
+ if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
+ MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
+ }
+#endif
+
+}
diff --git a/py/reload.h b/py/reload.h
new file mode 100644
index 000000000..72e84e5ca
--- /dev/null
+++ b/py/reload.h
@@ -0,0 +1,10 @@
+//
+// Created by Roy Hooper on 2018-05-14.
+//
+
+#ifndef CIRCUITPYTHON_RELOAD_H
+#define CIRCUITPYTHON_RELOAD_H
+
+void mp_raise_reload_exception(void);
+
+#endif //CIRCUITPYTHON_RELOAD_H
diff --git a/py/runtime.c b/py/runtime.c
index cbec82f17..a7ff57a47 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -84,6 +84,12 @@ void mp_init(void) {
MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
#endif
+ MP_STATE_VM(mp_reload_exception).base.type = &mp_type_ReloadException;
+ MP_STATE_VM(mp_reload_exception).traceback_alloc = 0;
+ MP_STATE_VM(mp_reload_exception).traceback_len = 0;
+ MP_STATE_VM(mp_reload_exception).traceback_data = NULL;
+ MP_STATE_VM(mp_reload_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
+
// call port specific initialization if any
#ifdef MICROPY_PORT_INIT_FUNC
MICROPY_PORT_INIT_FUNC;
diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c
index 3450b3971..36de117ac 100644
--- a/shared-bindings/audioio/AudioOut.c
+++ b/shared-bindings/audioio/AudioOut.c
@@ -80,7 +80,8 @@
//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
//| speaker_enable.switch_to_output(value=True)
//|
-//| wav = audioio.WaveFile("cplay-5.1-16bit-16khz.wav")
+//| data = open("cplay-5.1-16bit-16khz.wav", "rb")
+//| wav = audioio.WaveFile(data)
//| a = audioio.AudioOut(board.A0)
//|
//| print("playing")
diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c
index f8f60210e..a5c000ae5 100644
--- a/shared-bindings/bitbangio/I2C.c
+++ b/shared-bindings/bitbangio/I2C.c
@@ -35,6 +35,7 @@
#include "lib/utils/context_manager_helpers.h"
#include "py/mperrno.h"
#include "py/runtime.h"
+
//| .. currentmodule:: bitbangio
//|
//| :class:`I2C` --- Two wire serial protocol
@@ -49,6 +50,7 @@
//| :param ~microcontroller.Pin scl: The clock pin
//| :param ~microcontroller.Pin sda: The data pin
//| :param int frequency: The clock frequency of the bus
+//| :param int timeout: The maximum clock stretching timeout in microseconds
//|
STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
@@ -57,11 +59,12 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args,
self->base.type = &bitbangio_i2c_type;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
- enum { ARG_scl, ARG_sda, ARG_frequency };
+ enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -69,7 +72,7 @@ STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args,
assert_pin(args[ARG_sda].u_obj, false);
const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj);
const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
- shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int);
+ shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int);
return (mp_obj_t)self;
}
diff --git a/shared-bindings/bitbangio/I2C.h b/shared-bindings/bitbangio/I2C.h
index 9d393ee12..1ce4d21e9 100644
--- a/shared-bindings/bitbangio/I2C.h
+++ b/shared-bindings/bitbangio/I2C.h
@@ -39,7 +39,8 @@ extern const mp_obj_type_t bitbangio_i2c_type;
extern void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self,
const mcu_pin_obj_t * scl,
const mcu_pin_obj_t * sda,
- uint32_t frequency);
+ uint32_t frequency,
+ uint32_t us_timeout);
extern void shared_module_bitbangio_i2c_deinit(bitbangio_i2c_obj_t *self);
extern bool shared_module_bitbangio_i2c_deinited(bitbangio_i2c_obj_t *self);
diff --git a/shared-bindings/board/__init__.h b/shared-bindings/board/__init__.h
index 720239f28..2730e5f51 100644
--- a/shared-bindings/board/__init__.h
+++ b/shared-bindings/board/__init__.h
@@ -29,6 +29,8 @@
#include "py/obj.h"
+#include "shared-bindings/microcontroller/Pin.h" // for the pin definitions
+
extern const mp_obj_dict_t board_module_globals;
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BOARD___INIT___H
diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c
index b0954d6c8..0d21d30f0 100644
--- a/shared-bindings/busio/I2C.c
+++ b/shared-bindings/busio/I2C.c
@@ -56,6 +56,7 @@
//| :param ~microcontroller.Pin scl: The clock pin
//| :param ~microcontroller.Pin sda: The data pin
//| :param int frequency: The clock frequency in Hertz
+//| :param int timeout: The maximum clock stretching timeut - only for bitbang
//|
STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
@@ -63,11 +64,12 @@ STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
self->base.type = &busio_i2c_type;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
- enum { ARG_scl, ARG_sda, ARG_frequency };
+ enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -77,7 +79,7 @@ STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
assert_pin_free(scl);
const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj);
assert_pin_free(sda);
- common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int);
+ common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int);
return (mp_obj_t)self;
}
diff --git a/shared-bindings/busio/I2C.h b/shared-bindings/busio/I2C.h
index 7185d6075..739732e97 100644
--- a/shared-bindings/busio/I2C.h
+++ b/shared-bindings/busio/I2C.h
@@ -46,7 +46,8 @@ extern const mp_obj_type_t busio_i2c_type;
extern void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
const mcu_pin_obj_t * scl,
const mcu_pin_obj_t * sda,
- uint32_t frequency);
+ uint32_t frequency,
+ uint32_t timeout);
extern void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self);
extern bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self);
diff --git a/shared-bindings/gamepad/GamePad.c b/shared-bindings/gamepad/GamePad.c
index d80d1fcf6..1e95776d7 100644
--- a/shared-bindings/gamepad/GamePad.c
+++ b/shared-bindings/gamepad/GamePad.c
@@ -26,13 +26,15 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
+#include "py/gc.h"
+#include "py/mpstate.h"
+#include "shared-module/gamepad/__init__.h"
#include "shared-module/gamepad/GamePad.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/util.h"
#include "GamePad.h"
-gamepad_obj_t* gamepad_singleton = NULL;
-
//| .. currentmodule:: gamepad
//|
//| :class:`GamePad` -- Scan buttons for presses
@@ -93,18 +95,24 @@ gamepad_obj_t* gamepad_singleton = NULL;
//|
STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args,
size_t n_kw, const mp_obj_t *args) {
- if (!gamepad_singleton) {
- gamepad_singleton = m_new_obj(gamepad_obj_t);
- gamepad_singleton->base.type = &gamepad_type;
+ if (n_args > 8) {
+ mp_raise_TypeError("too many arguments");
}
for (size_t i = 0; i < n_args; ++i) {
if (!MP_OBJ_IS_TYPE(args[i], &digitalio_digitalinout_type)) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
- "Expected a %q", digitalio_digitalinout_type.name));
+ mp_raise_TypeError("expected a DigitalInOut");
}
+ digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(args[i]);
+ raise_error_if_deinited(
+ common_hal_digitalio_digitalinout_deinited(pin));
+ }
+ if (!MP_STATE_VM(gamepad_singleton)) {
+ gamepad_obj_t* gamepad_singleton = m_new_obj(gamepad_obj_t);
+ gamepad_singleton->base.type = &gamepad_type;
+ MP_STATE_VM(gamepad_singleton) = gc_make_long_lived(gamepad_singleton);
}
gamepad_init(n_args, args);
- return MP_OBJ_FROM_PTR(gamepad_singleton);
+ return MP_OBJ_FROM_PTR(MP_STATE_VM(gamepad_singleton));
}
@@ -119,9 +127,9 @@ STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args,
//| held down) can be recorded for the next call.
//|
STATIC mp_obj_t gamepad_get_pressed(mp_obj_t self_in) {
- gamepad_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_t gamepad = MP_OBJ_NEW_SMALL_INT(self->pressed);
- self->pressed = 0;
+ gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton);
+ mp_obj_t gamepad = MP_OBJ_NEW_SMALL_INT(gamepad_singleton->pressed);
+ gamepad_singleton->pressed = 0;
return gamepad;
}
MP_DEFINE_CONST_FUN_OBJ_1(gamepad_get_pressed_obj, gamepad_get_pressed);
@@ -132,14 +140,12 @@ MP_DEFINE_CONST_FUN_OBJ_1(gamepad_get_pressed_obj, gamepad_get_pressed);
//| Disable button scanning.
//|
STATIC mp_obj_t gamepad_deinit(mp_obj_t self_in) {
- gamepad_singleton = NULL;
+ gamepad_reset();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(gamepad_deinit_obj, gamepad_deinit);
-STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args,
- size_t n_kw, const mp_obj_t *args);
STATIC const mp_rom_map_elem_t gamepad_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_pressed), MP_ROM_PTR(&gamepad_get_pressed_obj)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gamepad_deinit_obj)},
diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst
index 76b5e340b..d98587880 100644
--- a/shared-bindings/index.rst
+++ b/shared-bindings/index.rst
@@ -17,6 +17,9 @@ SAMD51, SAMD51 Express, and ESP8266.
NOTE 2: **SAMD** and/or **SAMD Express** without additional numbers, means both SAMD21 & SAMD51 versions
are supported.
+NOTE 3: The `pIRkey SAMD21 board <https://www.adafruit.com/product/3364>`_ is specialized and may not
+have modules as listed below.
+
================= ==============================
Module Supported Ports
================= ==============================
@@ -38,6 +41,7 @@ Module Supported Ports
`os` **All Supported**
`pulseio` **SAMD/SAMD Express**
`random` **All Supported**
+`rotaryio` **SAMD51, SAMD Express**
`storage` **All Supported**
`struct` **All Supported**
`supervisor` **SAMD/SAMD Express**
diff --git a/shared-bindings/rotaryio/IncrementalEncoder.c b/shared-bindings/rotaryio/IncrementalEncoder.c
new file mode 100644
index 000000000..65d4ba98b
--- /dev/null
+++ b/shared-bindings/rotaryio/IncrementalEncoder.c
@@ -0,0 +1,168 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/runtime0.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/rotaryio/IncrementalEncoder.h"
+#include "shared-bindings/util.h"
+
+//| .. currentmodule:: rotaryio
+//|
+//| :class:`IncrementalEncoder` -- Track the relative position of an incremental encoder
+//| ====================================================================================
+//|
+//| IncrementalEncoder determines the relative rotational position based on two series of pulses.
+//|
+//| .. class:: IncrementalEncoder(pin_a, pin_b)
+//|
+//| Create an IncrementalEncoder object associated with the given pins. It tracks the positional
+//| state of an incremental rotary encoder (also known as a quadrature encoder.) Position is
+//| relative to the position when the object is contructed.
+//|
+//| :param ~microcontroller.Pin pin_a: First pin to read pulses from.
+//| :param ~microcontroller.Pin pin_b: Second pin to read pulses from.
+//|
+//| For example::
+//|
+//| import rotaryio
+//| import time
+//| from board import *
+//|
+//| enc = rotaryio.IncrementalEncoder(D1, D2)
+//| last_position = None
+//| while True:
+//| position = enc.position
+//| if last_position == None or position != last_position:
+//| print(position)
+//| last_position = position
+//|
+STATIC mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
+ mp_arg_check_num(n_args, n_kw, 2, 2, true);
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
+ enum { ARG_pin_a, ARG_pin_b };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_pin_a, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_pin_b, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ assert_pin(args[ARG_pin_a].u_obj, false);
+ const mcu_pin_obj_t* pin_a = MP_OBJ_TO_PTR(args[ARG_pin_a].u_obj);
+ assert_pin_free(pin_a);
+
+ assert_pin(args[ARG_pin_b].u_obj, false);
+ const mcu_pin_obj_t* pin_b = MP_OBJ_TO_PTR(args[ARG_pin_b].u_obj);
+ assert_pin_free(pin_b);
+
+ rotaryio_incrementalencoder_obj_t *self = m_new_obj(rotaryio_incrementalencoder_obj_t);
+ self->base.type = &rotaryio_incrementalencoder_type;
+
+ common_hal_rotaryio_incrementalencoder_construct(self, pin_a, pin_b);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitializes the IncrementalEncoder and releases any hardware resources for reuse.
+//|
+STATIC mp_obj_t rotaryio_incrementalencoder_deinit(mp_obj_t self_in) {
+ rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_rotaryio_incrementalencoder_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(rotaryio_incrementalencoder_deinit_obj, rotaryio_incrementalencoder_deinit);
+
+//| .. method:: __enter__()
+//|
+//| No-op used by Context Managers.
+//|
+// Provided by context manager helper.
+
+//| .. method:: __exit__()
+//|
+//| Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+STATIC mp_obj_t rotaryio_incrementalencoder_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_rotaryio_incrementalencoder_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rotaryio_incrementalencoder___exit___obj, 4, 4, rotaryio_incrementalencoder_obj___exit__);
+
+
+//| .. attribute:: position
+//|
+//| The current position in terms of pulses. The number of pulses per rotation is defined by the
+//| specific hardware.
+//|
+STATIC mp_obj_t rotaryio_incrementalencoder_obj_get_position(mp_obj_t self_in) {
+ rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_rotaryio_incrementalencoder_deinited(self));
+
+ return mp_obj_new_int(common_hal_rotaryio_incrementalencoder_get_position(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(rotaryio_incrementalencoder_get_position_obj, rotaryio_incrementalencoder_obj_get_position);
+
+STATIC mp_obj_t rotaryio_incrementalencoder_obj_set_position(mp_obj_t self_in, mp_obj_t new_position) {
+ rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_rotaryio_incrementalencoder_deinited(self));
+
+ common_hal_rotaryio_incrementalencoder_set_position(self, mp_obj_get_int(new_position));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(rotaryio_incrementalencoder_set_position_obj, rotaryio_incrementalencoder_obj_set_position);
+
+const mp_obj_property_t rotaryio_incrementalencoder_position_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&rotaryio_incrementalencoder_get_position_obj,
+ (mp_obj_t)&rotaryio_incrementalencoder_set_position_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t rotaryio_incrementalencoder_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rotaryio_incrementalencoder_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&rotaryio_incrementalencoder___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_position), MP_ROM_PTR(&rotaryio_incrementalencoder_position_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(rotaryio_incrementalencoder_locals_dict, rotaryio_incrementalencoder_locals_dict_table);
+
+const mp_obj_type_t rotaryio_incrementalencoder_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_IncrementalEncoder,
+ .make_new = rotaryio_incrementalencoder_make_new,
+ .locals_dict = (mp_obj_dict_t*)&rotaryio_incrementalencoder_locals_dict,
+};
diff --git a/shared-bindings/rotaryio/IncrementalEncoder.h b/shared-bindings/rotaryio/IncrementalEncoder.h
new file mode 100644
index 000000000..f70632aef
--- /dev/null
+++ b/shared-bindings/rotaryio/IncrementalEncoder.h
@@ -0,0 +1,43 @@
+/*
+ * 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_ROTARYIO_INCREMENTALENCODER_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO_INCREMENTALENCODER_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/rotaryio/IncrementalEncoder.h"
+
+extern const mp_obj_type_t rotaryio_incrementalencoder_type;
+
+extern void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t* self,
+ const mcu_pin_obj_t* pin_a, const mcu_pin_obj_t* pin_b);
+extern void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t* self);
+extern bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t* self);
+extern mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t* self);
+extern void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t* self,
+ mp_int_t new_position);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO_INCREMENTALENCODER_H
diff --git a/shared-bindings/rotaryio/__init__.c b/shared-bindings/rotaryio/__init__.c
new file mode 100644
index 000000000..a0166771a
--- /dev/null
+++ b/shared-bindings/rotaryio/__init__.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 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 <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/rotaryio/__init__.h"
+#include "shared-bindings/rotaryio/IncrementalEncoder.h"
+
+//| :mod:`rotaryio` --- Support for reading rotation sensors
+//| ========================================================
+//|
+//| .. module:: rotaryio
+//| :synopsis: Support for reading rotation sensors
+//| :platform: SAMD
+//|
+//| The `rotaryio` module contains classes to read different rotation encoding schemes. See
+//| `Wikipedia's Rotary Encoder page <https://en.wikipedia.org/wiki/Rotary_encoder>`_ for more
+//| background.
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| IncrementalEncoder
+//|
+
+//| .. warning:: This module is not available in some SAMD21 (aka M0) builds. See the
+//| :ref:`module-support-matrix` for more info.
+//|
+
+//| All classes change hardware state and should be deinitialized when they
+//| are no longer needed if the program continues after use. To do so, either
+//| call :py:meth:`!deinit` or use a context manager. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+
+STATIC const mp_rom_map_elem_t rotaryio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rotaryio) },
+ { MP_ROM_QSTR(MP_QSTR_IncrementalEncoder), MP_ROM_PTR(&rotaryio_incrementalencoder_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(rotaryio_module_globals, rotaryio_module_globals_table);
+
+const mp_obj_module_t rotaryio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&rotaryio_module_globals,
+};
diff --git a/shared-bindings/rotaryio/__init__.h b/shared-bindings/rotaryio/__init__.h
new file mode 100644
index 000000000..5d051d5a1
--- /dev/null
+++ b/shared-bindings/rotaryio/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft
+ *
+ * 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_ROTARYIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ROTARYIO___INIT___H
diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c
index a82459ad7..e6429be32 100644
--- a/shared-bindings/supervisor/__init__.c
+++ b/shared-bindings/supervisor/__init__.c
@@ -25,11 +25,16 @@
*/
#include "py/obj.h"
#include "py/runtime.h"
+ #include "py/reload.h"
+
+ #include "lib/utils/interrupt_char.h"
#include "supervisor/shared/autoreload.h"
+
#include "supervisor/shared/rgb_led_status.h"
#include "shared-bindings/supervisor/__init__.h"
#include "shared-bindings/supervisor/Runtime.h"
+
//| :mod:`supervisor` --- Supervisor settings
//| =================================================
//|
@@ -91,12 +96,25 @@ STATIC mp_obj_t supervisor_set_rgb_status_brightness(mp_obj_t lvl){
}
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_set_rgb_status_brightness);
+//| .. method:: reload()
+//|
+//| Reload the main Python code and run it (equivalent to hitting Ctrl-D at the REPL).
+//|
+STATIC mp_obj_t supervisor_reload(void) {
+ reload_requested = true;
+ mp_raise_reload_exception();
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);
+
+
STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) },
{ MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) },
};
STATIC MP_DEFINE_CONST_DICT(supervisor_module_globals, supervisor_module_globals_table);
diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c
index b4137706e..a105941c0 100644
--- a/shared-bindings/time/__init__.c
+++ b/shared-bindings/time/__init__.c
@@ -34,6 +34,8 @@
#include "shared-bindings/rtc/__init__.h"
#include "shared-bindings/time/__init__.h"
+#define EPOCH1970_EPOCH2000_DIFF_SECS 946684800
+
//| :mod:`time` --- time and timing related functions
//| ========================================================
//|
@@ -183,13 +185,14 @@ void struct_time_to_tm(mp_obj_t t, timeutils_struct_time_t *tm) {
// elems[8] tm_isdst is not supported
}
+#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
mp_obj_t MP_WEAK rtc_get_time_source_time(void) {
mp_raise_RuntimeError("RTC is not supported on this board");
}
//| .. method:: time()
//|
-//| Return the current time in seconds since since Jan 1, 2000.
+//| Return the current time in seconds since since Jan 1, 1970.
//|
//| :return: the current time
//| :rtype: int
@@ -197,17 +200,18 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) {
STATIC mp_obj_t time_time(void) {
timeutils_struct_time_t tm;
struct_time_to_tm(rtc_get_time_source_time(), &tm);
- mp_uint_t secs = timeutils_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, // mp_uint_t date
+ mp_uint_t secs = timeutils_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
- return mp_obj_new_int_from_uint(secs);
+ return mp_obj_new_int_from_uint(secs + EPOCH1970_EPOCH2000_DIFF_SECS);
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
//| .. method:: localtime([secs])
//|
-//| Convert a time expressed in seconds since Jan 1, 2000 to a struct_time in
+//| Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in
//| local time. If secs is not provided or None, the current time as returned
//| by time() is used.
+//| The earliest date for which it can generate a time is Jan 1, 2000.
//|
//| :return: the current time
//| :rtype: time.struct_time
@@ -217,8 +221,12 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
return rtc_get_time_source_time();
}
+ mp_int_t secs = mp_obj_int_get_checked(args[0]);
+ if (secs < EPOCH1970_EPOCH2000_DIFF_SECS)
+ mp_raise_msg(&mp_type_OverflowError, "timestamp out of range for platform time_t");
+
timeutils_struct_time_t tm;
- timeutils_seconds_since_2000_to_struct_time(mp_obj_get_int(args[0]), &tm);
+ timeutils_seconds_since_2000_to_struct_time(secs - EPOCH1970_EPOCH2000_DIFF_SECS, &tm);
return struct_time_from_tm(&tm);
}
@@ -247,11 +255,16 @@ STATIC mp_obj_t time_mktime(mp_obj_t t) {
mp_raise_TypeError("function takes exactly 9 arguments");
}
- return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),
- mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
+ if (mp_obj_get_int(elem[0]) < 2000)
+ mp_raise_msg(&mp_type_OverflowError, "timestamp out of range for platform time_t");
+
+ mp_uint_t secs = timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),
+ mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]));
+ return mp_obj_new_int_from_uint(secs + EPOCH1970_EPOCH2000_DIFF_SECS);
}
MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
-#endif
+#endif // MICROPY_LONGINT_IMPL
+#endif // MICROPY_PY_COLLECTIONS
STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) },
@@ -260,10 +273,14 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&time_sleep_obj) },
#if MICROPY_PY_COLLECTIONS
{ MP_ROM_QSTR(MP_QSTR_struct_time), MP_ROM_PTR(&struct_time_type_obj) },
+ #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
{ MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) },
{ MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) },
- #endif
+ #endif // MICROPY_LONGINT_IMPL
+ #endif // MICROPY_PY_COLLECTIONS
+ #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
diff --git a/shared-module/bitbangio/I2C.c b/shared-module/bitbangio/I2C.c
index 7eeda0e00..47529748a 100644
--- a/shared-module/bitbangio/I2C.c
+++ b/shared-module/bitbangio/I2C.c
@@ -25,16 +25,15 @@
*/
#include "shared-bindings/bitbangio/I2C.h"
-
#include "py/mperrno.h"
#include "py/obj.h"
+#include "py/runtime.h"
#include "common-hal/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-module/bitbangio/types.h"
-#define I2C_STRETCH_LIMIT 255
STATIC void delay(bitbangio_i2c_obj_t *self) {
// We need to use an accurate delay to get acceptable I2C
@@ -48,11 +47,16 @@ STATIC void scl_low(bitbangio_i2c_obj_t *self) {
STATIC void scl_release(bitbangio_i2c_obj_t *self) {
common_hal_digitalio_digitalinout_set_value(&self->scl, true);
+ uint32_t count = self->us_timeout;
delay(self);
// For clock stretching, wait for the SCL pin to be released, with timeout.
- for (int count = I2C_STRETCH_LIMIT; !common_hal_digitalio_digitalinout_get_value(&self->scl) && count; --count) {
+ for (; !common_hal_digitalio_digitalinout_get_value(&self->scl) && count; --count) {
common_hal_mcu_delay_us(1);
}
+ // raise exception on timeout
+ if (count == 0) {
+ mp_raise_msg(&mp_type_TimeoutError, "Clock stretch too long");
+ }
}
STATIC void sda_low(bitbangio_i2c_obj_t *self) {
@@ -142,7 +146,10 @@ STATIC bool read_byte(bitbangio_i2c_obj_t *self, uint8_t *val, bool ack) {
void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self,
const mcu_pin_obj_t * scl,
const mcu_pin_obj_t * sda,
- uint32_t frequency) {
+ uint32_t frequency,
+ uint32_t us_timeout) {
+
+ self->us_timeout = us_timeout;
self->us_delay = 500000 / frequency;
if (self->us_delay == 0) {
self->us_delay = 1;
diff --git a/shared-module/bitbangio/types.h b/shared-module/bitbangio/types.h
index dfe50f049..6d1723474 100644
--- a/shared-module/bitbangio/types.h
+++ b/shared-module/bitbangio/types.h
@@ -36,6 +36,7 @@ typedef struct {
digitalio_digitalinout_obj_t scl;
digitalio_digitalinout_obj_t sda;
uint32_t us_delay;
+ uint32_t us_timeout;
volatile bool locked;
} bitbangio_i2c_obj_t;
diff --git a/shared-module/busio/I2C.c b/shared-module/busio/I2C.c
index 68d6ea22a..06e1af10a 100644
--- a/shared-module/busio/I2C.c
+++ b/shared-module/busio/I2C.c
@@ -30,8 +30,8 @@
#include "py/nlr.h"
void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
- const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq) {
- shared_module_bitbangio_i2c_construct(&self->bitbang, scl, sda, freq);
+ const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq, uint32_t timeout) {
+ shared_module_bitbangio_i2c_construct(&self->bitbang, scl, sda, freq, timeout);
}
bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
diff --git a/shared-module/gamepad/GamePad.c b/shared-module/gamepad/GamePad.c
index cd1df9b57..2c14fa02a 100644
--- a/shared-module/gamepad/GamePad.c
+++ b/shared-module/gamepad/GamePad.c
@@ -26,6 +26,7 @@
#include <stdbool.h>
+#include "py/mpstate.h"
#include "__init__.h"
#include "GamePad.h"
@@ -35,17 +36,24 @@
void gamepad_init(size_t n_pins, const mp_obj_t* pins) {
- for (size_t i=0; i<8; ++i) {
+ gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton);
+ for (size_t i = 0; i < 8; ++i) {
gamepad_singleton->pins[i] = NULL;
}
- for (size_t i=0; i<n_pins; ++i) {
+ gamepad_singleton->pulls = 0;
+ for (size_t i = 0; i < n_pins; ++i) {
digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(pins[i]);
- raise_error_if_deinited(common_hal_digitalio_digitalinout_deinited(pin));
digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(pin);
- digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(pin);
- if (direction != DIRECTION_INPUT || pull == PULL_NONE) {
+ if (direction != DIRECTION_INPUT) {
common_hal_digitalio_digitalinout_switch_to_input(pin, PULL_UP);
}
+ digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(pin);
+ if (pull == PULL_NONE) {
+ common_hal_digitalio_digitalinout_set_pull(pin, PULL_UP);
+ }
+ if (pull != PULL_DOWN) {
+ gamepad_singleton->pulls |= 1 << i;
+ }
gamepad_singleton->pins[i] = pin;
}
gamepad_singleton->last = 0;
diff --git a/shared-module/gamepad/GamePad.h b/shared-module/gamepad/GamePad.h
index e5f709134..9fd5c9626 100644
--- a/shared-module/gamepad/GamePad.h
+++ b/shared-module/gamepad/GamePad.h
@@ -36,10 +36,9 @@ typedef struct {
digitalio_digitalinout_obj_t* pins[8];
volatile uint8_t last;
volatile uint8_t pressed;
+ uint8_t pulls;
} gamepad_obj_t;
-extern gamepad_obj_t* gamepad_singleton;
-
void gamepad_init(size_t n_pins, const mp_obj_t* pins);
#endif // MICROPY_INCLUDED_GAMEPAD_GAMEPAD_H
diff --git a/shared-module/gamepad/__init__.c b/shared-module/gamepad/__init__.c
index 591a2fa0a..8414ddfbe 100644
--- a/shared-module/gamepad/__init__.c
+++ b/shared-module/gamepad/__init__.c
@@ -26,6 +26,7 @@
#include <stdbool.h>
+#include "py/mpstate.h"
#include "__init__.h"
#include "GamePad.h"
@@ -33,25 +34,27 @@
void gamepad_tick(void) {
+ gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton);
if (!gamepad_singleton) {
return;
}
uint8_t gamepad_current = 0;
- for (int i=0; i<8; ++i) {
+ uint8_t bit = 1;
+ for (int i = 0; i < 8; ++i) {
digitalio_digitalinout_obj_t* pin = gamepad_singleton->pins[i];
if (!pin) {
break;
}
- digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(pin);
- bool value = common_hal_digitalio_digitalinout_get_value(pin);
- if ((pull == PULL_UP && !value) || (pull == PULL_DOWN && value)) {
- gamepad_current |= 1 << i;
+ if (common_hal_digitalio_digitalinout_get_value(pin)) {
+ gamepad_current |= bit;
}
+ bit <<= 1;
}
+ gamepad_current ^= gamepad_singleton->pulls;
gamepad_singleton->pressed |= gamepad_singleton->last & gamepad_current;
gamepad_singleton->last = gamepad_current;
}
void gamepad_reset(void) {
- gamepad_singleton = NULL;
+ MP_STATE_VM(gamepad_singleton) = NULL;
}
diff --git a/supervisor/shared/autoreload.c b/supervisor/shared/autoreload.c
index 39c33c05e..2a7fd1e9d 100644
--- a/supervisor/shared/autoreload.c
+++ b/supervisor/shared/autoreload.c
@@ -26,29 +26,29 @@
#include "autoreload.h"
-#include "lib/utils/interrupt_char.h"
#include "py/mphal.h"
+#include "py/reload.h"
volatile uint32_t autoreload_delay_ms = 0;
bool autoreload_enabled = false;
static bool autoreload_suspended = false;
-volatile bool reload_next_character = false;
+volatile bool reload_requested = false;
inline void autoreload_tick() {
if (autoreload_delay_ms == 0) {
return;
}
if (autoreload_delay_ms == 1 && autoreload_enabled &&
- !autoreload_suspended && !reload_next_character) {
- mp_keyboard_interrupt();
- reload_next_character = true;
+ !autoreload_suspended && !reload_requested) {
+ mp_raise_reload_exception();
+ reload_requested = true;
}
autoreload_delay_ms--;
}
void autoreload_enable() {
autoreload_enabled = true;
- reload_next_character = false;
+ reload_requested = false;
}
void autoreload_disable() {
@@ -73,5 +73,5 @@ void autoreload_start() {
void autoreload_stop() {
autoreload_delay_ms = 0;
- reload_next_character = false;
+ reload_requested = false;
}
diff --git a/supervisor/shared/autoreload.h b/supervisor/shared/autoreload.h
index 62f9fe073..bcb100151 100644
--- a/supervisor/shared/autoreload.h
+++ b/supervisor/shared/autoreload.h
@@ -29,7 +29,7 @@
#include <stdbool.h>
-extern volatile bool reload_next_character;
+extern volatile bool reload_requested;
void autoreload_tick(void);
diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c
index 8f1b506fe..584d021b0 100644
--- a/supervisor/shared/rgb_led_status.c
+++ b/supervisor/shared/rgb_led_status.c
@@ -27,7 +27,6 @@
#include "mphalport.h"
#include "common-hal/microcontroller/Pin.h"
#include "rgb_led_status.h"
-#include "pins.h"
#ifdef MICROPY_HW_NEOPIXEL
uint8_t rgb_status_brightness = 63;
diff --git a/tests/basics/errno1.py b/tests/basics/errno1.py
index 63930b767..bbbfac10c 100644
--- a/tests/basics/errno1.py
+++ b/tests/basics/errno1.py
@@ -11,7 +11,10 @@ print(type(uerrno.EIO))
# check that errors are rendered in a nice way
msg = str(OSError(uerrno.EIO))
-print(msg[:7], msg[-5:])
+print(msg[:7], msg[msg.find(']'):])
+
+msg = str(OSError(uerrno.ENOBUFS))
+print(msg[:7], msg[msg.find(']'):])
# check that unknown errno is still rendered
print(str(OSError(9999)))
diff --git a/tests/basics/errno1.py.exp b/tests/basics/errno1.py.exp
index c3703df4a..b5dd529e4 100644
--- a/tests/basics/errno1.py.exp
+++ b/tests/basics/errno1.py.exp
@@ -1,3 +1,4 @@
<class 'int'>
-[Errno ] EIO
+[Errno ] Input/output error
+[Errno ] ENOBUFS
9999
diff --git a/tests/pyboard.py b/tests/pyboard.py
index 3a82f6a6a..616773a31 120000
--- a/tests/pyboard.py
+++ b/tests/pyboard.py
@@ -1 +1 @@
-../tools/pyboard.py \ No newline at end of file
+../tools/cpboard.py \ No newline at end of file
diff --git a/tools/build_adafruit_bins.sh b/tools/build_adafruit_bins.sh
index 004877f8e..6ad085827 100755
--- a/tools/build_adafruit_bins.sh
+++ b/tools/build_adafruit_bins.sh
@@ -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 itsybitsy_m0_express itsybitsy_m4_express feather_m0_rfm69 feather_m0_rfm9x feather_m0_express feather_m4_express metro_m0_express metro_m4_express pirkey_m0 trinket_m0 gemma_m0 feather52"
+ATMEL_BOARDS="arduino_zero circuitplayground_express circuitplayground_express_crickit feather_m0_basic feather_m0_adalogger itsybitsy_m0_express itsybitsy_m4_express feather_m0_rfm69 feather_m0_rfm9x feather_m0_express feather_m0_express_crickit feather_m4_express metro_m0_express metro_m4_express pirkey_m0 trinket_m0 gemma_m0 feather52"
ROSIE_SETUPS="rosie-ci"
PARALLEL="-j 5"
diff --git a/tools/cpboard.py b/tools/cpboard.py
new file mode 100644
index 000000000..0b9c43c61
--- /dev/null
+++ b/tools/cpboard.py
@@ -0,0 +1,684 @@
+#!/usr/bin/env python3
+#
+# 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) 2018 Noralf Trønnes
+#
+# Parts taken from pyboard.py:
+# Copyright (c) 2014-2016 Damien P. George
+# Copyright (c) 2017 Paul Sokolovsky
+#
+# 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.
+
+import os
+import re
+import serial
+import sys
+import time
+
+import serial.tools.list_ports
+import sh
+import shutil
+
+class CPboardError(BaseException):
+ pass
+
+# supervisor/messages/default.h:
+MSG_NEWLINE = b"\r\n"
+MSG_SAFE_MODE_CRASH = b"Looks like our core CircuitPython code crashed hard. Whoops!"
+MSG_SAFE_MODE_BROWN_OUT_LINE_1 = b"The microcontroller's power dipped. Please make sure your power supply provides"
+MSG_SAFE_MODE_BROWN_OUT_LINE_2 = b"enough power for the whole circuit and press reset (after ejecting CIRCUITPY)."
+MSG_WAIT_BEFORE_REPL = b"Press any key to enter the REPL. Use CTRL-D to reload."
+
+class REPL:
+ CHAR_CTRL_A = b'\x01'
+ CHAR_CTRL_B = b'\x02'
+ CHAR_CTRL_C = b'\x03'
+ CHAR_CTRL_D = b'\x04'
+
+ def __init__(self, board):
+ self.board = board
+ self.write_chunk_size = 32
+ self.safe_mode = False
+ self.session = b''
+
+ def __enter__(self):
+ self.reset()
+ return self
+
+ def __exit__(self, exception_type, exception_value, traceback):
+ pass
+
+ @property
+ def serial(self):
+ return self.board.serial
+
+ def read(self):
+ if self.serial.inWaiting():
+ data = self.serial.read(self.serial.inWaiting())
+ else:
+ data = b''
+ self.session += data
+ return data
+
+ def read_until(self, ending, timeout=10):
+ data = b''
+ timeout_count = 0
+ while True:
+ if data.endswith(ending):
+ break
+ elif self.serial.inWaiting() > 0:
+ new_data = self.serial.read(1)
+ data += new_data
+ self.session += new_data
+ timeout_count = 0
+ else:
+ timeout_count += 1
+ if timeout is not None and timeout_count >= 100 * timeout:
+ raise TimeoutError(110, "timeout waiting for", ending)
+ time.sleep(0.01)
+ return data
+
+ def write(self, data, chunk_size=None):
+ if chunk_size is None:
+ chunk_size = self.write_chunk_size
+ if not isinstance(data, bytes):
+ data = bytes(data, encoding='utf8')
+
+ for i in range(0, len(data), chunk_size):
+ chunk = data[i:min(i + chunk_size, len(data))]
+ self.session += chunk
+ self.serial.write(chunk)
+ time.sleep(0.01)
+
+ def reset(self):
+ # Use read() since serial.reset_input_buffer() fails with termios.error now and then
+ self.read()
+ self.session = b''
+ self.write(b'\r' + REPL.CHAR_CTRL_C + REPL.CHAR_CTRL_C) # interrupt any running program
+ self.write(b'\r' + REPL.CHAR_CTRL_B) # enter or reset friendly repl
+ data = self.read_until(b'>>> ')
+
+ def execute(self, code, timeout=10, async=False):
+ self.read() # Throw away
+
+ self.write(REPL.CHAR_CTRL_A)
+ self.read_until(b'\r\n>')
+
+ self.write(code)
+
+ self.write(REPL.CHAR_CTRL_D)
+ if async:
+ return b'', b''
+ self.read_until(b'OK')
+
+ output = self.read_until(b'\x04', timeout=timeout)
+ output = output[:-1]
+
+ error = self.read_until(b'\x04')
+ error = error[:-1]
+
+ return output, error
+
+ def run(self):
+ if self.safe_mode:
+ raise RuntimeError("Can't run in safe mode")
+
+ self.reset()
+
+ self.write(REPL.CHAR_CTRL_D)
+ data = self.read_until(b' output:\r\n')
+ if b'Running in safe mode' in data:
+ self.safe_mode = True
+ raise RuntimeError("Can't run in safe mode")
+
+ # TODO: MSG_SAFE_MODE_CRASH
+ # TODO: BROWNOUT
+
+ marker = MSG_NEWLINE + MSG_WAIT_BEFORE_REPL + MSG_NEWLINE
+ data = self.read_until(marker)
+ data = data.split(marker)[0]
+
+ # Haven't found out why we have to strip off this...
+ if data.endswith(b'\r\n\r\n'):
+ data = data[:-4]
+ return data
+
+
+class Disk:
+ def __init__(self, dev):
+ self.dev = os.path.realpath(dev)
+ self.mountpoint = None
+ with open('/etc/mtab', 'r') as f:
+ mtab = f.read()
+ mount = [mount.split(' ') for mount in mtab.splitlines() if mount.startswith(self.dev)]
+ if mount:
+ self._path = mount[0][1]
+ else:
+ name = os.path.basename(dev)
+ sh.pmount("-tvfat", dev, name, _timeout=10)
+ self.mountpoint = "/media/" + name
+ self._path = self.mountpoint
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exception_type, exception_value, traceback):
+ try:
+ self.close()
+ except:
+ pass
+
+ @property
+ def path(self):
+ return self._path
+
+ def close(self):
+ if not self.mountpoint:
+ return
+ mountpoint = self.mountpoint
+ self.mountpoint = None
+
+ start_time = time.monotonic()
+ unmounted = False
+ while not unmounted and start_time - time.monotonic() < 30:
+ try:
+ sh.pumount(mountpoint)
+ unmounted = True
+ except sh.ErrorReturnCode_5:
+ time.sleep(0.1)
+
+ def sync(self):
+ disk_device = os.path.basename(self.dev)[:-1]
+ os.sync()
+ # Monitor the block device so we know when the sync request is actually finished.
+ with open("/sys/block/" + disk_device + "/stat", "r") as f:
+ disk_inflight = 1
+ last_wait_time = 0
+ wait_time = 1
+ while disk_inflight > 0 or wait_time > last_wait_time:
+ f.seek(0)
+ stats = f.read()
+ block_stats = stats.split()
+ disk_inflight = int(block_stats[8])
+ last_wait_time = wait_time
+ wait_time = int(block_stats[9])
+
+ def copy(self, src, dst=None, sync=True):
+ if dst is None:
+ dst = os.path.basename(src)
+ shutil.copy(src, os.path.join(self.path, dst))
+ if sync:
+ self.sync()
+
+
+class Firmware:
+ def __init__(self, board):
+ self.board = board
+
+ @property
+ def disk(self):
+ disks = self.board.get_disks()
+ if len(disks) != 1:
+ raise RuntimeError("Boot disk not found for: " + self.board.device)
+ return Disk(disks[0])
+
+ @property
+ def info(self):
+ with self.disk as disk:
+ fname = os.path.join(disk.path, 'INFO_UF2.TXT')
+ with open(fname, 'r') as f:
+ info = f.read()
+ lines = info.splitlines()
+ res = {}
+ res['header'] = lines[0]
+ for line in lines[1:]:
+ k, _, v = line.partition(':')
+ res[k.replace(':', '')] = v.strip()
+ return res
+
+ def upload(self, fw):
+ with open(fw, 'rb') as f:
+ header = f.read(32)
+ if header[0:4] != b'UF2\n':
+ raise ValueError('Only UF2 files are supported')
+ self.board.close()
+ with self.disk as disk:
+ disk.copy(fw, sync=False)
+
+
+class CPboard:
+ @classmethod
+ def from_try_all(cls, name, **kwargs):
+ try:
+ return CPboard.from_build_name(name, **kwargs)
+ except ValueError:
+ pass
+
+ vendor, _, product = name.partition(':')
+ if vendor and product:
+ return CPboard.from_usb(**kwargs, idVendor=int(vendor, 16), idProduct=int(product, 16))
+
+ return CPboard(name, **kwargs)
+
+ @classmethod
+ def from_build_name(cls, name, **kwargs):
+ boards = {
+ #'arduino_zero'
+ 'circuitplayground_express' : (0x239a, 0x8019),
+ #'feather_m0_adalogger' : (0x239a, ),
+ #'feather_m0_basic' : (0x239a, ),
+ 'feather_m0_express' : (0x239a, 0x8023),
+ #'feather_m0_rfm69' : (0x239a, ),
+ #'feather_m0_rfm9x' : (0x239a, ),
+ #'feather_m0_supersized' : (0x239a, ),
+ #'feather_m4_express' : (0x239a, ),
+ #'gemma_m0' : (0x239a, ),
+ #'itsybitsy_m0_express' : (0x239a, ),
+ #'itsybitsy_m4_express' : (0x239a, ),
+ 'metro_m0_express' : (0x239a, 0x8014),
+ 'metro_m4_express' : (0x239a, 0x8021),
+ #'metro_m4_express_revb' : (0x239a, ),
+ #'pirkey_m0' : (0x239a, ),
+ #'trinket_m0' : (0x239a, ),
+ #'trinket_m0_haxpress' : (0x239a, ),
+ #'ugame10'
+ }
+
+ try:
+ vendor, product = boards[name]
+ except KeyError:
+ raise ValueError("Unknown build name: " + name)
+
+ return CPboard.from_usb(**kwargs, idVendor=vendor, idProduct=product)
+
+ @classmethod
+ def from_build_name_bootloader(cls, name, **kwargs):
+ boards = {
+ #'arduino_zero'
+ #'circuitplayground_express' : (0x239a, ),
+ #'feather_m0_adalogger' : (0x239a, ),
+ #'feather_m0_basic' : (0x239a, ),
+ 'feather_m0_express' : (0x239a, 0x001b),
+ #'feather_m0_rfm69' : (0x239a, ),
+ #'feather_m0_rfm9x' : (0x239a, ),
+ #'feather_m0_supersized' : (0x239a, ),
+ #'feather_m4_express' : (0x239a, ),
+ #'gemma_m0' : (0x239a, ),
+ #'itsybitsy_m0_express' : (0x239a, ),
+ #'itsybitsy_m4_express' : (0x239a, ),
+ #'metro_m0_express' : (0x239a, 0x8014),
+ 'metro_m4_express' : (0x239a, 0x0021),
+ #'metro_m4_express_revb' : (0x239a, ),
+ #'pirkey_m0' : (0x239a, ),
+ #'trinket_m0' : (0x239a, ),
+ #'trinket_m0_haxpress' : (0x239a, ),
+ #'ugame10'
+ }
+
+ try:
+ vendor, product = boards[name]
+ except KeyError:
+ raise ValueError("Unknown build name: " + name)
+
+ board = CPboard.from_usb(**kwargs, idVendor=vendor, idProduct=product)
+ board.bootloader = True
+ return board
+
+ @classmethod
+ def from_usb(cls, baudrate=115200, wait=0, timeout=10, **kwargs):
+ import usb.core
+ dev = usb.core.find(**kwargs)
+ if not dev:
+ s = "Can't find USB device: "
+ args = []
+ for x in kwargs.items():
+ try:
+ args.append('%s=0x%x' % x)
+ except:
+ args.append('%s = %s' % x)
+ raise RuntimeError("Can't find USB device: " + ', '.join(args))
+ return cls(dev, baudrate=baudrate, wait=wait, timeout=timeout)
+
+ def __init__(self, device, baudrate=115200, wait=0, timeout=10):
+ self.device = device
+ self.usb_dev = None
+ try:
+ # Is it a usb.core.Device?
+ portstr = ':' + '.'.join(map(str, device.port_numbers)) + ':'
+ except:
+ pass
+ else:
+ serials = [serial for serial in os.listdir("/dev/serial/by-path") if portstr in serial]
+ if len(serials) != 1:
+ raise RuntimeError("Can't find excatly one matching usb serial device")
+ self.device = os.path.realpath("/dev/serial/by-path/" + serials[0])
+ self.usb_dev = device
+
+ self.baudrate = baudrate
+ self.wait = wait
+ self.timeout = timeout
+ self.debug = True
+ self.mount = None
+ self.serial = None
+ self.bootloader = False
+ self.repl = REPL(self)
+
+ def __enter__(self):
+ self.open()
+ return self
+
+ def __exit__(self, exception_type, exception_value, traceback):
+ self.close()
+
+ def open(self, baudrate=None, wait=None):
+ if self.serial:
+ return
+ if baudrate is None:
+ baudrate = self.baudrate
+ if wait is None:
+ wait = self.wait
+
+ delayed = False
+ for attempt in range(wait + 1):
+ try:
+ self.serial = serial.Serial(self.device, baudrate=self.baudrate, timeout=self.timeout, write_timeout=self.timeout, interCharTimeout=1)
+ break
+ except (OSError, IOError): # Py2 and Py3 have different errors
+ if wait == 0:
+ continue
+ if attempt == 0:
+ sys.stdout.write('Waiting {} seconds for board '.format(wait))
+ delayed = True
+ time.sleep(1)
+ sys.stdout.write('.')
+ sys.stdout.flush()
+ else:
+ if delayed:
+ print('')
+ raise CPboardError('failed to access ' + self.device)
+ if delayed:
+ print('')
+
+ def close(self):
+ if self.serial:
+ self.serial.close()
+ self.serial = None
+
+ def exec(self, command, timeout=10, async=False):
+ with self.repl as repl:
+ try:
+ output, error = repl.execute(command, timeout=timeout, async=async)
+ except OSError as e:
+ if self.debug:
+ print('exec: session: ', self.repl.session)
+ raise CPboardError('timeout', e)
+ if error:
+ raise CPboardError('exception', output, error)
+ return output
+
+ def eval(self, expression, timeout=10):
+ command = 'print({})'.format(expression)
+ with self.repl as repl:
+ output, error = repl.execute(command, timeout=timeout)
+ if error:
+ raise CPboardError('exception', output, error)
+ try:
+ res = eval(str(output, encoding='utf8'))
+ except:
+ raise CPboardError('failed to eval: %s' % output)
+ return res
+
+ def _reset(self, mode='NORMAL'):
+ self.exec("import microcontroller;microcontroller.on_next_reset(microcontroller.RunMode.%s)" % mode)
+ try:
+ self.exec("import microcontroller;microcontroller.reset()", async=True)
+ except OSError:
+ pass
+
+ def reset(self, safe_mode=False, delay=5, wait=10):
+ self._reset('SAFE_MODE' if safe_mode else 'NORMAL')
+ self.close()
+ time.sleep(delay)
+ self.open(wait)
+ time.sleep(delay)
+
+ def reset_to_bootloader(self, repl=False):
+ if repl:
+ self._reset('BOOTLOADER')
+ self.close()
+ else:
+ self.close()
+ s = serial.Serial(self.device, 1200, write_timeout=4, timeout=4)
+ s.close()
+
+ def get_port_info(self):
+ portinfo = None
+ for port_iter in serial.tools.list_ports.comports():
+ if port_iter.device == self.device:
+ portinfo = port_iter
+ break
+ return portinfo
+
+ @property
+ def serial_number(self):
+ try: # Permissions are needed to read the value
+ return self.usb_dev.serial_number
+ except:
+ pass
+ p = self.get_port_info()
+ return p.serial_number if p else None
+
+ def get_disks(self):
+ if self.usb_dev:
+ portstr = ':' + '.'.join(map(str, self.usb_dev.port_numbers)) + ':'
+ return ["/dev/disk/by-path/" + disk for disk in os.listdir("/dev/disk/by-path") if portstr in disk]
+ serial = self.serial_number
+ if not serial:
+ raise RuntimeError("Serial number not found for: " + self.device)
+ return ["/dev/disk/by-id/" + disk for disk in os.listdir("/dev/disk/by-id") if serial in disk]
+
+ @property
+ def disk(self):
+ disks = self.get_disks()
+
+ part = [part for part in disks if 'part1' in part]
+ if not part:
+ raise RuntimeError("Disk not found for: " + self.device)
+
+ return Disk(part[0])
+
+ @property
+ def firmware(self):
+ return Firmware(self)
+
+ def execfile_disk(self, filename):
+ with self.disk as disk:
+ disk.copy(filename, 'code.py')
+
+ with self.repl as repl:
+ try:
+ output = repl.run()
+ except OSError as e:
+ raise CPboardError('timeout', e)
+ except RuntimeError:
+ if self.repl.safe_mode:
+ raise PyboardError("Can't run in safe mode")
+ else:
+ raise
+
+ return output
+
+ def execfile(self, filename, timeout=10):
+ if os.environ.get('CPBOARD_EXEC_MODE') == 'disk':
+ return self.execfile_disk(filename)
+ else:
+ with open(filename, 'rb') as f:
+ pyfile = f.read()
+ return self.exec(pyfile, timeout=timeout)
+
+
+# Implement just enough to make tests/run-tests work
+PyboardError = CPboardError
+
+class Pyboard:
+ def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0):
+ self.board = CPboard.from_try_all(device, baudrate=baudrate, wait=wait)
+ with self.board.disk as disk:
+ disk.copy('skip_if.py')
+
+ def close(self):
+ self.board.close()
+
+ def enter_raw_repl(self):
+ self.board.open()
+
+ def execfile(self, filename):
+ return self.board.execfile(filename)
+
+
+def eval_namedtuple(board, command):
+ from collections import namedtuple
+ s = board.exec("print(%s)" % command)
+ s = s.decode().strip()
+ items = [key.split('=') for key in s[1:-1].split(', ')]
+ keys = [item[0] for item in items]
+ vals = [item[1] for item in items]
+ nt = namedtuple('eval', keys)
+ res = nt(*[eval(val) for val in vals])
+ return res
+
+
+def os_uname(board):
+ return eval_namedtuple(board, "__import__('os').uname()")
+
+def print_verbose(cargs, *args, **kwargs):
+ if cargs.verbose:
+ print(*args, flush=True, **kwargs)
+
+def upload(args):
+ try:
+ board = CPboard.from_build_name_bootloader(args.board)
+ print_verbose(args, 'Board is already in the bootloader')
+ except (ValueError, RuntimeError):
+ board = CPboard.from_try_all(args.board)
+
+ print_verbose(args, "Serial number :", board.serial_number)
+
+ if not (args.quiet or board.bootloader):
+ board.open()
+ print('Current version:', os_uname(board).version, flush=True)
+
+ if not board.bootloader:
+ print_verbose(args, 'Reset to bootloader...', end='')
+ board.reset_to_bootloader(repl=True) # Feather M0 Express doesn't respond to 1200 baud
+ time.sleep(5)
+ print_verbose(args, 'done')
+
+ print_verbose(args, 'Bootloader:', board.firmware.info)
+
+ print_verbose(args, 'Upload firmware...', end='')
+ board.firmware.upload(args.firmware)
+ print_verbose(args, 'done')
+
+ print_verbose(args, 'Wait for board...', end='')
+ time.sleep(5)
+ print_verbose(args, 'done')
+
+ if not args.quiet:
+ if board.bootloader:
+ board = CPboard.from_try_all(args.board)
+ board.open(wait=10)
+ print('New version:', os_uname(board).version, flush=True)
+
+def print_error_exit(args, e):
+ if args.debug:
+ return False
+ if not args.quiet:
+ print(e, file=sys.stderr)
+ sys.exit(1)
+
+def main():
+ import argparse
+ cmd_parser = argparse.ArgumentParser(description='Circuit Python Board Tool')
+ cmd_parser.add_argument('board', help='build_name, vid:pid or /dev/tty')
+ cmd_parser.add_argument('-f', '--firmware', help='upload UF2 firmware file')
+ cmd_parser.add_argument('-c', '--command', help='program passed in as string')
+ cmd_parser.add_argument('--tty', action='store_true', help='print tty')
+ cmd_parser.add_argument('--verbose', '-v', action='count', default=0, help='be verbose')
+ cmd_parser.add_argument('-q', '--quiet', action='store_true', help='be quiet')
+ cmd_parser.add_argument('--debug', action='store_true', help='raise exceptions')
+ args = cmd_parser.parse_args()
+
+ if args.quiet:
+ args.verbose = 0
+ args.debug = False
+
+ if args.firmware:
+ try:
+ upload(args)
+ except BaseException as e:
+ if not print_error_exit(args, e):
+ raise
+ sys.exit(0)
+
+ try:
+ board = CPboard.from_try_all(args.board)
+ except BaseException as e:
+ if not print_error_exit(args, e):
+ raise
+
+ if args.verbose:
+ exec_mode = os.environ.get('CPBOARD_EXEC_MODE')
+ if exec_mode:
+ print('CPBOARD_EXEC_MODE =', exec_mode)
+
+ # Make sure we can open serial
+ try:
+ with board:
+ pass
+ except BaseException as e:
+ if not print_error_exit(args, e):
+ raise
+
+ if args.tty:
+ print(board.device)
+ elif args.command:
+ with board as b:
+ print(b.eval(args.command))
+ else:
+ with board as b:
+ print('Device: ', end='')
+ if b.usb_dev:
+ print('%04x:%04x on ' % (b.usb_dev.idVendor, b.usb_dev.idProduct), end='')
+ print(b.device)
+ print('Serial number:', b.serial_number)
+ uname = os_uname(b)
+ print('os.uname:')
+ print(' sysname:', uname.sysname)
+ print(' nodename:', uname.nodename)
+ print(' release:', uname.release)
+ print(' version:', uname.version)
+ print(' machine:', uname.machine)
+
+if __name__ == "__main__":
+ main()