Compare commits

..

532 commits

Author SHA1 Message Date
Ha Thach
05e83bcb71
Merge pull request #373 from adafruit/add-issue-template
add issue template
2025-08-07 17:09:11 +07:00
hathach
0a48a55866
add issue template 2025-08-07 15:33:58 +07:00
Ha Thach
6653744ce4
Merge pull request #370 from adafruit/fix-TRRS-Trinkey-variant-name
fix variant folder name case for trrstrinkey_m0
2024-12-25 16:10:07 +07:00
hathach
592ec7707d
fix variant folder name case for trrstrinkey_m0 2024-12-25 15:06:00 +07:00
Mikey Sklar
bb552819ba
Pixel Trinkey Analog JST pin (#369)
Adding analog support to the 3-pin JST A6.
2024-09-18 13:54:26 -04:00
Ha Thach
8859387343
Merge pull request #367 from DennisErnst/master
Fix hangs when transfer errors occur
2024-09-05 19:00:38 +07:00
hathach
c8287a11c6
clean up format 2024-09-05 18:47:37 +07:00
Dennis Ernst
6e5580d9b2
Add files via upload 2024-07-21 10:50:03 -07:00
Dennis Ernst
ccfc7db988
Add files via upload 2024-07-18 12:43:41 -07:00
Ha Thach
ce20340620
Merge pull request #339 from yosinski/master
Add .ramfunc attribute to flash_with_bootloader.ld to enable keeping functions in RAM
2024-07-18 17:57:17 +07:00
Ha Thach
6ed425f871
Merge pull request #362 from nerdyscout/fix/update_TinyUSB
update to 3.1.5 of Adafruit TinyUSB
2024-07-18 17:47:55 +07:00
Liz
576d6271ed Revert "Merge pull request #363 from BlitzCityDIY/trrs_update"
This reverts commit e7a9d6d762, reversing
changes made to 9bb5b21093.
2024-06-25 19:14:24 -04:00
Liz
726453fa91 Revert "Merge pull request #364 from BlitzCityDIY/master"
This reverts commit 3044845d73, reversing
changes made to e7a9d6d762.
2024-06-25 19:14:19 -04:00
Liz
3044845d73
Merge pull request #364 from BlitzCityDIY/master
two more TRRS
2024-06-25 18:59:56 -04:00
Liz
12e2013e2b two more TRRS 2024-06-25 18:52:49 -04:00
e7a9d6d762
Merge pull request #363 from BlitzCityDIY/trrs_update
updating TRRS Trinkey naming for case sensitivity
2024-06-25 16:21:58 -05:00
Liz
463eb00619 updating TRRS Trinkey naming for case sensitivity 2024-06-25 16:30:51 -04:00
nerdyscout
c0c7bd0bcb update to 3.1.5 2024-06-10 13:29:54 +02:00
Ha Thach
9bb5b21093
Merge pull request #361 from adafruit/bump-1.7.16
bump up version 1.7.16
2024-05-22 09:52:13 +07:00
Ha Thach
3a527f8e85
bump up version 1.7.16 2024-05-22 09:45:15 +07:00
ladyada
7473729af3 Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2024-05-21 20:23:06 -04:00
ladyada
b64fe90c4a fix for rev B hardware
cc @blitzcitydiy
2024-05-21 20:23:02 -04:00
Ha Thach
4693b93d69
Merge pull request #360 from adafruit/minor-update
update makeboards.py, fix board name typo
2024-05-17 10:09:16 +07:00
hathach
ffb6935392
update makeboards.py, fix board name typo 2024-05-17 09:58:01 +07:00
Ha Thach
9dc3465b47
Merge pull request #359 from adafruit/bump-version-1.7.15
bump up version to 1.7.15
2024-05-17 09:38:04 +07:00
hathach
61da91c518
bump up version to 1.7.15 2024-05-17 09:24:46 +07:00
Ha Thach
ac9e81e58e
Merge pull request #358 from rcross-lc/master
Use the correct openocd flash driver for ATSAMD51 devices
2024-05-15 16:54:15 +07:00
ladyada
72e88b41ea many variant trinks! 2024-05-11 13:10:07 -04:00
ladyada
5a5790412c hardware design rev B 2024-05-11 13:09:32 -04:00
Robert Cross
634b97cc40 Use the correct openocd flash driver for ATSAMD51 devices
see openocd docs ( https://github.com/openocd-org/openocd/blob/v0.11.0/doc/openocd.texi#L5827C1-L5827C54 )
2024-05-09 16:44:23 -04:00
Liz
b2358faa51
increase version for 1.7.14 release 2024-03-26 08:38:21 -04:00
Liz
1a8763701d
Merge pull request #355 from adafruit/sht4xtrinkey
Tested SHT4x Trinkey
2024-03-25 08:22:29 -04:00
hathach
e82192ca1a
update makeboards.py 2024-03-13 17:42:41 +07:00
ladyada
9b1b3ba02d Tested SHT4x Trinkey 2024-03-05 11:00:29 -05:00
Ha Thach
0bf32589c9
Merge pull request #328 from caternuson/iss320_dotstar
add PIN_DOTSTAR_CLOCK
2024-03-05 12:58:34 +07:00
Ha Thach
e43b1ef3aa
Merge pull request #347 from IanBurwell/ib/pyportal-ss-fix
PyPortal: fix SS pin definition
2024-03-05 12:58:12 +07:00
Ha Thach
4c6cc0ef6f
Merge pull request #354 from adafruit/update-tinyusb
Update tinyusb to v3.1
2024-03-05 12:56:23 +07:00
hathach
c1b79a8231
udpate tinyusb to v3.1 2024-03-05 12:44:54 +07:00
Ha Thach
767168482d
Merge pull request #353 from adafruit/update-libraries
update tinyusb and zerodma libraries
2024-02-06 16:17:17 +07:00
hathach
8619fd9190 update tinyusb and zerodma libraries 2024-02-06 15:22:24 +07:00
Ha Thach
21ac7624c9
Merge pull request #351 from adafruit/fix-sendStringDescriptor
fix sendStringDescriptor() maxlen uitn8_t to uint32_t
2023-11-27 18:32:44 +07:00
hathach
f85cf1b8a3 fix sendStringDescriptor() maxlen uitn8_t to uint32_t 2023-11-27 11:54:09 +07:00
Ha Thach
e2b78cbd36
Merge pull request #348 from adafruit/hathach-patch-1
increase version for release 1.7.13
2023-06-23 10:48:43 +07:00
Ha Thach
eebe841a7d
increase version for release 1.7.13 2023-06-23 10:41:05 +07:00
Ha Thach
164decde3b
Merge pull request #346 from adafruit/ide2-debug
Arduino IDE v2 debuging suport
2023-06-23 10:38:54 +07:00
hathach
bc76c89c90 explicit specify openocd 0.11.0-arduino2 2023-06-23 09:55:55 +07:00
Ian Burwell
b0322762a5 pyportal: add SS pin 2023-06-22 20:34:16 -04:00
hathach
df5b8c6054 comment out jlink over openocd since IDE does not pick that up and could cause questions 2023-06-22 23:28:21 +07:00
hathach
c3d53add36 add support for jlink as transport for openocd
though menu selection does not seem to work with debug script. Though
this is probably IDE issue.
2023-06-22 23:05:24 +07:00
hathach
c9e285c482 fix ci, rename script 2023-06-22 19:19:18 +07:00
hathach
41cd7a70e1 adding samd51 debug, still wip 2023-06-22 16:42:55 +07:00
hathach
463beee02d debug work with itsybitsy and pico probe 2023-06-22 12:25:24 +07:00
hathach
2f8f40c05c more script update 2023-06-21 23:07:26 +07:00
hathach
ef8903ac8e move makboards.py scripts tools/, refactor to use f-string 2023-06-21 21:34:19 +07:00
Ha Thach
313ef47993
Merge pull request #344 from adafruit/release-1.7.12
fix incorrect PID for pIRKey board (conflict with M0 trinket)
2023-05-23 11:14:01 +07:00
hathach
c307d378eb
fix incorrect PID for pIRKey board (conflict with M0 trinket) 2023-05-23 10:12:41 +07:00
dherrada
159e3c31ed Update CI action versions 2023-05-12 11:24:12 -04:00
Jason Yosinski
a6b4ae7738 Added .ramfunc attribute to linker script to enable keeping functions in RAM. 2022-12-20 11:27:08 -08:00
Ha Thach
0fd44a54b7
Merge pull request #278 from rlcamp/master
Fix typo in samd51 clock init which was preventing XOSC1K from being used in RTCCTRL
2022-11-15 09:24:47 +07:00
Ha Thach
7812526590
Merge pull request #338 from rlcamp/ltofix
Prevent LTO from omitting the ISR vector table
2022-11-15 09:02:35 +07:00
Richard Campbell
7ca484ac85 Prevent LTO from omitting the ISR vector table for SAMD21 too 2022-11-13 22:13:30 -08:00
Richard Campbell
88bafcc09e Prevent LTO from omitting the ISR vector table 2022-11-13 10:53:59 -08:00
rlcamp
22176f8c20
Merge branch 'adafruit:master' into master 2022-11-13 10:35:57 -08:00
Ha Thach
024eaa50d1
Merge pull request #337 from adafruit/release-1.7.11
Remove ARDUINO_SAMD_ZERO for some boards
2022-11-01 12:09:42 +07:00
hathach
66ebeeb4dc
bump version to 1.7.11 2022-11-01 11:51:41 +07:00
hathach
7c47afb817
remove ARDUINO_SAMD_ZERO from some boards due to fastled issue 2022-11-01 11:51:14 +07:00
hathach
ad12ce969f fix possible windows bossac tool 2022-10-12 21:42:23 +07:00
Tim Vrakas
c2d4153929
Proposal to improve WVariant part number define logic (#326)
* add ethernet interupt dummy handler

* fix timer definitions for -N and -P SAMx5x parts
2022-07-31 23:38:27 -04:00
Ha Thach
bd2a9cdbe7
change the SDA, SCL timer from alt to primary to avoid pwm conflict (#331) 2022-06-05 16:49:30 -04:00
caternuson
b13ae7f0b7 add PIN_DOTSTAR_CLOCK 2022-03-23 11:43:51 -07:00
Ha Thach
137b8d2de0
fix typo board defines for feather m0 express (#325) 2022-03-08 14:24:19 -05:00
Ha Thach
85f71fb7c1
Merge pull request #324 from adafruit/release-1.7.10
increase verion to 1.7.10
2022-02-17 17:07:05 +07:00
hathach
ada1b9d9d3 increase verion to 1.7.10
bump up included tinyusb to 1.9.4
2022-02-17 16:54:43 +07:00
Ha Thach
81f9ee0889
Merge pull request #323 from adafruit/revert-bossac-to-1.8
revert bossac tool from 1.9 back to 1.8
2022-02-06 00:39:01 +07:00
hathach
327fbceb48 revert bossac tool from 1.9 back to 1.8
move blm badge up in boards.txt, update id for portal m4
2022-02-04 12:12:52 +07:00
Kattni
d4ed1fd456
Merge pull request #321 from caternuson/iss320_dotstar
Add defines for internal DotStar pins
2022-01-26 18:50:42 -05:00
caternuson
dd787f583c paran u 2022-01-26 15:23:50 -08:00
caternuson
6398c2a1ac add dotstar pin defs 2022-01-26 15:19:30 -08:00
Ha Thach
2a7aae79ee
Update makeboards.py 2022-01-27 01:15:58 +07:00
Ha Thach
d8893ff12f
Merge pull request #319 from adafruit/bossac-1.9
migrate all boards upload tool from bossac 1.8 to 1.9 and auto-generate boards.txt
2022-01-27 01:15:03 +07:00
hathach
5528bf224f add makeboard.py to genearte boards.txt to prevent error in board addition 2022-01-26 17:25:48 +07:00
hathach
6bc12c92fe
migrate all boards from bossac 1.8 to 1.9 2022-01-25 22:03:49 +07:00
Ha Thach
67dfb93a4a
migrate all m0 upload tool to bossac 1.8 (#318) 2022-01-14 16:59:59 -05:00
Ha Thach
c999601efc
increase version to 1.7.7 for release 2022-01-13 11:42:21 +07:00
Ha Thach
3f214fea3b
Merge pull request #317 from adafruit/more-bossac18
update bossac18 for neokey, neo, rotary, slide trinkey m0
2022-01-13 11:27:05 +07:00
hathach
53248609ec
update bossac18 for neokey, neo, rotary, slide trinkey m0
also add fake SPI interfaces for them as well
2022-01-13 11:04:19 +07:00
Ha Thach
525980e0ee
Prepare BSP for Internal Flash filesystem (#316)
* update upload tool for adafruit_proxlighttrinkey_m0 to bossac18

* fake SPI Interface so we could compile with SdFat
2022-01-12 13:34:27 -05:00
hathach
90b4d35236
increase version 1.7.6 for release 2022-01-10 22:46:08 +07:00
Ha Thach
9785217e25
Merge pull request #315 from adafruit/add-Werror=return-type
add -Werror=return-type for all warning options
2022-01-07 02:19:25 +07:00
hathach
bac2839448 add -Werror=return-type for all warning options 2022-01-06 18:20:59 +07:00
ladyada
a8c4b4d8e3 Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2022-01-04 13:50:18 -05:00
ladyada
3db7484736 'hot fix' for https://github.com/arduino-libraries/WiFiNINA/issues/184 2022-01-04 13:50:14 -05:00
Ha Thach
e669a01bc1
Merge pull request #314 from prampec/patch-1
Introduce digital pin definitions
2021-12-21 12:24:25 +07:00
Balázs Kelemen
e715d707ef
Introduce digital pin definitions
Pin definitions are based on the schematics.
2021-12-20 23:20:19 +01:00
Ha Thach
1710c41552
enable DRVSTR for output pin (#313)
add neopixel and button pin define for circuitplay
2021-12-13 22:58:26 -05:00
Ha Thach
41c0a72f37
Merge pull request #310 from MartinL1/master
Add int64_t and uint64_t data types to Serial.print(ln)
2021-10-01 15:21:57 +07:00
hathach
6f5a596b31
indentation 2021-10-01 14:58:17 +07:00
MartinL1
3b2df62575
Update Print.cpp 2021-09-30 12:27:12 +01:00
MartinL1
6907751dd1
Update Print.h 2021-09-30 12:25:26 +01:00
Ha Thach
8b70e4c252
Merge pull request #309 from zuyan9/master
Bugfix - waiting for first ADC read to complete after ADC enable.
2021-09-17 17:38:54 +07:00
Zuyang
6ddfddf877
Bugfix - waiting for first ADC read to complete after ADC enable. 2021-09-15 19:14:42 -04:00
Ha Thach
bafcb36c19
bump up version for release 1.7.5 2021-09-01 12:27:38 +07:00
Ha Thach
11b223acef
Merge pull request #308 from adafruit/more-m4-can-typo
fix m4 can typo
2021-08-31 22:28:27 +07:00
hathach
e24e4af26b
fix m4 can typo 2021-08-31 22:15:41 +07:00
Ha Thach
1b17683575
increase version for 1.7.4 release 2021-08-17 11:38:02 +07:00
Ha Thach
46e2271984
fix m4 can pin typo (#307)
also bump up tinyusb lib
2021-08-16 11:56:21 -04:00
Ha Thach
de975d929c
Merge pull request #306 from 2bndy5/global-define-for-any-adafruit-boards
add -DADAFRUIT_ARCH_SAMD to all board's build.extra_flags
2021-07-16 00:19:08 +07:00
Brendan
42d3ad1e0b requested changes 2021-07-15 00:20:52 -07:00
Brendan
a02b851395 add -DADAFRUIT_ARCH_SAMD to all board's build.extra_flags 2021-07-14 18:45:39 -07:00
hathach
f5564f85f1 bump TinyUSB to 1.3.0 2021-06-29 11:55:50 +07:00
hathach
2163aa82fe
bump tinyusb 2021-06-26 01:38:30 +07:00
Ha Thach
203746757a
Update tinyusb library to compatible with 1.2.0 (#303)
* more Adafruit_TinyUSB include

* add metro m0 m4 with tinyusb to ci

* correct fqbn

* support ci with tinyusb variant

bump zeroDMA and fix warnings with USBHost library example

* install missing libraries

* more libraries

* update tinyusb library to 1.2.0

increase version to 1.7.3
2021-06-25 10:08:33 -04:00
Ha Thach
4e51791226
Merge pull request #301 from adafruit/more-ci-work
More ci work
2021-05-26 13:13:26 +07:00
hathach
aff98b3875
increase version 1.7.2 for release 2021-05-26 12:54:37 +07:00
hathach
3c601b613e
bump builtin TinyUSB to 1.0.3 2021-05-26 10:05:12 +07:00
hathach
481e4920dd
always build with all warnings, but not fatal error 2021-05-25 22:37:20 +07:00
hathach
8c2dd0b682
bump zeroDMA 2021-05-25 22:01:22 +07:00
hathach
9c2bdbc314
include TinyUSB header for builtin libraries if selected 2021-05-25 18:30:09 +07:00
hathach
69a2211b81
add Adafruit_ZeroDMA as submodules 2021-05-25 18:04:21 +07:00
hathach
14a6b40ed9
remove local copy of Adafruit_ZeroDMA 2021-05-25 18:03:58 +07:00
Ha Thach
cca8448cfe
Merge pull request #300 from adafruit/fix-warnings
Fix warnings
2021-05-24 23:41:00 +07:00
hathach
33a1e15fb0 increase version to 1.7.1 2021-05-24 23:33:50 +07:00
hathach
e49dab6406 also bump tinyusb 2021-05-24 23:33:24 +07:00
hathach
51bd7a7967 better fix warning with "-Wclass-memaccess" in SPI 2021-05-24 21:31:52 +07:00
hathach
a7a8b02854 use CMSIS-Atmel-1.2.2 to fix LITTLE_ENDIAN warning 2021-05-24 20:44:16 +07:00
Ha Thach
fa24f50fb4
increase version to 1.7.0 for release 2021-05-19 13:24:46 +07:00
Ha Thach
7585cb7b76
Merge pull request #298 from adafruit/rework-tinyusb
Rework tinyusb lib
2021-05-19 13:23:48 +07:00
lady ada
32b62c86ff add AREF pin as A12 2021-05-18 11:13:01 -04:00
hathach
461f855940 ci skip tinyusb lib examples for now 2021-05-18 21:24:48 +07:00
hathach
a7bab5b591 update tinyusb lib to 1.0.0 2021-05-18 17:35:49 +07:00
ladyada
93b1ba1e4a A11 isnt an analog in! 2021-05-14 16:34:46 -04:00
lady ada
322f2ff8c9 add definition for touchpad 2021-05-13 10:12:18 -04:00
hathach
a9d41b6019 fix typo in tinyusb lib 2021-05-10 19:11:44 +07:00
hathach
c262dc2ff9 clean up and add note for "-Wclass-memaccess" 2021-05-10 19:06:44 +07:00
Ha Thach
48956ddef8
increase version for release 1.6.8 2021-05-10 18:23:18 +07:00
hathach
7234390bc1
sync tinyusb lib 2021-05-10 17:16:42 +07:00
hathach
3c173d5d19
update with TinyUSB_Device_FlushCDC() 2021-05-10 12:52:55 +07:00
hathach
30d0738262 sync with tinyusb lib latest change 2021-05-10 12:22:18 +07:00
Limor "Ladyada" Fried
c26a8371f9
Trinkeys (#296)
* add rotary trinkey rev B

* add slide trinkey

* proximity sensing trinkey

* update variant to shipping

* forgot one!

* fix two typos

* fix up slide trinkey for rev B
2021-05-08 16:28:31 -04:00
hathach
704450cc1c
add libraries/Adafruit_TinyUSB_Arduino as submodule
include Adafruit_USBD_CDC.h from submodule
2021-05-08 01:08:31 +07:00
hathach
15fd604313 clean up 2021-05-07 17:30:00 +07:00
hathach
88520ba975 update tinyusb header 2021-05-07 14:49:02 +07:00
hathach
1f029ece68 fix typo 2021-05-07 00:30:15 +07:00
hathach
6fd7609c6e add feather m4 can to ci 2021-05-07 00:15:08 +07:00
hathach
d3091df758
change porting API 2021-05-06 21:47:26 +07:00
hathach
fc358eaf65
remove tinyusb core submodule, move tinyusb src to its own library to reduce dependency 2021-05-06 16:03:34 +07:00
Henry Gabryjelski
439c6b51c9
Narrowly silence new (GCC 8.1+) warning (#290)
Fixes #287

The warnings look like:
```
      Line 338 Char 37
      warning: 'void* memcpy(void*, const void*, size_t)' 
               writing to an object of type 'struct DmacDescriptor'
               with no trivial copy-assignment [-Wclass-memaccess]
```
2021-04-30 11:42:15 -04:00
Ha Thach
ade7cafbae
Merge pull request #289 from henrygab/patch-2
Fix [-Wrestrict] bug
2021-04-13 12:46:32 +07:00
hathach
ea208a42b2
use correct CMSIS-Atmel-1.2.1.path 2021-04-09 14:07:30 +07:00
Ha Thach
dffa5b8acd
Merge pull request #291 from adafruit/use-same51-from-cmsis-atmel-tool
Use same51 from cmsis atmel tool
2021-04-09 13:52:16 +07:00
hathach
c47727252c
increase version to 1.6.7 2021-04-09 13:50:15 +07:00
hathach
1870cefd75
use same51 header from cmsis-atmel package 2021-04-09 13:33:17 +07:00
Henry Gabryjelski
a7a9d2dbc1
Fix loop iterations 2021-04-08 17:51:06 -07:00
Ha Thach
e3407013a8
Merge pull request #288 from henrygab/patch-1
Cast to integral type ignores qualifier `volatile`
2021-03-30 01:01:41 +07:00
Henry Gabryjelski
76f999b825
Fix [-Wrestrict] bug
Untested...
2021-03-25 15:09:54 -07:00
Henry Gabryjelski
d542a60ae6
Cast to integral type ignores qualifier volatile
Attempting to cast to a `volatile uint32_t` does nothing different from cast to a `uint32_t`,
with the exception of **_looking like_** it's accessing a register.
2021-03-25 14:52:25 -07:00
Ha Thach
243c208b22
bump version for 1.6.6 release 2021-03-15 23:40:24 +07:00
Ha Thach
9e15226813
Merge pull request #286 from adafruit/neotrinkey
add new variant
2021-03-15 23:22:22 +07:00
lady ada
af4f2cb75c typo fixes! 2021-03-15 12:13:48 -04:00
lady ada
3adf881254 add new variant 2021-03-14 17:22:49 -04:00
Phillip Pearson
aebf3cb686
Port some AVR Serial_ (SerialUSB) API's over (#285)
Co-authored-by: Sandeep Mistry <s.mistry@arduino.cc>
2021-03-06 11:56:47 -05:00
Ha Thach
e16a55ba0b
Merge pull request #281 from matt-chan/patch-1
Fix EINT listing for pin 4
2021-01-26 11:31:46 +07:00
lady ada
8dcab42ce3 bump to add fixes for CAN Feather and BLM Badge 2021-01-25 20:07:13 -05:00
lady ada
7716ebbcd6 update BLM badge for uart (used in testing) 2021-01-25 14:40:44 -05:00
Matthew Chan
8c6f2dd466
Fix remaining EINT values
Add additional EINT fixes for PA{0,1,30}, PB{3, 23}.
2021-01-25 13:12:49 -05:00
Matthew Chan
aa706d706d
Fix EINT listing for pin 4
I think this file doesn't match the circuit diagram listing at https://cdn-learn.adafruit.com/assets/assets/000/047/156/original/circuit_playground_Adafruit_Circuit_Playground_Express_Pinout.png?1507829017.

It causes the interrupt pin checking code in ArduinoLowPower to fail, meaning it won't listen to interrupts from button A. Button B works fine.
2021-01-25 03:07:12 -05:00
lady ada
812399fe45 Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2021-01-10 17:26:12 -05:00
lady ada
9ddc306013 CAN variant updates, fix for PDM on badge 2021-01-10 17:26:07 -05:00
Paint Your Dragon
12e0a79fea
Merge pull request #279 from RudolphRiedel/master
Added a isBusy() method to SPI calls to allow non-blocking polling of…
2020-12-28 11:46:52 -08:00
Rudolph Riedel
3c7a2d5bad Added a isBusy() method to SPI calls to allow non-blocking polling of the DMA transfer status. 2020-12-28 13:51:55 +01:00
Richard Campbell
146e8b8e53 Fix typo in samd51 clock init 2020-12-27 00:52:53 -08:00
Valerii Koval
dcc531f963
Typo fix in PID for BLM Badge (#274) 2020-12-10 14:38:38 -05:00
Limor "Ladyada" Fried
f2a72d1c1e
Fix addpath (#275)
* try it!
2020-12-10 14:25:11 -05:00
lady ada
ec69488b42 add boost enable pin for CAN feather 2020-12-01 20:12:05 -05:00
Ha Thach
1fa45ad6a6
update version to 1.6.4 for release 2020-11-05 22:43:46 +07:00
Limor "Ladyada" Fried
0b160161de
Merge pull request #270 from mdonoughe/matrixportal-led
update LED_BUILTIN for matrixportal_m4
2020-10-31 17:20:42 -04:00
Matthew Donoughe
b8235856be update LED_BUILTIN for matrixportal_m4 2020-10-31 16:16:44 -04:00
Limor "Ladyada" Fried
d0396b05ce
Merge pull request #269 from adafruit/m0-optimization-option
added optimization menu option for M0
2020-10-31 11:46:57 -04:00
hathach
54beccb9b4 added optimization menu option for M0 2020-10-31 14:39:22 +07:00
Limor "Ladyada" Fried
b94b432dad
Merge pull request #267 from jepler/feather-can-bsp
Adafruit Feather M4 CAN: Add support for board
2020-10-20 15:23:57 -04:00
da80034588 Add CAN handlers for SAM E51 2020-10-20 08:55:53 -05:00
3471cdffa4 update feather can board property 2020-10-08 21:04:11 -05:00
f077606591 correct board name string 2020-10-07 14:03:21 -05:00
3ab4dfe9de feather_can_m4: define PIN_CAN_abc macros 2020-10-07 13:29:44 -05:00
308e949881 feather_m4_can: Add CAN-related pins to variant files
40: CAN_STANDBY
41: CAN_TX
42: CAN_RX
2020-10-07 12:50:07 -05:00
ad022b412a Add special linker script stanza for CAN message RAM 2020-10-06 11:48:55 -05:00
7ae96b4323 Adapt feather_m4 variant files to can 2020-10-06 11:42:24 -05:00
1ffdc7d0f0 Files from Atmel.SAME51_DFP.1.1.139.atpack 2020-10-06 11:42:08 -05:00
0c8e1ede52 boards.txt: add Feather CAN 2020-10-06 10:47:41 -05:00
lady ada
4c6d754c50 fix https://github.com/adafruit/ArduinoCore-samd/issues/266 2020-10-01 16:18:06 -04:00
lady ada
fa095b35c0 Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2020-09-28 20:23:35 -04:00
Ha Thach
9d4bdb8a01
increase for 1.6.3 release 2020-09-23 10:27:54 +07:00
Limor "Ladyada" Fried
9c667a4409
Merge pull request #265 from adafruit/fix-warning
fix matrixportal_m4 warning define
2020-09-22 23:26:08 -04:00
Ha Thach
e99eb502ae
Merge pull request #264 from adafruit/qtpy
QT Py!
2020-09-23 10:23:39 +07:00
hathach
a2151f384e fix matrixportal_m4 warning define 2020-09-23 10:15:49 +07:00
lady ada
0d46fb5839 fix name of chip 2020-09-22 23:07:48 -04:00
lady ada
4a5f9f7aae add custom init code for neopixel power pin to default on 2020-09-22 22:48:50 -04:00
lady ada
bdd8ee911b rev C complete! 2020-09-22 22:41:26 -04:00
lady ada
a029d61925 Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2020-09-19 17:22:08 -04:00
lady ada
fad2d91143 increase serial buffer (helps with bno08x uart!) 2020-09-19 17:22:03 -04:00
Ha Thach
6a59e8347d
Merge pull request #262 from adafruit/update-tinyusb
update tinyusb core
2020-09-15 23:50:03 +07:00
Limor "Ladyada" Fried
e6c07cc7d0
Merge pull request #263 from ulysse314/adafruit-master
Avoiding unused parameter warning for dmaDoNothingCallback()
2020-09-15 10:51:59 -04:00
moussaillon
814a352588 Avoiding unused parameter warning for dmaDoNothingCallback() 2020-09-15 16:32:21 +02:00
hathach
4888cdc958 update tinyusb core to commit e7b892095f2bb5d8bef6a748238369bdd268ed5e 2020-09-15 20:59:46 +07:00
hathach
a0d7cfdebc update tinyusb core to commit 0328bd4c134d05b4bb0472e0db918153f4dd15dd
also set string descriptor for Serial CDC
2020-09-15 19:41:28 +07:00
lady ada
bdf5ac8117 fix some pin numbers so that there's an LED on pin 13
add external SPI
2020-09-13 17:08:19 -04:00
lady ada
28cbc716e4 test external SPI flash + I2S 2020-09-13 00:15:00 -04:00
lady ada
028ca90052 rev A variant 2020-09-12 17:21:18 -04:00
Ha Thach
9ba4e98237
Increase version for release 1.6.2 2020-09-08 10:34:51 +07:00
Limor "Ladyada" Fried
8d3b49bf39
Merge pull request #259 from adafruit/matrixportal
Matrix portal draft
2020-09-03 23:30:44 -04:00
lady ada
c044ba3929 add bootloader 2020-08-31 11:57:49 -04:00
lady ada
9827155244 oof bad merge 2020-08-30 15:36:21 -04:00
lady ada
287d079c4d Merge remote-tracking branch 'origin/master' into matrixportal 2020-08-30 14:03:12 -04:00
Limor "Ladyada" Fried
d1c52f223b
Merge pull request #258 from adafruit/blmbadge
add blm badge
2020-08-30 13:44:48 -04:00
lady ada
1ba7379107 add blm badge 2020-08-30 13:25:44 -04:00
lady ada
66097a89e7 add fake LED 2020-08-30 13:19:38 -04:00
lady ada
731adc71be add variant 2020-08-29 02:39:04 -04:00
lady ada
1264ec61d7 Merge branch 'master' into matrixportal 2020-08-29 00:49:38 -04:00
Ha Thach
83b63b1e83
Merge pull request #257 from adafruit/fix-tone
Fix tone on SAMD51
2020-08-29 00:20:13 +07:00
hathach
aa5fa81bb7 use TC1 for servo, TC0 for tone for samd51
- make Tone_Handler() a strong symbol
2020-08-28 14:41:48 +07:00
Phillip Burgess
1e92424a50 Obscure SPI DMA bug fixed. Also, big non-blocking transfers supported. 2020-08-20 20:22:39 -07:00
Ha Thach
37a6ab97fa
Merge pull request #196 from ulysse314/unusedvariable
Removing _dacResolution for __SAMD51__ is not defined (variable not used)
2020-08-20 13:23:37 +07:00
Ha Thach
94e908c453
Merge branch 'master' into unusedvariable 2020-08-20 10:57:40 +07:00
Phillip Burgess
420b9a8429 Small SPI lib fix, add SWO pin to variant header 2020-08-19 11:36:20 -07:00
Ha Thach
fd40287bcb
Merge pull request #207 from henrygab/fix_compile_warnings3
Improve build script & fix more warnings
2020-08-10 14:12:13 +07:00
Henry Gabryjelski
66b0a74073 Use FIXME instead of BUGBUG 2020-08-09 23:50:13 -07:00
Henry Gabryjelski
55a9930808 reduce affected area of diagnostic push/pop 2020-08-07 11:28:53 -07:00
Henry Gabryjelski
134ebe7e18 typo - missing semicolon 2020-08-06 16:11:10 -07:00
Henry Gabryjelski
528a25e0ab @hathach is uncomfortable with attributes on function parameters 2020-08-05 21:27:36 -07:00
Henry Gabryjelski
adc0866b7d Hathach doesn't like attributes on parameters 2020-08-05 01:54:03 -07:00
Henry Gabryjelski
eb3c11472c Revert "TEST: Is LITTLE_ENDIAN already properly defined?"
This reverts commit 5cbfd74f4d.
2020-08-04 21:08:58 -07:00
Henry Gabryjelski
77321a6827 Merge branch 'fix_compile_warnings3' of https://github.com/henrygab/ArduinoCore-samd into fix_compile_warnings3 2020-08-03 20:43:25 -07:00
Henry Gabryjelski
a2801a1602 fix tab/space mixtures -- whitespace only change 2020-08-03 20:43:13 -07:00
Henry Gabryjelski
25a57896c0
Merge branch 'master' into fix_compile_warnings3 2020-08-03 17:09:31 -07:00
Henry Gabryjelski
00dd2e0097 Per @hathach request 2020-08-03 17:06:51 -07:00
Limor "Ladyada" Fried
ea9f1a5d28
Merge pull request #243 from nekuneko/patch-1
Enable Interrupt #8 on Pin PORTA28 (GPIO2)
2020-07-27 10:38:03 -04:00
Neku
b1572ceb25
Enable Interrupt #8 on Pin PORTA28 (GPIO2)
In order to use IRLibRecvPCI class from IRLib2 with Adafruit pIRKey, it's necessary to allow interrupts on this pin.
2020-07-27 02:21:31 +02:00
lady ada
0947169772 add blm badge 2020-07-25 17:21:05 -04:00
Ha Thach
d9e9508be4
Merge pull request #242 from adafruit/fix-extint-m4
Fix extint m4
2020-07-25 00:14:20 +07:00
hathach
76f0206f01 fix all other incorrect EXTINT 2020-07-24 23:05:48 +07:00
hathach
860bc6c6b9 fix EXTINT for PA4 and PA6
follow up to #239
2020-07-24 19:05:16 +07:00
Ha Thach
3f0f35fbc5
Merge pull request #239 from NanoCodeBug/patch-1
Fix external pin interrupt definitions for Feather M4
2020-07-24 17:00:43 +07:00
Ha Thach
4141fce796
Merge pull request #241 from adafruit/sync-tinyusb-238a5c0b95fcd402d24524c7bebbdd822168a51e
Sync with Adafruit_TinyUSB_ArduinoCore
2020-07-24 02:01:06 +07:00
hathach
2555c2d68a
sync with Adafruit_TinyUSB_ArduinoCore commit 238a5c0b95fcd402d24524c7bebbdd822168a51e 2020-07-23 07:02:41 +07:00
NanoCodeBug
57db4d7132
Fix external pin interrupt definitions for Feather M4
Spent a while trying to figure out why analog pins A4/18 and A5/19 where not working as interrupts, turns out the external interrupt definitions are wrong in-code. These fixed definitions now match the published pinout diagram for the feather m4 and the samd51 datasheet.
2020-07-21 22:07:38 -07:00
Ha Thach
50f9be1544
increase 1.6.1 for release 2020-07-21 18:37:20 +07:00
Limor "Ladyada" Fried
4b669eadb0
Merge pull request #235 from hathach/fix-ci-build
move test_cmsis_fast_rfft example to its own folder to fix ci build
2020-07-13 08:21:17 -04:00
hathach
2569103e1a move test_cmsis_fast_rfft example to its own folder to fix ci build 2020-07-13 18:26:29 +07:00
Ha Thach
196a29fc90
Merge pull request #232 from hathach/update-toolchain-cmsis
Update toolchain cmsis, fix build with tensorflow
2020-07-07 11:06:21 +07:00
Ha Thach
53c92d46e9
Increase version to 1.6.0 per review 2020-07-07 09:37:15 +07:00
hathach
290f3d6308
update cmsis from 4.5.0 to 5.4.0 2020-07-06 16:22:30 +07:00
hathach
246c75a1ae
bump up version for 1.5.15 2020-07-05 22:57:40 +07:00
hathach
00a863c100
update tinyusb to 0749077 2020-07-05 22:57:02 +07:00
hathach
ff82b735f2
remove gcc 7-2017q4 specific 2020-07-05 22:40:37 +07:00
lady ada
fdddb19a3c add BLE uart test support 2020-06-23 14:57:52 -04:00
Limor "Ladyada" Fried
bdf0c84109
Merge pull request #227 from OPEnSLab-OSU/master
Fix I2C SERCOM Hang (from Arduino SAMD core)
2020-05-28 22:06:27 -04:00
Noah Laptop
dad77cd8cc add SERCOM patch from arduino SAMD core 2020-05-28 17:20:30 -07:00
Ha Thach
52d793ed8e
release 1.5.14
fix samd21 USB IRQ typo,
2020-05-04 22:11:14 +07:00
Ha Thach
e607c3ddbe
Merge pull request #226 from hathach/fix-samd21-usb
fix incorrect USB IRQ typo for samd
2020-05-04 22:09:56 +07:00
hathach
6d6e5b1ee9 fix incorrect USB IRQ typo for samd 2020-05-04 22:00:22 +07:00
Ha Thach
d60ec0fae3
Merge pull request #224 from hathach/release-.1.5.13
Update TinyUSB to commit c59fa77 due to a bug in the stack
2020-04-24 00:09:34 +07:00
hathach
159ae8e550 Update TinyUSB to commit c59fa77 due to a bug in the stack
increase version 1.5.13
2020-04-23 23:44:46 +07:00
Ha Thach
d56901d13b
increase version to release 1.5.12 2020-04-22 11:41:28 +07:00
Ha Thach
a45b5c56f6
Merge pull request #221 from hathach/update-tinyusb
update tinyusb core and samd port
2020-04-22 11:30:28 +07:00
Ha Thach
6c2a982c35
Merge pull request #222 from versioduo/midi-buffer-size
tinyusb: MIDI - Increase buffer size
2020-04-22 11:08:16 +07:00
Kay Sievers
aa9792167d tinyusb: MIDI - Increase buffer size
We only transfer new packets when 64 bytes are available in the FIFO
buffer. This increase the buffer, so we can receive the next new packet
while still processing the current one.
2020-04-21 20:28:02 +02:00
hathach
72ebc1a809 sync with tinyusb commit 1d33aa9
fix issue with MIDI sysex driver
2020-04-22 00:20:50 +07:00
hathach
f564235648 update tinyusb core and samd port 2020-04-21 12:05:51 +07:00
Limor "Ladyada" Fried
bf24e95f7e
Merge pull request #217 from d-a-v/wless
less warnings on featherM0
2020-03-05 15:09:32 -05:00
David Gauchard
1112d77c3d less warnings on featherM0 2020-03-05 18:25:12 +01:00
Ha Thach
aa21fb1e13
increase version 1.5.11 for release 2020-02-27 00:09:20 +07:00
Limor "Ladyada" Fried
18e455f2df
Merge pull request #214 from hathach/fix-CI_Tests-warning
add fake CI_Tests.h header to make Arduino happy
2020-02-10 22:18:40 -05:00
hathach
bfba9812b7 add fake CI_Tests.h header to make Arduino happy 2020-02-11 10:10:12 +07:00
Limor "Ladyada" Fried
5b24029000
Merge pull request #211 from GMagician/Fix-AGCM4-total-pins
[AGCM4] Update total pins
2020-02-08 19:21:30 -05:00
GMagician
a5271b3d1c Update total pins
pin 95 is onboard SD detect. Real total pins is then 96 not 95
2020-02-08 23:42:15 +01:00
Ha Thach
b13e6c68b5
Update platform.txt
Increase version for release 1.5.10
2020-02-03 14:23:30 +07:00
Ha Thach
f55ecadb78
Merge pull request #210 from adafruit/flashdefines
Flashdefines
2020-02-03 10:26:14 +07:00
Lady Ada
b09a92698a & circuitplay too! 2020-02-01 22:00:17 -05:00
Lady Ada
6be91634fd add flash definitions 2020-02-01 21:59:12 -05:00
Henry Gabryjelski
12c4506437 Improve variant compliance
Starting in SAMD CORE 1.6.6, `digitalPinToInterrupt`
was moved to Arduino.h, variant.h must no longer define it.
2020-01-17 01:16:20 -08:00
Henry Gabryjelski
c68c0b19ae Disable -Wimplicit-fallthrough in sections
These two files contain code with switch statements,
where one case "fall through" to the next case.
As it's not currently clear if this is intentional or not,
rather than modifying the code in any way (regression risk),
use GCC diagnostic pragmas to disable this warning for
only these two files, with BUGBUG marking to encourage
review by someone more familiar with this code.
2020-01-17 01:16:20 -08:00
Henry Gabryjelski
5cbfd74f4d TEST: Is LITTLE_ENDIAN already properly defined? 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
1a89b145ef Enhance warning output.
Add comment to line GCC points finger at.
This is not intended to fix the warning.
Rather, it is intended to make it clearer
that this may need a deeper review before
determining what (if any) code change would
be appropriate.
2020-01-17 01:16:20 -08:00
Henry Gabryjelski
e1e7b37ff3 Disable -Wimplicit-fallthrough for these two files.
These two files contain code with multiple switch statements,
where one case "fall through" to the next case.
As it's not currently clear if this is intentional or not,
rather than modifying the code in any way (regression risk),
use GCC diagnostic pragmas to disable this warning for
only these two files, with BUGBUG marking to encourage
review by someone more familiar with this code.
2020-01-17 01:16:20 -08:00
Henry Gabryjelski
4276526c67 Avoid compiler warning for unused parameter 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
a2dd8614d4 Avoid signed/unsigned comparison warning. 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
3253d46f45 Avoid unused parameter compiler warnings 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
d5935a8c51 remove 'unused parameter' compiler warning 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
4f80972c23 cast to uint32_t to avoid compiler warning
that said, it's possible this api might return
a variety of non-zero codes.  code could benefit
from being updated (e.g., documenting return codes)
2020-01-17 01:16:20 -08:00
Henry Gabryjelski
9ab68e1aff avoid warnings on unused parameter 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
155cbc5262 Friendlier name for -Wall build 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
622d9f6183 re-enable builds with all warnings 2020-01-17 01:16:20 -08:00
Henry Gabryjelski
cb97944642 Can we mark jobs as allowed to fail? 2020-01-17 01:16:20 -08:00
Limor "Ladyada" Fried
bee96c4a80
Merge pull request #206 from henrygab/fix_compile_warnings
Fix compile warnings
2020-01-16 21:16:54 -05:00
Henry Gabryjelski
8afd0523b1 Fix unintended fall-through
The compiler found this, not me.  Building with
all warnings enabled is recommended.
2020-01-16 16:15:34 -08:00
Henry Gabryjelski
52c988fea0 Mark unused parameters as such. 2020-01-16 16:14:30 -08:00
Henry Gabryjelski
70d3c1dbfe Fix warnings about redefinition of LITTLE_ENDIAN
For safety, this fix also validates that, if
`LITTLE_ENDIAN` was already defined, that it
was defined to have the same value that the
code sets this to.
2020-01-16 16:11:40 -08:00
Limor "Ladyada" Fried
330cb4e652
Merge pull request #202 from rlcamp/master
Force linker to use newer Arduino-provided versions of libarm_cortexM4lf_math.a
2020-01-07 00:01:56 -05:00
rlcamp
34013bfd63
Update boards.txt
Added extra space to force rerun of CI
2020-01-06 20:47:02 -08:00
Lady Ada
1df7e524ed add math linker test! 2020-01-06 23:34:20 -05:00
rlcamp
460b1c2249 Force linker to use newer Arduino-provided versions of libarm_cortexM4lf_math.a 2020-01-06 19:52:07 -08:00
Lady Ada
4cc3251b02 Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2020-01-06 22:35:55 -05:00
Lady Ada
ed2dded753 fix https://github.com/adafruit/ArduinoCore-samd/issues/187 2020-01-06 22:35:49 -05:00
Limor "Ladyada" Fried
c14e07828f
Merge pull request #200 from hathach/action-ci
Add action ci to build examples in libraries folder that comes with BSP
2020-01-02 14:05:29 -05:00
hathach
f2a21265b3 add action badge to readme 2020-01-02 17:24:17 +07:00
hathach
2cc7f72400 drop monster_m4sk 2020-01-02 17:17:30 +07:00
hathach
bab8b92f60 add skip file 2020-01-02 17:08:26 +07:00
hathach
c53c44331e build most of adafruit samd boards 2020-01-02 17:03:44 +07:00
hathach
9d9b509084 add metro_m4 test 2020-01-02 13:07:55 +07:00
hathach
1595e2f59b update lib deps 2020-01-02 12:53:46 +07:00
hathach
90c0b48235 add build all script 2020-01-02 12:47:54 +07:00
hathach
411cfa6d9a test metro_m0 build 2020-01-02 12:45:43 +07:00
Ha Thach
137c0bdf9f
increase version to 1.5.9 for release 2019-12-31 11:52:56 +07:00
Ha Thach
18b64d471f
Merge pull request #199 from hathach/develop
revert 6630fe7 availableForWrite() return int
2019-12-31 11:52:08 +07:00
hathach
fc737be24e revert 6630fe7cc0 availableForWrite() return int 2019-12-31 11:44:26 +07:00
Ha Thach
32e5394aea
Increase version for release 2019-12-30 15:55:52 +07:00
moussaillon
99f1fa3de8 Removing _dacResolution for no-__SAMD51__ (variable not used) 2019-12-29 02:29:16 +01:00
Ha Thach
2bf2a37784
Merge pull request #194 from hathach/develop
improve tinyusb samd driver
2019-12-27 11:17:42 +07:00
hathach
2ca9dfd40e
update tinyusb core 2019-12-27 11:15:59 +07:00
hathach
8e3c4bcaac
improve tinyusb samd driver 2019-12-26 23:00:37 +07:00
Ha Thach
1dcf3c53ed
Merge pull request #193 from hathach/develop
tinyusb core: improve setup handling
2019-12-25 23:19:02 +07:00
hathach
2179f63a97 tinyusb core: improve setup handling 2019-12-25 10:50:37 +07:00
Ha Thach
b1a79758ee
Merge pull request #192 from hathach/develop
update tinyusb
2019-12-24 22:22:14 +07:00
hathach
861fec5dbd update tinyusb core 2019-12-24 21:43:26 +07:00
hathach
31fc54d037 added option to debug tinyusb with Serial1 2019-12-24 16:03:23 +07:00
Limor "Ladyada" Fried
1941e1717a
Merge pull request #190 from hathach/develop
refactor tinyusb core
2019-12-20 12:30:38 -05:00
hathach
f996c946f3
clean up 2019-12-20 13:15:01 +07:00
hathach
21b3e13b70
update tinyusb core 2019-12-20 13:11:04 +07:00
hathach
bffd3048d7
clean up 2019-12-20 00:13:24 +07:00
hathach
dd19013a79
rename Adafruit_TinyUSB_Core.cpp to Adafruit_TinyUSB_SAMD.cpp 2019-12-20 00:11:19 +07:00
hathach
4f8ccb165c
move yield() to main.cpp 2019-12-19 23:54:15 +07:00
hathach
b92b61b36f
refactor load_serial_number() to Adafruit_USBD_Device::getSerialDescriptor() 2019-12-19 23:42:27 +07:00
hathach
a346cf760f
implement detach/attach 2019-12-19 23:12:25 +07:00
hathach
2bb0a7a759
tinyusb submodule work well 2019-12-19 14:49:53 +07:00
hathach
dfac9e8582
move tinyusb core & cdc to submodule 2019-12-19 13:25:36 +07:00
hathach
4cca5de20a Merge remote-tracking branch 'adafruit/master' 2019-12-18 22:27:22 +07:00
Lady Ada
516cec5a9b Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2019-12-10 22:41:17 -05:00
Lady Ada
6630fe7cc0 @hathach Arduino core now wants size_t returned 2019-12-10 22:41:12 -05:00
hathach
5f68c65680
Merge pull request #182 from kaysievers/tinyusb-descriptor-len
tinyusb: Correct descriptor string length calculation
2019-11-19 23:52:47 +07:00
Kay Sievers
7f3211f46d tinyusb: Correct descriptor string length calculation
This fixes strcpy_uni16() to return the correct number of characters.
It wasn't visible in the host so far, because the strings have been NUL
terminated.
2019-11-19 12:30:25 +01:00
Limor "Ladyada" Fried
361481d34d
Merge pull request #186 from adafruit/baud-fix
SAMD21: Fix freq clipping in SPI.h, allow 24 MHz SPI
2019-11-04 17:52:19 -05:00
Phillip Burgess
a2c0a5b547 SAMD21: Fix freq clipping in SPI.h, allow 24 MHz SPI
SPI clock freq previously clipped at MAX_SPI/2 (6 MHz) rather than MAX_SPI. Now works correctly.
Additionally, MAX_SPI set at 24 MHz on SAMD21. This is only slightly beyond spec and so far seems reliable with SD and SdFat tests on M0 Adalogger, eyes on HalloWing M0.
2019-11-04 14:45:51 -08:00
Lady Ada
9df0b07308 fix i2c for peripheral use thanks to https://github.com/adafruit/ArduinoCore-samd/pull/185 @JordanMajd 2019-11-02 23:26:49 -04:00
Lady Ada
6be0d1fa34 Merge branch 'JordanMajd-patch_samd51_i2c_slave' 2019-11-02 23:24:22 -04:00
Lady Ada
feb846a1ff add monster m4sk too 2019-11-02 22:44:40 -04:00
Jordan Majd
2b052e11f8 Reenable Serial1 sercom int handlers, disable Wire i2c slave int handlers 2019-10-31 18:26:16 +00:00
Jordan Majd
04a2dd8ace Preserve original formatting on base sercom handler 2019-10-31 16:32:16 +00:00
Jordan Majd
7a60a36a05 I2C slave support for Pyportal Titano M4 2019-10-31 03:51:06 +00:00
Jordan Majd
bc5fcc0d35 I2C slave support for Pyportal M4 2019-10-31 03:48:54 +00:00
Jordan Majd
8368e5f487 Update endif macro comment to reflect macro 2019-10-31 03:47:41 +00:00
Jordan Majd
684811d7ac I2C slave support for PyGamer M4 2019-10-31 03:46:38 +00:00
Jordan Majd
ccd2ef97c5 I2C slave support for PyGamer Advance M4 2019-10-31 03:44:15 +00:00
Jordan Majd
43e7bd8356 I2C slave support for Pybadge M4 2019-10-31 03:43:06 +00:00
Jordan Majd
84cef9a876 I2C slave support for Pybadge Airlift M4 2019-10-31 03:39:03 +00:00
Jordan Majd
3202e7794e I2C slave support for Metro Airlift M4 2019-10-31 03:35:27 +00:00
Jordan Majd
0897920a8c I2C slave support for Metro M4 2019-10-31 03:34:37 +00:00
Jordan Majd
74cfc245ba I2C slave support for Hallowing M4 2019-10-31 03:31:38 +00:00
Jordan Majd
efd29616db I2C slave support for Grand Central M4 2019-10-31 03:29:22 +00:00
Jordan Majd
3ed74de232 I2C slave support for Feather M4 2019-10-31 03:16:08 +00:00
Jordan Majd
4dbfc244cc I2C slave support for Trellis M4, temporarily disables UART Serial 1 2019-10-31 03:03:15 +00:00
Jordan Majd
e72343c867 Add the SAMD51s 4 i2c interrupts to ensure slave support 2019-10-31 01:11:32 +00:00
hathach
c7c17484b1 Merge remote-tracking branch 'adafruit/master' 2019-10-29 11:17:48 +07:00
ladyada
1ab7cb6cdd force using 2017 toolchain (instead of 2014) 2019-10-28 18:17:22 -04:00
ladyada
ee9df548b7 fix min/max macros
allow PDM mic on pybadge edge
change pyportal backlight timer
2019-10-27 23:53:38 -04:00
ladyada
841a1b8188 use arduino-api for min/max 2019-10-27 20:08:01 -04:00
ladyada
ceccc257e7 change backlight to tcc4 so it doesnt collide with servo 2019-10-17 01:35:53 -04:00
ladyada
6076e22f1a allow PDM mic on SPI 2019-10-16 19:24:58 -04:00
ladyada
a6e9eb3686 experiment with a bandgap analog read (not working) 2019-10-07 01:04:04 -04:00
ladyada
1efed72ada bump to add new boards, fix servo and tone 2019-10-04 18:28:54 -04:00
ladyada
1e9a669f07 change Tone on samd51 to be TC0 so we can use higher numbers for other stuff! (servo is TC1) 2019-10-04 18:26:27 -04:00
ladyada
e204bf375d add samd51-capable servo for now 2019-10-04 18:08:18 -04:00
ladyada
4bcbaa7287 fix typo from contrib 2019-10-04 18:06:23 -04:00
ladyada
ec12be530d Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2019-10-04 18:00:16 -04:00
ladyada
9a6ab51b0f remove serial1 2019-10-04 18:00:12 -04:00
hathach
bb4b17bf86 Merge remote-tracking branch 'adafruit/master' 2019-10-04 22:19:38 +07:00
hathach
2cc8b49e27
Merge pull request #179 from kaysievers/tinyusb-midi-jacks
tinyusb: MIDI - split descriptor initializer into individual sections
2019-10-04 21:59:54 +07:00
Limor "Ladyada" Fried
918379dacd
Merge pull request #180 from nekuneko/patch-1
Change references from A0 & A1 to DAC0 & DAC1
2019-09-19 22:01:42 -04:00
nekuneko
a09d821f9e
Change references from A0 & A1 to DAC0 & DAC1
New boards could have DAC0 & DAC1 on different pins. DAC0 & DAC1 pins are defined on each variant.h file, so it is not needed to reference to pins A0 & A1. With this change the code is more generic. Changes affect to analogWrite & analogRead functions.
2019-09-19 11:32:29 +02:00
Kay Sievers
e5af75a476 tinyusb: MIDI - split descriptor initializer into individual sections
This allows to compose the descriptor programmatically. The calling code
can compose a MIDI descriptor with up to 16 virtual wires/jacks at
initialization time.

Tested with the tinyusb -> MIDI -> midi_test example. This commit should
not change any behavior, future extensions of the calling MIDI device
will make use of it.
2019-09-11 12:58:36 +02:00
hathach
e5b45edf5b clean up 2019-09-10 17:21:47 +07:00
hathach
f739f3c37b
Merge pull request #177 from hathach/master
follow up to pr #172
2019-09-10 17:14:04 +07:00
hathach
7c02454fc7 added set/get LanguageDescriptor
add Descriptor to setManufacturer/setProduct
2019-09-10 17:11:40 +07:00
hathach
c4f34905db
Merge pull request #172 from kaysievers/usb-names-override
tinyusb: Allow to set the USB manufacturer/product identifiers
2019-09-10 16:49:02 +07:00
hathach
04eb7d174c
Merge pull request #173 from kaysievers/tinyusb-descriptor-size
tinyusb: Allow to replace the built-in descriptor buffer
2019-09-01 14:27:37 +07:00
Limor "Ladyada" Fried
ef4072fc23
Merge pull request #175 from nekuneko/patch-3
Added Additonal Timers
2019-08-28 14:52:07 -04:00
Limor "Ladyada" Fried
29c27b6a5a
Merge pull request #174 from nekuneko/patch-2
Enable TC6 & TC7 for __SAMD21J18A__
2019-08-28 14:51:34 -04:00
nekuneko
256bc5a70d
Added Additonal Timers
TC6_CH0, TC6_CH1, TC7_CH0, TC7_CH1 on SAMD21J
TCC0_CH6, TCC0_CH7, TCC1_CH4, TCC1_CH5, TCC1_CH6, TCC1_CH7, TC6_CH0, TC6_CH1, TC7_CH0, TC7_CH1 on SAMD51J
2019-08-28 13:36:51 +02:00
nekuneko
3591f2813f
Enable TC6 & TC7 for __SAMD21J18A__ 2019-08-28 13:26:48 +02:00
Kay Sievers
dcd4e5b4ff tinyusb: Allow to replace the built-in descriptor buffer
Huge USB configurations might need more than 256 bytes for the
config descriptor buffer. MIDI devices with 16 virtual ports
grow the descriptor to 600+ bytes.

This call replaces the built-in buffer with the supllied buffer. The
call copies the content of the old buffer to the new buffer:

  uint8_t buf[1024];
  USBDevice.setDescriptorBuffer(buf, sizeof(buf));
2019-08-27 13:04:18 +02:00
Kay Sievers
9417d790a7 tinyusb: Allow to set the USB manufacturer/product identifiers
Set the USB descriptor strings. I accepts UTF-8 strings with
codepoints up to 16 bit.

  void setup() {
    USBDevice.setManufacturer("MyManufacturer");
    USBDevice.setProduct("MyProduct");
  }
2019-08-27 12:05:44 +02:00
Limor "Ladyada" Fried
52ea598baa
Merge pull request #171 from kaysievers/platform-usb-power
platform: Add USB device MaxPower default setting
2019-08-26 12:48:48 -04:00
Kay Sievers
3a022a6812 platform: Add USB device MaxPower default setting
The MaxPower field specifies the maximum power that a device can
draw from the host, when the device is bus-powered.

Define the default value of 100mA default in the platform to
allow to override it from the board definition.

Some mobile devices will only supply 20mA. If a device is known to
draw less current, adding this to the board config will make it work:
  <boardname>.build.usb_power=20
2019-08-26 09:53:00 +02:00
hathach
e33ec1fe36
Merge pull request #167 from kaysievers/master
tinyusb: correct SAMD51 serial number extraction
2019-08-26 10:20:51 +07:00
hathach
3cad30de21
Merge pull request #170 from kaysievers/tinyusb-config-power
tinyusb: Allow configuration of power setting
2019-08-26 10:18:34 +07:00
hathach
c842d61919
Merge pull request #169 from kaysievers/tinyusb-warnings
tinyusb: Avoid compilation warnings
2019-08-26 10:17:23 +07:00
Limor "Ladyada" Fried
e214f12e28
Merge pull request #168 from kaysievers/warnings
Fix compilation warning
2019-08-24 23:00:31 -04:00
Kay Sievers
b369396d0a tinyusb: Allow configuration of power setting
In some cases the power value in the device descriptor needs to
be set to a lower value, commonly 20 mA, to not get rejected by iOS
devices.

The classic USB stack reads USB_CONFIG_POWER, this adds the same
logic to tinyusb.
2019-08-25 04:04:03 +02:00
Kay Sievers
4af46bfaaa tinyusb: Avoid compilation warnings
TinyUSB adds new warnings to the compilation process. Operations
inside of {} initializers get propagated to 'int' but get assigned
to uint8_t.

Add static casts to to uint8_t to avoid a bunch of warnings like this:
  cores/arduino/Adafruit_TinyUSB_Core/Adafruit_USBD_CDC.cpp: In member function
  'virtual uint16_t Adafruit_USBD_CDC::getDescriptor(uint8_t, uint8_t*, uint16_t)':
  cores/arduino/Adafruit_TinyUSB_Core/tinyusb/src/device/usbd.h:172:74: warning:
  narrowing conversion of '(((int)itfnum) + 1)' from 'int' to 'uint8_t
  {aka unsigned char}' inside { } [-Wnarrowing]
     5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (_itfnum) + 1,\
2019-08-25 03:13:43 +02:00
Kay Sievers
8f1711f7cc Fix compilation warning
Add 'const' declaration to avoid:
  cores/arduino/pulse.c: In function 'pulseIn':
    cores/arduino/pulse.c:44:29: warning: initialization discards
  'const' qualifier from pointer target type [enabled by default]
     volatile uint32_t *port = &(PORT->Group[p.ulPort].IN.reg);
                             ^
2019-08-25 03:08:17 +02:00
Kay Sievers
42915717a4 tinyusb: correct SAMD51 serial number extraction
TinyUSB does not match the exported serial numbers of the classic USB
stack.

The current code serializes the 32-bit words backwards, and the byte
nibbles are also backwards serialized.

A SAMD51 is exported like:
 EFADAF3113347335020202938343E0FF

while it should read:
  13FADAFE5337433139202020FF0E3438
2019-08-25 00:39:38 +02:00
Limor "Ladyada" Fried
54be8f04e3
Merge pull request #127 from GMagician/user-area
[SAMD51] Add software calibration init on startup
2019-08-22 12:56:38 -04:00
ladyada
3999dffd81 they'll need to define Serial1 so we dont get irq conflicts with DMA on the same pins, zats ok! 2019-08-14 18:19:55 -04:00
Ladyada
0b3ddf585a fix typo 2019-08-11 19:18:07 -04:00
hathach
955e28fe56
Merge pull request #164 from GMagician/fix-tinyusb
Fix tinyusb lost written chars
2019-08-08 13:25:07 +07:00
GMagician
15aaa2459c Revert "Remove unused method"
This reverts commit bc8148ba3a.
2019-08-08 07:02:16 +02:00
Limor "Ladyada" Fried
5ff858c1d5
Merge pull request #165 from brentru/add-pyportal-titano
Add Board Definition for PyPortal Titano
2019-08-07 17:42:37 -04:00
brentru
c551c20104 add definition for pyportal titano 2019-08-07 16:48:26 -04:00
GMagician
bc8148ba3a Remove unused method 2019-08-07 20:01:41 +02:00
GMagician
49f9e2f066 Fix tinyusb lost written chars
This will fix lost chars when tx buffer is full
2019-08-07 19:59:57 +02:00
ladyada
8a97e31803 unused file 2019-08-07 13:37:32 -04:00
hathach
e80f2f1b49
Update platform.txt 2019-08-06 12:23:32 +07:00
Limor "Ladyada" Fried
6ff862e6a4
Merge pull request #158 from hathach/tinyusb-webusb
update Tinyusb to support webusb
2019-08-01 13:29:46 -04:00
hathach
96adc67184 add PIN_NEOPIXEL macro for feather/metro m0/m4 hallow_m0 2019-08-01 21:31:56 +07:00
hathach
c4aebf3bd7 tinyusb clean up 2019-08-01 13:18:11 +07:00
hathach
b88912c4cf fix availableForWrite() signature 2019-08-01 11:25:57 +07:00
hathach
732bc9e3a0 add missing files 2019-08-01 11:17:20 +07:00
hathach
6f8675815e update tinyusb stack for webusb support
- add Serial availableForWrite()
-
2019-08-01 11:03:27 +07:00
Limor "Ladyada" Fried
553d3c8f0e
Merge pull request #155 from GMagician/fix-tone
Fix tone
2019-07-29 13:20:54 -04:00
GMagician
e51b006a3f Fix tone
- match timer and timer handler
- lower interrupt priority (0 seems to big for a simple tone)
- be sure 'toneIsActive' is always set (if previous tone was using a different pin, it's not set
2019-07-29 18:46:42 +02:00
Limor "Ladyada" Fried
b22e7654fc
Merge pull request #154 from adafruit/hallowings
hallowing m4 final UART fix
2019-07-27 13:21:29 -04:00
ladyada
0c63da60f7 hallowing m4 final UART fix 2019-07-27 13:20:45 -04:00
Limor "Ladyada" Fried
7cc4586130
Merge pull request #153 from adafruit/hallowings
add hallowing and m4sk
2019-07-27 13:19:16 -04:00
Limor "Ladyada" Fried
c08f564269
Merge pull request #152 from GMagician/Fix-missin-unsigned-pin
Fix missing unsigned pin and indetation
2019-07-26 16:59:18 -04:00
GMagician
2bf7821f70 Missing pin 2019-07-26 21:56:08 +02:00
Limor "Ladyada" Fried
3cd1d9e430
Merge pull request #151 from adafruit-mike-stone/master
minor correction to comments in variants/metro_m4/variant.cpp
2019-07-26 15:50:39 -04:00
Mike Stone
e20ac5e5be minor correction to comments in variants/metro_m4/variant.cpp 2019-07-26 14:43:02 -05:00
hathach
fbc7ec4dff
Merge pull request #149 from GMagician/fix-compile-warnings
Fix compile warnings
2019-07-27 01:19:08 +07:00
Limor "Ladyada" Fried
10ebeba6b9
Merge pull request #147 from GMagician/fixes
Remove unsigned from pins
2019-07-26 14:00:48 -04:00
GMagician
f937db2251 Fix compile warnings 2019-07-26 18:44:13 +02:00
GMagician
8362ba3b96 Removing unsigned from pins 2019-07-26 18:24:04 +02:00
Limor "Ladyada" Fried
f4f87c8ba3
Merge pull request #146 from GMagician/addmissingpin
Add missing pin
2019-07-25 17:31:48 -04:00
GMagician
54910c06cf Add missing pin
- Added onboard sd detect pin
- Removed duplicated space chars
2019-07-25 22:15:04 +02:00
Limor "Ladyada" Fried
6e78986f34
Merge pull request #145 from GMagician/uniform-with-arduino
Standardize pins count
2019-07-24 16:12:11 -04:00
GMagician
5e7f7a14bb Standardize pins count
Arduino framework doesn't force unsigned (checked in different boards).
This also prevent undesired warnings in Marlin Firmware
2019-07-24 22:06:11 +02:00
ladyada
d8b0ad85c3 fix for rev C 2019-07-23 17:06:24 -04:00
Limor "Ladyada" Fried
0b069c10e7
Merge pull request #143 from GMagician/fix-analog-count
Update nr of analog input
2019-07-22 12:25:27 -04:00
GMagician
56b5392088 Update nr of analog input
Following #125
2019-07-22 17:22:49 +02:00
Limor "Ladyada" Fried
751cec6c03
Merge pull request #140 from hathach/fix-samd51-ram-macro
Fix samd51 ram macro
2019-07-17 12:45:57 -04:00
hathach
2568b78213 use __SAMD51__ macro for io.h 2019-07-17 14:26:48 +07:00
hathach
3bb94f51b8 fix RAMSTART, RAMSIZE, RAMEND for samd51 and same21 2019-07-17 12:45:44 +07:00
ladyada
51461f9a3a add tinyusb midi support 2019-07-15 15:53:35 -04:00
ladyada
f8208799be Merge branch 'master' into hallowings 2019-07-14 17:40:51 -04:00
ladyada
70240054fb fix pin numberings 2019-07-14 17:40:37 -04:00
ladyada
9e2724918c update naming 2019-07-13 16:17:07 -04:00
Limor "Ladyada" Fried
68e65f2b9a
Merge pull request #138 from hathach/master
fix incorrect midi descriptor template
2019-07-08 23:41:07 -04:00
hathach
fa04386790 fix incorrect midi descriptor template 2019-07-09 10:38:04 +07:00
Limor "Ladyada" Fried
961c470159
Merge pull request #137 from hathach/master
fix auto descriptor's auto interface e.g MIDI interface
2019-07-08 12:16:14 -04:00
hathach
edc13ba71f add itfnum to getDescriptor() 2019-07-08 22:49:05 +07:00
ladyada
e8303705b3 fix missing dac1 definition (on stemma connector) 2019-07-07 18:57:11 -04:00
Limor "Ladyada" Fried
b216a22e0e
Merge pull request #136 from hathach/master
fix MIDI with window driver
2019-07-06 20:20:24 -04:00
hathach
11d6f547c3 midi only use audio 1.0 without IAD 2019-07-05 16:44:38 +07:00
ladyada
692b4a6944 hallowing m4 2019-07-04 13:21:32 -04:00
Limor "Ladyada" Fried
855523d669
Merge pull request #135 from hathach/tinyusb-midi
enable TinyUSB MIDI
2019-07-03 15:26:38 -04:00
hathach
ff7b62d45b enable usb midi in tusb_config.h 2019-07-04 01:48:24 +07:00
hathach
0aa2b2fcb6 update tinyusb to support midi 2019-07-04 01:48:08 +07:00
Limor "Ladyada" Fried
5c318aad3b
Merge pull request #134 from beeryt/patch-1
Wiring: Clean up repeated pin description access
2019-07-03 12:26:10 -04:00
T. Carl Beery
206a7acd99
Wiring: Clean up repeated pin description access 2019-07-03 08:24:06 -07:00
ladyada
d9ef135999 Merge branch 'hallowings' of github.com:adafruit/ArduinoCore-samd into hallowings 2019-06-29 00:29:16 -04:00
ladyada
3688c468ce fix some mask GPIO - add hallowing m4 (TFT untested) 2019-06-29 00:28:58 -04:00
Phillip Burgess
3b0115cffc SERCOM3 pad juggling for PDM 2019-06-27 18:21:39 -07:00
ladyada
5078941dfb some stuff working on mask (i2c, audio) 2019-06-25 21:32:32 -04:00
Limor "Ladyada" Fried
1672e7124b
Merge pull request #132 from kaysievers/master
USBCore: Read the SAMD51 serial number
2019-06-24 09:24:47 -04:00
Kay Sievers
23fd362a72 USBCore: Read the SAMD51 serial number
Export the unique hardware serial number from the SAMD51 MCU
to the USB device descriptor.

Remove the concatenation of the USB class device string, it is
superfluous, and an USB interface property should not become a
part of the USB device property.

Tested on SAMD21 and SAMD51:

Before:
  SAMD21: 10BD8E4051504C3750202020FF0B1410MIDI
  SAMD51: MIDI

After:
  SAMD21: 10BD8E4051504C3750202020FF0B1410
  SAMD51: AAFC165853574E514D202020FF083C44
2019-06-23 22:02:35 +02:00
Limor "Ladyada" Fried
5c60a5ac21
Merge pull request #130 from brentru/add-pybadge-airlift-m4
Add PyBadge AirLift
2019-06-20 13:33:46 -04:00
Limor "Ladyada" Fried
fd0d925466
Merge pull request #131 from brentru/add-nina-naming
Add NINA_ACK to WiFi Boards
2019-06-20 13:31:14 -04:00
brentru
616f0c929a add to pyportal 2019-06-20 11:14:52 -04:00
brentru
92d99e90ad add NINA_ACK standard pin 2019-06-20 11:12:33 -04:00
Limor "Ladyada" Fried
9b2e698f6b
Merge pull request #125 from GMagician/Fix-analogInputToDigitalPin
Fix analogInputToDigitalPin for Grand Central M4
2019-06-15 23:00:35 -04:00
ladyada
b2cf1b106c bump version, remove -g flags 2019-06-15 23:00:04 -04:00
ladyada
66a844f050 fix for trinket/gemma m0 2019-06-15 22:59:15 -04:00
brentru
135eb717f4 add tft pins 2019-06-14 10:09:44 -04:00
Giuliano Zaro
29bfe96f8e
Fix compiler error
Removed unnecessary bracket
missing usb padcal
2019-06-14 11:35:05 +02:00
brentru
c94e1598bf adding correct number of pins, fix header guard, cleanup comments, rename to nina fw defaults 2019-06-13 18:27:41 -04:00
brentru
aa23d7a56f fix SS and ACK pins 2019-06-13 17:55:07 -04:00
brentru
4269f8a3f3 add correct ESP32 pins 2019-06-13 16:16:38 -04:00
brentru
d78c105f08 add SPIWIF_ACK 2019-06-13 15:37:59 -04:00
brentru
ff27aa43e9 add updated pin variant 2019-06-13 15:29:38 -04:00
brentru
d1ae3d83af added variant for pybadge airlift, modified pins in variant.cpp to reflect schematic 2019-06-12 14:55:10 -04:00
brentru
e95527efbb changed size to match J20 size 2019-06-12 14:24:28 -04:00
brentru
b2dab994af added pybadge airlift to boards.txt 2019-06-12 14:17:20 -04:00
ladyada
cec0a6bd7d add opts all around 2019-06-09 22:11:04 -04:00
ladyada
b89404cf52 Merge branch 'master' of github.com:adafruit/ArduinoCore-samd 2019-06-08 13:50:39 -04:00
ladyada
02d93cca94 more opts! and advance 2019-06-08 13:50:34 -04:00
GMagician
7a550677bc [SAMD51] Add softwater calibration init on startup
Use calibration software area fuses to initialize devices
2019-06-08 18:45:23 +02:00
GMagician
3c7073326c Fix analogInputToDigitalPin for Grand Central M4 2019-06-06 18:57:08 +02:00
Limor "Ladyada" Fried
c84ce7edb1
Merge pull request #122 from hathach/tinyusb
run usb background when checking for Serial.available() if needed
2019-06-05 14:12:33 -04:00
hathach
34389498c5
yield() if needed when calling Serial.write() 2019-06-05 23:09:44 +07:00
hathach
a89950536a
run usb background when checking for Serial.available() if needed 2019-06-05 17:37:15 +07:00
ladyada
d787240dab add debug flag option 2019-06-03 18:45:22 -04:00
Limor "Ladyada" Fried
3ca3967711
Merge pull request #121 from adafruit/tinyusb
windows serial fix
2019-05-27 14:44:11 -04:00
Limor "Ladyada" Fried
c85d59c371
Merge pull request #120 from hathach/adafruit-tinyusb
fix windows serial issue
2019-05-27 14:43:11 -04:00
hathach
f8ad400ff2 fix serial issue with windows 2019-05-27 18:50:15 +07:00
Limor "Ladyada" Fried
b73c167ce0
Update platform.txt
Big update since we've added so much!
2019-05-26 23:33:44 -04:00
Limor "Ladyada" Fried
a027455d39
Merge pull request #119 from hathach/adafruit-tinyusb
fix load_serial_number() warning
2019-05-26 23:05:30 -04:00
hathach
4e4e2846f9 fix load_serial_number() warning 2019-05-25 14:01:25 +07:00
Limor "Ladyada" Fried
e7c57199e8
Merge pull request #117 from adafruit/tinyusb
Tinyusb branch
2019-05-24 01:54:00 -04:00
Limor "Ladyada" Fried
918d820d53
Merge pull request #118 from hathach/adafruit-tinyusb
fix tinyusb hid raw inout issue
2019-05-24 01:53:50 -04:00
hathach
3faad0375e fix tinyusb hid raw inout issue 2019-05-24 12:50:39 +07:00
Limor "Ladyada" Fried
6194fc367b
Merge pull request #116 from adafruit/pb-spi
Merge Adafruit_ZeroDMA into SAMD core libraries
2019-05-23 02:43:25 -04:00
Limor "Ladyada" Fried
595aa2c126
Merge pull request #115 from hathach/adafruit-tinyusb
minor enhancement for usb cdc
2019-05-21 22:21:33 -04:00
hathach
217fe38647 move yield() usb background in to TinyUSB Core 2019-05-22 09:02:24 +07:00
hathach
a75a324a4c fix TinyUSB stack read signed char 2019-05-22 08:59:10 +07:00
hathach
404c9e4068 improve TinyUSB port
add yield to stream timeRead() timePeek() and Serial::bool()
2019-05-22 00:48:41 +07:00
Limor "Ladyada" Fried
212c1922ba
Merge pull request #114 from hathach/adafruit-tinyusb
sync with master
2019-05-16 21:48:33 -04:00
hathach
0f22c475f5 Merge remote-tracking branch 'adafruit/master' into adafruit-tinyusb 2019-05-17 08:45:53 +07:00
hathach
a524e2cbea
add Adafruit_TinyUSB_Core_touch1200() 2019-05-15 23:32:56 +07:00
hathach
b148e8a614 update tinyusb 2019-05-15 23:26:45 +07:00
ladyada
3f79b9db6f add extra PID option https://github.com/adafruit/ArduinoCore-samd/issues/113 2019-05-13 17:22:49 -04:00
Limor "Ladyada" Fried
f36d409355
Merge pull request #112 from hathach/adafruit-tinyusb
update tinyusb
2019-05-13 01:01:48 -04:00
hathach
3e415ba7be
add tud_cdc_write_flush() call in main() and yield() 2019-05-12 23:51:37 +07:00
hathach
5632e53759
update tinyusb tud_descriptor_configuration_cb 2019-05-12 20:01:18 +07:00
hathach
caf36be549
update tinyusb for new string/hid/device/config descriptor callback 2019-05-12 15:45:42 +07:00
hathach
c727f2b197 update usb core to use tud_descriptor_string_cb() 2019-05-11 23:34:46 +07:00
Limor "Ladyada" Fried
60c0542463
Merge pull request #111 from adafruit/pb-spi
Fix typedef syntax
2019-05-11 00:40:07 -04:00
Limor "Ladyada" Fried
01ea159d19
Merge pull request #110 from adafruit/pb-spi
Better SPI SERCOM clock control
2019-05-10 21:33:23 -04:00
Limor "Ladyada" Fried
d81bda401e
Merge pull request #109 from hathach/adafruit-tinyusb
fix tinyusb bug with clear stall and reset data toggle
2019-05-09 13:37:17 -04:00
hathach
0552d34dab Merge remote-tracking branch 'adafruit/master' into adafruit-tinyusb 2019-05-10 00:12:33 +07:00
hathach
af90d98a6e fix samd dcd_clear_stall also reset data toggle 2019-05-10 00:08:23 +07:00
hathach
3c5f92d49d better use USE_TINYUSB for stack detection 2019-05-09 23:50:20 +07:00
hathach
4f9fef7b0e update tinyusb lib 2019-05-09 23:49:44 +07:00
ladyada
d331767eac woops wrong PIDs 2019-05-03 03:03:29 -04:00
hathach
e770ae4301 error message when compile usb demo without selecting it 2019-05-03 13:14:59 +07:00
Limor "Ladyada" Fried
cd0f54edfc
Merge pull request #108 from hathach/adafruit-tinyusb
fix load serial string based on device id
2019-05-03 02:11:45 -04:00
hathach
dda4eaf546 fix load serial string based on device id 2019-05-03 13:07:19 +07:00
Limor "Ladyada" Fried
4d317b03dc
Merge pull request #107 from hathach/adafruit-tinyusb
add bi-directional HID
2019-05-03 01:00:51 -04:00
hathach
c21b6014b6 add hid bufsize 2019-05-03 00:00:58 +07:00
hathach
71922ef9e2 Merge branch 'tinyusb' into adafruit-tinyusb 2019-05-02 21:05:40 +07:00
hathach
96075f637e update tinyusb to support bi-directional HID 2019-05-02 21:01:36 +07:00
Limor "Ladyada" Fried
7a2e3e1a99
Merge pull request #106 from hathach/adafruit-tinyusb
Add TinyUSB as optional usb stack (drop down selection)
2019-04-30 16:01:31 -04:00
hathach
ab16f9899d add menu dropdown list for usb stack selection 2019-05-01 01:01:59 +07:00
hathach
617cc6c596 rename usb core folder 2019-04-30 00:21:13 +07:00
hathach
9c07070580 get msc & hid example work with metro m0 express 2019-04-30 00:12:17 +07:00
288 changed files with 21302 additions and 2155 deletions

95
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View file

@ -0,0 +1,95 @@
name: Bug Report
description: Report a problem
labels: 'Bug'
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
It's okay to leave some blank if it doesn't apply to your problem.
- type: dropdown
attributes:
label: Operating System
options:
- Linux
- MacOS
- RaspberryPi OS
- Windows 7
- Windows 10
- Windows 11
- Others
validations:
required: true
- type: input
attributes:
label: Arduino IDE version
placeholder: e.g Arduino 1.8.15
validations:
required: true
- type: input
attributes:
label: Board
placeholder: e.g Metro M4 Express
validations:
required: true
- type: input
attributes:
label: ArduinoCore version
description: Can be found under "Board Manager" menu
validations:
required: true
- type: textarea
attributes:
label: Sketch as ATTACHED TXT
placeholder: |
e.g examples/MassStorage/msc_ramdisk.
If it is custom sketch, please provide it as **ATTACHED** files or link to it.
Pasting raw long code that hurts readability can get your issue **closed**
validations:
required: true
- type: textarea
attributes:
label: Compiled Log as ATTACHED TXT
placeholder: |
Compiled log from Arduino IDE as **ATTACHED** txt.
Pasting raw long log that hurts readability can get your issue **closed**
validations:
required: true
- type: textarea
attributes:
label: What happened ?
placeholder: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: How to reproduce ?
placeholder: |
1. Go to '...'
2. Click on '....'
3. See error
validations:
required: true
- type: textarea
attributes:
label: Debug Log as ATTACHED TXT
placeholder: |
Debug log where the issue occurred as attached txt file, best with comments to explain the actual events.
validations:
required: false
- type: textarea
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
validations:
required: false

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Adafruit Support Forum
url: https://forums.adafruit.com
about: If you have other questions or need help, post it here.

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: Feature
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

61
.github/workflows/githubci.yml vendored Normal file
View file

@ -0,0 +1,61 @@
name: Build
on: [pull_request, push]
jobs:
build:
strategy:
fail-fast: false
matrix:
board:
# Alphabetical order
- 'circuitplayground_m0'
- 'feather_m4_can'
- 'hallowing'
- 'hallowing_m4'
- 'metro_m0'
- 'metro_m4'
- 'pybadge_m4'
- 'pygamer_m4'
- 'pyportal_m4'
- 'pyportal_m4_titano'
# with TinyUSB
- 'metro_m0:usbstack=tinyusb'
- 'metro_m4:speed=120,usbstack=tinyusb'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: 'true'
- name: Install Arduino CLI and Tools
run: |
# make all our directories we need for files and libraries
mkdir $HOME/.arduino15
mkdir $HOME/.arduino15/packages
mkdir $HOME/Arduino
mkdir $HOME/Arduino/libraries
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
- name: Install BSP and Libraries
env:
BSP_URL: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
BSP_PATH: .arduino15/packages/adafruit/hardware/samd
run: |
arduino-cli config init
arduino-cli core update-index
arduino-cli core update-index --additional-urls $BSP_URL
arduino-cli core install arduino:samd --additional-urls $BSP_URL
arduino-cli core install adafruit:samd --additional-urls $BSP_URL
# Replace release BSP with our code
BSP_VERSION=`eval ls $HOME/$BSP_PATH`
rm -r $HOME/$BSP_PATH/*
ln -s $GITHUB_WORKSPACE $HOME/$BSP_PATH/$BSP_VERSION
arduino-cli lib install "Adafruit NeoPixel" "Adafruit seesaw Library" "Adafruit SPIFlash" "FlashStorage" "MIDI Library" "SD" "SdFat - Adafruit Fork"
- name: Build examples
run: python3 tools/build_all.py ${{ matrix.board }}

1
.gitignore vendored
View file

@ -3,3 +3,4 @@
bootloaders/*/build/
*~
/libraries/**/build/

6
.gitmodules vendored Normal file
View file

@ -0,0 +1,6 @@
[submodule "libraries/Adafruit_TinyUSB_Arduino"]
path = libraries/Adafruit_TinyUSB_Arduino
url = https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
[submodule "libraries/Adafruit_ZeroDMA"]
path = libraries/Adafruit_ZeroDMA
url = https://github.com/adafruit/Adafruit_ZeroDMA

View file

@ -1,5 +1,7 @@
# Arduino Core for SAMD21 and SAMD51 CPU
[![Build Status](https://github.com/adafruit/ArduinoCore-samd/workflows/Build/badge.svg)](https://github.com/adafruit/ArduinoCore-samd/actions)
This repository contains the source code and configuration files of the Arduino Core
for Atmel's SAMD21 and SAMD51 processor (used on the Arduino/Genuino Zero, MKR1000 and MKRZero boards).

2164
boards.txt

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

Binary file not shown.

Binary file not shown.

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -218,7 +218,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -222,7 +222,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -226,7 +226,11 @@ void I2S_Handler ( void );
* \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
*/
#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
#error "Little Endian is already defined, but to different value than expected?!"
#else
#define LITTLE_ENDIAN 1
#endif
#define __CM0PLUS_REV 1 /*!< Core revision r0p1 */
#define __MPU_PRESENT 0 /*!< MPU present or not */
#define __NVIC_PRIO_BITS 2 /*!< Number of bits used for Priority Levels */

View file

@ -46,7 +46,6 @@ extern "C"{
// Include Atmel headers
#include "sam.h"
#include "wiring_constants.h"
#define clockCyclesPerMicrosecond() ( SystemCoreClock / 1000000L )
@ -97,8 +96,33 @@ void loop( void ) ;
#undef abs
#endif // abs
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#ifdef __cplusplus
template<class T, class L>
auto min(const T& a, const L& b) -> decltype((b < a) ? b : a)
{
return (b < a) ? b : a;
}
template<class T, class L>
auto max(const T& a, const L& b) -> decltype((b < a) ? b : a)
{
return (a < b) ? b : a;
}
#else
#ifndef min
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
#endif
#ifndef max
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#endif
#endif
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
@ -124,10 +148,15 @@ void loop( void ) ;
#define digitalPinToInterrupt(P) ( P )
#endif
// USB Device
// USB
#ifdef USE_TINYUSB
// Needed for declaring Serial
#include "Adafruit_USBD_CDC.h"
#else
#include "USB/USBDesc.h"
#include "USB/USBCore.h"
#include "USB/USBAPI.h"
#include "USB/USB_host.h"
#endif
#endif // Arduino_h

View file

@ -94,6 +94,28 @@ size_t Print::print(unsigned long n, int base)
else return printNumber(n, base);
}
size_t Print::print(long long n, int base)
{
if (base == 0) {
return write(n);
} else if (base == 10) {
if (n < 0) {
int t = print('-');
n = -n;
return printULLNumber(n, 10) + t;
}
return printULLNumber(n, 10);
} else {
return printULLNumber(n, base);
}
}
size_t Print::print(unsigned long long n, int base)
{
if (base == 0) return write(n);
else return printULLNumber(n, base);
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
@ -172,6 +194,20 @@ size_t Print::println(unsigned long num, int base)
return n;
}
size_t Print::println(long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
@ -218,6 +254,81 @@ size_t Print::printNumber(unsigned long n, uint8_t base)
return write(str);
}
// REFERENCE IMPLEMENTATION FOR ULL
// size_t Print::printULLNumber(unsigned long long n, uint8_t base)
// {
// // if limited to base 10 and 16 the bufsize can be smaller
// char buf[65];
// char *str = &buf[64];
// *str = '\0';
// // prevent crash if called with base == 1
// if (base < 2) base = 10;
// do {
// unsigned long long t = n / base;
// char c = n - t * base; // faster than c = n%base;
// n = t;
// *--str = c < 10 ? c + '0' : c + 'A' - 10;
// } while(n);
// return write(str);
// }
// FAST IMPLEMENTATION FOR ULL
size_t Print::printULLNumber(unsigned long long n64, uint8_t base)
{
// if limited to base 10 and 16 the bufsize can be 20
char buf[64];
uint8_t i = 0;
uint8_t innerLoops = 0;
// prevent crash if called with base == 1
if (base < 2) base = 10;
// process chunks that fit in "16 bit math".
uint16_t top = 0xFFFF / base;
uint16_t th16 = 1;
while (th16 < top)
{
th16 *= base;
innerLoops++;
}
while (n64 > th16)
{
// 64 bit math part
uint64_t q = n64 / th16;
uint16_t r = n64 - q*th16;
n64 = q;
// 16 bit math loop to do remainder. (note buffer is filled reverse)
for (uint8_t j=0; j < innerLoops; j++)
{
uint16_t qq = r/base;
buf[i++] = r - qq*base;
r = qq;
}
}
uint16_t n16 = n64;
while (n16 > 0)
{
uint16_t qq = n16/base;
buf[i++] = n16 - qq*base;
n16 = qq;
}
size_t bytes = i;
for (; i > 0; i--)
write((char) (buf[i - 1] < 10 ?
'0' + buf[i - 1] :
'A' + buf[i - 1] - 10));
return bytes;
}
size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0;
@ -262,3 +373,4 @@ size_t Print::printFloat(double number, uint8_t digits)
return n;
}

View file

@ -37,6 +37,7 @@ class Print
private:
int write_error;
size_t printNumber(unsigned long, uint8_t);
size_t printULLNumber(unsigned long long, uint8_t);
size_t printFloat(double, uint8_t);
protected:
void setWriteError(int err = 1) { write_error = err; }
@ -69,6 +70,8 @@ class Print
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(long long, int = DEC);
size_t print(unsigned long long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
@ -81,6 +84,8 @@ class Print
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(long long, int = DEC);
size_t println(unsigned long long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(void);

View file

@ -29,7 +29,7 @@ extern "C" {
#if (ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10610)
extern const uint32_t __text_start__;
#define APP_START ((volatile uint32_t)(&__text_start__) + 4)
#define APP_START ((uint32_t)(&__text_start__) + 4)
#else

View file

@ -29,7 +29,7 @@
// location from which to read.
#ifndef SERIAL_BUFFER_SIZE
#define SERIAL_BUFFER_SIZE 256
#define SERIAL_BUFFER_SIZE 350
#endif
template <int N>

View file

@ -537,8 +537,18 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
// 7-bits address + 1-bits R/W
address = (address << 0x1ul) | flag;
// Wait idle or owner bus mode
while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
// If another master owns the bus or the last bus owner has not properly
// sent a stop, return failure early. This will prevent some misbehaved
// devices from deadlocking here at the cost of the caller being responsible
// for retrying the failed transmission. See SercomWireBusState for the
// possible bus states.
if(!isBusOwnerWIRE())
{
if( isBusBusyWIRE() || (isArbLostWIRE() && !isBusIdleWIRE()) || isBusUnknownWIRE() )
{
return false;
}
}
// Send start and address
sercom->I2CM.ADDR.bit.ADDR = address;
@ -546,29 +556,35 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
// Address Transmitted
if ( flag == WIRE_WRITE_FLAG ) // Write mode
{
while( !sercom->I2CM.INTFLAG.bit.MB )
{
while( !sercom->I2CM.INTFLAG.bit.MB ) {
// Wait transmission complete
// If certain errors occur, the MB bit may never be set (RFTM: SAMD21 sec:28.10.6; SAMD51 sec:36.10.7).
// The data transfer errors that can occur (including BUSERR) are all
// rolled up into INTFLAG.bit.ERROR from STATUS.reg
if (sercom->I2CM.INTFLAG.bit.ERROR) {
return false;
}
}
}
else // Read mode
{
while( !sercom->I2CM.INTFLAG.bit.SB )
{
while( !sercom->I2CM.INTFLAG.bit.SB ) {
// Wait transmission complete
// If the slave NACKS the address, the MB bit will be set.
// A variety of errors in the STATUS register can set the ERROR bit in the INTFLAG register
// In that case, send a stop condition and return false.
if (sercom->I2CM.INTFLAG.bit.MB) {
if (sercom->I2CM.INTFLAG.bit.MB || sercom->I2CM.INTFLAG.bit.ERROR) {
sercom->I2CM.CTRLB.bit.CMD = 3; // Stop condition
return false;
}
// Wait transmission complete
}
// Clean the 'Slave on Bus' flag, for further usage.
//sercom->I2CM.INTFLAG.bit.SB = 0x1ul;
}
//ACK received (0: ACK, 1: NACK)
if(sercom->I2CM.STATUS.bit.RXNACK)
{
@ -587,10 +603,11 @@ bool SERCOM::sendDataMasterWIRE(uint8_t data)
//Wait transmission successful
while(!sercom->I2CM.INTFLAG.bit.MB) {
// If a bus error occurs, the MB bit may never be set.
// Check the bus error bit and bail if it's set.
if (sercom->I2CM.STATUS.bit.BUSERR) {
// If a data transfer error occurs, the MB bit may never be set.
// Check the error bit and bail if it's set.
// The data transfer errors that can occur (including BUSERR) are all
// rolled up into INTFLAG.bit.ERROR from STATUS.reg
if (sercom->I2CM.INTFLAG.bit.ERROR) {
return false;
}
}
@ -634,6 +651,21 @@ bool SERCOM::isBusOwnerWIRE( void )
return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE;
}
bool SERCOM::isBusUnknownWIRE( void )
{
return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_UNKNOWN_STATE;
}
bool SERCOM::isArbLostWIRE( void )
{
return sercom->I2CM.STATUS.bit.ARBLOST == 1;
}
bool SERCOM::isBusBusyWIRE( void )
{
return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_BUSY_STATE;
}
bool SERCOM::isDataReadyWIRE( void )
{
return sercom->I2CS.INTFLAG.bit.DRDY;
@ -676,9 +708,17 @@ uint8_t SERCOM::readDataWIRE( void )
{
if(isMasterWIRE())
{
while( sercom->I2CM.INTFLAG.bit.SB == 0 )
{
while (sercom->I2CM.INTFLAG.bit.SB == 0) {
// Waiting complete receive
// A variety of errors in the STATUS register can set the ERROR bit in the INTFLAG register
// In that case, send a stop condition and return false.
// readDataWIRE should really be able to indicate an error (which would never be used
// because the readDataWIRE callers (in Wire.cpp) should have checked availableWIRE() first and timed it
// out if the data never showed up
if (sercom->I2CM.INTFLAG.bit.MB || sercom->I2CM.INTFLAG.bit.ERROR) {
sercom->I2CM.CTRLB.bit.CMD = 3; // Stop condition
return 0xFF;
}
}
return sercom->I2CM.DATA.bit.DATA ;

View file

@ -225,6 +225,9 @@ class SERCOM
bool isSlaveWIRE( void ) ;
bool isBusIdleWIRE( void ) ;
bool isBusOwnerWIRE( void ) ;
bool isBusUnknownWIRE( void ) ;
bool isArbLostWIRE( void );
bool isBusBusyWIRE( void );
bool isDataReadyWIRE( void ) ;
bool isStopDetectedWIRE( void ) ;
bool isRestartDetectedWIRE( void ) ;
@ -245,7 +248,7 @@ class SERCOM
uint32_t getFreqRef(void) { return freqRef; };
#else
// The equivalent SAMD21 dummy functions...
void setClockSource(int8_t idx, SercomClockSource src, bool core) { };
void setClockSource(int8_t idx, SercomClockSource src, bool core) { (void)idx; (void)src; (void)core; };
SercomClockSource getClockSource(void) { return SERCOM_CLOCK_SOURCE_FCPU; };
uint32_t getFreqRef(void) { return F_CPU; };
#endif

View file

@ -35,6 +35,7 @@ int Stream::timedRead()
do {
c = read();
if (c >= 0) return c;
yield(); // running TinyUSB task
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
@ -47,6 +48,7 @@ int Stream::timedPeek()
do {
c = peek();
if (c >= 0) return c;
yield(); // running TinyUSB task
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}

View file

@ -20,12 +20,6 @@
#include "Tone.h"
#include "variant.h"
#if defined(__SAMD51__)
#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.SYNCBUSY.bit.ENABLE);
#else
#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
#endif
uint32_t toneMaxFrequency = F_CPU / 2;
uint32_t lastOutputPin = 0xFFFFFFFF;
@ -37,22 +31,24 @@ volatile bool toneIsActive = false;
volatile bool firstTimeRunning = false;
#if defined(__SAMD51__)
#define TONE_TC TC3
#define TONE_TC_IRQn TC3_IRQn
#define TONE_TC_GCLK_ID TC3_GCLK_ID
#define TONE_TC TC0
#define TONE_TC_IRQn TC0_IRQn
#define TONE_TC_GCLK_ID TC0_GCLK_ID
#define Tone_Handler TC0_Handler
#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.SYNCBUSY.bit.ENABLE);
#else
#define TONE_TC TC5
#define TONE_TC_IRQn TC5_IRQn
#define Tone_Handler TC5_Handler
#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
#endif
#define TONE_TC_TOP 0xFFFF
#define TONE_TC_CHANNEL 0
#if defined(__SAMD51__)
void TC2_Handler (void) __attribute__ ((weak, alias("Tone_Handler")));
#else
void TC5_Handler (void) __attribute__ ((weak, alias("Tone_Handler")));
#endif
static inline void resetTC (Tc* TCx)
{
// Disable TCx
@ -72,6 +68,14 @@ void toneAccurateClock (uint32_t accurateSystemCoreClockFrequency)
void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
{
// Avoid divide by zero error by calling 'noTone' instead
if (frequency == 0)
{
noTone(outputPin);
return;
}
// Configure interrupt request
NVIC_DisableIRQ(TONE_TC_IRQn);
NVIC_ClearPendingIRQ(TONE_TC_IRQn);
@ -80,7 +84,7 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
{
firstTimeRunning = true;
NVIC_SetPriority(TONE_TC_IRQn, 0);
NVIC_SetPriority(TONE_TC_IRQn, 5);
#if defined(__SAMD51__)
GCLK->PCHCTRL[TONE_TC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
@ -91,9 +95,6 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
#endif
}
//if it's a rest, set to 1Hz (below audio range)
frequency = (frequency > 0 ? frequency : 1);
if (toneIsActive && (outputPin != lastOutputPin))
noTone(lastOutputPin);
@ -178,11 +179,21 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
}
void noTone (uint32_t outputPin)
{
/* 'tone' need to run at least once in order to enable GCLK for
* the timers used for the tone-functionality. If 'noTone' is called
* without ever calling 'tone' before then 'WAIT_TC16_REGS_SYNC(TCx)'
* will wait infinitely. The variable 'firstTimeRunning' is set the
* 1st time 'tone' is set so it can be used to detect wether or not
* 'tone' has been called before.
*/
if(firstTimeRunning)
{
resetTC(TONE_TC);
digitalWrite(outputPin, LOW);
toneIsActive = false;
}
}
#ifdef __cplusplus
extern "C" {

View file

@ -16,6 +16,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef USE_TINYUSB
#include <Arduino.h>
#include <Reset.h> // Needed for auto-reset with 1200bps port touch
@ -257,6 +259,52 @@ Serial_::operator bool()
return result;
}
int32_t Serial_::readBreak() {
uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0);
// disable interrupts,
// to avoid clearing a breakValue that might occur
// while processing the current break value
__disable_irq();
int32_t ret = breakValue;
breakValue = -1;
if (enableInterrupts) {
// re-enable the interrupts
__enable_irq();
}
return ret;
}
unsigned long Serial_::baud() {
return _usbLineInfo.dwDTERate;
}
uint8_t Serial_::stopbits() {
return _usbLineInfo.bCharFormat;
}
uint8_t Serial_::paritytype() {
return _usbLineInfo.bParityType;
}
uint8_t Serial_::numbits() {
return _usbLineInfo.bDataBits;
}
bool Serial_::dtr() {
return _usbLineInfo.lineState & 0x1;
}
bool Serial_::rts() {
return _usbLineInfo.lineState & 0x2;
}
Serial_ Serial(USBDevice);
#endif
#endif // USE_TINYUSB

View file

@ -17,6 +17,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef USE_TINYUSB
#include "USBAPI.h"
#include "USBDesc.h"
#include "USBCore.h"
@ -114,3 +116,5 @@ PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT)
#endif
#endif
#endif // USE_TINYUSB

View file

@ -5,6 +5,7 @@
* Author: deanm
*/
#ifndef USE_TINYUSB
#include "SAMD21_USBDevice.h"
@ -36,3 +37,5 @@ void USBDevice_SAMD21G18x::calibrate() {
usb.PADCAL.bit.TRANSP = pad_transp;
usb.PADCAL.bit.TRIM = pad_trim;
}
#endif // USE_TINYUSB

View file

@ -85,7 +85,7 @@ public:
uint32_t sendControl(int /* ep */, const void *data, uint32_t len) { return sendControl(data, len); }
uint32_t recvControl(void *data, uint32_t len);
uint32_t sendConfiguration(uint32_t maxlen);
bool sendStringDescriptor(const uint8_t *string, uint8_t maxlen);
bool sendStringDescriptor(const uint8_t *string, uint32_t maxlen);
void initControl(int end);
uint8_t SendInterfaces(uint32_t* total);
void packMessages(bool val);

View file

@ -16,7 +16,7 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef USE_TINYUSB
#if defined(USBCON)
#include <Arduino.h>
@ -110,12 +110,12 @@ static EPHandler *epHandlers[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
// Send a USB descriptor string. The string is stored as a
// plain ASCII string but is sent out as UTF-16 with the
// correct 2-byte prefix
bool USBDeviceClass::sendStringDescriptor(const uint8_t *string, uint8_t maxlen)
bool USBDeviceClass::sendStringDescriptor(const uint8_t *string, uint32_t maxlen)
{
if (maxlen < 2)
return false;
uint8_t buffer[maxlen];
uint8_t* buffer = (uint8_t*)malloc(maxlen);
buffer[0] = strlen((const char*)string) * 2 + 2;
buffer[1] = 0x03;
@ -126,7 +126,9 @@ bool USBDeviceClass::sendStringDescriptor(const uint8_t *string, uint8_t maxlen)
buffer[i] = 0;
}
return USBDevice.sendControl(buffer, i);
bool ret = USBDevice.sendControl(buffer, i);
free(buffer);
return ret;
}
bool _dry_run = false;
@ -244,26 +246,25 @@ bool USBDeviceClass::sendDescriptor(USBSetup &setup)
}
else if (setup.wValueL == ISERIAL) {
#ifdef PLUGGABLE_USB_ENABLED
#if defined(__SAMD51__)
char name[ISERIAL_MAX_LEN];
PluggableUSB().getShortName(name);
return sendStringDescriptor((uint8_t*)name, setup.wLength);
#else
#ifdef __SAMD51__
#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x008061FC)
#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x00806010)
#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x00806014)
#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x00806018)
#else // samd21
// from section 9.3.3 of the datasheet
#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C)
#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040)
#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044)
#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048)
#endif
char name[ISERIAL_MAX_LEN];
utox8(SERIAL_NUMBER_WORD_0, &name[0]);
utox8(SERIAL_NUMBER_WORD_1, &name[8]);
utox8(SERIAL_NUMBER_WORD_2, &name[16]);
utox8(SERIAL_NUMBER_WORD_3, &name[24]);
PluggableUSB().getShortName(&name[32]);
name[32] = '\0';
return sendStringDescriptor((uint8_t*)name, setup.wLength);
#endif
#endif
}
else {
@ -878,6 +879,7 @@ bool USBDeviceClass::handleStandardSetup(USBSetup &setup)
sendZlp(0);
return true;
}
return false;
case SET_ADDRESS:
setAddress(setup.wValueL);
@ -1039,3 +1041,4 @@ void USBDeviceClass::ISRHandler()
USBDeviceClass USBDevice;
#endif
#endif // USE_TINYUSB

View file

@ -17,6 +17,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef USE_TINYUSB
#include <stdio.h>
#include <stdint.h>
@ -553,3 +554,5 @@ uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type)
// }
#endif // HOST_DEFINED
#endif // USE_TINYUSB

View file

@ -250,8 +250,9 @@ void detachInterrupt(uint32_t pin)
* External Interrupt Controller NVIC Interrupt Handler
*/
#if defined(__SAMD51__)
void InterruptHandler(uint32_t i)
void InterruptHandler(uint32_t unused_i)
{
(void)unused_i;
// Calling the routine directly from -here- takes about 1us
// Depending on where you are in the list it will take longer

View file

@ -31,7 +31,7 @@ extern "C" {
#define FALLING 3
#define RISING 4
#define DEFAULT 1
//#define DEFAULT 1
#define EXTERNAL 0
typedef void (*voidFuncPtr)(void);

View file

@ -693,12 +693,21 @@ void String::remove(unsigned int index){
}
void String::remove(unsigned int index, unsigned int count){
if (index >= len) { return; }
if (count <= 0) { return; }
if (count > len - index) { count = len - index; }
// removes characters from the middle of a string.
if (count <= 0) { return; } // exit if nothing to remove
if (index >= len) { return; } // ensure start is within string length; thus, ensures (len-index >= 1)
if (count > len - index) { // ensure characters to remove is no larger than total length remaining
count = len - index;
}
char *writeTo = buffer + index;
char *copyFrom = buffer + index + count;
len = len - count;
strncpy(writeTo, buffer + index + count,len - index);
// strncpy() cannot be used with overlapping buffers, so copy one char at a time
unsigned int charactersToMove = len - index; // yes, uses post-adjusted length
for (unsigned int i = 0; i < charactersToMove; i++, writeTo++, copyFrom++) {
*writeTo = *copyFrom;
}
buffer[len] = 0;
}

View file

@ -57,6 +57,8 @@ typedef enum _EAnalogChannel
ADC_Channel19=19,
DAC_Channel0,
DAC_Channel1,
ADC_Channel_Bandgap=0x1B,
ADC_Channel_PTAT=0x1C,
} EAnalogChannel ;
#if defined(__SAMD51__)
@ -88,7 +90,7 @@ typedef enum _ETCChannel
TC3_CH0 = (6<<8)|(0),
TC3_CH1 = (6<<8)|(1),
} ETCChannel ;
#elif defined(__SAMD51J19A__) || defined(__SAMD51J20A__)
#elif defined(__SAMD51J19A__) || defined(__SAMD51J20A__) || defined(__SAME51J19A__)
typedef enum _ETCChannel
{
@ -99,10 +101,16 @@ typedef enum _ETCChannel
TCC0_CH3 = (0<<8)|(3),
TCC0_CH4 = (0<<8)|(4),
TCC0_CH5 = (0<<8)|(5),
TCC0_CH6 = (0<<8)|(6),
TCC0_CH7 = (0<<8)|(7),
TCC1_CH0 = (1<<8)|(0),
TCC1_CH1 = (1<<8)|(1),
TCC1_CH2 = (1<<8)|(2),
TCC1_CH3 = (1<<8)|(3),
TCC1_CH4 = (1<<8)|(4),
TCC1_CH5 = (1<<8)|(5),
TCC1_CH6 = (1<<8)|(6),
TCC1_CH7 = (1<<8)|(7),
TCC2_CH0 = (2<<8)|(0),
TCC2_CH1 = (2<<8)|(1),
TCC2_CH2 = (2<<8)|(2),
@ -122,9 +130,13 @@ typedef enum _ETCChannel
TC4_CH1 = (9<<8)|(1),
TC5_CH0 = (10<<8)|(0),
TC5_CH1 = (10<<8)|(1),
TC6_CH0 = (11<<8)|(0),
TC6_CH1 = (11<<8)|(1),
TC7_CH0 = (12<<8)|(0),
TC7_CH1 = (12<<8)|(1),
} ETCChannel ;
#elif defined(__SAMD51P19A__) || defined(__SAMD51P20A__)
#elif defined(__SAME53N20A__) || defined(__SAME53N19A__) || defined(__SAME54P20A__) || defined(__SAME54P19A__) || defined(__SAME54N20A__) || defined(__SAME54N19A__) || defined(__SAMD51P20A__) || defined(__SAMD51P19A__) || defined(__SAMD51N20A__) || defined(__SAMD51N19A__) || defined(__SAME51N20A__) || defined(__SAME51N19A__)
typedef enum _ETCChannel
{
@ -198,6 +210,12 @@ typedef enum _ETCChannel
TC4_CH1 = (4<<8)|(1),
TC5_CH0 = (5<<8)|(0),
TC5_CH1 = (5<<8)|(1),
#if defined (__SAMD21J18A__)
TC6_CH0 = (6<<8)|(0),
TC6_CH1 = (6<<8)|(1),
TC7_CH0 = (7<<8)|(0),
TC7_CH1 = (7<<8)|(1),
#endif // __SAMD21J18A__
} ETCChannel ;
// Definitions for PWM channels

View file

@ -25,8 +25,14 @@
#ifndef _IO_H_
#define _IO_H_
#ifdef __SAMD51__
#define RAMSTART (HSRAM_ADDR)
#define RAMSIZE (HSRAM_SIZE)
#else
#define RAMSTART (HMCRAMC0_ADDR)
#define RAMSIZE (HMCRAMC0_SIZE)
#endif
#define RAMEND (RAMSTART + RAMSIZE - 1)
#endif

View file

@ -127,10 +127,13 @@ void SERCOM7_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Han
void SERCOM7_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM7_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM7_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void CAN0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void CAN1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void USB_0_Handler ( void ) __attribute__ ((weak));
void USB_1_Handler ( void ) __attribute__ ((weak));
void USB_2_Handler ( void ) __attribute__ ((weak));
void USB_3_Handler ( void ) __attribute__ ((weak));
void GMAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TCC0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
@ -193,6 +196,7 @@ extern uint32_t __bss_end__;
extern uint32_t __StackTop;
/* Exception Table */
__attribute__ ((used))
__attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table =
{
/* Configure Initial Stack Pointer, using linker-generated symbols */
@ -294,13 +298,13 @@ __attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table =
(void*) SERCOM7_1_Handler, /* 75 Serial Communication Interface 7 IRQ 1 */
(void*) SERCOM7_2_Handler, /* 76 Serial Communication Interface 7 IRQ 2 */
(void*) SERCOM7_3_Handler, /* 77 Serial Communication Interface 7 IRQ 3 */
(void*) (0UL),
(void*) (0UL),
(void*) CAN0_Handler, /* 78 Control Area Network 0 (SAM E5x) */
(void*) CAN1_Handler, /* 79 Control Area Network 0 (SAM E5x) */
(void*) USB_0_Handler, /* 80 Universal Serial Bus IRQ 0 */
(void*) USB_1_Handler, /* 81 Universal Serial Bus IRQ 1 */
(void*) USB_2_Handler, /* 82 Universal Serial Bus IRQ 2 */
(void*) USB_3_Handler, /* 83 Universal Serial Bus IRQ 3 */
(void*) (0UL),
(void*) GMAC_Handler, /* 84 Ethernet MAC */
(void*) TCC0_0_Handler, /* 85 Timer Counter Control 0 IRQ 0 */
(void*) TCC0_1_Handler, /* 86 Timer Counter Control 0 IRQ 1 */
(void*) TCC0_2_Handler, /* 87 Timer Counter Control 0 IRQ 2 */
@ -404,6 +408,7 @@ extern uint32_t __bss_end__;
extern uint32_t __StackTop;
/* Exception Table */
__attribute__ ((used))
__attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table =
{
/* Configure Initial Stack Pointer, using linker-generated symbols */

View file

@ -117,6 +117,17 @@ void SysTick_DefaultHandler(void)
tickReset();
}
#if defined(USE_TINYUSB)
// run TinyUSB background task when yield()
void yield(void)
{
TinyUSB_Device_Task();
TinyUSB_Device_FlushCDC();
}
#endif
#ifdef __cplusplus
}
#endif

View file

@ -28,6 +28,7 @@
static void __empty() {
// Empty
}
void yield(void) __attribute__ ((weak, alias("__empty")));
/**

View file

@ -39,7 +39,10 @@ int main( void )
initVariant();
delay(1);
#if defined(USBCON)
#if defined(USE_TINYUSB)
TinyUSB_Device_Init(0);
#elif defined(USBCON)
USBDevice.init();
USBDevice.attach();
#endif
@ -49,6 +52,8 @@ int main( void )
for (;;)
{
loop();
yield(); // yield run usb background task
if (serialEventRun) serialEventRun();
}

View file

@ -164,13 +164,14 @@ void arm_float_to_q12_20(float *pIn, q31_t * pOut, uint32_t numSamples)
uint32_t arm_compare_fixed_q15(q15_t *pIn, q15_t * pOut, uint32_t numSamples)
{
uint32_t i;
int32_t diff, diffCrnt = 0;
int32_t diff;
uint32_t diffCrnt = 0;
uint32_t maxDiff = 0;
for (i = 0; i < numSamples; i++)
{
diff = pIn[i] - pOut[i];
diffCrnt = (diff > 0) ? diff : -diff;
diffCrnt = (uint32_t)( (diff > 0) ? diff : -diff );
if(diffCrnt > maxDiff)
{
@ -192,13 +193,14 @@ uint32_t arm_compare_fixed_q15(q15_t *pIn, q15_t * pOut, uint32_t numSamples)
uint32_t arm_compare_fixed_q31(q31_t *pIn, q31_t * pOut, uint32_t numSamples)
{
uint32_t i;
int32_t diff, diffCrnt = 0;
int32_t diff;
uint32_t diffCrnt = 0;
uint32_t maxDiff = 0;
for (i = 0; i < numSamples; i++)
{
diff = pIn[i] - pOut[i];
diffCrnt = (diff > 0) ? diff : -diff;
diffCrnt = (uint32_t)( (diff > 0) ? diff : -diff );
if(diffCrnt > maxDiff)
{

View file

@ -41,10 +41,10 @@ uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
* No assembly required, no conversion of loop counts to times (which is
* worrisome in the presence of cache.)
*/
volatile uint32_t *port = &(PORT->Group[p.ulPort].IN.reg);
const volatile uint32_t *port = &(PORT->Group[p.ulPort].IN.reg);
uint32_t usCallStart; // microseconds at start of call, for timeout.
uint32_t usPulseStart; // microseconds at start of measured pulse.
usCallStart = micros();
usCallStart = usPulseStart = micros();
// wait for any previous pulse to end
while ((*port & bit) == stateMask) {
if (micros() - usCallStart > timeout)

View file

@ -63,7 +63,7 @@ void SystemInit( void )
* 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
*/
OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_CGM_XT | OSC32KCTRL_XOSC32K_XTALEN;
OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_EN1K | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_CGM_XT | OSC32KCTRL_XOSC32K_XTALEN;
while( (OSC32KCTRL->STATUS.reg & OSC32KCTRL_STATUS_XOSC32KRDY) == 0 ){
/* Wait for oscillator to be ready */
@ -261,6 +261,47 @@ void SystemInit( void )
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
/* ----------------------------------------------------------------------------------------------
* 5) Load AC factory calibration values
*/
uint32_t bias0 = (*((uint32_t *)AC_FUSES_BIAS0_ADDR) & AC_FUSES_BIAS0_Msk) >> AC_FUSES_BIAS0_Pos;
AC->CALIB.reg = AC_CALIB_BIAS0(bias0);
/* ----------------------------------------------------------------------------------------------
* 6) Load ADC factory calibration values
*/
// ADC0 Bias Calibration
uint32_t biascomp = (*((uint32_t *)ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
uint32_t biasr2r = (*((uint32_t *)ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
uint32_t biasref = (*((uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
ADC0->CALIB.reg = ADC_CALIB_BIASREFBUF(biasref)
| ADC_CALIB_BIASR2R(biasr2r)
| ADC_CALIB_BIASCOMP(biascomp);
// ADC1 Bias Calibration
biascomp = (*((uint32_t *)ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
biasr2r = (*((uint32_t *)ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
biasref = (*((uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
ADC1->CALIB.reg = ADC_CALIB_BIASREFBUF(biasref)
| ADC_CALIB_BIASR2R(biasr2r)
| ADC_CALIB_BIASCOMP(biascomp);
/* ----------------------------------------------------------------------------------------------
* 7) Load USB factory calibration values
*/
//USB Calibration
uint32_t usbtransn = (*((uint32_t *)USB_FUSES_TRANSN_ADDR) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
uint32_t usbtransp = (*((uint32_t *)USB_FUSES_TRANSP_ADDR) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
uint32_t usbtrim = (*((uint32_t *)USB_FUSES_TRIM_ADDR) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos;
USB->DEVICE.PADCAL.reg = USB_PADCAL_TRIM(usbtrim)
| USB_PADCAL_TRANSN(usbtransn)
| USB_PADCAL_TRANSP(usbtransp);
//*************** END SAMD51 *************************//
#else
@ -536,4 +577,3 @@ void SystemInit( void )
NVMCTRL->CTRLB.bit.MANW = 1;
#endif
}

View file

@ -92,7 +92,7 @@ void init( void )
PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 | PM_APBCMASK_SERCOM3 | PM_APBCMASK_SERCOM4 | PM_APBCMASK_SERCOM5 ;
// Clock TC/TCC for Pulse and Analog
PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 ;
PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 | PM_APBCMASK_TC6 | PM_APBCMASK_TC7;
// ATSAMR, for example, doesn't have a DAC
#ifdef PM_APBCMASK_DAC

View file

@ -32,7 +32,7 @@ static int _writeResolution = 12;
static int _dacResolution = 12;
#else
static int _writeResolution = 8;
static int _dacResolution = 10;
//static int _dacResolution = 10;
#endif
@ -280,8 +280,8 @@ uint32_t analogRead(uint32_t pin)
#ifdef DAC
#if defined(__SAMD51__)
if (pin == A0 || pin == A1) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
uint8_t channel = (pin == PIN_A0 ? 0 : 1);
if (pin == PIN_DAC0 || pin == PIN_DAC1) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
uint8_t channel = (pin == PIN_DAC0 ? 0 : 1);
if(dacEnabled[channel]){
dacEnabled[channel] = false;
@ -298,7 +298,7 @@ uint32_t analogRead(uint32_t pin)
while (DAC->SYNCBUSY.bit.ENABLE);
#else
if (pin == A0) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
if (pin == PIN_DAC0) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
syncDAC();
DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC
@ -375,6 +375,9 @@ uint32_t analogRead(uint32_t pin)
syncADC();
ADC->SWTRIG.bit.START = 1;
// Waiting for the 1st conversion to complete
while (ADC->INTFLAG.bit.RESRDY == 0);
// Clear the Data Ready flag
ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;
@ -410,9 +413,9 @@ void analogWrite(uint32_t pin, uint32_t value)
{
// DAC handling code
#if defined(__SAMD51__)
if (pin == PIN_A0 || pin == PIN_A1) { // 2 DACs on A0 (PA02) and A1 (PA05)
if (pin == PIN_DAC0 || pin == PIN_DAC1) { // 2 DACs on A0 (PA02) and A1 (PA05)
#else
if (pin == PIN_A0) { // Only 1 DAC on A0 (PA02)
if (pin == PIN_DAC0) { // Only 1 DAC on A0 (PA02)
#endif
#if defined(__SAMD51__)
@ -420,7 +423,7 @@ void analogWrite(uint32_t pin, uint32_t value)
value = mapResolution(value, _writeResolution, _dacResolution);
uint8_t channel = (pin == PIN_A0 ? 0 : 1);
uint8_t channel = (pin == PIN_DAC0 ? 0 : 1);
pinPeripheral(pin, PIO_ANALOG);

View file

@ -30,39 +30,43 @@ void pinMode( uint32_t ulPin, uint32_t ulMode )
return ;
}
EPortType port = g_APinDescription[ulPin].ulPort;
uint32_t pin = g_APinDescription[ulPin].ulPin;
uint32_t pinMask = (1ul << pin);
// Set pin mode according to chapter '22.6.3 I/O Pin Configuration'
switch ( ulMode )
{
case INPUT:
// Set pin to input mode
PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
PORT->Group[port].PINCFG[pin].reg = (uint8_t) (PORT_PINCFG_INEN);
PORT->Group[port].DIRCLR.reg = pinMask;
break;
case INPUT_PULLUP:
// Set pin to input mode with pull-up resistor enabled
PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
PORT->Group[port].PINCFG[pin].reg = (uint8_t) (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN);
PORT->Group[port].DIRCLR.reg = pinMask;
// Enable pull level (cf '22.6.3.2 Input Configuration' and '22.8.7 Data Output Value Set')
PORT->Group[g_APinDescription[ulPin].ulPort].OUTSET.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
PORT->Group[port].OUTSET.reg = pinMask;
break;
case INPUT_PULLDOWN:
// Set pin to input mode with pull-down resistor enabled
PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
PORT->Group[port].PINCFG[pin].reg = (uint8_t) (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN);
PORT->Group[port].DIRCLR.reg = pinMask;
// Enable pull level (cf '22.6.3.2 Input Configuration' and '22.8.6 Data Output Value Clear')
PORT->Group[g_APinDescription[ulPin].ulPort].OUTCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
PORT->Group[port].OUTCLR.reg = pinMask;
break;
case OUTPUT:
// enable input, to support reading back values, with pullups disabled
PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
PORT->Group[port].PINCFG[pin].reg = (uint8_t) (PORT_PINCFG_INEN | PORT_PINCFG_DRVSTR);
// Set pin to output mode
PORT->Group[g_APinDescription[ulPin].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
PORT->Group[port].DIRSET.reg = pinMask;
break;
default:

View file

@ -25,6 +25,8 @@
#include "WVariant.h"
typedef int PinStatus;
/**
* \brief Configures the specified pin to behave either as an input or an output. See the description of digital pins for details.
*

@ -0,0 +1 @@
Subproject commit c953968c468218d8968138b5ed8482fa565373df

@ -0,0 +1 @@
Subproject commit acc5dadb458b2c329757a61dc4f18dda945a0c36

View file

@ -1,654 +0,0 @@
#include <Adafruit_ZeroDMA.h>
#include <malloc.h> // memalign() function
#include "utility/dma.h"
static volatile uint32_t _channelMask = 0; // Bitmask of allocated channels
// DMA descriptor list entry point (and writeback buffer) per channel
__attribute__((__aligned__(16))) static DmacDescriptor // 128 bit alignment
_descriptor[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR,
_writeback[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR;
// Pointer to ZeroDMA object for each channel is needed for the
// ISR (in C, outside of class context) to access callbacks.
static Adafruit_ZeroDMA *_dmaPtr[DMAC_CH_NUM] = { 0 }; // Init to NULL
// Adapted from ASF3 interrupt_sam_nvic.c:
static volatile unsigned long cpu_irq_critical_section_counter = 0;
static volatile unsigned char cpu_irq_prev_interrupt_state = 0;
static void cpu_irq_enter_critical(void) {
if(!cpu_irq_critical_section_counter) {
if(__get_PRIMASK() == 0) { // IRQ enabled?
__disable_irq(); // Disable it
__DMB();
cpu_irq_prev_interrupt_state = 1;
} else {
// Make sure the to save the prev state as false
cpu_irq_prev_interrupt_state = 0;
}
}
cpu_irq_critical_section_counter++;
}
static void cpu_irq_leave_critical(void) {
// Check if the user is trying to leave a critical section
// when not in a critical section
if(cpu_irq_critical_section_counter > 0) {
cpu_irq_critical_section_counter--;
// Only enable global interrupts when the counter
// reaches 0 and the state of the global interrupt flag
// was enabled when entering critical state */
if((!cpu_irq_critical_section_counter) &&
cpu_irq_prev_interrupt_state) {
__DMB();
__enable_irq();
}
}
}
// CONSTRUCTOR -------------------------------------------------------------
// Constructor initializes Adafruit_ZeroDMA basics but does NOT allocate a
// DMA channel (that's done in allocate()) or start a job (that's done in
// startJob()). This is because constructors in a global context are called
// before a sketch's setup() function, which may have some other hardware
// initialization of its own, don't want it clobbering us.
Adafruit_ZeroDMA::Adafruit_ZeroDMA(void) {
channel = 0xFF; // Channel not yet allocated
jobStatus = DMA_STATUS_OK;
hasDescriptors = false; // No descriptors allocated yet
loopFlag = false;
peripheralTrigger = 0; // Software trigger only by default
triggerAction = DMA_TRIGGER_ACTON_TRANSACTION;
memset(callback, 0, sizeof(callback));
}
// TODO: add destructor? Should stop job, delete descriptors, free channel.
// INTERRUPT SERVICE ROUTINE -----------------------------------------------
// This is a C function that exists outside the Adafruit_ZeroDMA context.
// DMA channel number is determined from the INTPEND register, from this
// we get a ZeroDMA object pointer through the _dmaPtr[] array.
// (It's done this way because jobStatus and callback[] are protected
// elements in the ZeroDMA object -- we can't touch them in C, but the
// next function after this, being part of the ZeroDMA class, can.)
#ifdef __SAMD51__
void DMAC_0_Handler(void) {
#else
void DMAC_Handler(void) {
#endif
cpu_irq_enter_critical();
uint8_t channel = DMAC->INTPEND.bit.ID; // Channel # causing interrupt
if(channel < DMAC_CH_NUM) {
Adafruit_ZeroDMA *dma;
if((dma = _dmaPtr[channel])) { // -> Channel's ZeroDMA object
#ifdef __SAMD51__
// Call IRQ handler with channel #
dma->_IRQhandler(channel);
#else
DMAC->CHID.bit.ID = channel;
// Call IRQ handler with interrupt flag(s)
dma->_IRQhandler(DMAC->CHINTFLAG.reg);
#endif
}
}
cpu_irq_leave_critical();
}
#ifdef __SAMD51__
void DMAC_1_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
void DMAC_2_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
void DMAC_3_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
void DMAC_4_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
#endif
void Adafruit_ZeroDMA::_IRQhandler(uint8_t flags) {
#ifdef __SAMD51__
// 'flags' is initially passed in as channel number,
// from which we look up the actual interrupt flags...
flags = DMAC->Channel[flags].CHINTFLAG.reg;
#endif
if(flags & DMAC_CHINTENCLR_TERR) {
// Clear error flag
#ifdef __SAMD51__
DMAC->Channel[channel].CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
#else
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
#endif
jobStatus = DMA_STATUS_ERR_IO;
if(callback[DMA_CALLBACK_TRANSFER_ERROR]) {
callback[DMA_CALLBACK_TRANSFER_ERROR](this);
}
} else if(flags & DMAC_CHINTENCLR_TCMPL) {
// Clear transfer complete flag
#ifdef __SAMD51__
DMAC->Channel[channel].CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
#else
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
#endif
jobStatus = DMA_STATUS_OK;
if(callback[DMA_CALLBACK_TRANSFER_DONE]) {
callback[DMA_CALLBACK_TRANSFER_DONE](this);
}
} else if(flags & DMAC_CHINTENCLR_SUSP) {
// Clear channel suspend flag
#ifdef __SAMD51__
DMAC->Channel[channel].CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP;
#else
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP;
#endif
jobStatus = DMA_STATUS_SUSPEND;
if(callback[DMA_CALLBACK_CHANNEL_SUSPEND]) {
callback[DMA_CALLBACK_CHANNEL_SUSPEND](this);
}
}
}
// DMA CHANNEL FUNCTIONS ---------------------------------------------------
// Allocates channel for ZeroDMA object
ZeroDMAstatus Adafruit_ZeroDMA::allocate(void) {
if(channel < DMAC_CH_NUM) return DMA_STATUS_OK; // Already alloc'd!
// Find index of first free DMA channel. As currently written,
// this "does not play well with others" as it assumes _channelMask
// is the final arbiter of channels in use (this is true only within
// this library -- but other DMA-driven code may have allocated its
// own channel(s) elsewhere, sometimes with an equally broken
// approach). A possible alternate approach, I haven't tested this
// yet, might be to loop through each channel, set DMAC->CHID.bit.ID
// and then test whether CHCTRLA.bit.ENABLE is set? But for now...
for(channel=0; (channel < DMAC_CH_NUM) &&
(_channelMask & (1 << channel)); channel++);
// Doesn't help that code later does a software reset of the DMA
// controller, which would blow out other DMA-using libraries
// anyway (or they're just as likely to blow out this one).
// I think it's just an all-or-nothing affair...use one library
// for DMA everything, never mix and match.
if(channel >= DMAC_CH_NUM) { // No free channel!
return DMA_STATUS_ERR_NOT_FOUND;
}
cpu_irq_enter_critical();
if(!_channelMask) { // No channels allocated yet; initialize DMA!
#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21)
PM->AHBMASK.bit.DMAC_ = 1;
#elif defined(__SAMD51__)
MCLK->AHBMASK.bit.DMAC_ = 1; // Initialize DMA clocks
#else
PM->AHBMASK.bit.DMAC_ = 1; // Initialize DMA clocks
PM->APBBMASK.bit.DMAC_ = 1;
#endif
DMAC->CTRL.bit.DMAENABLE = 0; // Disable DMA controller
DMAC->CTRL.bit.SWRST = 1; // Perform software reset
// Initialize descriptor list addresses
DMAC->BASEADDR.bit.BASEADDR = (uint32_t)_descriptor;
DMAC->WRBADDR.bit.WRBADDR = (uint32_t)_writeback;
memset(_descriptor, 0, sizeof(_descriptor));
memset(_writeback , 0, sizeof(_writeback));
// Re-enable DMA controller with all priority levels
DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xF);
// Enable DMA interrupt at lowest priority
#ifdef __SAMD51__
IRQn_Type irqs[] = { DMAC_0_IRQn, DMAC_1_IRQn, DMAC_2_IRQn,
DMAC_3_IRQn, DMAC_4_IRQn };
for(uint8_t i=0; i<(sizeof irqs / sizeof irqs[0]); i++) {
NVIC_EnableIRQ(irqs[i]);
NVIC_SetPriority(irqs[i], (1<<__NVIC_PRIO_BITS)-1);
}
#else
NVIC_EnableIRQ(DMAC_IRQn);
NVIC_SetPriority(DMAC_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
#endif
}
_channelMask |= 1 << channel; // Mark channel as allocated
_dmaPtr[channel] = this; // Channel-index-to-object pointer
// Reset the allocated channel
#ifdef __SAMD51__
DMAC->Channel[channel].CHCTRLA.bit.ENABLE = 0;
DMAC->Channel[channel].CHCTRLA.bit.SWRST = 1;
#else
DMAC->CHID.bit.ID = channel;
DMAC->CHCTRLA.bit.ENABLE = 0;
DMAC->CHCTRLA.bit.SWRST = 1;
#endif
// Clear software trigger
DMAC->SWTRIGCTRL.reg &= ~(1 << channel);
// Configure default behaviors
#ifdef __SAMD51__
DMAC->Channel[channel].CHPRILVL.bit.PRILVL = 0;
DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC = peripheralTrigger;
DMAC->Channel[channel].CHCTRLA.bit.TRIGACT = triggerAction;
DMAC->Channel[channel].CHCTRLA.bit.BURSTLEN =
DMAC_CHCTRLA_BURSTLEN_SINGLE_Val; // Single-beat burst length
#else
DMAC->CHCTRLB.bit.LVL = 0;
DMAC->CHCTRLB.bit.TRIGSRC = peripheralTrigger;
DMAC->CHCTRLB.bit.TRIGACT = triggerAction;
#endif
cpu_irq_leave_critical();
return DMA_STATUS_OK;
}
void Adafruit_ZeroDMA::setPriority(dma_priority pri) const {
#ifdef __SAMD51__
DMAC->Channel[channel].CHPRILVL.bit.PRILVL = pri;
#else
DMAC->CHCTRLB.bit.LVL = pri;
#endif
}
// Deallocate DMA channel
// TODO: should this delete/deallocate the descriptor list?
ZeroDMAstatus Adafruit_ZeroDMA::free(void) {
ZeroDMAstatus status = DMA_STATUS_OK;
cpu_irq_enter_critical(); // jobStatus is volatile
if(jobStatus == DMA_STATUS_BUSY) {
status = DMA_STATUS_BUSY; // Can't leave when busy
} else if((channel < DMAC_CH_NUM) && (_channelMask & (1 << channel))) {
// Valid in-use channel; release it
_channelMask &= ~(1 << channel); // Clear bit
if(!_channelMask) { // No more channels in use?
#ifdef __SAMD51__
NVIC_DisableIRQ(DMAC_0_IRQn); // Disable DMA interrupt
DMAC->CTRL.bit.DMAENABLE = 0; // Disable DMA
MCLK->AHBMASK.bit.DMAC_ = 0; // Disable DMA clock
#else
NVIC_DisableIRQ(DMAC_IRQn); // Disable DMA interrupt
DMAC->CTRL.bit.DMAENABLE = 0; // Disable DMA
PM->APBBMASK.bit.DMAC_ = 0; // Disable DMA clocks
PM->AHBMASK.bit.DMAC_ = 0;
#endif
}
_dmaPtr[channel] = NULL;
channel = 0xFF;
} else {
status = DMA_STATUS_ERR_NOT_INITIALIZED; // Channel not in use
}
cpu_irq_leave_critical();
return status;
}
// Start DMA transfer job. Channel and descriptors should be allocated
// before calling this.
ZeroDMAstatus Adafruit_ZeroDMA::startJob(void) {
ZeroDMAstatus status = DMA_STATUS_OK;
cpu_irq_enter_critical(); // Job status is volatile
if(jobStatus == DMA_STATUS_BUSY) {
status = DMA_STATUS_BUSY; // Resource is busy
} else if(channel >= DMAC_CH_NUM) {
status = DMA_STATUS_ERR_NOT_INITIALIZED; // Channel not in use
} else if(!hasDescriptors || (_descriptor[channel].BTCNT.reg <= 0)) {
status = DMA_STATUS_ERR_INVALID_ARG; // Bad transfer size
} else {
uint8_t i, interruptMask = 0;
for(i=0; i<DMA_CALLBACK_N; i++) {
if(callback[i]) interruptMask |= (1 << i);
}
jobStatus = DMA_STATUS_BUSY;
#ifdef __SAMD51__
DMAC->Channel[channel].CHINTENSET.reg =
DMAC_CHINTENSET_MASK & interruptMask;
DMAC->Channel[channel].CHINTENCLR.reg =
DMAC_CHINTENCLR_MASK & ~interruptMask;
DMAC->Channel[channel].CHCTRLA.bit.ENABLE = 1;
#else
DMAC->CHID.bit.ID = channel;
DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK & interruptMask;
DMAC->CHINTENCLR.reg = DMAC_CHINTENCLR_MASK & ~interruptMask;
DMAC->CHCTRLA.bit.ENABLE = 1; // Enable the transfer channel
#endif
}
cpu_irq_leave_critical();
return status;
}
// Set and enable callback function for ZeroDMA object. This can be called
// before or after channel and/or descriptors are allocated, but needs
// to be called before job is started.
void Adafruit_ZeroDMA::setCallback(
void (*cb)(Adafruit_ZeroDMA *), dma_callback_type type) {
callback[type] = cb;
}
// Suspend/resume don't quite do what I thought -- avoid using for now.
void Adafruit_ZeroDMA::suspend(void) const {
cpu_irq_enter_critical();
#ifdef __SAMD51__
DMAC->Channel[channel].CHCTRLB.reg |= DMAC_CHCTRLB_CMD_SUSPEND;
#else
DMAC->CHID.bit.ID = channel;
DMAC->CHCTRLB.reg |= DMAC_CHCTRLB_CMD_SUSPEND;
#endif
cpu_irq_leave_critical();
}
#define MAX_JOB_RESUME_COUNT 10000
void Adafruit_ZeroDMA::resume(void) {
cpu_irq_enter_critical(); // jobStatus is volatile
if(jobStatus == DMA_STATUS_SUSPEND) {
int count;
uint32_t bitMask = 1 << channel;
#ifdef __SAMD51__
DMAC->Channel[channel].CHCTRLB.reg |= DMAC_CHCTRLB_CMD_RESUME;
#else
DMAC->CHID.bit.ID = channel;
DMAC->CHCTRLB.reg |= DMAC_CHCTRLB_CMD_RESUME;
#endif
for(count = 0; (count < MAX_JOB_RESUME_COUNT) &&
!(DMAC->BUSYCH.reg & bitMask); count++);
jobStatus = (count < MAX_JOB_RESUME_COUNT) ?
DMA_STATUS_BUSY : DMA_STATUS_ERR_TIMEOUT;
}
cpu_irq_leave_critical();
}
// Abort is OK though.
void Adafruit_ZeroDMA::abort(void) {
if(channel <= DMAC_CH_NUM) {
cpu_irq_enter_critical();
#ifdef __SAMD51__
DMAC->Channel[channel].CHCTRLA.reg = 0; // Disable channel
#else
DMAC->CHID.bit.ID = channel; // Select channel
DMAC->CHCTRLA.reg = 0; // Disable
#endif
jobStatus = DMA_STATUS_ABORTED;
cpu_irq_leave_critical();
}
}
// Set DMA peripheral trigger.
// This can be done before or after channel is allocated.
void Adafruit_ZeroDMA::setTrigger(uint8_t trigger) {
peripheralTrigger = trigger; // Save value for allocate()
// If channel already allocated, configure peripheral trigger
// (old lib required configure before alloc -- either way OK now)
if(channel < DMAC_CH_NUM) {
cpu_irq_enter_critical();
#ifdef __SAMD51__
DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC = trigger;
#else
DMAC->CHID.bit.ID = channel;
DMAC->CHCTRLB.bit.TRIGSRC = trigger;
#endif
cpu_irq_leave_critical();
}
}
// Set DMA trigger action.
// This can be done before or after channel is allocated.
void Adafruit_ZeroDMA::setAction(dma_transfer_trigger_action action) {
triggerAction = action; // Save value for allocate()
// If channel already allocated, configure trigger action
// (old lib required configure before alloc -- either way OK now)
if(channel < DMAC_CH_NUM) {
cpu_irq_enter_critical();
#ifdef __SAMD51__
DMAC->Channel[channel].CHCTRLA.bit.TRIGACT = action;
#else
DMAC->CHID.bit.ID = channel;
DMAC->CHCTRLB.bit.TRIGACT = action;
#endif
cpu_irq_leave_critical();
}
}
// Issue software trigger. Channel must be allocated & descriptors added!
void Adafruit_ZeroDMA::trigger(void) const {
if((channel <= DMAC_CH_NUM) & hasDescriptors) {
DMAC->SWTRIGCTRL.reg |= (1 << channel);
}
}
// Returns true if DMA transfer in progress.
bool Adafruit_ZeroDMA::isActive(void) const {
return _writeback[channel].BTCTRL.bit.VALID;
}
// DMA DESCRIPTOR FUNCTIONS ------------------------------------------------
// Allocates a new DMA descriptor (if needed) and appends it to the
// channel's descriptor list. Returns pointer to DmacDescriptor,
// or NULL on various errors. You'll want to keep the pointer for
// later if you need to modify or free the descriptor.
// Channel must be allocated first!
DmacDescriptor *Adafruit_ZeroDMA::addDescriptor(
void *src,
void *dst,
uint32_t count,
dma_beat_size size,
bool srcInc,
bool dstInc,
uint32_t stepSize,
bool stepSel) {
// Channel must be allocated first
if(channel >= DMAC_CH_NUM) return NULL;
// Can't do while job's busy
if(jobStatus == DMA_STATUS_BUSY) return NULL;
DmacDescriptor *desc;
// Scan descriptor list to find last entry. If an entry's
// DESCADDR value is 0, that's the end of the list and it's
// currently un-looped. If the DESCADDR value is the same
// as the first entry, that's the end of the list and it's
// looped. Either way, set the last entry's DESCADDR value
// to the new descriptor, and the descriptor's own DESCADDR
// will be set later either to 0 or the list head.
if(hasDescriptors) {
// DMA descriptors must be 128-bit (16 byte) aligned.
// memalign() is considered 'obsolete' but it's replacements
// (aligned_alloc() or posix_memalign()) are not currently
// available in the version of ARM GCC in use, but this is,
// so here we are.
if(!(desc = (DmacDescriptor *)memalign(16, sizeof(DmacDescriptor)))) {
return NULL;
}
DmacDescriptor *prev = &_descriptor[channel];
while(prev->DESCADDR.reg &&
(prev->DESCADDR.reg != (uint32_t)&_descriptor[channel])) {
prev = (DmacDescriptor *)prev->DESCADDR.reg;
}
prev->DESCADDR.reg = (uint32_t)desc;
} else {
desc = &_descriptor[channel];
}
hasDescriptors = true;
uint8_t bytesPerBeat; // Beat transfer size IN BYTES
switch(size) {
default: bytesPerBeat = 1; break;
case DMA_BEAT_SIZE_HWORD: bytesPerBeat = 2; break;
case DMA_BEAT_SIZE_WORD: bytesPerBeat = 4; break;
}
desc->BTCTRL.bit.VALID = true;
desc->BTCTRL.bit.EVOSEL = DMA_EVENT_OUTPUT_DISABLE;
desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_NOACT;
desc->BTCTRL.bit.BEATSIZE = size;
desc->BTCTRL.bit.SRCINC = srcInc;
desc->BTCTRL.bit.DSTINC = dstInc;
desc->BTCTRL.bit.STEPSEL = stepSel;
desc->BTCTRL.bit.STEPSIZE = stepSize;
desc->BTCNT.reg = count;
desc->SRCADDR.reg = (uint32_t)src;
if(srcInc) {
if(stepSel) {
desc->SRCADDR.reg += bytesPerBeat * count * (1 << stepSize);
} else {
desc->SRCADDR.reg += bytesPerBeat * count;
}
}
desc->DSTADDR.reg = (uint32_t)dst;
if(dstInc) {
if(!stepSel) {
desc->DSTADDR.reg += bytesPerBeat * count * (1 << stepSize);
} else {
desc->DSTADDR.reg += bytesPerBeat * count;
}
}
desc->DESCADDR.reg = loopFlag ? (uint32_t)&_descriptor[channel] : 0;
return desc;
}
// Modify DMA descriptor with a new source address, destination address &
// block transfer count. All other attributes (including increment enables,
// etc.) are unchanged. Mostly for changing the data being pushed to a
// peripheral (DAC, SPI, whatev.)
void Adafruit_ZeroDMA::changeDescriptor(DmacDescriptor *desc,
void *src, void *dst, uint32_t count) {
uint8_t bytesPerBeat; // Beat transfer size IN BYTES
switch(desc->BTCTRL.bit.BEATSIZE) {
default: bytesPerBeat = 1; break;
case DMA_BEAT_SIZE_HWORD: bytesPerBeat = 2; break;
case DMA_BEAT_SIZE_WORD: bytesPerBeat = 4; break;
}
if(count) desc->BTCNT.reg = count;
if(src) {
desc->SRCADDR.reg = (uint32_t)src;
if(desc->BTCTRL.bit.SRCINC) {
if(desc->BTCTRL.bit.STEPSEL) {
desc->SRCADDR.reg += desc->BTCNT.reg *
bytesPerBeat * (1 << desc->BTCTRL.bit.STEPSIZE);
} else {
desc->SRCADDR.reg += desc->BTCNT.reg * bytesPerBeat;
}
}
}
if(dst) {
desc->DSTADDR.reg = (uint32_t)dst;
if(desc->BTCTRL.bit.DSTINC) {
if(!desc->BTCTRL.bit.STEPSEL) {
desc->DSTADDR.reg += desc->BTCNT.reg *
bytesPerBeat * (1 << desc->BTCTRL.bit.STEPSIZE);
} else {
desc->DSTADDR.reg += desc->BTCNT.reg * bytesPerBeat;
}
}
}
// I think this code is here by accident -- disabling for now.
#if 0
cpu_irq_enter_critical();
jobStatus = DMA_STATUS_OK;
#ifdef __SAMD51__
DMAC->Channel[channel].CHCTRLA.bit.ENABLE = 1;
#else
DMAC->CHID.bit.ID = channel;
DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
#endif
cpu_irq_leave_critical();
#endif
}
// TODO: delete descriptor, delete whole descriptor chain
// Select whether channel's descriptor list should repeat or not.
// This can be done before or after channel & any descriptors are allocated.
void Adafruit_ZeroDMA::loop(boolean flag) {
// The loop selection is 'sticky' -- that is, you can enable or
// disable looping before a descriptor list is built, or after
// the fact. This requires some extra steps in the library code
// but avoids a must-do-in-X-order constraint on user.
loopFlag = flag;
if(hasDescriptors) { // Descriptor list already started?
// Scan descriptor list to find last entry. If an entry's
// DESCADDR value is 0, that's the end of the list and it's
// currently un-looped. If the DESCADDR value is the same
// as the first entry, that's the end of the list and it's
// already looped.
DmacDescriptor *desc = &_descriptor[channel];
while(desc->DESCADDR.reg &&
(desc->DESCADDR.reg != (uint32_t)&_descriptor[channel])) {
desc = (DmacDescriptor *)desc->DESCADDR.reg;
}
// Loop or unloop descriptor list as appropriate
desc->DESCADDR.reg = loopFlag ? (uint32_t)&_descriptor[channel] : 0;
}
}
// MISCELLANY --------------------------------------------------------------
void Adafruit_ZeroDMA::printStatus(ZeroDMAstatus s) const {
if(s == DMA_STATUS_JOBSTATUS) s = jobStatus;
Serial.print("Status: ");
switch(s) {
case DMA_STATUS_OK:
Serial.println("OK");
break;
case DMA_STATUS_ERR_NOT_FOUND:
Serial.println("NOT FOUND");
break;
case DMA_STATUS_ERR_NOT_INITIALIZED:
Serial.println("NOT INITIALIZED");
break;
case DMA_STATUS_ERR_INVALID_ARG:
Serial.println("INVALID ARGUMENT");
break;
case DMA_STATUS_ERR_IO:
Serial.println("IO ERROR");
break;
case DMA_STATUS_ERR_TIMEOUT:
Serial.println("TIMEOUT");
break;
case DMA_STATUS_BUSY:
Serial.println("BUSY");
break;
case DMA_STATUS_SUSPEND:
Serial.println("SUSPENDED");
break;
case DMA_STATUS_ABORTED:
Serial.println("ABORTED");
break;
default:
Serial.print("Unknown 0x");
Serial.println((int)s);
break;
}
}

View file

@ -1,66 +0,0 @@
#ifndef _ADAFRUIT_ZERODMA_H_
#define _ADAFRUIT_ZERODMA_H_
#include "Arduino.h"
#include "utility/dma.h"
// Status codes returned by some DMA functions and/or held in
// a channel's jobStatus variable.
enum ZeroDMAstatus {
DMA_STATUS_OK = 0,
DMA_STATUS_ERR_NOT_FOUND,
DMA_STATUS_ERR_NOT_INITIALIZED,
DMA_STATUS_ERR_INVALID_ARG,
DMA_STATUS_ERR_IO,
DMA_STATUS_ERR_TIMEOUT,
DMA_STATUS_BUSY,
DMA_STATUS_SUSPEND,
DMA_STATUS_ABORTED,
DMA_STATUS_JOBSTATUS = -1 // For printStatus() function
};
class Adafruit_ZeroDMA {
public:
Adafruit_ZeroDMA(void);
// DMA channel functions
ZeroDMAstatus allocate(void), // Allocates DMA channel
startJob(void),
free(void); // Deallocates DMA channel
void trigger(void) const,
setTrigger(uint8_t trigger),
setAction(dma_transfer_trigger_action action),
setCallback(void (*callback)(Adafruit_ZeroDMA *) = NULL,
dma_callback_type type = DMA_CALLBACK_TRANSFER_DONE),
loop(boolean flag),
suspend(void) const,
resume(void),
abort(void),
setPriority(dma_priority pri) const,
printStatus(ZeroDMAstatus s = DMA_STATUS_JOBSTATUS) const;
uint8_t getChannel(void) const { return channel; }
// DMA descriptor functions
DmacDescriptor *addDescriptor(void *src, void *dst, uint32_t count = 0,
dma_beat_size size = DMA_BEAT_SIZE_BYTE,
bool srcInc = true, bool dstInc = true,
uint32_t stepSize = DMA_ADDRESS_INCREMENT_STEP_SIZE_1,
bool stepSel = DMA_STEPSEL_DST);
void changeDescriptor(DmacDescriptor *d, void *src = NULL,
void *dst = NULL, uint32_t count = 0);
bool isActive(void) const;
void _IRQhandler(uint8_t flags); // DO NOT TOUCH
protected:
uint8_t channel;
volatile enum ZeroDMAstatus jobStatus;
bool hasDescriptors;
bool loopFlag;
uint8_t peripheralTrigger;
dma_transfer_trigger_action triggerAction;
void (*callback[DMA_CALLBACK_N])(Adafruit_ZeroDMA *);
};
#endif // _ADAFRUIT_ZERODMA_H_

View file

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 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.

View file

@ -1,6 +0,0 @@
# Adafruit_ZeroDMA
DMA helper/wrapped for ATSAMD21 such as Arduino Zero &amp; Feather M0
Current version of this library no longer requires Adafruit_ASFcore as a prerequisite. However...IT BREAKS COMPATIBILITY WITH PRIOR VERSIONS. Function names, calling sequence and return types/values have changed. See examples!
Item(s) in 'utility' directory are much pared-down derivatives of Atmel ASFcore 3 files. Please keep their original copyright and license intact when editing.

View file

@ -1,94 +0,0 @@
// Simple ZeroDMA example -- an equivalent to the memcpy() function.
// Decause it uses DMA, unlike memcpy(), your code could be doing other
// things simultaneously while the copy operation runs.
#include <Adafruit_ZeroDMA.h>
#include "utility/dma.h"
Adafruit_ZeroDMA myDMA;
ZeroDMAstatus stat; // DMA status codes returned by some functions
// The memory we'll be moving:
#define DATA_LENGTH 1024
uint8_t source_memory[DATA_LENGTH],
destination_memory[DATA_LENGTH];
volatile bool transfer_is_done = false; // Done yet?
// Callback for end-of-DMA-transfer
void dma_callback(Adafruit_ZeroDMA *dma) {
transfer_is_done = true;
}
void setup() {
uint32_t t;
pinMode(LED_BUILTIN, OUTPUT); // Onboard LED can be used for precise
digitalWrite(LED_BUILTIN, LOW); // benchmarking with an oscilloscope
Serial.begin(115200);
while(!Serial); // Wait for Serial monitor before continuing
Serial.println("DMA test: memory copy");
Serial.print("Allocating DMA channel...");
stat = myDMA.allocate();
myDMA.printStatus(stat);
Serial.println("Setting up transfer");
myDMA.addDescriptor(source_memory, destination_memory, DATA_LENGTH);
Serial.println("Adding callback");
// register_callback() can optionally take a second argument
// (callback type), default is DMA_CALLBACK_TRANSFER_DONE
myDMA.setCallback(dma_callback);
// Fill the source buffer with incrementing bytes, dest buf with 0's
for(uint32_t i=0; i<DATA_LENGTH; i++) source_memory[i] = i;
memset(destination_memory, 0, DATA_LENGTH);
// Show the destination buffer is empty before transfer
Serial.println("Destination buffer before transfer:");
dump();
Serial.println("Starting transfer job");
stat = myDMA.startJob();
myDMA.printStatus(stat);
Serial.println("Triggering DMA transfer...");
t = micros();
digitalWrite(LED_BUILTIN, HIGH);
myDMA.trigger();
// Your code could do other things here while copy happens!
while(!transfer_is_done); // Chill until DMA transfer completes
digitalWrite(LED_BUILTIN, LOW);
t = micros() - t; // Elapsed time
Serial.print("Done! ");
Serial.print(t);
Serial.println(" microseconds");
Serial.println("Destination buffer after transfer:");
dump();
// Now repeat the same operation, but 'manually' using memcpy() (not DMA):
t = micros();
digitalWrite(LED_BUILTIN, HIGH);
memcpy(destination_memory, source_memory, DATA_LENGTH);
digitalWrite(LED_BUILTIN, LOW);
t = micros() - t; // Elapsed time
Serial.print("Same operation without DMA: ");
Serial.print(t);
Serial.println(" microseconds");
}
// Show contents of destination_memory[] array
void dump() {
for(uint32_t i=0; i<DATA_LENGTH; i++) {
Serial.print(destination_memory[i], HEX); Serial.print(' ');
if ((i & 15) == 15) Serial.println();
}
}
void loop() { }

View file

@ -1,97 +0,0 @@
// DMA-based SPI buffer write. This is transmit-only as written, i.e.
// not equivalent to Arduino's SPI.transfer() which both sends and
// receives a single byte or word. Also, this is single-buffered to
// demonstrate a simple SPI write case. See zerodma_spi2.ino for an
// example using double buffering (2 buffers alternating fill & transmit).
#include <SPI.h>
#include <Adafruit_ZeroDMA.h>
#include "utility/dma.h"
Adafruit_ZeroDMA myDMA;
ZeroDMAstatus stat; // DMA status codes returned by some functions
// The memory we'll be issuing to SPI:
#define DATA_LENGTH 2048
uint8_t source_memory[DATA_LENGTH];
volatile bool transfer_is_done = false; // Done yet?
// Callback for end-of-DMA-transfer
void dma_callback(Adafruit_ZeroDMA *dma) {
transfer_is_done = true;
}
void setup() {
uint32_t t;
pinMode(LED_BUILTIN, OUTPUT); // Onboard LED can be used for precise
digitalWrite(LED_BUILTIN, LOW); // benchmarking with an oscilloscope
Serial.begin(115200);
while(!Serial); // Wait for Serial monitor before continuing
Serial.println("DMA test: SPI data out");
SPI.begin();
Serial.println("Configuring DMA trigger");
#ifdef __SAMD51__
// SERCOM2 is the 'native' SPI SERCOM on Metro M4
myDMA.setTrigger(SERCOM2_DMAC_ID_TX);
#else
// SERCOM4 is the 'native' SPI SERCOM on most M0 boards
myDMA.setTrigger(SERCOM4_DMAC_ID_TX);
#endif
myDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
Serial.print("Allocating DMA channel...");
stat = myDMA.allocate();
myDMA.printStatus(stat);
Serial.println("Setting up transfer");
myDMA.addDescriptor(
source_memory, // move data from here
#ifdef __SAMD51__
(void *)(&SERCOM2->SPI.DATA.reg), // to here (M4)
#else
(void *)(&SERCOM4->SPI.DATA.reg), // to here (M0)
#endif
DATA_LENGTH, // this many...
DMA_BEAT_SIZE_BYTE, // bytes/hword/words
true, // increment source addr?
false); // increment dest addr?
Serial.println("Adding callback");
// register_callback() can optionally take a second argument
// (callback type), default is DMA_CALLBACK_TRANSFER_DONE
myDMA.setCallback(dma_callback);
// Fill the source buffer with incrementing bytes
for(uint32_t i=0; i<DATA_LENGTH; i++) source_memory[i] = i;
// Start SPI transaction at 12 MHz
SPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
Serial.println("Starting transfer job");
t = micros();
digitalWrite(LED_BUILTIN, HIGH);
// Because we've configured a peripheral trigger (SPI), there's
// no need to manually trigger transfer, it starts up on its own.
stat = myDMA.startJob();
// Your code could do other things here while SPI write happens!
while(!transfer_is_done); // Chill until DMA transfer completes
digitalWrite(LED_BUILTIN, LOW);
t = micros() - t; // Elapsed time
SPI.endTransaction();
myDMA.printStatus(stat); // Results of start_transfer_job()
Serial.print("Done! ");
Serial.print(t);
Serial.println(" microseconds");
}
void loop() { }

View file

@ -1,103 +0,0 @@
// Double-buffered DMA on auxiliary SPI peripheral on pins 11/12/13.
// Continuously alternates between two data buffers...one is filled
// with new data as the other is being transmitted.
#include <SPI.h>
#include <Adafruit_ZeroDMA.h>
#include "utility/dma.h"
#include "wiring_private.h" // pinPeripheral() function
// Declare our own SPI peripheral 'mySPI' on pins 11/12/13:
// (Do not call this SPI1; Arduino Zero and Metro M0 already
// have an SPI1 (the EDBG interface) and it won't compile.)
SPIClass mySPI(
&sercom1, // -> Sercom peripheral
34, // MISO pin (also digital pin 12)
37, // SCK pin (also digital pin 13)
35, // MOSI pin (also digital pin 11)
SPI_PAD_0_SCK_1, // TX pad (MOSI, SCK pads)
SERCOM_RX_PAD_3); // RX pad (MISO pad)
Adafruit_ZeroDMA myDMA;
ZeroDMAstatus stat; // DMA status codes returned by some functions
// Data we'll issue to mySPI. There are TWO buffers; one being
// filled with new data while the other's being transmitted in
// the background.
#define DATA_LENGTH 512
uint8_t source_memory[2][DATA_LENGTH],
buffer_being_filled = 0, // Index of 'filling' buffer
buffer_value = 0; // Value of fill
volatile bool transfer_is_done = true; // Done yet?
// Callback for end-of-DMA-transfer
void dma_callback(Adafruit_ZeroDMA *dma) {
transfer_is_done = true;
}
DmacDescriptor *desc; // DMA descriptor address (so we can change contents)
void setup() {
Serial.begin(115200);
while(!Serial); // Wait for Serial monitor before continuing
Serial.println("DMA test: SPI data out");
mySPI.begin();
// Assign pins 11, 12, 13 to SERCOM functionality
pinPeripheral(11, PIO_SERCOM);
pinPeripheral(12, PIO_SERCOM);
pinPeripheral(13, PIO_SERCOM);
// Configure DMA for SERCOM1 (our 'mySPI' port on 11/12/13)
Serial.println("Configuring DMA trigger");
myDMA.setTrigger(SERCOM1_DMAC_ID_TX);
myDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
Serial.print("Allocating DMA channel...");
stat = myDMA.allocate();
myDMA.printStatus(stat);
desc = myDMA.addDescriptor(
source_memory[buffer_being_filled], // move data from here
(void *)(&SERCOM1->SPI.DATA.reg), // to here
DATA_LENGTH, // this many...
DMA_BEAT_SIZE_BYTE, // bytes/hword/words
true, // increment source addr?
false); // increment dest addr?
Serial.println("Adding callback");
// register_callback() can optionally take a second argument
// (callback type), default is DMA_CALLBACK_TRANSFER_DONE
myDMA.setCallback(dma_callback);
}
void loop() {
// Fill buffer with new data. The other buffer might
// still be transmitting in the background via DMA.
memset(source_memory[buffer_being_filled], buffer_value, DATA_LENGTH);
// Wait for prior transfer to complete before starting new one...
Serial.print("Waiting on prior transfer...");
while(!transfer_is_done) Serial.write('.');
mySPI.endTransaction();
Serial.println("Done!");
// Modify the DMA descriptor using the newly-filled buffer as source...
myDMA.changeDescriptor(desc, // DMA descriptor address
source_memory[buffer_being_filled]); // New src; dst & count don't change
// Begin new transfer...
Serial.println("Starting new transfer job");
mySPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
transfer_is_done = false; // Reset 'done' flag
stat = myDMA.startJob(); // Go!
myDMA.printStatus(stat);
// Switch buffer indices so the alternate buffer is filled/xfer'd
// on the next pass.
buffer_being_filled = 1 - buffer_being_filled;
buffer_value++;
}

View file

@ -1,9 +0,0 @@
name=Adafruit Zero DMA Library
version=1.0.4
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=DMA helper/wrapped for ATSAMD21 such as Arduino Zero & Feather M0
paragraph=DMA helper/wrapped for ATSAMD21 such as Arduino Zero & Feather M0
category=Signal Input/Output
url=https://github.com/adafruit/Adafruit_ZeroDMA
architectures=samd

View file

@ -1,145 +0,0 @@
/**
* \file
*
* \brief SAM Direct Memory Access Controller Driver
*
* Copyright (C) 2014-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef DMA_H_INCLUDED
#define DMA_H_INCLUDED
// THIS IS A PARED-DOWN VERSION OF DMA.H FROM ATMEL ASFCORE 3.
// Please keep original copyright and license intact!
#ifdef __cplusplus
extern "C" {
#endif
#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || defined(__DOXYGEN__) || defined(__SAMD51__)
#define FEATURE_DMA_CHANNEL_STANDBY
#endif
enum dma_transfer_trigger_action{
#ifdef __SAMD51__
// SAMD51 has a 'burst' transfer which can be set to one
// beat to accomplish same idea as SAMD21's 'beat' transfer.
// Trigger name is ACTON_BEAT for backward compatibility.
DMA_TRIGGER_ACTON_BLOCK = DMAC_CHCTRLA_TRIGACT_BLOCK_Val,
DMA_TRIGGER_ACTON_BEAT = DMAC_CHCTRLA_TRIGACT_BURST_Val,
DMA_TRIGGER_ACTON_TRANSACTION = DMAC_CHCTRLA_TRIGACT_TRANSACTION_Val,
#else
DMA_TRIGGER_ACTON_BLOCK = DMAC_CHCTRLB_TRIGACT_BLOCK_Val,
DMA_TRIGGER_ACTON_BEAT = DMAC_CHCTRLB_TRIGACT_BEAT_Val,
DMA_TRIGGER_ACTON_TRANSACTION = DMAC_CHCTRLB_TRIGACT_TRANSACTION_Val,
#endif
};
enum dma_callback_type {
// First item here is for any transfer errors. A transfer error is
// flagged if a bus error is detected during an AHB access or when
// the DMAC fetches an invalid descriptor
DMA_CALLBACK_TRANSFER_ERROR,
DMA_CALLBACK_TRANSFER_DONE,
DMA_CALLBACK_CHANNEL_SUSPEND,
DMA_CALLBACK_N, // Number of available callbacks
};
enum dma_beat_size {
DMA_BEAT_SIZE_BYTE = 0, // 8-bit
DMA_BEAT_SIZE_HWORD, // 16-bit
DMA_BEAT_SIZE_WORD, // 32-bit
};
enum dma_event_output_selection {
DMA_EVENT_OUTPUT_DISABLE = 0, // Disable event generation
DMA_EVENT_OUTPUT_BLOCK, // Event strobe when block xfer complete
DMA_EVENT_OUTPUT_RESERVED,
DMA_EVENT_OUTPUT_BEAT, // Event strobe when beat xfer complete
};
enum dma_block_action {
DMA_BLOCK_ACTION_NOACT = 0,
// Channel in normal operation and sets transfer complete interrupt
// flag after block transfer
DMA_BLOCK_ACTION_INT,
// Trigger channel suspend after block transfer and sets channel
// suspend interrupt flag once the channel is suspended
DMA_BLOCK_ACTION_SUSPEND,
// Sets transfer complete interrupt flag after a block transfer and
// trigger channel suspend. The channel suspend interrupt flag will
// be set once the channel is suspended.
DMA_BLOCK_ACTION_BOTH,
};
// DMA step selection. This bit determines whether the step size setting
// is applied to source or destination address.
enum dma_step_selection {
DMA_STEPSEL_DST = 0,
DMA_STEPSEL_SRC,
};
// Address increment step size. These bits select the address increment step
// size. The setting apply to source or destination address, depending on
// STEPSEL setting.
enum dma_address_increment_stepsize {
DMA_ADDRESS_INCREMENT_STEP_SIZE_1 = 0, // beat size * 1
DMA_ADDRESS_INCREMENT_STEP_SIZE_2, // beat size * 2
DMA_ADDRESS_INCREMENT_STEP_SIZE_4, // beat size * 4
DMA_ADDRESS_INCREMENT_STEP_SIZE_8, // etc...
DMA_ADDRESS_INCREMENT_STEP_SIZE_16,
DMA_ADDRESS_INCREMENT_STEP_SIZE_32,
DMA_ADDRESS_INCREMENT_STEP_SIZE_64,
DMA_ADDRESS_INCREMENT_STEP_SIZE_128,
};
// higher numbers are higher priority
enum dma_priority {
DMA_PRIORITY_0, // lowest (default)
DMA_PRIORITY_1,
DMA_PRIORITY_2,
DMA_PRIORITY_3, // highest
};
#ifdef __cplusplus
}
#endif
#endif // DMA_H_INCLUDED

View file

@ -0,0 +1 @@
// fake empty header file to make Arduino IDE happy

View file

@ -0,0 +1,12 @@
#include <arm_math.h>
arm_rfft_fast_instance_f32 plan;
void setup() {
arm_rfft_fast_init_f32(&plan, 256);
}
void loop() {
float in[256] = { 0 }, out[256] = { 0 };
arm_rfft_fast_f32(&plan, in, out, 0);
}

View file

@ -37,6 +37,12 @@ static I2SDevice_SAMD21G18x i2sd(*I2S);
#include "I2S.h"
#ifdef USE_TINYUSB
// For Serial when selecting TinyUSB
#include <Adafruit_TinyUSB.h>
#endif
int I2SClass::_beginCount = 0;
I2SClass::I2SClass(uint8_t deviceIndex, uint8_t clockGenerator, uint8_t sdPin, uint8_t sckPin, uint8_t fsPin) :

View file

@ -19,6 +19,11 @@
#include "SAMD_AnalogCorrection.h"
#ifdef USE_TINYUSB
// For Serial when selecting TinyUSB
#include <Adafruit_TinyUSB.h>
#endif
void analogReadCorrection (int offset, uint16_t gain)
{
Adc *adc;

View file

@ -22,6 +22,11 @@
#include <wiring_private.h>
#include <assert.h>
#ifdef USE_TINYUSB
// For Serial when selecting TinyUSB
#include <Adafruit_TinyUSB.h>
#endif
#define SPI_IMODE_NONE 0
#define SPI_IMODE_EXTINT 1
#define SPI_IMODE_GLOBAL 2
@ -46,7 +51,16 @@ SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint
void SPIClass::begin()
{
init();
if(!initialized) {
interruptMode = SPI_IMODE_NONE;
interruptSave = 0;
interruptMask = 0;
initialized = true;
}
if(!use_dma) {
dmaAllocate();
}
// PIO init
pinPeripheral(_uc_pinMiso, g_APinDescription[_uc_pinMiso].ulPinType);
@ -56,16 +70,6 @@ void SPIClass::begin()
config(DEFAULT_SPI_SETTINGS);
}
void SPIClass::init()
{
if (initialized)
return;
interruptMode = SPI_IMODE_NONE;
interruptSave = 0;
interruptMask = 0;
initialized = true;
}
void SPIClass::config(SPISettings settings)
{
_p_sercom->disableSPI();
@ -80,6 +84,7 @@ void SPIClass::end()
{
_p_sercom->resetSPI();
initialized = false;
// Add DMA deallocation here
}
#ifndef interruptsStatus
@ -235,157 +240,239 @@ void SPIClass::transfer(void *buf, size_t count)
}
}
// Pointer to SPIClass object, one per DMA channel.
// DMA-based SPI transfer() function ---------------------------------------
// IMPORTANT: references to 65535 throughout the DMA code are INTENTIONAL.
// DO NOT try to 'fix' by changing to 65536, or large transfers will fail!
// The BTCNT value of a DMA descriptor is an unsigned 16-bit value with a
// max of 65535. Larger transfers are handled by linked descriptors.
// Pointer to SPIClass object, one per DMA channel. This allows the
// DMA callback (which has to exist outside the class context) to have
// a reference back to the originating SPIClass object.
static SPIClass *spiPtr[DMAC_CH_NUM] = { 0 }; // Legit inits list to NULL
void SPIClass::dmaCallback(Adafruit_ZeroDMA *dma) {
// dmaCallback() receives an Adafruit_ZeroDMA object. From this we can get
// a channel number (0 to DMAC_CH_NUM-1, always unique per ZeroDMA object),
// then locate the originating SPIClass object using array lookup, setting
// the dma_busy element 'false' to indicate end of transfer.
// the dma_busy element 'false' to indicate end of transfer. Doesn't matter
// if it's a read or write transfer...both channels get pointers to it.
spiPtr[dma->getChannel()]->dma_busy = false;
}
void SPIClass::transfer(const void* txbuf, void* rxbuf, size_t count,
bool block) {
// For read-only and read+write transfers, a callback is assigned only
// to the read channel to indicate end-of-transfer, and the write channel's
// callback is assigned to this nonsense function (for reasons I'm not
// entirely sure of, setting the callback to NULL doesn't work).
static void dmaDoNothingCallback(Adafruit_ZeroDMA *dma) { (void)dma; }
// If receiving data and the RX DMA channel is not yet allocated...
if(rxbuf && (readChannel.getChannel() >= DMAC_CH_NUM)) {
// This could've gone in begin(), but for the sake of organization...
void SPIClass::dmaAllocate(void) {
// In order to support fully non-blocking SPI transfers, DMA descriptor
// lists must be created for the input and/or output data. Rather than
// do this dynamically with every transfer, the lists are allocated once
// on SPI init. Maximum list size is finite and knowable -- transfers to
// or from RAM or from flash memory will never exceed the corresponding
// memory size (if they do, you have bigger problems). Descriptors
// aren't large and there's usually only a handful to a dozen, so this
// isn't an excessive burden in exchange for big non-blocking transfers.
uint32_t maxWriteBytes = FLASH_SIZE; // Writes can't exceed all of flash
#if defined(__SAMD51__)
uint32_t maxReadBytes = HSRAM_SIZE; // Reads can't exceed all of RAM
#else
uint32_t maxReadBytes = HMCRAMC0_SIZE;
#endif
if(maxReadBytes > maxWriteBytes) { // I don't think any SAMD devices
maxWriteBytes = maxReadBytes; // have RAM > flash, but just in case
}
// VITAL to alloc read channel first, assigns it a higher DMA priority!
if(readChannel.allocate() == DMA_STATUS_OK) {
readDescriptor =
readChannel.addDescriptor(
if(writeChannel.allocate() == DMA_STATUS_OK) {
// Both DMA channels (read and write) allocated successfully,
// set up transfer triggers and other basics...
// readChannel callback only needs to be set up once.
// Unlike the write callback which may get switched on or off,
// read callback stays put. In certain cases the read DMA job
// just isn't started and the callback is a non-issue then.
readChannel.setTrigger(getDMAC_ID_RX());
readChannel.setAction(DMA_TRIGGER_ACTON_BEAT);
readChannel.setCallback(dmaCallback);
spiPtr[readChannel.getChannel()] = this;
writeChannel.setTrigger(getDMAC_ID_TX());
writeChannel.setAction(DMA_TRIGGER_ACTON_BEAT);
spiPtr[writeChannel.getChannel()] = this;
// One descriptor per channel has already been allocated
// in Adafruit_ZeroDMA, this just gets pointers to them...
firstReadDescriptor = readChannel.addDescriptor(
(void *)getDataRegister(), // Source address (SPI data reg)
NULL, // Dest address (set later)
0, // Count (set later)
DMA_BEAT_SIZE_BYTE, // Bytes/hwords/words
false, // Don't increment source address
true); // Increment dest address
readChannel.setTrigger(getDMAC_ID_RX());
readChannel.setAction(DMA_TRIGGER_ACTON_BEAT);
spiPtr[readChannel.getChannel()] = this;
// Since all RX transfers involve a TX, a
// separate callback here is not necessary.
}
}
// Unlike the rxbuf check above, where a RX DMA channel is allocated
// only if receiving data (and channel not previously alloc'd), the
// TX DMA channel is always needed, because even RX-only SPI requires
// writing dummy bytes to the peripheral.
if(writeChannel.getChannel() >= DMAC_CH_NUM) {
if(writeChannel.allocate() == DMA_STATUS_OK) {
writeDescriptor =
writeChannel.addDescriptor(
firstWriteDescriptor = writeChannel.addDescriptor(
NULL, // Source address (set later)
(void *)getDataRegister(), // Dest (SPI data register)
0, // Count (set later)
DMA_BEAT_SIZE_BYTE, // Bytes/hwords/words
true, // Increment source address
false); // Don't increment dest address
writeChannel.setTrigger(getDMAC_ID_TX());
writeChannel.setAction(DMA_TRIGGER_ACTON_BEAT);
writeChannel.setCallback(dmaCallback);
spiPtr[writeChannel.getChannel()] = this;
// This is the number of EXTRA descriptors beyond the first.
int numReadDescriptors = ((maxReadBytes + 65534) / 65535) - 1;
int numWriteDescriptors = ((maxWriteBytes + 65534) / 65535) - 1;
int totalDescriptors = numReadDescriptors + numWriteDescriptors;
if(totalDescriptors <= 0) { // Don't need extra descriptors,
use_dma = true; // channels are allocated, we're good.
} else { // Else allocate extra descriptor lists...
// Although DMA descriptors are technically a linked list, we just
// allocate a chunk all at once, and finesse the pointers later.
if((extraReadDescriptors = (DmacDescriptor *)malloc(
totalDescriptors * sizeof(DmacDescriptor)))) {
use_dma = true; // Everything allocated successfully
extraWriteDescriptors = &extraReadDescriptors[numReadDescriptors];
// Initialize descriptors (copy from first ones)
// cast to void* to suppress warning: with no trivial copy-assignment [-Wclass-memaccess]
for(int i=0; i<numReadDescriptors; i++) {
memcpy((void*) &extraReadDescriptors[i], firstReadDescriptor,
sizeof(DmacDescriptor));
}
for(int i=0; i<numWriteDescriptors; i++) {
memcpy((void*) &extraWriteDescriptors[i], firstWriteDescriptor,
sizeof(DmacDescriptor));
}
} // end malloc
} // end extra descriptor check
if(use_dma) { // If everything allocated successfully,
return; // then we're done here.
} // Otherwise clean up interim allocations...
writeChannel.free();
} // end writeChannel alloc
readChannel.free();
} // end readChannel alloc
// NOT FATAL if channel or descriptor allocation fails.
// transfer() function will fall back on a manual byte-by-byte loop.
}
if(writeDescriptor && (readDescriptor || !rxbuf)) {
void SPIClass::transfer(const void *txbuf, void *rxbuf, size_t count,
bool block) {
if((!txbuf && !rxbuf) || !count) { // Validate inputs
return;
}
// OK to assume now that txbuf and/or rxbuf are non-NULL, an if/else is
// often sufficient, don't need else-ifs for everything buffer related.
uint8_t *txbuf8 = (uint8_t *)txbuf; // Must cast to byte size
uint8_t *rxbuf8 = (uint8_t *)rxbuf; // for pointer math
if(use_dma) { // DMA-BASED TRANSFER YAY ----------------------------------
static const uint8_t dum = 0xFF; // Dummy byte for read-only xfers
// Initialize read descriptor dest address to rxbuf
if(rxbuf) readDescriptor->DSTADDR.reg = (uint32_t)rxbuf;
// Set up DMA descriptor lists -----------------------------------------
// If reading only, set up writeDescriptor to issue dummy bytes
// (set SRCADDR to &dum and SRCINC to 0). Otherwise, set SRCADDR
// to txbuf and SRCINC to 1. Only needed once at start.
if(rxbuf && !txbuf) {
writeDescriptor->SRCADDR.reg = (uint32_t)&dum;
writeDescriptor->BTCTRL.bit.SRCINC = 0;
} else {
writeDescriptor->SRCADDR.reg = (uint32_t)txbuf;
writeDescriptor->BTCTRL.bit.SRCINC = 1;
DmacDescriptor *rDesc = firstReadDescriptor;
DmacDescriptor *wDesc = firstWriteDescriptor;
int descIdx = 0; // Index into extra descriptor lists
while(count) { // Counts down to end of transfer
uint32_t bytesThisDescriptor = count;
if(bytesThisDescriptor > 65535) { // Limit each descriptor
bytesThisDescriptor = 65535; // to 65535 (not 65536) bytes
}
rDesc->BTCNT.reg = wDesc->BTCNT.reg = bytesThisDescriptor;
if(rxbuf) { // Read-only or read+write
// Auto-inc addresses in DMA descriptors must point to END of data.
// Buf pointers would advance at end of loop anyway, do it now...
rxbuf8 += bytesThisDescriptor;
rDesc->DSTADDR.reg = (uint32_t)rxbuf8;
}
if(txbuf) { // Write-only or read+write
txbuf8 += bytesThisDescriptor; // Same as above
wDesc->SRCADDR.reg = (uint32_t)txbuf8;
wDesc->BTCTRL.bit.SRCINC = 1; // Increment source pointer
} else { // Read-only requires dummy write
wDesc->SRCADDR.reg = (uint32_t)&dum;
wDesc->BTCTRL.bit.SRCINC = 0; // Don't increment source pointer
}
count -= bytesThisDescriptor;
if(count) { // Still more data?
// Link to next descriptors. Extra descriptors are IN ADDITION
// to first, so it's safe and correct that descIdx starts at 0.
rDesc->DESCADDR.reg = (uint32_t)&extraReadDescriptors[descIdx];
wDesc->DESCADDR.reg = (uint32_t)&extraWriteDescriptors[descIdx];
rDesc = &extraReadDescriptors[descIdx]; // Update pointers to
wDesc = &extraWriteDescriptors[descIdx]; // next descriptors
descIdx++;
// A write-only transfer doesn't use the read descriptor list, but
// it's quicker to build it (full of nonsense) anyway than to check.
} else { // No more data, end descriptor linked lists
rDesc->DESCADDR.reg = wDesc->DESCADDR.reg = 0;
}
}
while(count > 0) {
// Maximum bytes per DMA descriptor is 65,535 (NOT 65,536).
// We could set up a descriptor chain, but that gets more
// complex. For now, instead, break up long transfers into
// chunks of 65,535 bytes max...these transfers are all
// blocking, regardless of the "block" argument, except
// for the last one which will observe the background request.
// The fractional part is done first, so for any "partially
// blocking" transfers like these at least it's the largest
// single-descriptor transfer possible that occurs in the
// background, rather than the tail end.
int bytesThisPass;
bool blockThisPass;
if(count > 65535) { // Too big for 1 descriptor
blockThisPass = true;
bytesThisPass = count % 65535; // Fractional part
if(!bytesThisPass) bytesThisPass = 65535;
} else {
blockThisPass = block;
bytesThisPass = count;
}
// Set up DMA transfer job(s) ------------------------------------------
// Issue 'bytesThisPass' bytes...
if(rxbuf) {
// Reading, or reading + writing.
// Set up read descriptor.
// Src address doesn't change, only dest & count.
// DMA needs address set to END of buffer, so
// increment the address now, before the transfer.
readDescriptor->DSTADDR.reg += bytesThisPass;
readDescriptor->BTCNT.reg = bytesThisPass;
// Start the RX job BEFORE the TX job!
// That's the whole secret sauce to the two-channel transfer.
// Nothing will actually happen until the write channel job
// is also started.
if(rxbuf) { // Read+write or read-only
// End-of-read callback is already set up, disable write CB, start job
writeChannel.setCallback(dmaDoNothingCallback);
readChannel.startJob();
} else { // Write-only, use end-of-write callback
writeChannel.setCallback(dmaCallback);
}
if(txbuf) {
// DMA needs address set to END of buffer, so
// increment the address now, before the transfer.
writeDescriptor->SRCADDR.reg += bytesThisPass;
}
writeDescriptor->BTCNT.reg = bytesThisPass;
// Run DMA jobs, blocking if requested ---------------------------------
dma_busy = true;
writeChannel.startJob();
count -= bytesThisPass;
if(blockThisPass) {
while(dma_busy);
writeChannel.startJob(); // All xfers, even read-only, need write job.
if(block) { // If blocking transfer requested,
while(dma_busy); // wait for job to finish
}
}
} else {
// Non-DMA fallback.
uint8_t *txbuf8 = (uint8_t *)txbuf,
*rxbuf8 = (uint8_t *)rxbuf;
if(rxbuf8) {
} else { // NON-DMA FALLBACK ---------------------------------------------
if(txbuf8) {
// Writing and reading simultaneously
if(rxbuf8) { // Write + read simultaneously
while(count--) {
*rxbuf8++ = _p_sercom->transferDataSPI(*txbuf8++);
}
} else {
// Reading only
while(count--) {
*rxbuf8++ = _p_sercom->transferDataSPI(0xFF);
}
}
} else if(txbuf) {
// Writing only
} else { // Write only
while(count--) {
(void)_p_sercom->transferDataSPI(*txbuf8++);
}
}
} else { // Read only
while(count--) {
*rxbuf8++ = _p_sercom->transferDataSPI(0xFF);
}
}
} // end non-DMA
}
// Waits for a prior in-background DMA transfer to complete.
void SPIClass::waitForTransfer(void) {
while(dma_busy);
}
/* returns the current DMA transfer status to allow non-blocking polling */
bool SPIClass::isBusy(void) {
return dma_busy;
}
// End DMA-based SPI transfer() code ---------------------------------------
void SPIClass::attachInterrupt() {
// Should be enableInterrupt()
}
@ -405,8 +492,12 @@ static const struct {
{ &SERCOM1->SPI.DATA.reg, SERCOM1_DMAC_ID_TX, SERCOM1_DMAC_ID_RX },
{ &SERCOM2->SPI.DATA.reg, SERCOM2_DMAC_ID_TX, SERCOM2_DMAC_ID_RX },
{ &SERCOM3->SPI.DATA.reg, SERCOM3_DMAC_ID_TX, SERCOM3_DMAC_ID_RX },
#if defined(SERCOM4)
{ &SERCOM4->SPI.DATA.reg, SERCOM4_DMAC_ID_TX, SERCOM4_DMAC_ID_RX },
#endif
#if defined(SERCOM5)
{ &SERCOM5->SPI.DATA.reg, SERCOM5_DMAC_ID_TX, SERCOM5_DMAC_ID_RX },
#endif
#if defined(SERCOM6)
{ &SERCOM6->SPI.DATA.reg, SERCOM6_DMAC_ID_TX, SERCOM6_DMAC_ID_RX },
#endif
@ -477,4 +568,3 @@ void SPIClass::setClockSource(SercomClockSource clk) {
#if SPI_INTERFACES_COUNT > 5
SPIClass SPI5(&PERIPH_SPI5, PIN_SPI5_MISO, PIN_SPI5_SCK, PIN_SPI5_MOSI, PAD_SPI5_TX, PAD_SPI5_RX);
#endif

View file

@ -52,9 +52,11 @@
// The datasheet specifies a typical SPI SCK period (tSCK) of 42 ns,
// see "Table 36-48. SPI Timing Characteristics and Requirements",
// which translates into a maximum SPI clock of 23.8 MHz.
// Conservatively, the divider is set for a 12 MHz maximum SPI clock.
// We'll permit use of 24 MHz SPI even though this is slightly out
// of spec. Given how clock dividers work, the next "sensible"
// threshold would be a substantial drop down to 12 MHz.
#if !defined(MAX_SPI)
#define MAX_SPI 12000000
#define MAX_SPI 24000000
#endif
#define SPI_MIN_CLOCK_DIVIDER (uint8_t)(1 + ((F_CPU - 1) / MAX_SPI))
#endif
@ -81,7 +83,7 @@ class SPISettings {
#if defined(__SAMD51__)
this->clockFreq = clock; // Clipping handled in SERCOM.cpp
#else
this->clockFreq = (clock >= (MAX_SPI * 2 / SPI_MIN_CLOCK_DIVIDER) ? MAX_SPI * 2 / SPI_MIN_CLOCK_DIVIDER : clock);
this->clockFreq = clock >= MAX_SPI ? MAX_SPI : clock;
#endif
this->bitOrder = (bitOrder == MSBFIRST ? MSB_FIRST : LSB_FIRST);
@ -118,6 +120,7 @@ class SPIClass {
void transfer(const void* txbuf, void* rxbuf, size_t count,
bool block = true);
void waitForTransfer(void);
bool isBusy(void);
// Transaction Functions
void usingInterrupt(int interruptNumber);
@ -147,11 +150,10 @@ class SPIClass {
#else
// On SAMD21, this compiles to nothing, so user code doesn't need to
// check and conditionally compile lines for different architectures.
void setClockSource(SercomClockSource clk) { };
void setClockSource(SercomClockSource clk) { (void)clk; };
#endif // end __SAMD51__
private:
void init();
void config(SPISettings settings);
SERCOM *_p_sercom;
@ -167,12 +169,16 @@ class SPIClass {
char interruptSave;
uint32_t interruptMask;
// transfer(txbuf, rxbuf, count, block) uses DMA if possible
Adafruit_ZeroDMA readChannel,
writeChannel;
DmacDescriptor *readDescriptor = NULL,
*writeDescriptor = NULL;
// transfer(txbuf, rxbuf, count, block) uses DMA when possible
Adafruit_ZeroDMA readChannel;
Adafruit_ZeroDMA writeChannel;
DmacDescriptor *firstReadDescriptor = NULL; // List entry point
DmacDescriptor *firstWriteDescriptor = NULL;
DmacDescriptor *extraReadDescriptors = NULL; // Add'l descriptors
DmacDescriptor *extraWriteDescriptors = NULL;
bool use_dma = false; // true on successful alloc
volatile bool dma_busy = false;
void dmaAllocate(void);
static void dmaCallback(Adafruit_ZeroDMA *dma);
};

View file

@ -0,0 +1,25 @@
= Servo Library for Arduino =
This library allows an Arduino board to control RC (hobby) servo motors.
For more information about this library please visit us at
http://www.arduino.cc/en/Reference/Servo
== License ==
Copyright (c) 2013 Arduino LLC. All right reserved.
Copyright (c) 2009 Michael Margolis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

View file

@ -0,0 +1,27 @@
/*
Controlling a servo position using a potentiometer (variable resistor)
by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
modified on 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Knob
*/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}

View file

@ -0,0 +1,32 @@
/* Sweep
by BARRAGAN <http://barraganstudio.com>
This example code is in the public domain.
modified 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Sweep
*/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}

View file

@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map Servo
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Servo KEYWORD1 Servo
#######################################
# Methods and Functions (KEYWORD2)
#######################################
attach KEYWORD2
detach KEYWORD2
write KEYWORD2
read KEYWORD2
attached KEYWORD2
writeMicroseconds KEYWORD2
readMicroseconds KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View file

@ -0,0 +1,9 @@
name=Servo
version=1.1.4
author=Michael Margolis, Arduino
maintainer=Arduino <info@arduino.cc>
sentence=Allows Arduino/Genuino boards to control a variety of servo motors.
paragraph=This library can control a great number of servos.<br />It makes careful use of timers: the library can control 12 servos using only 1 timer.<br />On the Arduino Due you can control up to 60 servos.<br />
category=Device Control
url=http://www.arduino.cc/en/Reference/Servo
architectures=avr,megaavr,sam,samd,nrf52,stm32f4

121
libraries/Servo/src/Servo.h Normal file
View file

@ -0,0 +1,121 @@
/*
Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
Copyright (c) 2009 Michael Margolis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
A servo is activated by creating an instance of the Servo class passing
the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently
written using the write() method.
Note that analogWrite of PWM on pins associated with the timer are
disabled when the first servo is attached.
Timers are seized as needed in groups of 12 servos - 24 servos use two
timers, 48 servos will use four.
The sequence used to sieze timers is defined in timers.h
The methods are:
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin ) - Attaches a servo motor to an i/o pin.
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
default min is 544, max is 2400
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
*/
#ifndef Servo_h
#define Servo_h
#include <inttypes.h>
/*
* Defines for 16 bit timers used with Servo library
*
* If _useTimerX is defined then TimerX is a 16 bit timer on the current board
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
* _Nbr_16timers indicates how many 16 bit timers are available.
*/
// Architecture specific include
#if defined(ARDUINO_ARCH_AVR)
#include "avr/ServoTimers.h"
#elif defined(ARDUINO_ARCH_SAM)
#include "sam/ServoTimers.h"
#elif defined(ARDUINO_ARCH_SAMD)
#include "samd/ServoTimers.h"
#elif defined(ARDUINO_ARCH_STM32F4)
#include "stm32f4/ServoTimers.h"
#elif defined(ARDUINO_ARCH_NRF52)
#include "nrf52/ServoTimers.h"
#elif defined(ARDUINO_ARCH_MEGAAVR)
#include "megaavr/ServoTimers.h"
#else
#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor."
#endif
#define Servo_VERSION 2 // software version of this library
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
#define INVALID_SERVO 255 // flag indicating an invalid servo index
#if !defined(ARDUINO_ARCH_STM32F4)
typedef struct {
uint8_t nbr :6 ; // a pin number from 0 to 63
uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
} ServoPin_t ;
typedef struct {
ServoPin_t Pin;
volatile unsigned int ticks;
} servo_t;
class Servo
{
public:
Servo();
uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
void detach();
void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // returns current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
bool attached(); // return true if this servo is attached, otherwise false
private:
uint8_t servoIndex; // index into the channel data for this servo
int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
};
#endif
#endif

View file

@ -0,0 +1,318 @@
/*
Servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
Copyright (c) 2009 Michael Margolis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if defined(ARDUINO_ARCH_AVR)
#include <avr/interrupt.h>
#include <Arduino.h>
#include "Servo.h"
#define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009
#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
//#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER)
static servo_t servos[MAX_SERVOS]; // static array of servo structures
static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
uint8_t ServoCount = 0; // the total number of attached servos
// convenience macros
#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
#define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
/************ static functions common to all instances ***********************/
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
{
if( Channel[timer] < 0 )
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
else{
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
}
Channel[timer]++; // increment to the next channel
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
*OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
}
else {
// finished all channels so wait for the refresh period to expire before starting over
if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
else
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
}
}
#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
// Interrupt handlers for Arduino
#if defined(_useTimer1)
SIGNAL (TIMER1_COMPA_vect)
{
handle_interrupts(_timer1, &TCNT1, &OCR1A);
}
#endif
#if defined(_useTimer3)
SIGNAL (TIMER3_COMPA_vect)
{
handle_interrupts(_timer3, &TCNT3, &OCR3A);
}
#endif
#if defined(_useTimer4)
SIGNAL (TIMER4_COMPA_vect)
{
handle_interrupts(_timer4, &TCNT4, &OCR4A);
}
#endif
#if defined(_useTimer5)
SIGNAL (TIMER5_COMPA_vect)
{
handle_interrupts(_timer5, &TCNT5, &OCR5A);
}
#endif
#elif defined WIRING
// Interrupt handlers for Wiring
#if defined(_useTimer1)
void Timer1Service()
{
handle_interrupts(_timer1, &TCNT1, &OCR1A);
}
#endif
#if defined(_useTimer3)
void Timer3Service()
{
handle_interrupts(_timer3, &TCNT3, &OCR3A);
}
#endif
#endif
static void initISR(timer16_Sequence_t timer)
{
#if defined (_useTimer1)
if(timer == _timer1) {
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
TIFR |= _BV(OCF1A); // clear any pending interrupts;
TIMSK |= _BV(OCIE1A) ; // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
#endif
#if defined(WIRING)
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif
#if defined (_useTimer3)
if(timer == _timer3) {
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#if defined(__AVR_ATmega128__)
TIFR |= _BV(OCF3A); // clear any pending interrupts;
ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt
#else
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt
#endif
#if defined(WIRING)
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
}
#endif
#if defined (_useTimer4)
if(timer == _timer4) {
TCCR4A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8
TCNT4 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt
}
#endif
#if defined (_useTimer5)
if(timer == _timer5) {
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt
}
#endif
}
static void finISR(timer16_Sequence_t timer)
{
//disable use of the given timer
#if defined WIRING // Wiring
if(timer == _timer1) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
TIMSK1 &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
#else
TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
#endif
timerDetach(TIMER1OUTCOMPAREA_INT);
}
else if(timer == _timer3) {
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
TIMSK3 &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
#else
ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
#endif
timerDetach(TIMER3OUTCOMPAREA_INT);
}
#else
//For arduino - in future: call here to a currently undefined function to reset the timer
(void) timer; // squash "unused parameter 'timer' [-Wunused-parameter]" warning
#endif
}
static boolean isTimerActive(timer16_Sequence_t timer)
{
// returns true if any servo is active on this timer
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
if(SERVO(timer,channel).Pin.isActive == true)
return true;
}
return false;
}
/****************** end of static functions ******************************/
Servo::Servo()
{
if( ServoCount < MAX_SERVOS) {
this->servoIndex = ServoCount++; // assign a servo index to this instance
servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
}
else
this->servoIndex = INVALID_SERVO ; // too many servos
}
uint8_t Servo::attach(int pin)
{
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
}
uint8_t Servo::attach(int pin, int min, int max)
{
if(this->servoIndex < MAX_SERVOS ) {
pinMode( pin, OUTPUT) ; // set servo pin to output
servos[this->servoIndex].Pin.nbr = pin;
// todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
this->max = (MAX_PULSE_WIDTH - max)/4;
// initialize the timer if it has not already been initialized
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if(isTimerActive(timer) == false)
initISR(timer);
servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
}
return this->servoIndex ;
}
void Servo::detach()
{
servos[this->servoIndex].Pin.isActive = false;
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
if(isTimerActive(timer) == false) {
finISR(timer);
}
}
void Servo::write(int value)
{
if(value < MIN_PULSE_WIDTH)
{ // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
if(value < 0) value = 0;
if(value > 180) value = 180;
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
}
this->writeMicroseconds(value);
}
void Servo::writeMicroseconds(int value)
{
// calculate and store the values for the given channel
byte channel = this->servoIndex;
if( (channel < MAX_SERVOS) ) // ensure channel is valid
{
if( value < SERVO_MIN() ) // ensure pulse width is valid
value = SERVO_MIN();
else if( value > SERVO_MAX() )
value = SERVO_MAX();
value = value - TRIM_DURATION;
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
uint8_t oldSREG = SREG;
cli();
servos[channel].ticks = value;
SREG = oldSREG;
}
}
int Servo::read() // return the value as degrees
{
return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
}
int Servo::readMicroseconds()
{
unsigned int pulsewidth;
if( this->servoIndex != INVALID_SERVO )
pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009
else
pulsewidth = 0;
return pulsewidth;
}
bool Servo::attached()
{
return servos[this->servoIndex].Pin.isActive ;
}
#endif // ARDUINO_ARCH_AVR

Some files were not shown because too many files have changed in this diff Show more