diff --git a/IDE_Board_Manager/package_sparkfun_index.json b/IDE_Board_Manager/package_sparkfun_index.json index 2085be70..9dea7b57 100644 --- a/IDE_Board_Manager/package_sparkfun_index.json +++ b/IDE_Board_Manager/package_sparkfun_index.json @@ -1,543 +1,633 @@ -{ - "packages":[ - { - "name":"SparkFun", - "maintainer":"SparkFun Electronics", - "websiteURL":"https://SparkFun.com", - "email":"TechSupport@SparkFun.com", - "help":{ - "online":"https://forum.sparkfun.com" - }, - "platforms":[ - { - "name":"SparkFun AVR Boards", - "architecture":"avr", - "version":"1.1.5", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfunboards.1.1.5.tar.bz2", - "archiveFileName":"sparkfunboards.1.1.5.tar.bz2", - "checksum":"SHA-256:41f9728983e0dbab597bb46ddf00b5bac6cfec7c8f3771ecd1612dae58bb0366", - "size":"1162215", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"RedBoard" - }, - { - "name":"MaKey MaKey" - }, - { - "name":"Pro Micro" - }, - { - "name":"Fio v3" - }, - { - "name":"Qduino Mini" - }, - { - "name":"Digital Sandbox" - }, - { - "name":"Mega Pro" - }, - { - "name":"RedBot" - }, - { - "name":"Serial 7-segment Display" - }, - { - "name":"ATmega128RFA1 Dev Board" - } - ], - "toolsDependencies":[ - - ] - }, - { - "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.5)", - "architecture":"samd", - "version":"1.0.0", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.0.0.tar.bz2", - "archiveFileName":"sparkfun-samd-1.0.0.tar.bz2", - "checksum":"SHA-256:12e0be6862a3a28b6515755dcad2842757caf4e5270326554f95059512ebaab5", - "size":"268954", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"SparkFun SAMD21 Mini Breakout" - }, - { - "name":"SparkFun SAMD21 Dev Breakout" - } - ], - "toolsDependencies":[ - - ] - }, - { - "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.5)", - "architecture":"samd", - "version":"1.1.0", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.1.0.tar.bz2", - "archiveFileName":"sparkfun-samd-1.1.0.tar.bz2", - "checksum":"SHA-256:5d71cbf8ccf5781eef9809d7b3141041daf3ed1a1272f5278762ece5a0aecf44", - "size":"279683", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"SparkFun SAMD21 Mini Breakout" - }, - { - "name":"SparkFun SAMD21 Dev Breakout" - } - ], - "toolsDependencies":[ - - ] - }, - { - "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.5)", - "architecture":"samd", - "version":"1.2.0", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.2.0.tar.bz2", - "archiveFileName":"sparkfun-samd-1.2.0.tar.bz2", - "checksum":"SHA-256:50e055f311e07ba4d154bf00aa10579648024bef680bb3eb267401c496f791e6", - "size":"281932", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"SparkFun SAMD21 Mini Breakout" - }, - { - "name":"SparkFun SAMD21 Dev Breakout" - } - ], - "toolsDependencies":[ - - ] - }, - { - "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.6)", - "architecture":"samd", - "version":"1.2.1", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.2.1.tar.bz2", - "archiveFileName":"sparkfun-samd-1.2.1.tar.bz2", - "checksum":"SHA-256:63b90fb26a18a89b2f51556a08286117cdade38d6cb7a16eb1eccb7d1d92422a", - "size":"280405", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"SparkFun SAMD21 Mini Breakout" - }, - { - "name":"SparkFun SAMD21 Dev Breakout" - } - ], - "toolsDependencies":[ - - ] - }, - { - "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.8)", - "architecture":"samd", - "version":"1.2.2", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.2.2.tar.bz2", - "archiveFileName":"sparkfun-samd-1.2.2.tar.bz2", - "checksum":"SHA-256:21bc1ab1a8fd6550dca3b4953deaa2066d49ffa2583cd8e8a1e36d0c0ab00d52", - "size":"283240", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"SparkFun SAMD21 Mini Breakout" - }, - { - "name":"SparkFun SAMD21 Dev Breakout" - } - ], - "toolsDependencies":[ - - ] - }, - { - "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.8)", - "architecture":"samd", - "version":"1.3.0", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.3.0.tar.bz2", - "archiveFileName":"sparkfun-samd-1.3.0.tar.bz2", - "checksum":"SHA-256:87695137f303000099e7e6d3fae3e87d5882ed999e4c14403c65cf51a4d6a6be", - "size":"195440", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"SparkFun SAMD21 Mini Breakout" - }, - { - "name":"SparkFun SAMD21 Dev Breakout" - }, - { - "name":"SparkFun 9DoF Razor IMU M0" - } - ], - "toolsDependencies":[ - - ] - }, - { - "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.9)", - "architecture":"samd", - "version":"1.3.2", - "category":"Contributed", - "url":"https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.3.2.tar.bz2", - "archiveFileName":"sparkfun-samd-1.3.2.tar.bz2", - "checksum":"SHA-256:eb4274a3df4c6c4dbc1396600b1efc9cd9454e5be4880530ff87ba4fb3e6216a", - "size":"206253", - "help":{ - "online":"https://forums.sparkfun.com" - }, - "boards":[ - { - "name":"SparkFun SAMD21 Mini Breakout" - }, - { - "name":"SparkFun SAMD21 Dev Breakout" - }, - { - "name":"SparkFun 9DoF Razor IMU M0" - } - ], - "toolsDependencies":[ - - ] - } - ], - "tools":[ - - ] - }, - { - "maintainer":"SparkFun Electronics", - "help":{ - "online":"http://SparkFun.com" - }, - "websiteURL":"https://github.com/sparkfun/Arduino_Boards", - "platforms":[ - { - "category":"Contributed", - "name":"SparkFun ESP8266 Boards", - "url":"https://cdn.sparkfun.com/assets/learn_tutorials/4/9/5/sparkfun-esp8266-2.1.0.tar.bz2", - "checksum":"SHA-256:FE3E0504B38A5A4C912801A3E4633380A666DC77B8D3043548187AF8675477DA", - "help":{ - "online":"https://learn.sparkfun.com" - }, - "version":"2.1.0", - "architecture":"esp8266", - "archiveFileName":"sparkfun-esp8266-2.1.0.tar.bz2", - "boards":[ - { - "name":"SparkFun Blynk Board - ESP8266" - }, - { - "name":"SparkFun ESP8266 Thing" - }, - { - "name":"SparkFun ESP8266 Thing - Development Board" - }, - { - "name":"Generic ESP8266 Module" - } - ], - "toolsDependencies":[ - { - "packager":"esp8266", - "version":"0.4.8", - "name":"esptool" - }, - { - "packager":"esp8266", - "version":"1.20.0-26-gb404fb9-2", - "name":"xtensa-lx106-elf-gcc" - }, - { - "packager":"esp8266", - "version":"0.1.2", - "name":"mkspiffs" - } - ], - "size":"5436076" - } - ], - "tools":[ - { - "version":"1.20.0-26-gb404fb9-2", - "name":"xtensa-lx106-elf-gcc", - "systems":[ - { - "url":"http://arduino.esp8266.com/win32-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "checksum":"SHA-256:10476b9c11a7a90f40883413ddfb409f505b20692e316c4e597c4c175b4be09c", - "host":"i686-mingw32", - "archiveFileName":"win32-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "size":"153527527" - }, - { - "url":"http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "checksum":"SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", - "host":"x86_64-apple-darwin", - "archiveFileName":"osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "size":"35385382" - }, - { - "url":"http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "checksum":"SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", - "host":"i386-apple-darwin", - "archiveFileName":"osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "size":"35385382" - }, - { - "url":"http://arduino.esp8266.com/linux64-xtensa-lx106-elf-gb404fb9.tar.gz", - "checksum":"SHA-256:46f057fbd8b320889a26167daf325038912096d09940b2a95489db92431473b7", - "host":"x86_64-pc-linux-gnu", - "archiveFileName":"linux64-xtensa-lx106-elf-gb404fb9.tar.gz", - "size":"30262903" - }, - { - "url":"http://arduino.esp8266.com/linux32-xtensa-lx106-elf.tar.gz", - "checksum":"SHA-256:b24817819f0078fb05895a640e806e0aca9aa96b47b80d2390ac8e2d9ddc955a", - "host":"i686-pc-linux-gnu", - "archiveFileName":"linux32-xtensa-lx106-elf.tar.gz", - "size":"32734156" - } - ] - }, - { - "version":"1.20.0-26-gb404fb9", - "name":"xtensa-lx106-elf-gcc", - "systems":[ - { - "url":"http://arduino.esp8266.com/win32-xtensa-lx106-elf-gb404fb9.tar.gz", - "checksum":"SHA-256:1561ec85cc58cab35cc48bfdb0d0087809f89c043112a2c36b54251a13bf781f", - "host":"i686-mingw32", - "archiveFileName":"win32-xtensa-lx106-elf-gb404fb9.tar.gz", - "size":"153807368" - }, - { - "url":"http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "checksum":"SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", - "host":"x86_64-apple-darwin", - "archiveFileName":"osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "size":"35385382" - }, - { - "url":"http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "checksum":"SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", - "host":"i386-apple-darwin", - "archiveFileName":"osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", - "size":"35385382" - }, - { - "url":"http://arduino.esp8266.com/linux64-xtensa-lx106-elf-gb404fb9.tar.gz", - "checksum":"SHA-256:46f057fbd8b320889a26167daf325038912096d09940b2a95489db92431473b7", - "host":"x86_64-pc-linux-gnu", - "archiveFileName":"linux64-xtensa-lx106-elf-gb404fb9.tar.gz", - "size":"30262903" - }, - { - "url":"http://arduino.esp8266.com/linux32-xtensa-lx106-elf.tar.gz", - "checksum":"SHA-256:b24817819f0078fb05895a640e806e0aca9aa96b47b80d2390ac8e2d9ddc955a", - "host":"i686-pc-linux-gnu", - "archiveFileName":"linux32-xtensa-lx106-elf.tar.gz", - "size":"32734156" - } - ] - }, - { - "version":"0.4.8", - "name":"esptool", - "systems":[ - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-win32.zip", - "checksum":"SHA-256:8d09cb0df6234c2a0562389ceedd11482b44a3f538695f9a4df80f9f10411ece", - "host":"i686-mingw32", - "archiveFileName":"esptool-0.4.8-win32.zip", - "size":"32192" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-osx.tar.gz", - "checksum":"SHA-256:2bcbf19934543fb06c505b2a595b68a76e4cab8e3d8968a4d1802195c87126cf", - "host":"x86_64-apple-darwin", - "archiveFileName":"esptool-0.4.8-osx.tar.gz", - "size":"28798" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-osx.tar.gz", - "checksum":"SHA-256:2bcbf19934543fb06c505b2a595b68a76e4cab8e3d8968a4d1802195c87126cf", - "host":"i386-apple-darwin", - "archiveFileName":"esptool-0.4.8-osx.tar.gz", - "size":"28798" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-linux64.tar.gz", - "checksum":"SHA-256:1cd9a6014bbbc37ba6dc249f4fc027f0ca9bbc6dd0e203ebc7d146dfd78a6e78", - "host":"x86_64-pc-linux-gnu", - "archiveFileName":"esptool-0.4.8-linux64.tar.gz", - "size":"15479" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-linux32.tar.gz", - "checksum":"SHA-256:b0d6e71e6f41d4ed7e167bb4b3f4f0b1b3e49d69af50ab7fbe952cbfed83f164", - "host":"i686-pc-linux-gnu", - "archiveFileName":"esptool-0.4.8-linux32.tar.gz", - "size":"15444" - } - ] - }, - { - "version":"0.4.5", - "name":"esptool", - "systems":[ - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-win32.zip", - "checksum":"SHA-256:1b0a7d254e74942d820a09281aa5dc2af1c8314ae5ee1a5abb0653d0580e531b", - "host":"i686-mingw32", - "archiveFileName":"esptool-0.4.5-win32.zip", - "size":"17408" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-osx.tar.gz", - "checksum":"SHA-256:924d31c64f4bb9f748e70806dafbabb15e5eb80afcdde33715f3ec884be1652d", - "host":"x86_64-apple-darwin", - "archiveFileName":"esptool-0.4.5-osx.tar.gz", - "size":"11359" - }, - { - "url":"http://arduino.esp8266.com/esptool-0.4.5-1-gfaa5794-osx.tar.gz", - "checksum":"SHA-256:722142071f6cf4d8c02dea42497a747e06abf583d86137a6a256b7db71dc61f6", - "host":"i386-apple-darwin", - "archiveFileName":"esptool-0.4.5-1-gfaa5794-osx.tar.gz", - "size":"20751" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-linux64.tar.gz", - "checksum":"SHA-256:4ce799e13fbd89f8a8f08a08db77dc3b1362c4486306fe1b3801dee80cfa3203", - "host":"x86_64-pc-linux-gnu", - "archiveFileName":"esptool-0.4.5-linux64.tar.gz", - "size":"12789" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-linux32.tar.gz", - "checksum":"SHA-256:a7a2c3200786d7396e8cafca1b9aefe56db8ec1dab5e9163d4a19358232a7d87", - "host":"i686-pc-linux-gnu", - "archiveFileName":"esptool-0.4.5-linux32.tar.gz", - "size":"12055" - } - ] - }, - { - "version":"0.4.6", - "name":"esptool", - "systems":[ - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-win32.zip", - "checksum":"SHA-256:0248bf78514a3195f583e29218ca7828a66e13c6e5545a078f1c1257033e4927", - "host":"i686-mingw32", - "archiveFileName":"esptool-0.4.6-win32.zip", - "size":"17481" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-osx.tar.gz", - "checksum":"SHA-256:0fe87ba7e29ee90a9fc72492aada8c0796f9e8f8a1c594b6b26cee2610d09bb3", - "host":"x86_64-apple-darwin", - "archiveFileName":"esptool-0.4.6-osx.tar.gz", - "size":"20926" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-osx.tar.gz", - "checksum":"SHA-256:0fe87ba7e29ee90a9fc72492aada8c0796f9e8f8a1c594b6b26cee2610d09bb3", - "host":"i386-apple-darwin", - "archiveFileName":"esptool-0.4.6-osx.tar.gz", - "size":"20926" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-linux64.tar.gz", - "checksum":"SHA-256:f9f456e9a42bb2597126c513cb8865f923fb978865d4838b9623d322216b74d0", - "host":"x86_64-pc-linux-gnu", - "archiveFileName":"esptool-0.4.6-linux64.tar.gz", - "size":"12885" - }, - { - "url":"https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-linux32.tar.gz", - "checksum":"SHA-256:85275ca03a82bfc456f5a84e86962ca1e470ea2e168829c38ca29ee668831d93", - "host":"i686-pc-linux-gnu", - "archiveFileName":"esptool-0.4.6-linux32.tar.gz", - "size":"13417" - } - ] - }, - { - "version":"0.1.2", - "name":"mkspiffs", - "systems":[ - { - "url":"https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-windows.zip", - "checksum":"SHA-256:0a29119b8458b61a877408f7995e4944623a712e0d313a2c2f76af9ab55cc9f2", - "host":"i686-mingw32", - "archiveFileName":"mkspiffs-0.1.2-windows.zip", - "size":"230802" - }, - { - "url":"https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-osx.tar.gz", - "checksum":"SHA-256:df656fae21a41c1269ea50cb53752dcaf6a4e1437255f3a9fb50b4025549b58e", - "host":"x86_64-apple-darwin", - "archiveFileName":"mkspiffs-0.1.2-osx.tar.gz", - "size":"115091" - }, - { - "url":"https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-osx.tar.gz", - "checksum":"SHA-256:df656fae21a41c1269ea50cb53752dcaf6a4e1437255f3a9fb50b4025549b58e", - "host":"i386-apple-darwin", - "archiveFileName":"mkspiffs-0.1.2-osx.tar.gz", - "size":"115091" - }, - { - "url":"https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-linux64.tar.gz", - "checksum":"SHA-256:1a1dd81b51daf74c382db71b42251757ca4136e8762107e69feaa8617bac315f", - "host":"x86_64-pc-linux-gnu", - "archiveFileName":"mkspiffs-0.1.2-linux64.tar.gz", - "size":"46281" - }, - { - "url":"https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-linux32.tar.gz", - "checksum":"SHA-256:e990d545dfcae308aabaac5fa9e1db734cc2b08167969e7eedac88bd0839667c", - "host":"i686-pc-linux-gnu", - "archiveFileName":"mkspiffs-0.1.2-linux32.tar.gz", - "size":"45272" - } - ] - } - ], - "email":"ivan@esp8266.com", - "name":"esp8266" - } - ] +{ + "packages": [ + { + "name": "SparkFun", + "maintainer": "SparkFun Electronics", + "websiteURL": "https://SparkFun.com", + "email": "TechSupport@SparkFun.com", + "help": { + "online": "https://forum.sparkfun.com" + }, + "platforms": [ + { + "name": "SparkFun AVR Boards", + "architecture": "avr", + "version": "1.1.5", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfunboards.1.1.5.tar.bz2", + "archiveFileName": "sparkfunboards.1.1.5.tar.bz2", + "checksum": "SHA-256:41f9728983e0dbab597bb46ddf00b5bac6cfec7c8f3771ecd1612dae58bb0366", + "size": "1162215", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "RedBoard" + }, + { + "name": "MaKey MaKey" + }, + { + "name": "Pro Micro" + }, + { + "name": "Fio v3" + }, + { + "name": "Qduino Mini" + }, + { + "name": "Digital Sandbox" + }, + { + "name": "Mega Pro" + }, + { + "name": "RedBot" + }, + { + "name": "Serial 7-segment Display" + }, + { + "name": "ATmega128RFA1 Dev Board" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun AVR Boards", + "architecture": "avr", + "version": "1.1.6", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/LilyMini_testing/IDE_Board_Manager/sparkfunboards.1.1.6.tar.bz2", + "archiveFileName": "sparkfunboards.1.1.6.tar.bz2", + "checksum": "SHA-256:049FA0DF51602120EC1BDAC19F440FC0CC448C23BB277DD0D8DF855C52ACD483", + "size": "1159276", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "RedBoard" + }, + { + "name": "MaKey MaKey" + }, + { + "name": "Pro Micro" + }, + { + "name": "Fio v3" + }, + { + "name": "Qduino Mini" + }, + { + "name": "Digital Sandbox" + }, + { + "name": "Mega Pro" + }, + { + "name": "RedBot" + }, + { + "name": "Serial 7-segment Display" + }, + { + "name": "ATmega128RFA1 Dev Board" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.5)", + "architecture": "samd", + "version": "1.0.0", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.0.0.tar.bz2", + "archiveFileName": "sparkfun-samd-1.0.0.tar.bz2", + "checksum": "SHA-256:12e0be6862a3a28b6515755dcad2842757caf4e5270326554f95059512ebaab5", + "size": "268954", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.5)", + "architecture": "samd", + "version": "1.1.0", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.1.0.tar.bz2", + "archiveFileName": "sparkfun-samd-1.1.0.tar.bz2", + "checksum": "SHA-256:5d71cbf8ccf5781eef9809d7b3141041daf3ed1a1272f5278762ece5a0aecf44", + "size": "279683", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.5)", + "architecture": "samd", + "version": "1.2.0", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.2.0.tar.bz2", + "archiveFileName": "sparkfun-samd-1.2.0.tar.bz2", + "checksum": "SHA-256:50e055f311e07ba4d154bf00aa10579648024bef680bb3eb267401c496f791e6", + "size": "281932", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.6)", + "architecture": "samd", + "version": "1.2.1", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.2.1.tar.bz2", + "archiveFileName": "sparkfun-samd-1.2.1.tar.bz2", + "checksum": "SHA-256:63b90fb26a18a89b2f51556a08286117cdade38d6cb7a16eb1eccb7d1d92422a", + "size": "280405", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.8)", + "architecture": "samd", + "version": "1.2.2", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.2.2.tar.bz2", + "archiveFileName": "sparkfun-samd-1.2.2.tar.bz2", + "checksum": "SHA-256:21bc1ab1a8fd6550dca3b4953deaa2066d49ffa2583cd8e8a1e36d0c0ab00d52", + "size": "283240", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.8)", + "architecture": "samd", + "version": "1.3.0", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.3.0.tar.bz2", + "archiveFileName": "sparkfun-samd-1.3.0.tar.bz2", + "checksum": "SHA-256:87695137f303000099e7e6d3fae3e87d5882ed999e4c14403c65cf51a4d6a6be", + "size": "195440", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + }, + { + "name": "SparkFun 9DoF Razor IMU M0" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.9)", + "architecture": "samd", + "version": "1.3.2", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/master/IDE_Board_Manager/sparkfun-samd-1.3.2.tar.bz2", + "archiveFileName": "sparkfun-samd-1.3.2.tar.bz2", + "checksum": "SHA-256:eb4274a3df4c6c4dbc1396600b1efc9cd9454e5be4880530ff87ba4fb3e6216a", + "size": "206253", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + }, + { + "name": "SparkFun 9DoF Razor IMU M0" + } + ], + "toolsDependencies": [] + }, + { + "name": "SparkFun SAMD Boards", + "architecture": "samd", + "version": "1.4.0", + "category": "Contributed", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/LilyMini_testing/IDE_Board_Manager/sparkfun-samd-1.4.0.tar.bz2", + "archiveFileName": "sparkfun-samd-1.4.0.tar.bz2", + "checksum": "SHA-256:968918117E6EA9C7F3982F83E07B6459663AB844779855B5E175E19461C16691", + "size": "289555", + "help": { + "online": "https://forums.sparkfun.com" + }, + "boards": [ + { + "name": "SparkFun SAMD21 Mini Breakout" + }, + { + "name": "SparkFun SAMD21 Dev Breakout" + }, + { + "name": "SparkFun 9DoF Razor IMU M0" + }, + { + "name": "LilyPad LilyMini" + } + ], + "toolsDependencies": [ + { + "packager": "SparkFun", + "name": "bossac", + "version": "1.4.0" + } + ] + } + ], + "tools": [ + { + "name": "bossac", + "version": "1.4.0", + "systems": [ + { + "host": "i686-mingw32", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/LilyMini_testing/sparkfun/samd-tools/bossac/bossac-1.4.0-win.zip", + "archiveFileName": "bossac-1.4.0-win.zip", + "checksum": "SHA-256:BCA6503F5DBB1F96693AFD0701A759ECFB3BE5B9FB3F9D901CA17853B224F4EB", + "size": "314705" + }, + { + "host": "x86_64-pc-linux-gnu", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/LilyMini_testing/sparkfun/samd-tools/bossac/bossac-1.4.0-linux64.tar.bz2", + "archiveFileName": "bossac-1.4.0-linux64.tar.bz2", + "checksum": "SHA-256:BB8F398BF84C5F31880FE9A2C7AE0174592516CE4821B49744B426AA968ADA10", + "size": "225696" + }, + { + "host": "x86_64-apple-darwin", + "url": "https://github.com/sparkfun/Arduino_Boards/raw/LilyMini_testing/sparkfun/samd-tools/bossac/bossac-1.4.0-osx.tar.bz2", + "archiveFileName": "bossac-1.4.0-osx.tar.bz2", + "checksum": "SHA-256:D0F225846D7BC80A74324D783CDB35C42A7F85EAD73CC016C0CC767B0AA5E81C", + "size": "74461" + } + ] + } + ] + }, + { + "maintainer": "SparkFun Electronics", + "help": { + "online": "http://SparkFun.com" + }, + "websiteURL": "https://github.com/sparkfun/Arduino_Boards", + "platforms": [ + { + "category": "Contributed", + "name": "SparkFun ESP8266 Boards", + "url": "https://cdn.sparkfun.com/assets/learn_tutorials/4/9/5/sparkfun-esp8266-2.1.0.tar.bz2", + "checksum": "SHA-256:FE3E0504B38A5A4C912801A3E4633380A666DC77B8D3043548187AF8675477DA", + "help": { + "online": "https://learn.sparkfun.com" + }, + "version": "2.1.0", + "architecture": "esp8266", + "archiveFileName": "sparkfun-esp8266-2.1.0.tar.bz2", + "boards": [ + { + "name": "SparkFun Blynk Board - ESP8266" + }, + { + "name": "SparkFun ESP8266 Thing" + }, + { + "name": "SparkFun ESP8266 Thing - Development Board" + }, + { + "name": "Generic ESP8266 Module" + } + ], + "toolsDependencies": [ + { + "packager": "esp8266", + "version": "0.4.8", + "name": "esptool" + }, + { + "packager": "esp8266", + "version": "1.20.0-26-gb404fb9-2", + "name": "xtensa-lx106-elf-gcc" + }, + { + "packager": "esp8266", + "version": "0.1.2", + "name": "mkspiffs" + } + ], + "size": "5436076" + } + ], + "tools": [ + { + "version": "1.20.0-26-gb404fb9-2", + "name": "xtensa-lx106-elf-gcc", + "systems": [ + { + "url": "http://arduino.esp8266.com/win32-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "checksum": "SHA-256:10476b9c11a7a90f40883413ddfb409f505b20692e316c4e597c4c175b4be09c", + "host": "i686-mingw32", + "archiveFileName": "win32-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "size": "153527527" + }, + { + "url": "http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "checksum": "SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", + "host": "x86_64-apple-darwin", + "archiveFileName": "osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "size": "35385382" + }, + { + "url": "http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "checksum": "SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", + "host": "i386-apple-darwin", + "archiveFileName": "osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "size": "35385382" + }, + { + "url": "http://arduino.esp8266.com/linux64-xtensa-lx106-elf-gb404fb9.tar.gz", + "checksum": "SHA-256:46f057fbd8b320889a26167daf325038912096d09940b2a95489db92431473b7", + "host": "x86_64-pc-linux-gnu", + "archiveFileName": "linux64-xtensa-lx106-elf-gb404fb9.tar.gz", + "size": "30262903" + }, + { + "url": "http://arduino.esp8266.com/linux32-xtensa-lx106-elf.tar.gz", + "checksum": "SHA-256:b24817819f0078fb05895a640e806e0aca9aa96b47b80d2390ac8e2d9ddc955a", + "host": "i686-pc-linux-gnu", + "archiveFileName": "linux32-xtensa-lx106-elf.tar.gz", + "size": "32734156" + } + ] + }, + { + "version": "1.20.0-26-gb404fb9", + "name": "xtensa-lx106-elf-gcc", + "systems": [ + { + "url": "http://arduino.esp8266.com/win32-xtensa-lx106-elf-gb404fb9.tar.gz", + "checksum": "SHA-256:1561ec85cc58cab35cc48bfdb0d0087809f89c043112a2c36b54251a13bf781f", + "host": "i686-mingw32", + "archiveFileName": "win32-xtensa-lx106-elf-gb404fb9.tar.gz", + "size": "153807368" + }, + { + "url": "http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "checksum": "SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", + "host": "x86_64-apple-darwin", + "archiveFileName": "osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "size": "35385382" + }, + { + "url": "http://arduino.esp8266.com/osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "checksum": "SHA-256:0cf150193997bd1355e0f49d3d49711730035257bc1aee1eaaad619e56b9e4e6", + "host": "i386-apple-darwin", + "archiveFileName": "osx-xtensa-lx106-elf-gb404fb9-2.tar.gz", + "size": "35385382" + }, + { + "url": "http://arduino.esp8266.com/linux64-xtensa-lx106-elf-gb404fb9.tar.gz", + "checksum": "SHA-256:46f057fbd8b320889a26167daf325038912096d09940b2a95489db92431473b7", + "host": "x86_64-pc-linux-gnu", + "archiveFileName": "linux64-xtensa-lx106-elf-gb404fb9.tar.gz", + "size": "30262903" + }, + { + "url": "http://arduino.esp8266.com/linux32-xtensa-lx106-elf.tar.gz", + "checksum": "SHA-256:b24817819f0078fb05895a640e806e0aca9aa96b47b80d2390ac8e2d9ddc955a", + "host": "i686-pc-linux-gnu", + "archiveFileName": "linux32-xtensa-lx106-elf.tar.gz", + "size": "32734156" + } + ] + }, + { + "version": "0.4.8", + "name": "esptool", + "systems": [ + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-win32.zip", + "checksum": "SHA-256:8d09cb0df6234c2a0562389ceedd11482b44a3f538695f9a4df80f9f10411ece", + "host": "i686-mingw32", + "archiveFileName": "esptool-0.4.8-win32.zip", + "size": "32192" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-osx.tar.gz", + "checksum": "SHA-256:2bcbf19934543fb06c505b2a595b68a76e4cab8e3d8968a4d1802195c87126cf", + "host": "x86_64-apple-darwin", + "archiveFileName": "esptool-0.4.8-osx.tar.gz", + "size": "28798" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-osx.tar.gz", + "checksum": "SHA-256:2bcbf19934543fb06c505b2a595b68a76e4cab8e3d8968a4d1802195c87126cf", + "host": "i386-apple-darwin", + "archiveFileName": "esptool-0.4.8-osx.tar.gz", + "size": "28798" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-linux64.tar.gz", + "checksum": "SHA-256:1cd9a6014bbbc37ba6dc249f4fc027f0ca9bbc6dd0e203ebc7d146dfd78a6e78", + "host": "x86_64-pc-linux-gnu", + "archiveFileName": "esptool-0.4.8-linux64.tar.gz", + "size": "15479" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.8/esptool-0.4.8-linux32.tar.gz", + "checksum": "SHA-256:b0d6e71e6f41d4ed7e167bb4b3f4f0b1b3e49d69af50ab7fbe952cbfed83f164", + "host": "i686-pc-linux-gnu", + "archiveFileName": "esptool-0.4.8-linux32.tar.gz", + "size": "15444" + } + ] + }, + { + "version": "0.4.5", + "name": "esptool", + "systems": [ + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-win32.zip", + "checksum": "SHA-256:1b0a7d254e74942d820a09281aa5dc2af1c8314ae5ee1a5abb0653d0580e531b", + "host": "i686-mingw32", + "archiveFileName": "esptool-0.4.5-win32.zip", + "size": "17408" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-osx.tar.gz", + "checksum": "SHA-256:924d31c64f4bb9f748e70806dafbabb15e5eb80afcdde33715f3ec884be1652d", + "host": "x86_64-apple-darwin", + "archiveFileName": "esptool-0.4.5-osx.tar.gz", + "size": "11359" + }, + { + "url": "http://arduino.esp8266.com/esptool-0.4.5-1-gfaa5794-osx.tar.gz", + "checksum": "SHA-256:722142071f6cf4d8c02dea42497a747e06abf583d86137a6a256b7db71dc61f6", + "host": "i386-apple-darwin", + "archiveFileName": "esptool-0.4.5-1-gfaa5794-osx.tar.gz", + "size": "20751" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-linux64.tar.gz", + "checksum": "SHA-256:4ce799e13fbd89f8a8f08a08db77dc3b1362c4486306fe1b3801dee80cfa3203", + "host": "x86_64-pc-linux-gnu", + "archiveFileName": "esptool-0.4.5-linux64.tar.gz", + "size": "12789" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.5/esptool-0.4.5-linux32.tar.gz", + "checksum": "SHA-256:a7a2c3200786d7396e8cafca1b9aefe56db8ec1dab5e9163d4a19358232a7d87", + "host": "i686-pc-linux-gnu", + "archiveFileName": "esptool-0.4.5-linux32.tar.gz", + "size": "12055" + } + ] + }, + { + "version": "0.4.6", + "name": "esptool", + "systems": [ + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-win32.zip", + "checksum": "SHA-256:0248bf78514a3195f583e29218ca7828a66e13c6e5545a078f1c1257033e4927", + "host": "i686-mingw32", + "archiveFileName": "esptool-0.4.6-win32.zip", + "size": "17481" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-osx.tar.gz", + "checksum": "SHA-256:0fe87ba7e29ee90a9fc72492aada8c0796f9e8f8a1c594b6b26cee2610d09bb3", + "host": "x86_64-apple-darwin", + "archiveFileName": "esptool-0.4.6-osx.tar.gz", + "size": "20926" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-osx.tar.gz", + "checksum": "SHA-256:0fe87ba7e29ee90a9fc72492aada8c0796f9e8f8a1c594b6b26cee2610d09bb3", + "host": "i386-apple-darwin", + "archiveFileName": "esptool-0.4.6-osx.tar.gz", + "size": "20926" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-linux64.tar.gz", + "checksum": "SHA-256:f9f456e9a42bb2597126c513cb8865f923fb978865d4838b9623d322216b74d0", + "host": "x86_64-pc-linux-gnu", + "archiveFileName": "esptool-0.4.6-linux64.tar.gz", + "size": "12885" + }, + { + "url": "https://github.com/igrr/esptool-ck/releases/download/0.4.6/esptool-0.4.6-linux32.tar.gz", + "checksum": "SHA-256:85275ca03a82bfc456f5a84e86962ca1e470ea2e168829c38ca29ee668831d93", + "host": "i686-pc-linux-gnu", + "archiveFileName": "esptool-0.4.6-linux32.tar.gz", + "size": "13417" + } + ] + }, + { + "version": "0.1.2", + "name": "mkspiffs", + "systems": [ + { + "url": "https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-windows.zip", + "checksum": "SHA-256:0a29119b8458b61a877408f7995e4944623a712e0d313a2c2f76af9ab55cc9f2", + "host": "i686-mingw32", + "archiveFileName": "mkspiffs-0.1.2-windows.zip", + "size": "230802" + }, + { + "url": "https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-osx.tar.gz", + "checksum": "SHA-256:df656fae21a41c1269ea50cb53752dcaf6a4e1437255f3a9fb50b4025549b58e", + "host": "x86_64-apple-darwin", + "archiveFileName": "mkspiffs-0.1.2-osx.tar.gz", + "size": "115091" + }, + { + "url": "https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-osx.tar.gz", + "checksum": "SHA-256:df656fae21a41c1269ea50cb53752dcaf6a4e1437255f3a9fb50b4025549b58e", + "host": "i386-apple-darwin", + "archiveFileName": "mkspiffs-0.1.2-osx.tar.gz", + "size": "115091" + }, + { + "url": "https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-linux64.tar.gz", + "checksum": "SHA-256:1a1dd81b51daf74c382db71b42251757ca4136e8762107e69feaa8617bac315f", + "host": "x86_64-pc-linux-gnu", + "archiveFileName": "mkspiffs-0.1.2-linux64.tar.gz", + "size": "46281" + }, + { + "url": "https://github.com/igrr/mkspiffs/releases/download/0.1.2/mkspiffs-0.1.2-linux32.tar.gz", + "checksum": "SHA-256:e990d545dfcae308aabaac5fa9e1db734cc2b08167969e7eedac88bd0839667c", + "host": "i686-pc-linux-gnu", + "archiveFileName": "mkspiffs-0.1.2-linux32.tar.gz", + "size": "45272" + } + ] + } + ], + "email": "ivan@esp8266.com", + "name": "esp8266" + } + ] } \ No newline at end of file diff --git a/IDE_Board_Manager/sparkfun-samd-1.4.0.tar.bz2 b/IDE_Board_Manager/sparkfun-samd-1.4.0.tar.bz2 new file mode 100644 index 00000000..aa7f62a0 Binary files /dev/null and b/IDE_Board_Manager/sparkfun-samd-1.4.0.tar.bz2 differ diff --git a/IDE_Board_Manager/sparkfunboards.1.1.6.tar.bz2 b/IDE_Board_Manager/sparkfunboards.1.1.6.tar.bz2 new file mode 100644 index 00000000..cf8890e6 Binary files /dev/null and b/IDE_Board_Manager/sparkfunboards.1.1.6.tar.bz2 differ diff --git a/README.md b/README.md index 19002827..fb07d995 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # SparkFun Arduino Boards -This repository contains support for the following SparkFun Arduino-compatible development boards: +This repository contains support for the following SparkFun Arduino-compatible development boards. + +**IMPORTANT NOTE:** These board files have been updated for compatibility with Arduino version 1.8 and higher. Some boards (e.g. SAMD) may not compile correctly with earlier versions of Arduino. If you need compatibility with earlier versions of Arduino, you can choose previous releases of these boards from the Boards Manager. #### AVR Boards @@ -21,43 +23,55 @@ This repository contains support for the following SparkFun Arduino-compatible d * [SparkFun SAMD21 Dev Breakout](https://www.sparkfun.com/products/13672) * [SparkFun SAMD21 Mini Breakout](https://www.sparkfun.com/products/13664) +* [SparkFun 9DoF Razor IMU M0 (SAMD21)](https://www.sparkfun.com/products/14001) +* [SparkFun LilyMini ProtoSnap (SAMD11)](https://www.sparkfun.com/products/14063) +* [SparkFun LilyMini (SAMD11)](https://www.sparkfun.com/products/14064) #### ESP8266 Boards * [ESP8266 Thing](https://www.sparkfun.com/products/13231) * [ESP8266 WiFi Shield](https://www.sparkfun.com/products/13287) -Each board will be added as an entry to the Arduino **Tools** > **Board** menu. - -![Example image](example.png) - ### Installation Instructions -To add board support for our products, go to **File** > **Preferences**, and paste this URL into the 'Additional Boards Manager URLs' input field: +To add board support for our products, start Arduino and open the Preferences window (**File** > **Preferences**). Now copy and paste the following URL into the 'Additional Boards Manager URLs' input field: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json -![Adding a board manager list](https://cdn.sparkfun.com/assets/learn_tutorials/4/5/4/arduino-board-add.png) +![Location of Additional Boards Manager URL input field](prefs-arrow.png) + +If there is already an URL from another manufacturer in that field, click the button at the right end of the field. This will open an editing window allowing you to paste the above URL onto a new line. + +### AVR and ESP Installation Instructions -This field can be found in 'Preferences...' under the Arduino File menu. +Open the Boards Manager window by selecting **Tools** > **Board**, scroll to the top of the board list, and select **Boards Manager**. -Now, under the **Tools** > **Board** > **Boards Manager...**, if you type in "sparkfun", you will see an option to install board files for SparkFun Arduino compatible boards. Click "Install" to add these to your list. +![Boards Manager Menu](manager-menu.png) -**NOTE: If you are using Arduino 1.6.6 and the link isn't working for you, change "https" at the beginning of the link to "http" and try again. We're working to figure out why this is happening in version 1.6.6.** +If you type "sparkfun" (without quotes) into the "filter your search" field, you will see options to install SparkFun's AVR and ESP board files. Click in the desired box, and click the "Install" button that appears. Once installed, the boards will appear at the bottom of the board list. -![SparkFun Boards image](https://cdn.sparkfun.com/assets/learn_tutorials/4/5/4/sparkfun-arduino-board-install.png) +![Sparkfun Boards](sparkfunboards.png) -Now, when you select the Boards list, you will see a collection of new boards for SparkFun. +### SAMD Installation Instructions -![SparkFun Boards List](boards_list.png) +When installing SAMD boards, you will need to first install Arduino SAMD support, then SparkFun's SAMD boards. -### Cleaning up the Boards Menu +Open the Boards Manager window by selecting **Tools** > **Board**, scroll to the top of the board list, and select **Boards Manager**. Now type "samd" (without quotes) into the "filter your search" field at the top of the window. Two entries should show up, one for Arduino SAMD boards, and one for SparkFun SAMD boards. We'll install both of these, starting with Arduino SAMD boards. -Each entry in the boards list is defined in [boards.txt](https://github.com/sparkfun/Arduino_Boards/blob/master/sparkfun/avr/boards.txt). If you want to de-clutter the menu, you can comment out a board by inserting a `#` at the beginning of each line. +Click anywhere in the "Arduino SAMD Boards" box, and click "Install". This is a large installation and will take a while. + +![Arduino SAMD Boards](manager-arrow.png) + +Now click anywhere in the "SparkFun SAMD Boards" box, and click "Install". This is a small installation and will happen much faster. + +![SparkFun SAMD Boards](manager-arrow2.png) + +You're now ready to use SparkFun SAMD boards. They will appear at the bottom of the board list. ### Notes -* **Please note: This will only work under Arduino IDE versions 1.5 and up.** -* Some boards such as the Pro Micro and the Mega Pro come in more than one form. For these **you must select the correct processor** in the 'Tools' menu. +* Some boards such as the Arduino Pro and Pro Mini come in more than one flavor. For these **you must select the correct processor** in the 'Tools' menu. * Information on compiling and programming the bootloaders can be found in the bootloaders directory. -* **Bugs introduced in the Arduino IDE version 1.6.6 through at least 1.6.9 produce errors indicating there is something wrong with these files. This can be resolved by reverting back to 1.6.5-r5. So far all reports seem to indicated that 1.6.10 has also fixed the issues. These intermittent issues are difficult to reliably reproduce.** + +**Have fun!**
+\-Your friends at SparkFun \ No newline at end of file diff --git a/SparkFunBoards.png b/SparkFunBoards.png deleted file mode 100644 index b16dec0b..00000000 Binary files a/SparkFunBoards.png and /dev/null differ diff --git a/boards_list.png b/boards_list.png deleted file mode 100644 index 213aeec7..00000000 Binary files a/boards_list.png and /dev/null differ diff --git a/example.png b/example.png deleted file mode 100644 index 1aa5b707..00000000 Binary files a/example.png and /dev/null differ diff --git a/manager-arrow.png b/manager-arrow.png new file mode 100644 index 00000000..81e913a6 Binary files /dev/null and b/manager-arrow.png differ diff --git a/manager-arrow2.png b/manager-arrow2.png new file mode 100644 index 00000000..17691f71 Binary files /dev/null and b/manager-arrow2.png differ diff --git a/manager-menu.png b/manager-menu.png new file mode 100644 index 00000000..c145ea92 Binary files /dev/null and b/manager-menu.png differ diff --git a/prefs-arrow.png b/prefs-arrow.png new file mode 100644 index 00000000..01a359b9 Binary files /dev/null and b/prefs-arrow.png differ diff --git a/sparkfun/avr/boards.txt b/sparkfun/avr/boards.txt index f5c0c696..844b0658 100644 --- a/sparkfun/avr/boards.txt +++ b/sparkfun/avr/boards.txt @@ -220,7 +220,7 @@ digitalsandbox.build.mcu=atmega328p # Can run at less than 5V on battery, so run at only 8MHz digitalsandbox.build.f_cpu=8000000L digitalsandbox.build.core=arduino:arduino -digitalsandbox.build.variant=arduino:standard +digitalsandbox.build.variant=digitalsandbox ################################################################################ diff --git a/sparkfun/avr/variants/digitalsandbox/pins_arduino.h b/sparkfun/avr/variants/digitalsandbox/pins_arduino.h new file mode 100644 index 00000000..38427629 --- /dev/null +++ b/sparkfun/avr/variants/digitalsandbox/pins_arduino.h @@ -0,0 +1,264 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + 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., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define NUM_DIGITAL_PINS 20 +#define NUM_ANALOG_INPUTS 6 +#define analogInputToDigitalPin(p) ((p < 6) ? (p) + 14 : -1) + +#if defined(__AVR_ATmega8__) +#define digitalPinHasPWM(p) ((p) == 9 || (p) == 10 || (p) == 11) +#else +#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11) +#endif + +#define PIN_SPI_SS (10) +#define PIN_SPI_MOSI (11) +#define PIN_SPI_MISO (12) +#define PIN_SPI_SCK (13) + +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +#define PIN_WIRE_SDA (18) +#define PIN_WIRE_SCL (19) + +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +#define LED_BUILTIN 13 + +#define PIN_A0 (14) +#define PIN_A1 (15) +#define PIN_A2 (16) +#define PIN_A3 (17) +#define PIN_A4 (18) +#define PIN_A5 (19) +#define PIN_A6 (20) +#define PIN_A7 (21) + +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; +static const uint8_t A7 = PIN_A7; + +#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0)) +#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1)) +#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0)))) +#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14))) + +#define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : NOT_AN_INTERRUPT)) + +#ifdef ARDUINO_MAIN + +// On the Arduino board, digital pins are also used +// for the analog output (software PWM). Analog input +// pins are a separate set. + +// ATMEL ATMEGA8 & 168 / ARDUINO +// +// +-\/-+ +// PC6 1| |28 PC5 (AI 5) +// (D 0) PD0 2| |27 PC4 (AI 4) +// (D 1) PD1 3| |26 PC3 (AI 3) +// (D 2) PD2 4| |25 PC2 (AI 2) +// PWM+ (D 3) PD3 5| |24 PC1 (AI 1) +// (D 4) PD4 6| |23 PC0 (AI 0) +// VCC 7| |22 GND +// GND 8| |21 AREF +// PB6 9| |20 AVCC +// PB7 10| |19 PB5 (D 13) +// PWM+ (D 5) PD5 11| |18 PB4 (D 12) +// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM +// (D 7) PD7 13| |16 PB2 (D 10) PWM +// (D 8) PB0 14| |15 PB1 (D 9) PWM +// +----+ +// +// (PWM+ indicates the additional PWM pins on the ATmega168.) + +// ATMEL ATMEGA1280 / ARDUINO +// +// 0-7 PE0-PE7 works +// 8-13 PB0-PB5 works +// 14-21 PA0-PA7 works +// 22-29 PH0-PH7 works +// 30-35 PG5-PG0 works +// 36-43 PC7-PC0 works +// 44-51 PJ7-PJ0 works +// 52-59 PL7-PL0 works +// 60-67 PD7-PD0 works +// A0-A7 PF0-PF7 +// A8-A15 PK0-PK7 + + +// these arrays map port names (e.g. port B) to the +// appropriate addresses for various functions (e.g. reading +// and writing) +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &DDRB, + (uint16_t) &DDRC, + (uint16_t) &DDRD, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PORTB, + (uint16_t) &PORTC, + (uint16_t) &PORTD, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t) &PINB, + (uint16_t) &PINC, + (uint16_t) &PIND, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = { + PD, /* 0 */ + PD, + PD, + PD, + PD, + PD, + PD, + PD, + PB, /* 8 */ + PB, + PB, + PB, + PB, + PB, + PC, /* 14 */ + PC, + PC, + PC, + PC, + PC, +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { + _BV(0), /* 0, port D */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(6), + _BV(7), + _BV(0), /* 8, port B */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), + _BV(0), /* 14, port C */ + _BV(1), + _BV(2), + _BV(3), + _BV(4), + _BV(5), +}; + +const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { + NOT_ON_TIMER, /* 0 - port D */ + NOT_ON_TIMER, + NOT_ON_TIMER, + // on the ATmega168, digital pin 3 has hardware pwm +#if defined(__AVR_ATmega8__) + NOT_ON_TIMER, +#else + TIMER2B, +#endif + NOT_ON_TIMER, + // on the ATmega168, digital pins 5 and 6 have hardware pwm +#if defined(__AVR_ATmega8__) + NOT_ON_TIMER, + NOT_ON_TIMER, +#else + TIMER0B, + TIMER0A, +#endif + NOT_ON_TIMER, + NOT_ON_TIMER, /* 8 - port B */ + TIMER1A, + TIMER1B, +#if defined(__AVR_ATmega8__) + TIMER2, +#else + TIMER2A, +#endif + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, /* 14 - port C */ + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +// Digital Sandbox specific functions + +void initVariant() { + +// Set pin 3 to be a low output to avoid heating up buzzer attached to expansion port + + pinMode(3,OUTPUT); + digitalWrite(3,LOW); +} + +#endif + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_HARDWARE Serial + +#endif diff --git a/sparkfun/samd-tools/bossac/bossac-1.4.0-linux64.tar.bz2 b/sparkfun/samd-tools/bossac/bossac-1.4.0-linux64.tar.bz2 new file mode 100644 index 00000000..12e6b8a7 Binary files /dev/null and b/sparkfun/samd-tools/bossac/bossac-1.4.0-linux64.tar.bz2 differ diff --git a/sparkfun/samd-tools/bossac/bossac-1.4.0-osx.tar.bz2 b/sparkfun/samd-tools/bossac/bossac-1.4.0-osx.tar.bz2 new file mode 100644 index 00000000..c5fe56ee Binary files /dev/null and b/sparkfun/samd-tools/bossac/bossac-1.4.0-osx.tar.bz2 differ diff --git a/sparkfun/samd-tools/bossac/bossac-1.4.0-win.zip b/sparkfun/samd-tools/bossac/bossac-1.4.0-win.zip new file mode 100644 index 00000000..cbc1873e Binary files /dev/null and b/sparkfun/samd-tools/bossac/bossac-1.4.0-win.zip differ diff --git a/sparkfun/samd/boards.txt b/sparkfun/samd/boards.txt index 0b86f291..c8a7e4e0 100644 --- a/sparkfun/samd/boards.txt +++ b/sparkfun/samd/boards.txt @@ -70,6 +70,34 @@ samd21_mini.build.pid=0x8D21 samd21_mini.bootloader.tool=openocd samd21_mini.bootloader.file=zero/SparkFun_SAMD21_Dev.bin +LilyMini.name=LilyPad LilyMini +LilyMini.vid.0=0x1B4F +LilyMini.pid.0=0x0100 +LilyMini.vid.1=0x1B4F +LilyMini.pid.1=0x0101 +LilyMini.upload.tool=bossac +LilyMini.upload.protocol=sam-ba +LilyMini.upload.maximum_size=12030 +LilyMini.upload.use_1200bps_touch=true +LilyMini.upload.wait_for_upload_port=true +LilyMini.upload.native_usb=true +LilyMini.build.mcu=cortex-m0plus +LilyMini.build.f_cpu=48000000L +LilyMini.build.usb_product="SFE LILYMINI" +LilyMini.build.usb_manufacturer="SparkFun" +LilyMini.build.board=SAMD_ZERO +LilyMini.build.core=lilymini +LilyMini.build.extra_flags=-D__SAMD11D14AM__ {build.usb_flags} +LilyMini.build.ldscript=linker_scripts/gcc/flash_with_4kbootloader.ld +LilyMini.build.openocdscript=openocd_scripts/arduino_zero.cfg +LilyMini.build.variant=SparkFun_LilyMini +LilyMini.build.variant_system_lib= +LilyMini.build.extra_combine_flags= +LilyMini.build.vid=0x1B4F +LilyMini.build.pid=0x0100 +LilyMini.bootloader.tool=openocd +LilyMini.bootloader.file=LilyMini/samd11_sam_ba.bin + samd21_9dof.name=SparkFun 9DoF Razor IMU M0 samd21_9dof.vid.0=0x1B4F samd21_9dof.pid.0=0x9D0E diff --git a/sparkfun/samd/bootloaders/LilyMini/LilyMini_Protosnap_Light_Sensor_Arduino_V10.ino.bin b/sparkfun/samd/bootloaders/LilyMini/LilyMini_Protosnap_Light_Sensor_Arduino_V10.ino.bin new file mode 100644 index 00000000..b375b0ec Binary files /dev/null and b/sparkfun/samd/bootloaders/LilyMini/LilyMini_Protosnap_Light_Sensor_Arduino_V10.ino.bin differ diff --git a/sparkfun/samd/bootloaders/LilyMini/LilyMini_Protosnap_Light_Sensor_combined_V10.hex b/sparkfun/samd/bootloaders/LilyMini/LilyMini_Protosnap_Light_Sensor_combined_V10.hex new file mode 100644 index 00000000..af48d14f --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/LilyMini_Protosnap_Light_Sensor_combined_V10.hex @@ -0,0 +1,1025 @@ +:10000000001000204D0500003D05000041050000E6 +:1000100000000000000000000000000000000000E0 +:100020000000000000000000000000004505000086 +:100030000000000000000000490500000000000072 +:1000400010B5064C2378002B07D1054B002B02D0AE +:10005000044800E000BF0123237010BD58000020B9 +:1000600000000000DC0E000008B5084B002B03D098 +:100070000748084900E000BF07480368002B03D089 +:10008000064B002B00D0984708BDC046000000007A +:10009000DC0E00005C000020540000200000000086 +:1000A00070B50368041C988B1A1C0821FF320842A3 +:1000B00028D0988B174D0143802099839872112383 +:1000C00053704021144B917150715E68C0202E40D6 +:1000D000800506435E605E693540284358610F48DD +:1000E00018600F4818615D680E4828408025AD02F1 +:1000F000284358605868800B800358600023517172 +:10010000237105E0137ADA0602D5201C00F0C4FA48 +:10011000207970BDFFFFFF8F840100208400002044 +:1001200004010020FF3F00F0002303714371044BE2 +:10013000016083600B78022213430B707047C04646 +:10014000A100000038B5364B2021DA6901200A43AE +:10015000DA61344B06241A7802431A70324B0F22AC +:100160001978914319701978214319702F490C7827 +:100170002043087019780A401A701A7860210A43DF +:100180001A702B4B2B4A5A805A7852B2002AFBDB4A +:10019000294B01211A780A431A709A78D107FCD4A6 +:1001A00026480268510B1F221140914200D10521BF +:1001B00011408C011D8D2249294021431985046875 +:1001C000A10C0A401F2A00D11D221C8D1F210A40AC +:1001D0008C4322431A8502680721D20D0A408A42C5 +:1001E00000D103220A40188D1103164A02400A4327 +:1001F0001A8519787F220A401A701A780421124849 +:100200000A431A7058621A890C218A431A811A8982 +:1002100001218A431A810021802200F014FE38BD9A +:1002200000040040584400413C440041594400410E +:10023000000C004006400000005000412460800097 +:100240003FF8FFFFFF8FFFFF84010020F7B5141C6C +:10025000234A5F0101971D1CD319061C5869271CEE +:100260004000400F03301033C74006D00F1C8022DF +:10027000596812060A435A6009E02F1C7B1E9F41F1 +:10028000184BBF01FF18381C221C00F0D3FD019948 +:100290001348083542181761131C5269A104920BC8 +:1002A000890C92030A435A6159690F4A02200A4095 +:1002B0005A616B01F318D979032211400143D879AF +:1002C0009043021C0A43DA715979802252420A4350 +:1002D0005A716B01F318DB799A07FAD5201CFEBD21 +:1002E0008401002004010020FF3F00F0F8B51E4EFD +:1002F000041C3378151C002B12D11C4B1C4A1A64A9 +:100300005A6C920B92035A64586C1A4A02405A640F +:10031000A2235B00E25C40200243E25401233370DD +:100320004827FF37E25D012313401AD00F4B5A6C68 +:100330009204920CAA4202D25D6CAD04AD0C081C72 +:100340002A1C0B4900F076FDE25D03231A400121CF +:100350000A43E15D99430B1C1343E35500233370BB +:1003600000E01D1C281CF8BD740000208401002042 +:10037000C4000020FF3F00F0FF30827930239A4311 +:10038000131C2022002900D11022134383717047CF +:100390000C4BFF305A690221920B92035A61027A88 +:1003A00003231A400A43017A99430B1C1343037237 +:1003B000827980235B4213438371037A9A07FCD5C9 +:1003C0007047C0468401002080235B421943C9B2B4 +:1003D0008172704770B5A02303225B00C254134B97 +:1003E000134A5C6CC021144089050C4346255C64AB +:1003F000FF35402444550F4D30261D6490256D0077 +:1004000046555D6B15402943922559636D00802147 +:100410004155094D1D63B0256D0044555C6F224068 +:100420005A67B2235B00C15470BDC04684010020EE +:10043000FFFFFF8FC40000204401002030B5364A82 +:100440001E23516808209943022319435160334900 +:100450008A6902438A613248324A9082908A034311 +:100460009382D3689807FCD52F4B01201870187819 +:10047000C40704D52C48407840B20028F7DB01209F +:100480009860587840B20028FBDB284C264844602E +:10049000587840B20028FBDB82242348E4014480E2 +:1004A000587840B20028FBDB908C8024A0439084D5 +:1004B000D068C506FCD51E4C1A48C462D4681948D9 +:1004C000E506FBD5848C1B4D2C438484D4681548E9 +:1004D000E506FBD5848C02252C438484D068040671 +:1004E000FCD51048C0684506F8D5D068C406FCD5D0 +:1004F00000229A605A7852B2002AFBDB0E480A4A60 +:1005000050605A7852B2002AFBDB00230B724B7208 +:100510008B72CB7230BDC0460040004100040040E9 +:100520000C06000000080040000C0040010501001E +:10053000B805FF7D040A0000000703000EBEFEE7B9 +:100540000DBEFEE705BEFEE702BEFEE70E4A0F48FF +:1005500038B5824204D10E4A0E4B93420ED10AE0C6 +:100560000D4C9442F7D00023D1188842F3D9E558B6 +:1005700004330D60F8E700F011F804E09342FAD27A +:10058000002102C3FAE7FEE7000000205800002027 +:100590008402002058000020E00E000070B5234BBC +:1005A000234A244C9A62802080218022C0050905BC +:1005B000120620250626986099609A6098619961D4 +:1005C0005A615D6026709D611E6A1C1C2E4213D00C +:1005D000194B1D686E1C03D16061A161A2610BE023 +:1005E000A061A161A26185F30888FF22191C9143D3 +:1005F000124A91605B681847FFF720FF62B600F06F +:100600001FF8051C281CAB6898470028FAD08023E7 +:10061000DB05A36180231B06A36180231B056361A7 +:1006200000F07EFA00F0B4FAFCE7C0460044004156 +:10063000004000C0454400410010000000ED00E013 +:1006400010B5054B054C2360FFF77CFD201C21688D +:10065000FFF76AFD201C10BD00500041040200207D +:1006600070B55200C0B06C46023222700322627034 +:100670005B0801240A19013A15786200002D05D1A2 +:1006800069460023FFF7E2FD40B070BD9C42F7DAF7 +:100690006E46B5520134EDE7F7B50468051C201C21 +:1006A000FF30037AAF4A10210B430372AE4F137829 +:1006B000AE493B705378AE4E0B7093783380D1784F +:1006C000338809020B4333801179AA4B1980517981 +:1006D0001F8809020F431F809779A7490F80D2799D +:1006E0000F8812023A430A80402242719F489E4F6F +:1006F0000278387812020243A0480F1C8446181C66 +:10070000624500D1C3E020DC802149008A4200D14B +:1007100085E109DC812A00D193E0822A00D196E0AC +:10072000802A00D07BE18CE081235B009A4200D1DB +:10073000D6E000DA6FE1C0239B009A4200D16EE15F +:100740008F4B9A4200D166E169E190231B019A42E6 +:100750006AD015DCD023DB009A4222D088231B010B +:100760009A426AD0A023DB009A4200D057E1201CB5 +:10077000FFF70EFE3188286889B2FFF725FE52E1A7 +:10078000804B9A4200D146E100DC48E17E4B9A4220 +:1007900000D134E17D4B9A4200D040E133886B7147 +:1007A00039E133881B0A012B08D10B8812222868F3 +:1007B000934201D80A8892B2754928E133881B0A0E +:1007C000022B08D10B8843222868934201D80A885B +:1007D00092B270491BE133881B0A032B00D01EE143 +:1007E0003388DBB2012B17D0002B07D0022B00D0AF +:1007F00015E10B882868DBB2674911E0042201A8E3 +:10080000664900F017FB3B8804222868934201D810 +:100810003A8892B201A9FAE00B8828686049DBB2F5 +:100820000822FFF71DFFFEE03388201C2B71FFF725 +:10083000AFFD201CFFF7CEFDF5E0291C01C9012208 +:10084000E5E0584900230B8028680222E0E0554982 +:1008500000220A80188850221040534A10701E88C7 +:100860000F20304018801888032800D9D7E012786C +:100870001B8808335B01E418A379002A01D09B068A +:1008800000E0DB06DB0F0B8028680222BFE019883E +:100890007F229143444AC9B2117018880F21014048 +:1008A00019803188002900D0B9E01988002900D1C9 +:1008B000B5E01988032900D9B1E012781B88083304 +:1008C0005B01E318002A04D05A7930218A432021A1 +:1008D00003E05A7930218A4310210A435A719AE081 +:1008E00002887F239A43304BD2B21A7001880F22BC +:1008F0000A4002803288002A00D090E00288002A54 +:1009000000D18CE00288032A00D988E01B78002BF4 +:100910004CD0038808335B01E3189B799A0600D416 +:1009200079E00388302108335B01E3181A798A43A0 +:1009300020210A431A71038808335B01E318DB792D +:100940005F0668D50388602108335B01E318DA7914 +:100950008A4340210A43DA710388022208335B018B +:10096000E3184AE0840000207C000020780000208A +:10097000760000207A0000207E00002002030000A4 +:100980000103000021200000A1210000212200001D +:10099000880E0000000000207D0E0000700E000098 +:1009A000740E0000800000208200002003880833BD +:1009B0005B01E3189B79D9062DD5038830210833D4 +:1009C0005B01E3181A798A4310210A431A710388DC +:1009D00008335B01E318DB799A061CD50388602194 +:1009E00008335B01E318DA798A4320210A43DA717C +:1009F0000388012208335B01E3181A710BE00B88AE +:100A000008222868934201D80A8892B20649002336 +:100A1000FFF71CFC07E0201CFFF7BAFC03E0201CDA +:100A20000121FFF7A9FCF7BD4400002007B5054BE5 +:100A30000122019001A91868131CFFF707FC01208F +:100A40000EBDC0460402002013B5054B6C460734AA +:100A50001868211C0122FFF749FC207816BDC0460A +:100A60000402002010B5074C201CFFF719FB031CE3 +:100A70000020834205D022684823FF33D05C012345 +:100A8000184010BD0402002010B5054A0C1C031CC0 +:100A9000191C10680123221CFFF7D8FB201C10BD75 +:100AA0000402002070B5084C061C201C0D1CFFF72A +:100AB000F7FA0023984205D02068311C2A1CFFF762 +:100AC00015FC031C181C70BD04020020F8B50C4C6A +:100AD000051C201C0E1CFFF7E3FA0023271C341C06 +:100AE00098420AD0002C07D0291C221C3868FFF736 +:100AF000FDFB241A2D18F5E7331C181CF8BDC04661 +:100B00000402002008B5031C081C111C984700288B +:100B100003D08022014BD205DA6108BD00440041B8 +:100B2000044A054B1A60054B00221A60044B7A22D6 +:100B30001A7070479C0E00007402002070020020A2 +:100B40001C02002008B50A1C0349031C0968C86878 +:100B5000191CFFF7D7FF08BD740200200A4B802242 +:100B6000D2059A61802212059A61802212069A614A +:100B700072B6EFF30883054A1360036883F30888AD +:100B8000436818477047C04600440041780200207F +:100B9000F0B5974D974C2B6885B01B69201C402100 +:100BA0009847002803D08022934B1205DA61934BBB +:100BB000934A1C60934B002110601960914E904A3B +:100BC00037681068874200D310E18C4C21680A789E +:100BD000FF2A00D101E1232A00D0DAE08A4B1B78FA +:100BE000532B39D1B8421AD9884B01371B680131D0 +:100BF0003760C01B2160864F984201D2386000E008 +:100C00003B60844B3A68186800F014F93B68306820 +:100C100021681A183260CA1822607F4A1370794A14 +:100C200078481268131C013B03602368774A013B34 +:100C30002360794B11681B788B420BD22A68754868 +:100C4000C91A006892699047002803D080226A4B35 +:100C50001205DA61C04696E0522B0ED16D4A2B6820 +:100C600010686A4A5B6911689847002800D18AE0D9 +:100C70008022614BD205DA6185E04F2B05D1654BAF +:100C8000624A1B6812681A707DE0482B05D1614BDF +:100C90005E4A1B6812681A8075E0572B05D15D4BC0 +:100CA0005A4A1B6812681A606DE06F2B03D1594BCA +:100CB0000121186807E0682B08D1564B53481B6880 +:100CC00002211B880360FFF73DFF5CE0772B06D114 +:100CD000504B4E481B6804211B680360F3E7472B09 +:100CE00009D14A4B1868FFF739FF4C4B1B6883F357 +:100CF000088862B647E0562B45D12B684849D8682A +:100D00000722FFF7FFFE2B684649D8680122FFF74C +:100D1000F9FE4549002321603360384A374813689B +:100D20005A1C02601F78002F06D0364A35481268D8 +:100D3000131C01330360F0E72B68324ED868326829 +:100D4000FFF7E0FE2B683749D8680122FFF7DAFE8B +:100D5000364937602160294A1368581C10601B7897 +:100D6000002B03D0336801333360F4E7254A2B6846 +:100D70001268D8680192FFF7C5FE2B682C49D86825 +:100D80000222FFF7BFFE204B7A221A7000221F4B6F +:100D900022E0111C3039C8B21C4B092804D818684D +:100DA00002011143196018E0111C4139052901D8CD +:100DB000373A04E0111C6139052904D8573A1868FC +:100DC00001010A4308E02C2A03D1124A1968116074 +:100DD00001E00D490A7000221A600A4B1A680132BC +:100DE0001A60064B1A6801321A60E7E605B0F0BDDA +:100DF000740200203002002000440041180200204C +:100E000014020020280200201C0200207C02002086 +:100E100080020020700200201002002078020020D2 +:100E2000D20E0000B80E0000BA0E0000C60E000080 +:100E3000CF0E000010B50023934203D0CC5CC45405 +:100E40000133F9E710BD031C8218934202D01970D8 +:100E50000133FAE770470000F8B5C046F8BC08BC9B +:100E60009E467047F8B5C046F8BC08BC9E46704721 +:100E700004030904537061726B46756E004C696C13 +:100E8000794D696E690000001201100102000040F6 +:100E90004F1B000100020102000100002D0A0000AA +:100EA000490A0000650A0000890A0000A50A00003E +:100EB000890A0000CD0A0000200044656320203428 +:100EC00020323031360030313A35393A3433000A85 +:100ED0000D004431312D312E3000000000000000A3 +:100EE00009024300020100803209040000010202ED +:100EF000000005240010010424020005240600015E +:100F00000524010001070583030800FF090401000F +:100F1000020A0000000705810240000007050202E6 +:100F20004000000000C2010000000800690000004D +:100F30004100000000000000FFFFFFFFFFFFFFFF78 +:100F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:100F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:100F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:100F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:100F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:100F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:100FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:100FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:100FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:100FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:100FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 +:100FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:1010000000100020451500002D1500002D150000D2 +:1010100000000000000000000000000000000000D0 +:101020000000000000000000000000002D1500007E +:1010300000000000000000002D1500009D150000BC +:101040002D1500002D1500002D1500002D15000098 +:10105000FD1400002D1500002D15000031150000B5 +:101060002D150000991300002D1500002D1500000E +:101070002D1500002D1500002D1500002D15000068 +:101080002D1500002D1500002D15000010B5064C83 +:101090002378002B07D1054B002B02D0044800E039 +:1010A00000BF0123237010BD0C01002000000000D0 +:1010B000D437000008B5084B002B03D00748084977 +:1010C00000E000BF07480368002B03D0064B002B4D +:1010D00000D0984708BDC04600000000D43700008B +:1010E00010010020080100200000000070B5164D1E +:1010F000013D002DFCD1022000F03AFD134C144EAE +:101100002378002812D1002B19D100F055FA33684A +:10111000C01A0A2813D90F4B0122196822708918A6 +:101120001960196803290ADD1A6008E0002B06D04F +:1011300000F042FA3368C01A142800D9257000F074 +:101140003BFA306070BDC04680BB00002C0100201F +:10115000280100200000002008B50520012100F032 +:1011600073FC0620012100F06FFC0720012100F034 +:101170006BFC0320012100F067FC0420012100F03A +:1011800063FC0220011C00F05FFC02200249021CEB +:1011900000F032F908BDC046ED100000F0B50520A2 +:1011A00085B0012100F0ACFC0620012100F0A8FC74 +:1011B0000720012100F0A4FC0320012100F0A0FC85 +:1011C0000420012100F09CFC724C2368012BFBD011 +:1011D0000520012100F094FC0620002100F090FC85 +:1011E0000720012100F08CFCFF25291C032000F0C2 +:1011F000A1FB291C042000F09DFB013D012000F013 +:10120000E1F9002DF1D12368022B4FD1012523688C +:10121000022B03D00135032DF5D0F8E70126236812 +:10122000022B03D00136032EF9D1F3E7012000F0A1 +:10123000FDFA052358432D30FF300190019B3020EB +:1012400058430321012E1AD102F00AF80026071C88 +:101250002368022B0CD10320012D00D00420311C67 +:1012600000F068FB019B002B02D03B1C013BFDD131 +:10127000802301365B009E42EAD10226CFE701F0CF +:10128000EFFFFF2703902368022B0CD10320012DD1 +:1012900000D00420391C00F04DFB019B002B02D034 +:1012A000039B013BFDD1013FEDD2BBE705200021AF +:1012B00000F026FC0720012100F022FC0320002181 +:1012C00000F01EFC0420002100F01AFC2368032B10 +:1012D0005ED1012000F0AAFA1E2852DC182802DD97 +:1012E000029B002B4DD0FA20800000F09DFE0028CC +:1012F00019D1051C0320291C00F01CFBC8235B012D +:10130000013BFDD1802301355B009D42F2D1FF25D9 +:101310000320291C00F00EFBC8235B01013BFDD11B +:10132000013DF5D203E00320002100F003FBFA2089 +:10133000C00000F079FE002819D1051C0420291CEA +:1013400000F0F8FAC8235B01013BFDD18023013591 +:101350005B009D42F2D1FF250420291C00F0EAFA2F +:10136000C8235B01013BFDD1013DF5D203E0042020 +:10137000002100F0DFFA0620002100F0C1FB01236C +:1013800004E00620012100F0BBFB002302939DE74F +:1013900005B0F0BD0000002008B5024800F0BCFD1B +:1013A00008BDC0463001002013B50C4C0C49201C70 +:1013B00000F082FC0B490C4800F07EFC0B490C4805 +:1013C00000F07AFC0123009300230193211C0322E7 +:1013D0000423084800F07CFD13BDC04690010020A6 +:1013E00000080042000C004294010020001000425E +:1013F0009801002030010020F0B51823434385B048 +:101400000292364A1625D3185D5701900391691C44 +:1014100062D0102D60D0324B324C196800291FD198 +:101420004422314801F0FBFF30491022CA67304B9B +:10143000C02149005A50C12189005858FF26B043A5 +:1014400058501A602B4A2C4B5A802378022213439F +:1014500023706378DB09012BFBD0214B01221A603A +:10146000012763693E1CAE4033436361002101984C +:1014700000F096FB1C4A0399AB009950072D00DC45 +:101480000027FB00029AED1AAD00042A22D8101C96 +:10149000BF0001F0DBFE03080D121700114B0522FF +:1014A000FF18BB6912E00F4904227F18BB690DE0E9 +:1014B0000C4ABF18BB69032208E00A4B0222FF183E +:1014C000BB6903E0074901227F18BB69AA40151CCC +:1014D0001D43BD61F6B2E66005B0F0BD28360000E0 +:1014E0009C01002000180040A001002004E100E061 +:1014F00000E100E005400000000C004070B5002451 +:10150000084D01262B69A640334206D0064BA200A7 +:10151000D358002B00D098472E610134102CEFD106 +:1015200070BDC04600180040A0010020FEE700008A +:1015300008B5034B1B68002B00D0984708BDC04678 +:10154000E401002038B51049104CA14206D101F049 +:1015500037FF00F065F800F00DFF0BE00C4D8D42F9 +:10156000F5D00023CA18E818A24204D20068043358 +:101570001060F7E7FEE79042E9D0064B064A934237 +:10158000E5D2002204C3F9E7000000200C0100208E +:10159000D83700000C010020DC08002008B500F05E +:1015A0002CF8002801D100F01DF808BD014B18608F +:1015B0007047C046E4010020014B18687047C046E0 +:1015C000E801002070B5041E08D0054B1D681E1CE4 +:1015D00000F012F833685B1BA342F9D370BDC0461C +:1015E000E801002008B5034B1A6801321A6000F0C8 +:1015F00035FB08BDE801002070470020704700005F +:10160000024B5B785BB2002BFADB7047000C0040AA +:10161000024BDB68DA06FBD57047C0460008004085 +:10162000F8B53F4B1E2259683E4F914302221143A9 +:101630005960B96908200143B9613B4C3B49A1821B +:10164000A18A0A43A282E3689A07FCD5384D012398 +:101650002B702B78DA0704D5354B5B785BB2002B07 +:10166000F7DB0123AB60FFF7CBFF324B6B60FFF77B +:10167000C7FF8223DB016B80FFF7C2FFA38C8022B0 +:101680009343A384FFF7C4FF2B4BE362FFF7C0FF34 +:10169000A38C2A4A1343A384FFF7BAFFA38C022228 +:1016A0001343A384E36880221F4E1342FAD0F368E9 +:1016B0005A06F7D50024FFF7ABFFAC60FFF7A0FF99 +:1016C0001F4B6B60FFF79CFF326A1E4B1340336267 +:1016D000336A8022934333620323AB601A4B6B60FF +:1016E000FFF78EFF194B1A4A3C727C72BC72FC7277 +:1016F0001A60184B184A1B6812685801FF21D20E55 +:10170000014011439A06520F12020B1C1343134A55 +:101710001385034A536880221343014A5360F8BD7E +:101720000040004100040040000800400C0600009A +:10173000000C004001050100B805FF7D040A00000F +:1017400000070300FFFCFFFF03060100100000205C +:10175000006CDC02246080002060800000200042D9 +:10176000294BFA21186810B5890001F079FD274B43 +:10177000013898421CD8264B264A5860106AC0216E +:101780000002000A090601431162002407229C603E +:101790001A60214B1C211A6A0A431A621A6AE02154 +:1017A0000A431A62196A802252000A431A6200E050 +:1017B000FEE7201C0021013400F046F90C2CF8D182 +:1017C000164B5A7852B2002AFADB154A5A80154B4A +:1017D0005A7ED209012AFAD0E222D2009A803F2210 +:1017E000DA70597E0F4AC9090129FAD0C0235B017A +:1017F000136142239370002000F06AF80A4B06211F +:101800001A6C0A431A6410BD10000020FFFFFF008D +:1018100010E000E000ED00E000040040000C00409B +:10182000134000000020004200080040031C183B49 +:1018300010B5042B12D900230C2842D81822424399 +:1018400021498A180821515601313AD010241457E1 +:10185000611C36D0012100F0A3F9201C72B61B4B8D +:101860005A7ED209012AFAD019691F2210409143E9 +:1018700008431861597E154AC9090129FAD011781F +:10188000022001431170597E104AC9090129FAD07A +:10189000117B0220014311731A7ED107FCD50B4A3C +:1018A000518B89B2587E094AC0090128FAD01078B4 +:1018B0000224A04310705A7ED209012AFBD062B6DE +:1018C0000B1C181C10BDC04628360000002000422A +:1018D00008B5164A517E131CC9090129F9D00138EF +:1018E000042813D81969124A0A401A615A780F213C +:1018F0008A4301F0ABFC030507090300012100E066 +:1019000003210A435A700CE00221FAE71169F0231F +:101910001B050B43136153780F218B4302210B43AB +:1019200053700020FFF782FF08BDC0460020004230 +:10193000FFFFFFF0F8B5182343433E4F0826FB187E +:10194000DB68041C0D1C1E4068D00421DA0600D49C +:10195000052100F025F918235C433F19798A364A9E +:10196000CCB209B209128B00002902DDD358002243 +:1019700001E0D25800233148002904D005DB0229B8 +:1019800003DC2F4900E02F4941804178C909012932 +:10199000FBD00221002B20D01A888A431A80DA7BE0 +:1019A000D209FCD11A8804210A431A801A884021DE +:1019B0000A43EDB21C191A802576DA7BD209FCD1D4 +:1019C000FF221A75DA7BD209FCD11A8802210A4358 +:1019D0001A80DA7BD209FCD12AE013688B431360AA +:1019E00093685B01FCD1D36B02210B43D3639368F3 +:1019F0005B01FCD11034A4001419656093685B018D +:101A0000FCD1FF23136493685B01FCD113680221AE +:101A10000B43136093685B01FCD109E0012100F0E6 +:101A200013F8201C311C7F2D00D9012100F068F82B +:101A3000F8BDC0462836000004000020000C00401D +:101A4000124000001140000010B51824021C201C98 +:101A50005043284B1818007A40B2013048D003296F +:101A600046D8081C211C01F0F1FB0233112162430E +:101A700098569A18C301204852681B18991840318B +:101A80000220087001219140596031E0624398566C +:101A900019499A185268C3015B18991840310620F9 +:101AA0000870012191405960996121E051435A56D3 +:101AB000114859184B68D2011118C8184030062433 +:101AC00004700120984048600C49521850600FE0A3 +:101AD000624398569A18C301074852681B18991810 +:101AE000403108780224A043087001219140996098 +:101AF00010BDC0462836000000440041104400419B +:101B0000182270B5151C4543154B08265C19A657BD +:101B1000013624D0EE566568F4012C19114D641974 +:101B200004252570441F022C02D8002902D10CE0A4 +:101B300000290AD1504319561818436801229A40C7 +:101B4000CB0109495B185A6009E05043195618182F +:101B500043680122054D9A40CB015B199A6170BD23 +:101B60002836000040440041104400410044004138 +:101B700018235843084A082113185956013109D02F +:101B800082560649D20152185B68106AD840012378 +:101B9000184000E000207047283600000044004153 +:101BA0001822424370B5244C031CA218082010567A +:101BB000421C40D072B6481C0C2837D801F046FBB6 +:101BC00039181818181818181807070707000929CE +:101BD00002D1181C002108E00A2902D1181C022198 +:101BE00003E00B2922D1181C0121FFF72DFF1DE076 +:101BF00018225343E218E3565268104DDB01540893 +:101C00005B191C1901203034024204D026780D01E2 +:101C10000F21314002E025780F26B54329439A1859 +:101C2000C9B22170403213781843107062B6002098 +:101C300001E00120404270BD283600000044004110 +:101C4000014B18607047C04614000020024B01226F +:101C500052421A607047C04614000020104A1368B0 +:101C6000591C1CD0013B1360002B18D172B60D4BD0 +:101C70001A7DD107FBD5198B2022FF320A431A8324 +:101C8000094ADA61094A1A801A7DD107FCD5BFF3E7 +:101C90004F8F074A074BDA60BFF34F8FFEE770475D +:101CA00014000020004000410208000002A5FFFFD0 +:101CB0000400FA0500ED00E001607047F7B508ACDC +:101CC000267804689D1E27686C1EA541ECB2920719 +:101CD00005683A4327063A432A60026807252940E7 +:101CE0005068B501002C00D05C03294301430C432C +:101CF0005460F7BD30B50368C0251C68AD031205FC +:101D00002A402243C024A40209042140114319603F +:101D100003685A6814435C6030BD036801211A6887 +:101D20000A431A600268116801231942FBD1D16984 +:101D30001942F8D17047036802211A680A431A60F1 +:101D40000268D3699907FCD470470268137E99072B +:101D5000FCD57047036800225A8370470368187ED9 +:101D60004007C00F70470368187EC00970470368BA +:101D70008022197E52420A431A7670470368188DF2 +:101D8000C0B2704703681A7E01200242FBD0198559 +:101D9000704700000368184A30B5934208D0174ACC +:101DA000934208D0164A934224D10B22102304E018 +:101DB00009220E2301E00A220F23D4B20121114A85 +:101DC000A14011600320C221890004405558E00061 +:101DD000FF248440A5432C1CC0258540281C20439B +:101DE00050508022D2011343074A538053785BB28C +:101DF000002BFBDB30BDC04600080042000C004257 +:101E00000010004200E100E0000C0040F8B5041CA6 +:101E1000151C0E1C1F1CFFF7BDFF201CFFF77DFFCC +:101E2000B1001C220A4069072368090C0A431A60A2 +:101E3000226884239375012E1AD10821012D00D127 +:101E400010210C4B79431868C00001F009FA23688F +:101E500007219A890140D2044903D20C0A439A818E +:101E600023680004C20C9889400B400310439881FA +:101E7000F8BDC046100000200120704708B5036877 +:101E80001322DB69984708BD10B5041C0069FFF7F1 +:101E900044FF201C143001F03DF810BD08B5006966 +:101EA000FFF753FF08BD08B5143001F045F808BD31 +:101EB00008B5143001F046F808BD08B5143001F03B +:101EC0002DF808BD08B50069FFF75CFF012008BDCB +:101ED000F7B51D1C08AB1B78041C009309AB1B78DD +:101EE000161C019300234360FA239B008360094B77 +:101EF0000F1C08330360143000F0F6FF009A231C17 +:101F00005C3327619A70019A1E705D70201CDA7034 +:101F1000FEBDC0464837000010B5041C0069FFF73D +:101F20001DFF002807D02069FFF728FF011C201C97 +:101F3000143000F0E4FF2069FFF715FF002805D0FA +:101F40002069FFF714FF2069FFF704FF10BDF0239D +:101F5000081C18403038434258417047F0231B0199 +:101F6000194080239B0099420CD0C0239B009942CA +:101F700006D080235B000520994204D0002002E0B7 +:101F8000072000E0062070470F231940012905D0E3 +:101F900002394B424B410220C01A00E0002070473A +:101FA000F0B5031C85B003915C33041C1827187826 +:101FB0003B1C43431B4E0821F3185956151CFFF7D1 +:101FC000EFFD231C5D33187808214743F61971563D +:101FD000FFF7E6FD01210A1C039B2069FFF716FFAE +:101FE000291C201CFFF7BAFF291C071C201CFFF727 +:101FF000CBFF291C061C201CFFF7A9FF391C0090F1 +:10200000331C20690122FFF759FE231C5F33197826 +:10201000013B1A782069FFF76DFE2069FFF78BFE00 +:1020200005B0F0BD28360000002110B5041E8C421A +:1020300004D001F0FDF9211C01F0B6F9081C10BD17 +:1020400070B50121051C0520FFF7FEFC06200121CB +:10205000FFF7FAFC07200121FFF7F6FC052000211D +:10206000FFF74EFD06200021FFF74AFD0021072063 +:10207000FFF746FD1B20FFF7D9FB061C1920FFF7D1 +:10208000D5FB642358430B2101F0EAF8FA2424011C +:102090007443011C201C01F0E3F8F9248442A4419C +:1020A00064420534002D3AD0201C0121FFF728FDA1 +:1020B0002D4B013B002BFCD1FF255026201C01217C +:1020C000FFF71EFD00230133AB42FCDD201C002185 +:1020D000FFF716FD0023FF22521B934201DC013360 +:1020E000F9E7013E002EE9D1013DE6D205200021AD +:1020F000FFF706FD06200021FFF702FD0720002163 +:10210000FFF7FEFC05200021FFF79EFC06200021C2 +:10211000FFF79AFC07200021FFF796FC70BD5026C0 +:10212000201C0121FFF7ECFC00230133AB42FCDD56 +:10213000201C0021FFF7E4FC0023FF22521B9342E6 +:1021400001DC0133F9E7013E002EE9D1802301359E +:102150005B009D42E3D1201C0121FFF7D1FC024B23 +:10216000013B002BFCD1C1E7813E0000F8B54A4B92 +:102170004A4C1F784A4DFFB2002F48D000221A70F7 +:10218000236902218B4323612B6C06210B432B64B3 +:10219000131C444A01339342FBD9434A0020136085 +:1021A000FFF74EFF414B424A1978424B1170424AA9 +:1021B0001178424A1170424A1178424A1170424ADB +:1021C0001178424A1170424A1178424A1170424ACB +:1021D0001178424A1170424A1178424A1170424ABB +:1021E0001178424A1170424A12681A60414A1268D4 +:1021F0001A61414B00221A61404A1268DA60404C71 +:10220000201C00F06DF9201C00F0CAF942E0012604 +:102210003B481E7000F002FA374B384A9968301C70 +:102220001160DF229A60234B314A196811601969E5 +:10223000304A11601E4A11781C4A11701F4A1178E9 +:102240001D4A11701F4A11781D4A11701F4A1178DA +:102250001D4A11701F4A11781D4A11701F4A1178CA +:102260001D4A11701F4A11781D4A11701F4A1178BA +:102270001D4A1170234A1F601A61234A9A62234A39 +:102280009A62FFF7DDFE2A6C06239A432A642269CC +:1022900013432361F8BDC046F801002000ED00E0C3 +:1022A00000080040FF9E2400FC01002000020020E6 +:1022B0004E44004100440041010200204F440041CF +:1022C000020200204744004103020020464400412E +:1022D000040200205E440041050200205B440041EE +:1022E000060200205F4400410702002042440041F2 +:1022F000F0010020EC01002000180040F401002053 +:102300008F06002020800000DF7F0040FFFF00C01C +:1023100010B505200121FFF797FB06200121FFF7EB +:1023200093FB07200121FFF78FFB05200021FFF71A +:10233000E7FB06200021FFF7E3FB07200021FFF762 +:10234000DFFB0A4B00240B2002211C70FFF77CFBF3 +:10235000221C0B200649FFF74FF808200121FFF748 +:1023600073FB08200121FFF7CBFB10BDF801002013 +:102370006D21000010B5FFF7F3F9FFF7C9FF012049 +:10238000FFF720F9084C201C00F0AAF8201C00F0F0 +:1023900007F9FEF7E1FEFEF701FF044B002BFAD030 +:1023A00000E000BFF7E7C0468F06002000000000F5 +:1023B00070B5C2B219495301CB189E68184DC0249C +:1023C0002E40A40526439E60164E800109683018F1 +:1023D000083258605201505C0726B0430126304352 +:1023E00050549E6935402C439C610F4C5C61505C9D +:1023F0007024A0431024204350549C680B488A1832 +:102400002040802464032043986098684021800B1A +:102410008003986053790B43537170BD940600207C +:10242000FFFFFF8FCC0400200C030020FF3F00F0D3 +:1024300038B5041C08CC01211A78051C0A431A700F +:102440008022201C0021520000F0E9FF2B689A78BE +:10245000D107FCD45C6238BD134BF0B51B689903FF +:102460005A029B01C90ED20E5B0F1F2900D1052114 +:102470001F2A00D11D22072B00D1032304688E01DF +:10248000278D0A491F2539403143218501682A409B +:102490000C8DAC4322430A8502681903108D044B4E +:1024A00003400B431385F0BD246080003FF8FFFF1D +:1024B000FF8FFFFF37B500236C46E3710734201C04 +:1024C0000D1C00F00BFE2B681818286000F0ACFE05 +:1024D000211C00F063FE2B681818286020783EBD90 +:1024E00038B5264B2021DA69051C0A43DA61244BF2 +:1024F00001201A78062402431A70224B0F22197801 +:10250000914319701978214319701F490C782043A1 +:10251000087019780A401A701A7860210A431A70F4 +:102520001A4B1B4A5A805A78D209FCD11948FFF736 +:102530003DF8194C201CFFF77BFF201CFFF78CFF98 +:1025400023687F2219780A401A701A7804210A43F6 +:102550001A701A890C218A431A81C1210F4A8900F5 +:1025600050580002000A5050802111601A78022150 +:102570000A431A7001232B7038BDC0460004004086 +:10258000584400413C44004159440041000C004083 +:1025900006400000B12E00009406002000E100E09B +:1025A0000078002810D0094B01211B681A898A4342 +:1025B0001A811A8B08210A431A831A8B04210A43B1 +:1025C0001A83034B00221A607047C046940600200D +:1025D000980700200F4B9A69920B92039A611B682F +:1025E0000222FF331A7298798022524202439A7172 +:1025F0001A7A9007FCD5084B081C997A7F22104064 +:10260000914301439972997A802252420A439A7205 +:102610007047C04694060020005000410078002812 +:1026200005D0034B01211B681A890A431A817047A0 +:102630009406002010B50B790C1C002B0BD1081C44 +:1026400000F05AFD002804D1094B9A69920B9203BD +:102650009A6101200BE000F0E7FD211C00F0D2FDA3 +:102660000028F6D1024B9A69920B92039A6110BD31 +:102670009406002038B5832A16D1CAB231485301D6 +:10268000C3189D69304C89012C40C025AD052C43F1 +:102690009C612E4C08326118596103685201D15C6B +:1026A00070208143402044E0022A24D1C8B2254A48 +:1026B0004301D3189D68244C89012C40C025AD05E9 +:1026C0002C439C60224C126861185960011C08312F +:1026D0004901885C0724A043032420438854996857 +:1026E0001C4A0A40802149030A439A609A68920B67 +:1026F00092039A6025E0822A1ED1CAB21148530182 +:10270000C3189D69104C89012C40C025AD052C4390 +:102710009C610E4C08326118596103685201991886 +:102720000C798020404220430871D15C70208143A5 +:1027300030200143D15404E0002A02D1081CFFF7E5 +:1027400037FE38BD94060020FFFFFF8F0C030020EA +:10275000CC040020FF3F00F038B5051C0124064BD7 +:10276000A200D258002A06D0211C281C0134FFF7F1 +:1027700081FFE4B2F3E738BD18000020CBB2094A6C +:1027800059015118896889040AD0116808335B011E +:10279000C9184A7980235B4213434B710223CB71E2 +:1027A0007047C04694060020034BC9B2490159182E +:1027B00088688004800C70479406002070B5CAB207 +:1027C000134B1448540189015918031959609D6825 +:1027D0001149083229408025AD0229439960996842 +:1027E0004026890B890399600368510159180D79B6 +:1027F00035430D715101591889794D06FAD55101AA +:102800005918C979CD07FAD50419A068C0B270BDAE +:10281000CC04002094060020FF3F00F038B50C4B9C +:10282000141C1B680D1CFF335A7940210A435A714E +:102830000021FFF7C3FFA04200D9201C0023A342C0 +:1028400004D0044A9A5CEA540133F8E738BDC04624 +:1028500094060020CC04002010B5C9B20C484901F0 +:1028600043189A689204920C3F2A08D9141C9A685B +:10287000403CA404920BA40C9203224302E09A6809 +:10288000920B92039A6041188868C0B210BDC0468E +:1028900094060020F7B51C1C1F4B0F1C1B680192EF +:1028A000002B34D0CDB21D4E6B01F3189A68920400 +:1028B000920CA24202D29C68A404A40C391CFFF71B +:1028C000CBFF326869015318FF335A7A0091032114 +:1028D0008A4301210A431249BF015A72C91901985A +:1028E000221C00F093FD0020844214D0009AB318FB +:1028F0009B689B0483420DD1336808356D015D19D7 +:102900002B79402213432B710123EB7102E001204C +:10291000404200E0201CFEBD9807002094060020E5 +:10292000CC040020F0B51C1C234B85B01B680F1C89 +:10293000161C002B3CD08023DB019C4238D8002C95 +:1029400034D0251E3F2D00D940251C4ABB01D31889 +:10295000181C311C2A1C039300F058FDF9B2184AC8 +:1029600003984B01D3185861A804800C039002917E +:102970009969880B03998003014399610299126850 +:1029800008314B01D3180220D87101925A79802066 +:1029900003924242039810435871019A4B01D31895 +:1029A000DB799807F9D5641B7619C8E7201C01E08C +:1029B0000120404205B0F0BD980700200C03002024 +:1029C0009406002070B50E4D1C1C8B01ED18281CC0 +:1029D0000E1C111C221C00F019FDF6B209497601EB +:1029E00089194D618A69084B201C13408B618B69E2 +:1029F000A2049B0B920C9B0313438B6170BDC046DA +:102A00000C03002094060020FF3F00F0F7B5114BA7 +:102A100001901B780F1C141C002B19D10E4B1E7833 +:102A2000002E01D1151C08E00C4D0D482E88801990 +:102A3000361900F0EBFC2E800AE0002D08D0BA1900 +:102A40002B1C01980021FFF7BDFF36182D1AF4E763 +:102A5000201CFEBD8E0600208C0600200A030020EC +:102A600009020020F8B50E1C00AF151E012D28D953 +:102A7000D31DDB08DB006A46D21A9546081C00F01D +:102A800013FD01306C464000032320706370022266 +:102A9000AA420ED23378002B0BD0511CC9B201369A +:102AA000A354A94204D0002302326354D2B2EFE708 +:102AB0002A1C0548211CFFF7A9FF431E9841C0B2FC +:102AC00000E00020BD46F8BD8F06002008B5044B8D +:102AD00000221A70034B04491A88FFF797FF08BDBC +:102AE0008C0600200A03002009020020F0B5204ACD +:102AF00087B001230026009102A91370051C0296DD +:102B0000FFF7D8FC03AC092701903A1C201C311CAC +:102B100000F085FC022363708023E371FA232372A3 +:102B2000029B0122DB196380019B62712371104AB1 +:102B3000009B27701670BB4205D1281C211C1A1C53 +:102B4000FFF764FF11E00B4B01221A700A4B211CA6 +:102B50003A1C281C1E800296FFF758FF281C02A969 +:102B6000FFF7A8FC281CFFF7B1FF012007B0F0BD5C +:102B70008E0600208C0600200A03002070B5CE7857 +:102B800086B0051C0C1C022E08D1C9882348FFF70B +:102B9000ADFF031C581E8341D8B23DE000F044FB5A +:102BA000211C00F010FB002803D0C3171B1AD80FFC +:102BB00032E0012E04D1E2881949112A27D823E0F6 +:102BC000032E29D1A278002A05D11649E2880B7874 +:102BD000934219D81BE0022A03D1A279281C12497A +:102BE00004E0012A05D1A2791049281CFFF73AFF19 +:102BF00012E0032A10D100F017FB01A900F0F3FA4C +:102C0000A279281C01A9F1E7D2B2002A00D10A78E2 +:102C1000281CFFF7FBFE012006B070BD8F060020C8 +:102C20008537000078370000973700007C370000B8 +:102C300073B5051C48780C1C0B287BD800F006FBEC +:102C4000081C7A287A3E4306474B6B72002072E0DC +:102C5000097801AA002903D111705170281C09E0DC +:102C6000002313705370344B1B78012B00D1137069 +:102C7000281C0021022352E08A780023012A04D173 +:102C800001AA137053702D4BEEE72B4A13704CE0E2 +:102C90008E78012E07D1294B01AA00211E701170D8 +:102CA000281C331C3BE0002E08D1234A012313705B +:102CB000234A9169890B890391613BE0A178281C23 +:102CC000FFF788FC36E0281CFFF758FF33E0281C8C +:102CD00000211C4A22E00A780020D3062BD1281CB0 +:102CE000FFF73AFDA2781649164B2A201A600A68A7 +:102CF000FF30145C03239C4302252C4314544A20C8 +:102D0000FF30145C9C4301231C4314548A69920BCA +:102D100092038A610EE00C4A281C00210123FFF770 +:102D200051FE07E08A78084B1A60054B9A69920BAE +:102D300092039A61012076BD080200208D060020D2 +:102D4000940600209807002090060020014A024BBC +:102D50001A607047005000419406002008B502290F +:102D600007D1134B9B6C9B0420D0124800F014F940 +:102D70001CE003290BD10E4BB2221B685200985C59 +:102D80008021494201439954022168220CE0012923 +:102D90000CD1074B92221B685200985C802149425B +:102DA0000143995402212822FF32995408BDC0469C +:102DB00094060020A8080020F8B5384B071C1C78A2 +:102DC000002C6AD1364D2868838B19070DD5201C3D +:102DD000FFF7EEFA2B6810201A1CFF32917A01439C +:102DE0009172304A146008229A832B689A8B50079C +:102DF00001D504229A83FF331A7AD10628D51022EE +:102E00001A725A7940210A4327495A710A78602375 +:102E1000381C1A4202D1FFF70BFF01E0FFF70AFC52 +:102E2000002806D02B688022FF33997952420A434A +:102E300001E01E4B20229A712B68FF331A7A50064C +:102E400006D540221A72597A602081430A435A7289 +:102E50002968FE230E8C00241E40E1B2002E1CD0F7 +:102E6000331C0122234113420FD0231C286808334E +:102E70005B01C318D87910420BD1DA7903231340D0 +:102E80009A0706D40123A3409E430134092CE4D1C0 +:102E900003E0381CFFF762FFF4E7F8BD8C06002062 +:102EA0009406002098070020CC040020FF50004129 +:102EB00008B50248FFF780FF08BDC0468F06002016 +:102EC000F7B58A18061C0D1C01920C1C019B671B90 +:102ED0009C4207D0336821781B68301C9847013426 +:102EE0000028F3D1381CFEBD10B500214022041C7F +:102EF00000F095FA0023201C2364636410BD026C6B +:102F000010B53F23541C2340446CA34201D081548C +:102F1000036410BD0023036443647047436C026C78 +:102F2000934206D0C25C3F2101330B404364101C26 +:102F300001E0012040427047026C436CD01A00D57A +:102F400040307047436C026C934201D0C05C01E09A +:102F50000120404270470000094B1A1CFC325068A7 +:102F600091681A1C884206D1FF335B7A002B02D18C +:102F70000120404203E0131CFC339B68D05C704787 +:102F80009C07002013B502686B46D971073354685B +:102F9000191C0122A04716BDF0B58023C1B0022143 +:102FA0006A465B000069FFF775FCEFF310850123AB +:102FB0001D40AC4672B6114A0021131CFC335B68FD +:102FC000814212D0141CFF34667A002E0DD16D465A +:102FD0006F5C5E1CD754F3B2161CFC36B668B34265 +:102FE00001D1012666720131EAE7FC325360634683 +:102FF000002B00D162B641B0F0BDC0469C07002056 +:1030000038B5184C051C231CFC335A689B689A423F +:103010000ED1231CFF335B7A002B09D100690221FA +:10302000FFF7C2FB002803D02B68281C9B69984738 +:10303000231CFC335A689B689A4207D1231CFF3338 +:103040005B7A002B02D1012040420AE0231CFC33B2 +:103050009A68A05C9A68FF340132D2B29A60002369 +:10306000637238BD9C07002008B500690321FFF793 +:1030700085FB08BD0C4B1A1CFF32527A002A10D176 +:103080001A1CFC3251689268914204D14A220749C5 +:103090000120FF328854FC3358689B68C01AC0B2C4 +:1030A00001E08020400070479C0700200050004154 +:1030B00038B5131C084A041CD2790D1C002A06D00E +:1030C000006903212A1CFFF72DFC002801D00123F1 +:1030D0006360002038BDC0468800002008B5037832 +:1030E00003490233037042220248FFF78FFC08BDF8 +:1030F000440000208F06002010B50178031C4278A0 +:103100000020A12908D1212A2FD1184818490722C7 +:10311000FFF77CFC012028E0212926D1202A05D1B7 +:10312000134907221148FFF779FB04E0222A10D146 +:103130009A780F4BDA710E4B96221968D2009142A1 +:1031400010D1DC7901231C400CD1FA20FEF778FD68 +:103150000AE0232A09D1DA789B7812021A43054B38 +:103160001A6002E0FEF772FD002010BD8F060020FD +:103170008800002040000020054B00225A60FA22FF +:1031800092009A60034A08321A60034A1A61704733 +:10319000A8080020A83700008F06002070B54468FA +:1031A0000E1C0025002C09D02368201C5B68311CF4 +:1031B0009847002804DB2D18E468F3E7281C01E099 +:1031C0000120404270BD38B544680D1C002C08D069 +:1031D0002368201C9B68291C9847002802D1E468BA +:1031E000F4E7201C38BD38B544680D1C002C07D00E +:1031F0002368201C291CDB689847E4682D18F5E734 +:103200002C7038BD38B544680D1C002C08D02368DC +:10321000201C1B68291C9847002803D1E468F4E7A8 +:10322000201C00E0012038BD064B0122196810B5B2 +:103230001140054805D10224047004244470416003 +:103240001A6010BDC8080020C008002002B47146F2 +:1032500049084900095C49008E4402BC7047C046D9 +:10326000002934D00123002210B488422CD3012439 +:103270002407A14204D2814202D209011B01F8E7CE +:10328000E400A14204D2814202D249005B00F8E787 +:10329000884201D3401A1A434C08A04202D3001BB3 +:1032A0005C0822438C08A04202D3001B9C082243E6 +:1032B000CC08A04202D3001BDC082243002803D024 +:1032C0001B0901D00909E3E7101C10BC7047002856 +:1032D00001D00020C04307B4024802A14018029068 +:1032E00003BDC046D90000000029F0D003B5FFF7A8 +:1032F000B9FF0EBC4243891A1847C046002941D085 +:1033000010B4041C4C40A44601230022002900D51F +:103310004942002800D5404288422CD3012424078A +:10332000A14204D2814202D209011B01F8E7E40064 +:10333000A14204D2814202D249005B00F8E78842F0 +:1033400001D3401A1A434C08A04202D3001B5C0868 +:1033500022438C08A04202D3001B9C082243CC08C5 +:10336000A04202D3001BDC082243002803D01B0923 +:1033700001D00909E3E7101C6446002C00D5404247 +:1033800010BC7047002806D003DB0020C043400873 +:1033900001E08020000607B4024802A14018029014 +:1033A00003BDC046190000000029EBD003B5FFF7AC +:1033B000A7FF0EBC4243891A1847C0467047C04653 +:1033C00070B50E4B0E4D0024ED1AAD101E1CAC4214 +:1033D00004D0A300F35898470134F8E700F018F937 +:1033E000084B094D0024ED1AAD101E1CAC4204D050 +:1033F000A300F35898470134F8E770BDF4000020AB +:10340000F4000020F40000200401002010B5002387 +:10341000934203D0CC5CC4540133F9E710BD031CC4 +:103420008218934202D019700133FAE77047000006 +:10343000174B10B51C68A36B002B15D1182000F09A +:103440003BF8144BA0630380134B4380134B8380E2 +:10345000134BC380134B0381052343810B238381CB +:103460000122002302614361084B074AA46B2069D3 +:10347000616900F091F80122002380185941206110 +:1034800061614800400810BD2D7F954C2DF45158C6 +:10349000F00000200E330000CDABFFFF341200001F +:1034A0006DE6FFFFECDEFFFF0023C25C0133002A64 +:1034B000FBD1581E7047000008B5034B011C18686B +:1034C00000F004F808BDC046F000002070B50323EA +:1034D000CD1C9D430835061C0C2D01D20C2501E0A6 +:1034E000002D3FDB8D423DD3204B1C681A1C211C54 +:1034F000002913D00868431B0DD40B2B02D90B6095 +:10350000CC181EE08C4202D1636813601AE0486850 +:1035100060600C1C16E00C1C4968E9E7144C20683C +:10352000002803D1301C00F025F82060301C291C35 +:1035300000F020F8431C15D0C41C03239C43844294 +:103540000AD12560201C0B300722231D9043C31A8B +:103550000BD05A42E25008E0211A301C00F00AF861 +:103560000130EED10C233360002070BDD008002064 +:10357000CC08002038B5074C0023051C081C23602C +:1035800000F02CF8431C03D12368002B00D02B60E3 +:1035900038BDC046D80800209C460304F0B51B0C7B +:1035A00017043F0C150C1E1C041C000C7E436B43BF +:1035B00047434543FB18300C1818874202D9802333 +:1035C0005B02ED18030CED1863465C434A43360476 +:1035D000360CA118000480194919F0BD094A136876 +:1035E000002B0CD018186946884202D81060181CAD +:1035F0007047054B0C2201201A604042F8E7034B4C +:103600001360EFE7D4080020D8080020DC08002071 +:10361000F8B5C046F8BC08BC9E467047F8B5C04631 +:10362000F8BC08BC9E467047000000000E00000079 +:10363000080000004E00000006000000000010001E +:10364000000000000E000000080000004E00000016 +:103650000600000000001000000000000F00000045 +:10366000080000004E0000000700010001000100FA +:103670000000000007000000080000004E000000ED +:103680000500030003000700000000000600000022 +:10369000080000004E0000000400020002000600C6 +:1036A000000000001E0000000B0000000C000000E5 +:1036B000FF0000020002FF00000000001B000000ED +:1036C0000B00000004000000FF00FFFFFFFFFF00F1 +:1036D000000000001F0000000B0000000C000000B4 +:1036E000FF0001020102FF000000000002000000D4 +:1036F0000B000000060000000000FFFFFFFFFF00BE +:10370000000000001800000006000000000000009B +:10371000FF00FFFFFFFFFF00000000001900000096 +:103720000600000000000000FF00FFFFFFFFFF0099 +:10373000000000000500000008000000400000003C +:10374000FF00FFFFFFFF0500000000000000000079 +:10375000C51E0000C12E0000A71E0000BB1E0000F9 +:10376000B11E00009D1E00007D1E0000A11F000074 +:10377000891E0000791E0000040309045370617261 +:103780006B46756E0012011001EF0201404F1B00E5 +:1037900001000101020301534645204C494C594D9B +:1037A000494E490000000000000000000000000039 +:1037B000852F0000B130000075300000013000009E +:1037C000592F000069300000992F00000000000010 +:1037D000430000000000000001000000001400424F +:1037E00000180042001C004240420F00FFFFFFFF94 +:1037F00000000000830000000200000082000000C2 +:1038000000000000000000000000000000000000B8 +:103810000000000000000000FFFFFFFF080B000297 +:103820000202000009040000010202000005240059 +:1038300010010424020605240600010524010101EB +:103840000705810310001009040100020A000000AE +:103850000705020240000007058302400000000047 +:1038600000C201000000080000000000000000008D +:103870000000000000000000000000000000000048 +:103880000000000000000000D03700000000000031 +:103890000000000000000000000000000000000028 +:1038A0000000000000000000000000000000000018 +:1038B0000000000000000000000000000000000008 +:1038C000000000000000000090000020B510000083 +:1038D000A91300004D2D0000793100008D1000006B +:1038E00000000000000008000000000000000000D0 +:1038F00000000000000000000000000000000000C8 +:10390000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 +:10391000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 +:10392000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 +:10393000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 +:10394000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 +:10395000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 +:10396000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 +:10397000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 +:10398000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 +:10399000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 +:1039A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 +:1039B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17 +:1039C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 +:1039D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 +:1039E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 +:1039F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 +:103A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 +:103A1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 +:103A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6 +:103A3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF96 +:103A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86 +:103A5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF76 +:103A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66 +:103A7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF56 +:103A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46 +:103A9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36 +:103AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26 +:103AB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 +:103AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 +:103AD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 +:103AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 +:103AF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 +:103B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5 +:103B1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 +:103B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5 +:103B3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 +:103B4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85 +:103B5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 +:103B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65 +:103B7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 +:103B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45 +:103B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 +:103BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 +:103BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 +:103BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 +:103BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 +:103BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5 +:103BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5 +:103C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4 +:103C1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 +:103C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4 +:103C3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 +:103C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84 +:103C5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 +:103C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64 +:103C7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 +:103C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44 +:103C9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 +:103CA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24 +:103CB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14 +:103CC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04 +:103CD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4 +:103CE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4 +:103CF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 +:103D0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3 +:103D1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3 +:103D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3 +:103D3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93 +:103D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83 +:103D5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73 +:103D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 +:103D7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 +:103D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43 +:103D9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 +:103DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23 +:103DB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 +:103DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03 +:103DD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3 +:103DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3 +:103DF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3 +:103E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 +:103E1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 +:103E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2 +:103E3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 +:103E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82 +:103E5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 +:103E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62 +:103E7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 +:103E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42 +:103E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 +:103EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 +:103EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 +:103EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 +:103ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 +:103EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 +:103EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 +:103F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 +:103F1000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:103F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:103F3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:103F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:103F5000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:103F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:103F7000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:103F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:103F9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:103FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21 +:103FB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 +:103FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:103FD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 +:103FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 +:103FF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 +:00000001FF diff --git a/sparkfun/samd/bootloaders/LilyMini/Makefile b/sparkfun/samd/bootloaders/LilyMini/Makefile new file mode 100644 index 00000000..654004d2 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/Makefile @@ -0,0 +1,180 @@ +# Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. All right reserved. +# Copyright (c) 2015 Arduino LLC. 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 + +# ----------------------------------------------------------------------------- +# Boards definitions +BOARD_ID?=LilyMini +NAME?=samd11_sam_ba +MCU?=__SAMD11D14AM__ +LINKER_SCRIPT?=bootloader4k_samd11.ld + +# ----------------------------------------------------------------------------- +# Paths +ifeq ($(OS),Windows_NT) + # Are we using mingw/msys/msys2/cygwin? + ifeq ($(TERM),xterm) + T=$(shell cygpath -u $(LOCALAPPDATA)) + MODULE_PATH?=$(T)/Arduino15/packages/arduino + RM=rm + SEP=/ + else + MODULE_PATH?=$(LOCALAPPDATA)/Arduino15/packages/arduino + RM=rm + SEP=\\ + endif +else + UNAME_S := $(shell uname -s) + + ifeq ($(UNAME_S),Linux) + MODULE_PATH?=$(HOME)/.arduino15/packages/arduino + RM=rm + SEP=/ + endif + + ifeq ($(UNAME_S),Darwin) + MODULE_PATH?=$(HOME)/Library/Arduino15/packages/arduino/ + RM=rm + SEP=/ + endif +endif + +ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi- +BUILD_PATH=build + +# ----------------------------------------------------------------------------- +# Tools +CC=$(ARM_GCC_PATH)gcc +OBJCOPY=$(ARM_GCC_PATH)objcopy +NM=$(ARM_GCC_PATH)nm +SIZE=$(ARM_GCC_PATH)size + +# ----------------------------------------------------------------------------- +# Compiler options +CFLAGS_EXTRA=-D__SAMD11D14AM__ -DBOARD_ID_$(BOARD_ID) +CFLAGS=-mthumb -mcpu=cortex-m0plus -Wall -c -std=gnu99 -ffunction-sections -fdata-sections -nostdlib -nostartfiles --param max-inline-insns-single=500 +ifdef DEBUG + CFLAGS+=-g3 -O1 -DDEBUG=1 +else + CFLAGS+=-Os -DDEBUG=0 +endif + +ELF=$(NAME).elf +BIN=$(NAME).bin +HEX=$(NAME).hex + +INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/Device/ATMEL/" + +# ----------------------------------------------------------------------------- +# Linker options +LDFLAGS=-mthumb -mcpu=cortex-m0plus -Wall -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all +LDFLAGS+=-Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols --specs=nano.specs --specs=nosys.specs + +# ----------------------------------------------------------------------------- +# Source files and objects +SOURCES= \ + board_driver_led.c \ + board_driver_usb.c \ + board_init.c \ + board_startup.c \ + main.c \ + sam_ba_usb.c \ + sam_ba_cdc.c \ + sam_ba_monitor.c + +#SOURCES= \ +# board_driver_led.c \ +# board_driver_serial.c \ +# board_driver_usb.c \ +# board_init.c \ +# board_startup.c \ +# main.c \ +# sam_ba_usb.c \ +# sam_ba_cdc.c \ +# sam_ba_monitor.c \ +# sam_ba_serial.c + +OBJECTS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.o)) +DEPS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.d)) + +ifneq "test$(AVRSTUDIO_EXE_PATH)" "test" + AS_BUILD=copy_for_atmel_studio + AS_CLEAN=clean_for_atmel_studio +else + AS_BUILD= + AS_CLEAN= +endif + +all: print_info $(SOURCES) $(BIN) $(HEX) $(AS_BUILD) + +$(ELF): Makefile $(BUILD_PATH) $(OBJECTS) + @echo ---------------------------------------------------------- + @echo Creating ELF binary + "$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -T$(LINKER_SCRIPT) -Wl,-Map,"$(BUILD_PATH)/$(NAME).map" -o "$(BUILD_PATH)/$(ELF)" -Wl,--start-group $(OBJECTS) -lm -Wl,--end-group + "$(NM)" "$(BUILD_PATH)/$(ELF)" >"$(BUILD_PATH)/$(NAME)_symbols.txt" + "$(SIZE)" --format=sysv -t -x $(BUILD_PATH)/$(ELF) + +$(BIN): $(ELF) + @echo ---------------------------------------------------------- + @echo Creating flash binary + "$(OBJCOPY)" -O binary $(BUILD_PATH)/$< $@ + +$(HEX): $(ELF) + @echo ---------------------------------------------------------- + @echo Creating flash binary + "$(OBJCOPY)" -O ihex $(BUILD_PATH)/$< $@ + +$(BUILD_PATH)/%.o: %.c + @echo ---------------------------------------------------------- + @echo Compiling $< to $@ + "$(CC)" $(CFLAGS) $(CFLAGS_EXTRA) $(INCLUDES) $< -o $@ + @echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +$(BUILD_PATH): + @echo ---------------------------------------------------------- + @echo Creating build folder + -mkdir $(BUILD_PATH) + +print_info: + @echo ---------------------------------------------------------- + @echo Compiling bootloader using + @echo BASE PATH = $(MODULE_PATH) + @echo GCC PATH = $(ARM_GCC_PATH) + @echo OS = $(OS) + @echo SHELL = $(SHELL) + @echo TERM = $(TERM) + "$(CC)" -v +# env + +copy_for_atmel_studio: $(BIN) $(HEX) + @echo ---------------------------------------------------------- + @echo Atmel Studio detected, copying ELF to project root for debug + cp $(BUILD_PATH)/$(ELF) . + +clean_for_atmel_studio: + @echo ---------------------------------------------------------- + @echo Atmel Studio detected, cleaning ELF from project root + -$(RM) ./$(ELF) + +clean: $(AS_CLEAN) + @echo ---------------------------------------------------------- + @echo Cleaning project + -$(RM) $(BIN) + -$(RM) $(HEX) + -$(RM) $(BUILD_PATH)/*.* + -rmdir $(BUILD_PATH) + +.phony: print_info $(BUILD_PATH) diff --git a/sparkfun/samd/bootloaders/LilyMini/README.md b/sparkfun/samd/bootloaders/LilyMini/README.md new file mode 100644 index 00000000..b0d939db --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/README.md @@ -0,0 +1,95 @@ +# Arduino Zero Bootloader + +## 1- Prerequisites + +The project build is based on Makefile system. +Makefile is present at project root and try to handle multi-platform cases. + +Multi-plaform GCC is provided by ARM here: https://launchpad.net/gcc-arm-embedded/+download + +Atmel Studio contains both make and ARM GCC toolchain. You don't need to install them in this specific use case. + +For all builds and platforms you will need to have the Arduino IDE installed and the board support +package for "Arduino SAMD Boards (32-bits ARM Cortex-M0+)". You can install the latter +from the former's "Boards Manager" UI. + +### Windows + +* Native command line +Make binary can be obtained here: http://gnuwin32.sourceforge.net/packages/make.htm + +* Cygwin/MSys/MSys2/Babun/etc... +It is available natively in all distributions. + +* Atmel Studio +An Atmel Studio **7** Makefile-based project is present at project root, just open samd21_sam_ba.atsln file in AS7. + +### Linux + +Make is usually available by default. + +### OS X + +Make is available through XCode package. + + +## 2- Selecting available SAM-BA interfaces + +By default both USB and UART are made available, but this parameter can be modified in sam_ba_monitor.h, line 31: + +Set the define SAM_BA_INTERFACE to +* SAM_BA_UART_ONLY for only UART interface +* SAM_BA_USBCDC_ONLY for only USB CDC interface +* SAM_BA_BOTH_INTERFACES for enabling both the interfaces + +## 3- Behaviour + +This bootloader implements the double-tap on Reset button. +By quickly pressing this button two times, the board will reset and stay in bootloader, waiting for communication on either USB or USART. + +The USB port in use is the USB Native port, close to the Reset button. +The USART in use is the one available on pins D0/D1, labelled respectively RX/TX. Communication parameters are a baudrate at 115200, 8bits of data, no parity and 1 stop bit (8N1). + +## 4- Description + +**Pinmap** + +The following pins are used by the program : +PA25 : input/output (USB DP) +PA24 : input/output (USB DM) +PA11 : input (USART RX) +PA10 : output (USART TX) + +The application board shall avoid driving the PA25, PA24, PB23 and PB22 signals while the boot program is running (after a POR for example). + +**Clock system** + +CPU runs at 48MHz from Generic Clock Generator 0 on DFLL48M. + +Generic Clock Generator 1 is using external 32kHz oscillator and is the source of DFLL48M. + +USB and USART are using Generic Clock Generator 0 also. + +**Memory Mapping** + +Bootloader code will be located at 0x0 and executed before any applicative code. + +Applications compiled to be executed along with the bootloader will start at 0x2000 (see linker script bootloader_samd21x18.ld). + +Before jumping to the application, the bootloader changes the VTOR register to use the interrupt vectors of the application @0x2000.<- not required as application code is taking care of this. + +## 5- How to build + +If not specified the makefile builds for **Arduino Zero**: + +``` +make +``` + +if you want to make a custom bootloader for a derivative board you must supply all the necessary information in a `board_definitions_xxx.h` file, and add the corresponding case in `board_definitions.h`. +For example for the **Arduino MKR1000** we use `board_definitions_arduino_mkr1000.h` and it is build with the following command: + +``` +BOARD_ID=arduino_mkr1000 NAME=samd21_sam_ba_arduino_mkr1000 make clean all +``` + diff --git a/sparkfun/samd/bootloaders/LilyMini/board_definitions.h b/sparkfun/samd/bootloaders/LilyMini/board_definitions.h new file mode 100644 index 00000000..ca5adb54 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/board_definitions.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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(BOARD_ID_arduino_zero) + #include "board_definitions_arduino_zero.h" +#elif defined(BOARD_ID_genuino_zero) + #include "board_definitions_genuino_zero.h" +#elif defined(BOARD_ID_arduino_mkr1000) + #include "board_definitions_arduino_mkr1000.h" +#elif defined(BOARD_ID_genuino_mkr1000) + #include "board_definitions_genuino_mkr1000.h" +#elif defined(BOARD_ID_LilyMini) + #include "board_definitions_lilymini.h" + +#else + #error You must define a BOARD_ID and add the corresponding definitions in board_definitions.h +#endif + +// Common definitions +// ------------------ + +#ifdef BOOT_LOAD_PIN + #define BOOT_PIN_MASK (1U << (BOOT_LOAD_PIN & 0x1f)) +#endif + diff --git a/sparkfun/samd/bootloaders/LilyMini/board_definitions_lilymini.h b/sparkfun/samd/bootloaders/LilyMini/board_definitions_lilymini.h new file mode 100644 index 00000000..ff1aafdc --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/board_definitions_lilymini.h @@ -0,0 +1,95 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#ifndef _BOARD_DEFINITIONS_H_ +#define _BOARD_DEFINITIONS_H_ + +/* + * USB device definitions + */ +#define STRING_MANUFACTURER "SparkFun" +#define STRING_MANUFACTURER_LENGTH 8 +#define STRING_PRODUCT "LilyMini" +#define STRING_PRODUCT_LENGTH 8 + +// LilyMini ID +#define USB_VID_HIGH 0x1B +#define USB_VID_LOW 0x4F +#define USB_PID_HIGH 0x01 +#define USB_PID_LOW 0x00 + +// Bootloader version +#define SAM_BA_VERSION "D11-1.0" +#define SAM_BA_VERSION_STRLEN 7 + +/* + * If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by + * quickly tapping two times on the reset button. + * BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not + * be touched from the loaded application. + */ +//#define BOOT_DOUBLE_TAP_ADDRESS (0x20000FFCul) +//#define BOOT_DOUBLE_TAP_DATA (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS)) + +/* + * If BOOT_LOAD_PIN is defined the bootloader is started if the selected + * pin is tied LOW. + */ +//#define BOOT_LOAD_PIN PIN_PA21 // Pin 7 +//#define BOOT_LOAD_PIN PIN_PA15 // Pin 5 + +//#define BOOT_USART_MODULE SERCOM0 +//#define BOOT_USART_BUS_CLOCK_INDEX PM_APBCMASK_SERCOM0 +//#define BOOT_USART_PER_CLOCK_INDEX GCLK_ID_SERCOM0_CORE +//#define BOOT_USART_PAD_SETTINGS UART_RX_PAD1_TX_PAD0 +//#define BOOT_USART_PAD3 PINMUX_UNUSED +//#define BOOT_USART_PAD2 PINMUX_UNUSED +//#define BOOT_USART_PAD1 PINMUX_PA07C_SERCOM0_PAD1 +//#define BOOT_USART_PAD0 PINMUX_PA06C_SERCOM0_PAD0 + +/* Master clock frequency */ +#define CPU_FREQUENCY (48000000ul) +#define VARIANT_MCK CPU_FREQUENCY + +/* Frequency of the board main oscillator */ +#define VARIANT_MAINOSC (32768ul) + +/* Calibration values for DFLL48 pll */ +#define NVM_SW_CALIB_DFLL48M_COARSE_VAL (58) +#define NVM_SW_CALIB_DFLL48M_FINE_VAL (64) + +/* + * LEDs definitions + */ +#define BOARD_LED_RED_PORT (0) +#define BOARD_LED_RED_PIN (30) + +#define BOARD_LED_GREEN_PORT (0) +#define BOARD_LED_GREEN_PIN (27) + +#define BOARD_LED_BLUE_PORT (0) +#define BOARD_LED_BLUE_PIN (31) + +/* + * Button definition + */ +#define BOARD_BUTTON_PORT (0) +#define BOARD_BUTTON_PIN (5) + +#endif // _BOARD_DEFINITIONS_H_ diff --git a/sparkfun/samd/bootloaders/LilyMini/board_driver_led.c b/sparkfun/samd/bootloaders/LilyMini/board_driver_led.c new file mode 100644 index 00000000..02c9af92 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/board_driver_led.c @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#include "board_driver_led.h" + +//volatile uint8_t ledKeepValue = 0; +//volatile uint8_t ledTargetValue = 20; +//volatile int8_t ledDirection = 1; +// +//inline void LED_pulse() +//{ + //if (ledKeepValue == 0) { + //ledTargetValue += ledDirection; + //LED_toggle(); + //} + //ledKeepValue ++; +// + //if (ledTargetValue > 240 || ledTargetValue < 10) { + //ledDirection = -ledDirection; + //ledTargetValue += ledDirection; + //} +// + //if (ledKeepValue == ledTargetValue) { + //LED_toggle(); + //} +//} diff --git a/sparkfun/samd/bootloaders/LilyMini/board_driver_led.h b/sparkfun/samd/bootloaders/LilyMini/board_driver_led.h new file mode 100644 index 00000000..6f2a30ce --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/board_driver_led.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#ifndef _BOARD_DRIVER_LED_ +#define _BOARD_DRIVER_LED_ + +#include +#include "board_definitions.h" + +inline void LED_RED_init(void) { PORT->Group[BOARD_LED_RED_PORT].WRCONFIG.reg = (PORT_WRCONFIG_HWSEL | PORT_WRCONFIG_WRPINCFG | /* PORT_WRCONFIG_DRVSTR | */ (1 << 14)); \ +PORT->Group[BOARD_LED_RED_PORT].DIRSET.reg = (1<Group[BOARD_LED_RED_PORT].DIRSET.reg = (1<Group[BOARD_LED_RED_PORT].OUTCLR.reg = (1<Group[BOARD_LED_RED_PORT].OUTSET.reg = (1<Group[BOARD_LED_RED_PORT].OUTTGL.reg = (1<Group[BOARD_LED_RED_PORT].DIRCLR.reg = (1<Group[BOARD_LED_GREEN_PORT].DIRSET.reg = (1<Group[BOARD_LED_GREEN_PORT].OUTCLR.reg = (1<Group[BOARD_LED_GREEN_PORT].OUTSET.reg = (1<Group[BOARD_LED_GREEN_PORT].OUTTGL.reg = (1<Group[BOARD_LED_GREEN_PORT].DIRCLR.reg = (1<Group[BOARD_LED_BLUE_PORT].DIRSET.reg = (1<Group[BOARD_LED_BLUE_PORT].OUTCLR.reg = (1<Group[BOARD_LED_BLUE_PORT].OUTSET.reg = (1<Group[BOARD_LED_BLUE_PORT].OUTTGL.reg = (1<Group[BOARD_LED_BLUE_PORT].DIRCLR.reg = (1< +#include "board_driver_usb.h" +#include "sam_ba_usb.h" +#include "sam_ba_cdc.h" + +#define NVM_USB_PAD_TRANSN_POS (45) +#define NVM_USB_PAD_TRANSN_SIZE (5) +#define NVM_USB_PAD_TRANSP_POS (50) +#define NVM_USB_PAD_TRANSP_SIZE (5) +#define NVM_USB_PAD_TRIM_POS (55) +#define NVM_USB_PAD_TRIM_SIZE (3) + +__attribute__((__aligned__(4))) UsbDeviceDescriptor usb_endpoint_table[MAX_EP]; // Initialized to zero in USB_Init +__attribute__((__aligned__(4))) uint8_t udd_ep_out_cache_buffer[2][64]; //1 for CTRL, 1 for BULK +__attribute__((__aligned__(4))) uint8_t udd_ep_in_cache_buffer[2][64]; //1 for CTRL, 1 for BULK + +static volatile bool read_job = false; + +/*---------------------------------------------------------------------------- + * \brief + */ +P_USB_CDC USB_Open(P_USB_CDC pCdc, Usb *pUsb) +{ + pCdc->pUsb = pUsb; + pCdc->currentConfiguration = 0; + pCdc->currentConnection = 0; + pCdc->IsConfigured = USB_IsConfigured; +// pCdc->Write = USB_Write; +// pCdc->Read = USB_Read; + + pCdc->pUsb->HOST.CTRLA.bit.ENABLE = true; + + return pCdc; +} + +/*---------------------------------------------------------------------------- + * \brief Initializes USB + */ +void USB_Init(void) +{ + uint32_t pad_transn, pad_transp, pad_trim; + + /* Enable USB clock */ + PM->APBBMASK.reg |= PM_APBBMASK_USB; + + /* Set up the USB DP/DN pins */ + PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u))); + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u)); + PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u))); + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u)); + + /* ---------------------------------------------------------------------------------------------- + * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference) + */ + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 6 ) | // Generic Clock Multiplexer 6 + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_CLKEN ; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } + + /* Reset */ + USB->DEVICE.CTRLA.bit.SWRST = 1; + while (USB->DEVICE.SYNCBUSY.bit.SWRST) + { + /* Sync wait */ + } + + /* Load Pad Calibration */ + pad_transn =( *((uint32_t *)(NVMCTRL_OTP4) + + (NVM_USB_PAD_TRANSN_POS / 32)) + >> (NVM_USB_PAD_TRANSN_POS % 32)) + & ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1); + + if (pad_transn == 0x1F) + { + pad_transn = 5; + } + + USB->HOST.PADCAL.bit.TRANSN = pad_transn; + + pad_transp =( *((uint32_t *)(NVMCTRL_OTP4) + + (NVM_USB_PAD_TRANSP_POS / 32)) + >> (NVM_USB_PAD_TRANSP_POS % 32)) + & ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1); + + if (pad_transp == 0x1F) + { + pad_transp = 29; + } + + USB->HOST.PADCAL.bit.TRANSP = pad_transp; + pad_trim =( *((uint32_t *)(NVMCTRL_OTP4) + + (NVM_USB_PAD_TRIM_POS / 32)) + >> (NVM_USB_PAD_TRIM_POS % 32)) + & ((1 << NVM_USB_PAD_TRIM_SIZE) - 1); + + if (pad_trim == 0x7) + { + pad_trim = 3; + } + + USB->HOST.PADCAL.bit.TRIM = pad_trim; + + /* Set the configuration */ + /* Set mode to Device mode */ + USB->HOST.CTRLA.bit.MODE = 0; + /* Enable Run in Standby */ + USB->HOST.CTRLA.bit.RUNSTDBY = true; + /* Set the descriptor address */ + USB->HOST.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]); + /* Set speed configuration to Full speed */ + USB->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val; + /* Attach to the USB host */ + USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH; + + /* Initialize endpoint table RAM location to a known value 0 */ + memset((uint8_t *)(&usb_endpoint_table[0]), 0, sizeof(usb_endpoint_table)); +} + +uint32_t USB_Write(Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num) +{ + uint32_t data_address; + uint8_t buf_index; + + /* Set buffer index */ + buf_index = (ep_num == 0) ? 0 : 1; + + /* Check for requirement for multi-packet or auto zlp */ + if (length >= (1 << (usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.SIZE + 3))) + { + /* Update the EP data address */ + data_address = (uint32_t) pData; + /* Enable auto zlp */ + usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = true; + } + else + { + /* Copy to local buffer */ + memcpy(udd_ep_in_cache_buffer[buf_index], pData, length); + /* Update the EP data address */ + data_address = (uint32_t) &udd_ep_in_cache_buffer[buf_index]; + } + + /* Set the buffer address for ep data */ + usb_endpoint_table[ep_num].DeviceDescBank[1].ADDR.reg = data_address; + /* Set the byte count as zero */ + usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = length; + /* Set the multi packet size as zero for multi-packet transfers where length > ep size */ + usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0; + /* Clear the transfer complete flag */ + //pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT1 = true; + pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT |= (1<<1); + /* Set the bank as ready */ + pUsb->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.bit.BK1RDY = true; + + /* Wait for transfer to complete */ + while ( (pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT & (1<<1)) == 0 ); + + return length; +} + +/*---------------------------------------------------------------------------- + * \brief Read available data from Endpoint OUT + */ +uint32_t USB_Read(Usb *pUsb, char *pData, uint32_t length) +{ + uint32_t packetSize = 0; + + if (!read_job) + { + /* Set the buffer address for ep data */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[USB_EP_OUT-1]; + /* Set the byte count as zero */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; + /* Set the byte count as zero */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0; + /* Start the reception by clearing the bank 0 ready bit */ + pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSCLR.bit.BK0RDY = true; + /* set the user flag */ + read_job = true; + } + + /* Check for Transfer Complete 0 flag */ + if ( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0) ) + { + /* Set packet size */ + packetSize = SAM_BA_MIN(usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT, length); + /* Copy read data to user buffer */ + memcpy(pData, udd_ep_out_cache_buffer[USB_EP_OUT-1], packetSize); + /* Clear the Transfer Complete 0 flag */ + //pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 = true; + pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT |= (1 << 0); + /* Clear the user flag */ + read_job = false; + } + + return packetSize; +} + +uint32_t USB_Read_blocking(Usb *pUsb, char *pData, uint32_t length) +{ + if (read_job) + { + /* Stop the reception by setting the bank 0 ready bit */ + pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSSET.bit.BK0RDY = true; + /* Clear the user flag */ + read_job = false; + } + + /* Set the buffer address for ep data */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = ((uint32_t)pData); + /* Set the byte count as zero */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; + /* Set the multi packet size as zero for multi-packet transfers where length > ep size */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = length; + /* Clear the bank 0 ready flag */ + pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSCLR.bit.BK0RDY = true; + /* Wait for transfer to complete */ + while (!( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0) )); + /* Clear Transfer complete 0 flag */ + //pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 = true; + pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT |= (1 << 0); + + return length; +} + +/*---------------------------------------------------------------------------- + * \brief Test if the device is configured and handle enumeration + */ +uint8_t USB_IsConfigured(P_USB_CDC pCdc) +{ + Usb *pUsb = pCdc->pUsb; + + /* Check for End of Reset flag */ + if (pUsb->DEVICE.INTFLAG.reg & USB_DEVICE_INTFLAG_EORST) + { + /* Clear the flag */ + pUsb->DEVICE.INTFLAG.bit.EORST = true; + /* Set Device address as 0 */ + pUsb->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | 0; + /* Configure endpoint 0 */ + /* Configure Endpoint 0 for Control IN and Control OUT */ + pUsb->DEVICE.DeviceEndpoint[0].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(1) | USB_DEVICE_EPCFG_EPTYPE1(1); + pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY; + pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY; + /* Configure control OUT Packet size to 64 bytes */ + usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3; + /* Configure control IN Packet size to 64 bytes */ + usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3; + /* Configure the data buffer address for control OUT */ + usb_endpoint_table[0].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[0]; + /* Configure the data buffer address for control IN */ + usb_endpoint_table[0].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[0]; + /* Set Multipacket size to 8 for control OUT and byte count to 0*/ + usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 8; + usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; + pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY; + + // Reset current configuration value to 0 + pCdc->currentConfiguration = 0; + } + else + { + if (pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_RXSTP) + { + sam_ba_usb_CDC_Enumerate(pCdc); + } + } + + return pCdc->currentConfiguration; +} + +/*---------------------------------------------------------------------------- + * \brief Stall the control endpoint + */ +void USB_SendStall(Usb *pUsb, bool direction_in) +{ + /* Check the direction */ + if (direction_in) + { + /* Set STALL request on IN direction */ + //pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1; + pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ = (1<<1); + } + else + { + /* Set STALL request on OUT direction */ + //pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0; + pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ = (1<<0); + } +} + +/*---------------------------------------------------------------------------- + * \brief Send zero length packet through the control endpoint + */ +void USB_SendZlp(Usb *pUsb) +{ + /* Set the byte count as zero */ + usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0; + /* Clear the transfer complete flag */ + //pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 = true; + pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT |= (1 << 1); + /* Set the bank as ready */ + pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.BK1RDY = true; + /* Wait for transfer to complete */ + while (!( pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT & (1<<1) )); +} + +/*---------------------------------------------------------------------------- + * \brief Set USB device address obtained from host + */ +void USB_SetAddress(Usb *pUsb, uint16_t wValue) +{ + pUsb->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | wValue; +} + +/*---------------------------------------------------------------------------- + * \brief Configure USB device + */ +void USB_Configure(Usb *pUsb) +{ + /* Configure BULK OUT endpoint for CDC Data interface*/ + pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(3); + /* Set maximum packet size as 64 bytes */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3; + pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY; + /* Configure the data buffer */ + usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[1]; + + /* Configure BULK IN endpoint for CDC Data interface */ + pUsb->DEVICE.DeviceEndpoint[USB_EP_IN].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(3); + /* Set maximum packet size as 64 bytes */ + usb_endpoint_table[USB_EP_IN].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3; + pUsb->DEVICE.DeviceEndpoint[USB_EP_IN].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY; + /* Configure the data buffer */ + usb_endpoint_table[USB_EP_IN].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[1]; + + /* Configure INTERRUPT IN endpoint for CDC COMM interface*/ + pUsb->DEVICE.DeviceEndpoint[USB_EP_COMM].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(4); + /* Set maximum packet size as 64 bytes */ + usb_endpoint_table[USB_EP_COMM].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0; + pUsb->DEVICE.DeviceEndpoint[USB_EP_COMM].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY; +} diff --git a/sparkfun/samd/bootloaders/LilyMini/board_driver_usb.h b/sparkfun/samd/bootloaders/LilyMini/board_driver_usb.h new file mode 100644 index 00000000..4e71b8c1 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/board_driver_usb.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#ifndef _BOARD_DRIVER_USB_H_ +#define _BOARD_DRIVER_USB_H_ + +#include "sam_ba_cdc.h" + +extern UsbDeviceDescriptor usb_endpoint_table[MAX_EP]; +extern uint8_t udd_ep_out_cache_buffer[2][64]; //1 for CTRL, 1 for BULK +extern uint8_t udd_ep_in_cache_buffer[2][64]; //1 for CTRL, 1 for BULK + +P_USB_CDC USB_Open(P_USB_CDC pCdc, Usb *pUsb); + +void USB_Init(void); + +uint32_t USB_Write(Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num); +uint32_t USB_Read(Usb *pUsb, char *pData, uint32_t length); +uint32_t USB_Read_blocking(Usb *pUsb, char *pData, uint32_t length); + +uint8_t USB_IsConfigured(P_USB_CDC pCdc); + +void USB_SendStall(Usb *pUsb, bool direction_in); +void USB_SendZlp(Usb *pUsb); + +void USB_SetAddress(Usb *pUsb, uint16_t wValue); +void USB_Configure(Usb *pUsb); + +#endif // _BOARD_DRIVER_USB_H_ diff --git a/sparkfun/samd/bootloaders/LilyMini/board_init.c b/sparkfun/samd/bootloaders/LilyMini/board_init.c new file mode 100644 index 00000000..4f3645a2 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/board_init.c @@ -0,0 +1,214 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#include +#include "board_definitions.h" + +/** + * \brief system_init() configures the needed clocks and according Flash Read Wait States. + * At reset: + * - OSC8M clock source is enabled with a divider by 8 (1MHz). + * - Generic Clock Generator 0 (GCLKMAIN) is using OSC8M as source. + * We need to: + * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator), will be used as DFLL48M reference. + * 2) Put XOSC32K as source of Generic Clock Generator 1 + * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) + * 4) Enable DFLL48M clock + * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. + * 6) Modify PRESCaler value of OSCM to have 8MHz + * 7) Put OSC8M as source for Generic Clock Generator 3 + */ +// Constants for Clock generators +#define GENERIC_CLOCK_GENERATOR_MAIN (0u) +#define GENERIC_CLOCK_GENERATOR_XOSC32K (1u) +#define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */ +#define GENERIC_CLOCK_GENERATOR_OSC8M (3u) +// Constants for Clock multiplexers +#define GENERIC_CLOCK_MULTIPLEXER_DFLL48M (0u) + +void board_init(void) +{ + /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */ + NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val; + + /* Turn on the digital interface clock */ + PM->APBAMASK.reg |= PM_APBAMASK_GCLK; + + /* ---------------------------------------------------------------------------------------------- + * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator) + */ + SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */ + SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K; + SYSCTRL->XOSC32K.bit.ENABLE = 1; /* separate call, as described in chapter 15.6.3 */ + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 ) + { + /* Wait for oscillator stabilization */ + } + + /* Software reset the module to ensure it is re-initialized correctly */ + /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete. + * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1 + */ + GCLK->CTRL.reg = GCLK_CTRL_SWRST; + + while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) ) + { + /* Wait for reset to complete */ + } + + /* ---------------------------------------------------------------------------------------------- + * 2) Put XOSC32K as source of Generic Clock Generator 1 + */ + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ); // Generic Clock Generator 1 + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } + + /* Write Generic Clock Generator 1 configuration */ + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1 + GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator +// GCLK_GENCTRL_OE | // Output clock to a pin for tests + GCLK_GENCTRL_GENEN; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } + + /* ---------------------------------------------------------------------------------------------- + * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) + */ + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0 + GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source + GCLK_CLKCTRL_CLKEN; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } + + /* ---------------------------------------------------------------------------------------------- + * 4) Enable DFLL48M clock + */ + + /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */ + + /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */ + SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0; + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) + { + /* Wait for synchronization */ + } + + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value + SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value + SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK/VARIANT_MAINOSC) ); // External 32KHz is the reference + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) + { + /* Wait for synchronization */ + } + + /* Write full configuration to DFLL control register */ + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */ + SYSCTRL_DFLLCTRL_WAITLOCK | + SYSCTRL_DFLLCTRL_QLDIS; /* Disable Quick lock */ + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) + { + /* Wait for synchronization */ + } + + /* Enable the DFLL */ + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE; + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 || + (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 ) + { + /* Wait for locks flags */ + } + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) + { + /* Wait for synchronization */ + } + + /* ---------------------------------------------------------------------------------------------- + * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. + */ + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ); // Generic Clock Generator 0 + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } + + /* Write Generic Clock Generator 0 configuration */ + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0 + GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz +// GCLK_GENCTRL_OE | // Output clock to a pin for tests + GCLK_GENCTRL_IDC | // Set 50/50 duty cycle + GCLK_GENCTRL_GENEN; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } + +#if 0 + /* ---------------------------------------------------------------------------------------------- + * 6) Modify PRESCaler value of OSC8M to have 8MHz + */ + SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_1_Val; + SYSCTRL->OSC8M.bit.ONDEMAND = 0; + + /* ---------------------------------------------------------------------------------------------- + * 7) Put OSC8M as source for Generic Clock Generator 3 + */ + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ); // Generic Clock Generator 3 + + /* Write Generic Clock Generator 3 configuration */ + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3 + GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset) +// GCLK_GENCTRL_OE | // Output clock to a pin for tests + GCLK_GENCTRL_GENEN; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } +#endif //0 + + /* + * Now that all system clocks are configured, we can set CPU and APBx BUS clocks. + * These values are normally the ones present after Reset. + */ + PM->CPUSEL.reg = PM_CPUSEL_CPUDIV_DIV1; + PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val; + PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val; + PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val; + + // systick initialization + +// SysTick_Config(48000L); +} diff --git a/sparkfun/samd/bootloaders/LilyMini/board_startup.c b/sparkfun/samd/bootloaders/LilyMini/board_startup.c new file mode 100644 index 00000000..6064e7ae --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/board_startup.c @@ -0,0 +1,141 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#include + +struct ConstVectors +{ + /* Stack pointer */ + void* pvStack; + + /* Cortex-M handlers */ + void* pfnReset_Handler; + void* pfnNMI_Handler; + void* pfnHardFault_Handler; + void* pfnReservedM12; + void* pfnReservedM11; + void* pfnReservedM10; + void* pfnReservedM9; + void* pfnReservedM8; + void* pfnReservedM7; + void* pfnReservedM6; + void* pfnSVC_Handler; + void* pfnReservedM4; + void* pfnReservedM3; + void* pfnPendSV_Handler; + void* pfnSysTick_Handler; +}; + +/* Symbols exported from linker script */ +extern uint32_t __etext ; +extern uint32_t __data_start__ ; +extern uint32_t __data_end__ ; +extern uint32_t __bss_start__ ; +extern uint32_t __bss_end__ ; +extern uint32_t __StackTop; + +extern int main(void); +extern void __libc_init_array(void); + +/* Exception Table */ +__attribute__ ((section(".isr_vector"))) +const struct ConstVectors exception_table = +{ + /* Configure Initial Stack Pointer, using linker-generated symbols */ + .pvStack = (void*) (&__StackTop), + + .pfnReset_Handler = (void*) Reset_Handler, + .pfnNMI_Handler = (void*) NMI_Handler, + .pfnHardFault_Handler = (void*) HardFault_Handler, + .pfnReservedM12 = (void*) (0UL), /* Reserved */ + .pfnReservedM11 = (void*) (0UL), /* Reserved */ + .pfnReservedM10 = (void*) (0UL), /* Reserved */ + .pfnReservedM9 = (void*) (0UL), /* Reserved */ + .pfnReservedM8 = (void*) (0UL), /* Reserved */ + .pfnReservedM7 = (void*) (0UL), /* Reserved */ + .pfnReservedM6 = (void*) (0UL), /* Reserved */ + .pfnSVC_Handler = (void*) SVC_Handler, + .pfnReservedM4 = (void*) (0UL), /* Reserved */ + .pfnReservedM3 = (void*) (0UL), /* Reserved */ + .pfnPendSV_Handler = (void*) PendSV_Handler, + .pfnSysTick_Handler = (void*) (0UL), //SysTick_Handler, +}; + +/** + * \brief This is the code that gets called on processor reset. + * Initializes the device and call the main() routine. + */ +void Reset_Handler( void ) +{ + uint32_t *pSrc, *pDest; + + /* Initialize the initialized data section */ + pSrc = &__etext; + pDest = &__data_start__; + + if ( (&__data_start__ != &__data_end__) && (pSrc != pDest) ) + { + for (; pDest < &__data_end__ ; pDest++, pSrc++ ) + { + *pDest = *pSrc ; + } + } + + /* Clear the zero section */ + if ( &__bss_start__ != &__bss_end__ ) + { + for ( pDest = &__bss_start__ ; pDest < &__bss_end__ ; pDest++ ) + { + *pDest = 0ul ; + } + } + +// board_init(); // will be done in main() after app check + + /* Initialize the C library */ +// __libc_init_array(); + + main(); + + while (1); +} + +void NMI_Handler(void) +{ + __BKPT(14); + while (1); +} + +void HardFault_Handler(void) +{ + __BKPT(13); + while (1); +} + +void SVC_Handler(void) +{ + __BKPT(5); + while (1); +} + +void PendSV_Handler(void) +{ + __BKPT(2); + while (1); +} diff --git a/sparkfun/samd/bootloaders/LilyMini/bootloader4k_samd11.ld b/sparkfun/samd/bootloaders/LilyMini/bootloader4k_samd11.ld new file mode 100644 index 00000000..da8da44b --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/bootloader4k_samd11.ld @@ -0,0 +1,223 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +/* Modified for SAMD11D by M Grusin, SparkFun Electronics */ + +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x1000 /* First 4KB used by bootloader */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0001000 /* 4KB of SRAM */ +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __sketch_vectors_ptr + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + . = ORIGIN(FLASH); + + .vectors : + { + KEEP(*(.isr_vector)) + } > FLASH + + .text : + { + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + PROVIDE(__sketch_vectors_ptr = ORIGIN(FLASH) + LENGTH(FLASH)); + + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + __ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/sparkfun/samd/bootloaders/LilyMini/main.c b/sparkfun/samd/bootloaders/LilyMini/main.c new file mode 100644 index 00000000..31b7d082 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/main.c @@ -0,0 +1,137 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +// Modified for 4K SAMD11 bootloader by Mike Grusin, SparkFun Electronics +// With acknowledgement to Justin Mattair, Mattairtech + +#include +#include +#include "sam_ba_monitor.h" +#include "board_definitions.h" +#include "board_driver_led.h" +#include "sam_ba_usb.h" +#include "sam_ba_cdc.h" + +extern uint32_t __sketch_vectors_ptr; // Exported value from linker script +extern void board_init(void); +//static volatile long int tick = 0L; + +/** + * \brief Check the application startup condition + * + */ +static void check_start_application(void) +{ + uint32_t* pulSketch_Start_Address; + + /* + * Test sketch stack pointer @ &__sketch_vectors_ptr + * Stay in SAM-BA if value @ (&__sketch_vectors_ptr) == 0xFFFFFFFF (Erased flash cell value) + */ + if (__sketch_vectors_ptr == 0xFFFFFFFF) + { + LED_RED_on(); // Red: no upload present, staying in bootloader + LED_GREEN_off(); + LED_BLUE_off(); + return; + } + + // Prepare to jump to code + + LED_RED_off(); // All LEDs off + LED_GREEN_off(); + LED_BLUE_off(); + + /* + * Load the sketch Reset Handler address + * __sketch_vectors_ptr is exported from linker script and point on first 32b word of sketch vector table + * First 32b word is sketch stack + * Second 32b word is sketch entry point: Reset_Handler() + */ + pulSketch_Start_Address = &__sketch_vectors_ptr ; + pulSketch_Start_Address++ ; + + /* Rebase the Stack Pointer */ + __set_MSP( (uint32_t)(__sketch_vectors_ptr) ); + + /* Rebase the vector table base address */ + SCB->VTOR = ((uint32_t)(&__sketch_vectors_ptr) & SCB_VTOR_TBLOFF_Msk); + + /* Jump to application Reset Handler in the application */ + asm("bx %0"::"r"(*pulSketch_Start_Address)); +} + +/** + * \brief SAMD21 SAM-BA Main loop. + * \return Unused (ANSI-C compatibility). + */ +int main(void) +{ + P_USB_CDC pCdc; + + // Initialize LEDs + LED_RED_init(); + LED_GREEN_init(); + LED_BLUE_init(); + + LED_RED_off(); + LED_GREEN_off(); + LED_BLUE_on(); // Blue: power on + + // Stay in bootloader if power button is held down during powerup: + + // Initialize button + PORT->Group[BOARD_BUTTON_PORT].DIRCLR.reg = (1<Group[BOARD_BUTTON_PORT].PINCFG[BOARD_BUTTON_PIN].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN; + PORT->Group[BOARD_BUTTON_PORT].OUTSET.reg = (1<Group[BOARD_BUTTON_PORT].IN.reg & (1<IsConfigured(pCdc) != 0) + { + LED_RED_off(); + LED_GREEN_on(); // Green: we have a connection! + LED_BLUE_off(); + + sam_ba_monitor_init(); + + while (1) + { + sam_ba_monitor_run(); + } + } + } +} + +//void SysTick_Handler(void) +// To use, set vector in board_startup.c, initialize in board_init.c +//{ +// tick++; +//} \ No newline at end of file diff --git a/sparkfun/samd/bootloaders/LilyMini/sam_ba_cdc.c b/sparkfun/samd/bootloaders/LilyMini/sam_ba_cdc.c new file mode 100644 index 00000000..fc5efe34 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/sam_ba_cdc.c @@ -0,0 +1,98 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#include "sam_ba_cdc.h" +#include "board_driver_usb.h" + +usb_cdc_line_coding_t line_coding= +{ + 115200, // baudrate + 0, // 1 Stop Bit + 0, // None Parity + 8 // 8 Data bits +}; + +#define pCdc (&sam_ba_cdc) + +int cdc_putc(/*P_USB_CDC pCdc,*/ int value) +{ + /* Send single byte on USB CDC */ + USB_Write(pCdc->pUsb, (const char *)&value, 1, USB_EP_IN); + + return 1; +} + +int cdc_getc(/*P_USB_CDC pCdc*/void) +{ + uint8_t rx_char; + + /* Read singly byte on USB CDC */ + USB_Read(pCdc->pUsb, (char *)&rx_char, 1); + + return (int)rx_char; +} + +bool cdc_is_rx_ready(/*P_USB_CDC pCdc*/void) +{ + /* Check whether the device is configured */ + if ( !USB_IsConfigured(pCdc) ) + return 0; + + /* Return transfer complete 0 flag status */ + return (pCdc->pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0)); +} + +uint32_t cdc_write_buf(/*P_USB_CDC pCdc,*/ void const* data, uint32_t length) +{ + /* Send the specified number of bytes on USB CDC */ + USB_Write(pCdc->pUsb, (const char *)data, length, USB_EP_IN); + return length; +} + +uint32_t cdc_read_buf(/*P_USB_CDC pCdc,*/ void* data, uint32_t length) +{ + /* Check whether the device is configured */ + if ( !USB_IsConfigured(pCdc) ) + return 0; + + /* Read from USB CDC */ + return USB_Read(pCdc->pUsb, (char *)data, length); +} + +uint32_t cdc_read_buf_xmd(/*P_USB_CDC pCdc,*/ void* data, uint32_t length) +{ + /* Check whether the device is configured */ + if ( !USB_IsConfigured(pCdc) ) + return 0; + + /* Blocking read till specified number of bytes is received */ + // XXX: USB_Read_blocking is not reliable + // return USB_Read_blocking(pCdc, (char *)data, length); + + char *dst = (char *)data; + uint32_t remaining = length; + while (remaining) + { + uint32_t readed = USB_Read(pCdc->pUsb, (char *)dst, remaining); + remaining -= readed; + dst += readed; + } + + return length; +} diff --git a/sparkfun/samd/bootloaders/LilyMini/sam_ba_cdc.h b/sparkfun/samd/bootloaders/LilyMini/sam_ba_cdc.h new file mode 100644 index 00000000..49b7643c --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/sam_ba_cdc.h @@ -0,0 +1,91 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#ifndef _SAM_BA_USB_CDC_H_ +#define _SAM_BA_USB_CDC_H_ + +#include +#include "sam_ba_usb.h" + +typedef struct +{ + uint32_t dwDTERate; + uint8_t bCharFormat; + uint8_t bParityType; + uint8_t bDataBits; +} usb_cdc_line_coding_t; + +/* CDC Class Specific Request Code */ +#define GET_LINE_CODING 0x21A1 +#define SET_LINE_CODING 0x2021 +#define SET_CONTROL_LINE_STATE 0x2221 + +extern usb_cdc_line_coding_t line_coding; + + +/** + * \brief Sends a single byte through USB CDC + * + * \param Data to send + * \return number of data sent + */ +int cdc_putc(/*P_USB_CDC pCdc,*/ int value); + +/** + * \brief Reads a single byte through USB CDC + * + * \return Data read through USB + */ +int cdc_getc(/*P_USB_CDC pCdc*/); + +/** + * \brief Checks if a character has been received on USB CDC + * + * \return \c 1 if a byte is ready to be read. + */ +bool cdc_is_rx_ready(/*P_USB_CDC pCdc*/); + +/** + * \brief Sends buffer on USB CDC + * + * \param data pointer + * \param number of data to send + * \return number of data sent + */ +uint32_t cdc_write_buf(/*P_USB_CDC pCdc,*/ void const* data, uint32_t length); + +/** + * \brief Gets data on USB CDC + * + * \param data pointer + * \param number of data to read + * \return number of data read + */ +uint32_t cdc_read_buf(/*P_USB_CDC pCdc,*/ void* data, uint32_t length); + +/** + * \brief Gets specified number of bytes on USB CDC + * + * \param data pointer + * \param number of data to read + * \return number of data read + */ +uint32_t cdc_read_buf_xmd(/*P_USB_CDC pCdc,*/ void* data, uint32_t length); + +#endif // _SAM_BA_USB_CDC_H_ diff --git a/sparkfun/samd/bootloaders/LilyMini/sam_ba_monitor.c b/sparkfun/samd/bootloaders/LilyMini/sam_ba_monitor.c new file mode 100644 index 00000000..d1d2cc63 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/sam_ba_monitor.c @@ -0,0 +1,332 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +// Modified for 4K SAMD11 bootloader by Mike Grusin, SparkFun Electronics +// With acknowledgement to Justin Mattair, Mattairtech + +// REMOVED: +// Extended capabilities +// USART mode +// Interactive mode + +#include "sam.h" +#include +#include "sam_ba_monitor.h" +#include "board_driver_usb.h" +#include "sam_ba_usb.h" +#include "sam_ba_cdc.h" +#include "board_driver_led.h" +#include "board_definitions.h" + +const char RomBOOT_Version[] = SAM_BA_VERSION; + +uint32_t current_number; +uint32_t i, length; +uint8_t command, *ptr_data, *ptr, data[SIZEBUFMAX]; +uint8_t j; +uint32_t u32tmp; +uint32_t PAGE_SIZE, PAGES, MAX_FLASH; + +typedef struct +{ + /* send one byte of data */ + int (*put_c)(int value); + /* Get one byte */ + int (*get_c)(void); + /* Receive buffer not empty */ + bool (*is_rx_ready)(void); + /* Send given data (polling) */ + uint32_t (*putdata)(void const* data, uint32_t length); + /* Get data from comm. device */ + uint32_t (*getdata)(void* data, uint32_t length); + /* Send given data (polling) using xmodem (if necessary) */ + uint32_t (*putdata_xmd)(void const* data, uint32_t length); + /* Get data from comm. device using xmodem (if necessary) */ + uint32_t (*getdata_xmd)(void* data, uint32_t length); +} t_monitor_if; + +const t_monitor_if usbcdc_if = +{ + .put_c = cdc_putc, + .get_c = cdc_getc, + .is_rx_ready = cdc_is_rx_ready, + .putdata = cdc_write_buf, + .getdata = cdc_read_buf, + .putdata_xmd = cdc_write_buf, + .getdata_xmd = cdc_read_buf_xmd +}; + +/* The pointer to the interface object use by the monitor */ +t_monitor_if * ptr_monitor_if; + +void sam_ba_monitor_init() +{ + ptr_monitor_if = (t_monitor_if*) &usbcdc_if; + ptr_data = NULL; + command = 'z'; +} + +/* + * Central SAM-BA monitor putdata function + */ +static uint32_t sam_ba_putdata(t_monitor_if* pInterface, void const* data, uint32_t length) +{ + uint32_t result ; + + result=pInterface->putdata(data, length); + + if (result) + { + LED_RED_toggle(); + } + + return result; +} + +/* + * Central SAM-BA monitor getdata function + */ +static uint32_t sam_ba_getdata(t_monitor_if* pInterface, void* data, uint32_t length) +{ + uint32_t result ; + + result=pInterface->getdata(data, length); + + if (result) + { + LED_GREEN_toggle(); + } + + return result; +} + +/* + * Central SAM-BA monitor putdata function using + */ +static uint32_t sam_ba_putdata_xmd(t_monitor_if* pInterface, void const* data, uint32_t length) +{ + uint32_t result ; + + result=pInterface->putdata_xmd(data, length); + + if (result) + { + LED_RED_toggle(); + } + + return result; +} + +/* + * Central SAM-BA monitor getdata function + */ +static uint32_t sam_ba_getdata_xmd(t_monitor_if* pInterface, void* data, uint32_t length) +{ + uint32_t result ; + + result=pInterface->getdata_xmd(data, length); + + if (result) + { + LED_GREEN_toggle(); + } + + return result; +} + +/** + * \brief This function allows data emission by USART + * + * \param *data Data pointer + * \param length Length of the data + */ +void sam_ba_putdata_term(uint8_t* data, uint32_t length) +{ + sam_ba_putdata(ptr_monitor_if, data, length); + return; +} + +volatile uint32_t sp; + +void call_applet(uint32_t address) +{ + uint32_t app_start_address; + + LED_RED_off(); + LED_GREEN_off(); + LED_BLUE_off(); + + __disable_irq(); + + sp = __get_MSP(); + + /* Rebase the Stack Pointer */ + __set_MSP(*(uint32_t *) address); + + /* Load the Reset Handler address of the application */ + app_start_address = *(uint32_t *)(address + 4); + + /* Jump to application Reset Handler in the application */ + asm("bx %0"::"r"(app_start_address)); +} + +static void sam_ba_monitor_loop(void) +{ + length = sam_ba_getdata(ptr_monitor_if, data, SIZEBUFMAX); + ptr = data; + + for (i = 0; i < length; i++, ptr++) + { + if (*ptr == 0xff) continue; + + if (*ptr == '#') + { + if (command == 'S') // send data to device + { + //Check if some data are remaining in the "data" buffer + if(length>i) + { + //Move current indexes to next avail data (currently ptr points to "#") + ptr++; + i++; + + //We need to add first the remaining data of the current buffer already read from usb + //read a maximum of "current_number" bytes + if ((length-i) < current_number) + { + u32tmp=(length-i); + } + else + { + u32tmp=current_number; + } + + memcpy(ptr_data, ptr, u32tmp); + i += u32tmp; + ptr += u32tmp; + j = u32tmp; + } + //update i with the data read from the buffer + i--; + ptr--; + //Do we expect more data ? + if(j +#include +#include "board_definitions.h" +#include "sam_ba_usb.h" +#include "board_driver_usb.h" +#include "sam_ba_cdc.h" + +/* This data array will be copied into SRAM as its length is inferior to 64 bytes, + * and so can stay in flash. + */ +static __attribute__((__aligned__(4))) +const char devDescriptor[] = +{ + /* Device descriptor */ + 0x12, // bLength + 0x01, // bDescriptorType + 0x10, // bcdUSB L // USB 1.1 + 0x01, // bcdUSB H +// 0x00, // bcdUSB L // USB 2.0 +// 0x02, // bcdUSB H + 0x02, // bDeviceClass: CDC class code + 0x00, // bDeviceSubclass: CDC class sub code + 0x00, // bDeviceProtocol: CDC Device protocol + 0x40, // bMaxPacketSize0 + USB_VID_LOW, // idVendor L + USB_VID_HIGH, // idVendor H + USB_PID_LOW, // idProduct L + USB_PID_HIGH, // idProduct H + 0x00, // bcdDevice L, here matching SAM-BA version + 0x02, // bcdDevice H + STRING_INDEX_MANUFACTURER, // iManufacturer + STRING_INDEX_PRODUCT, // iProduct + 0x00, // SerialNumber, should be based on product unique ID + 0x01 // bNumConfigs +}; + +/* This data array will be consumed directly by USB_Write() and must be in SRAM. + * We cannot send data from product internal flash. + */ +static __attribute__((__aligned__(4))) +char cfgDescriptor[] = +{ + /* ============== CONFIGURATION 1 =========== */ + /* Configuration 1 descriptor */ + 0x09, // CbLength + 0x02, // CbDescriptorType + 0x43, // CwTotalLength 2 EP + Control + 0x00, + 0x02, // CbNumInterfaces + 0x01, // CbConfigurationValue + 0x00, // CiConfiguration + 0x80, // CbmAttributes Bus powered without remote wakeup: 0x80, Self powered without remote wakeup: 0xc0 + 0x32, // CMaxPower, report using 100mA, enough for a bootloader + + /* Communication Class Interface Descriptor Requirement */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints + 0x02, // bInterfaceClass + 0x02, // bInterfaceSubclass + 0x00, // bInterfaceProtocol + 0x00, // iInterface + + /* Header Functional Descriptor */ + 0x05, // bFunction Length + 0x24, // bDescriptor type: CS_INTERFACE + 0x00, // bDescriptor subtype: Header Func Desc + 0x10, // bcdCDC:1.1 + 0x01, + + /* ACM Functional Descriptor */ + 0x04, // bFunctionLength + 0x24, // bDescriptor Type: CS_INTERFACE + 0x02, // bDescriptor Subtype: ACM Func Desc + 0x00, // bmCapabilities + + /* Union Functional Descriptor */ + 0x05, // bFunctionLength + 0x24, // bDescriptorType: CS_INTERFACE + 0x06, // bDescriptor Subtype: Union Func Desc + 0x00, // bMasterInterface: Communication Class Interface + 0x01, // bSlaveInterface0: Data Class Interface + + /* Call Management Functional Descriptor */ + 0x05, // bFunctionLength + 0x24, // bDescriptor Type: CS_INTERFACE + 0x01, // bDescriptor Subtype: Call Management Func Desc + 0x00, // bmCapabilities: D1 + D0 + 0x01, // bDataInterface: Data Class Interface 1 + + /* Endpoint 1 descriptor */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x83, // bEndpointAddress, Endpoint 03 - IN + 0x03, // bmAttributes INT + 0x08, // wMaxPacketSize + 0x00, + 0xFF, // bInterval + + /* Data Class Interface Descriptor Requirement */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x01, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + 0x0A, // bInterfaceClass + 0x00, // bInterfaceSubclass + 0x00, // bInterfaceProtocol + 0x00, // iInterface + + /* First alternate setting */ + /* Endpoint 1 descriptor */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x81, // bEndpointAddress, Endpoint 01 - IN + 0x02, // bmAttributes BULK + USB_EP_IN_SIZE, // wMaxPacketSize + 0x00, + 0x00, // bInterval + + /* Endpoint 2 descriptor */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x02, // bEndpointAddress, Endpoint 02 - OUT + 0x02, // bmAttributes BULK + USB_EP_OUT_SIZE, // wMaxPacketSize + 0x00, + 0x00 // bInterval +}; + +#ifndef STRING_MANUFACTURER +# define STRING_MANUFACTURER "Arduino LLC" +#endif + +#ifndef STRING_PRODUCT +# define STRING_PRODUCT "Arduino Zero" +#endif + +USB_CDC sam_ba_cdc; + +/*---------------------------------------------------------------------------- + * \brief This function is a callback invoked when a SETUP packet is received + */ +void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc) +{ + Usb *pUsb = pCdc->pUsb; + static volatile uint8_t bmRequestType, bRequest, dir; + static volatile uint16_t wValue, wIndex, wLength, wStatus; + + /* Clear the Received Setup flag */ + pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.RXSTP = true; + + /* Read the USB request parameters */ + bmRequestType = udd_ep_out_cache_buffer[0][0]; + bRequest = udd_ep_out_cache_buffer[0][1]; + wValue = (udd_ep_out_cache_buffer[0][2] & 0xFF); + wValue |= (udd_ep_out_cache_buffer[0][3] << 8); + wIndex = (udd_ep_out_cache_buffer[0][4] & 0xFF); + wIndex |= (udd_ep_out_cache_buffer[0][5] << 8); + wLength = (udd_ep_out_cache_buffer[0][6] & 0xFF); + wLength |= (udd_ep_out_cache_buffer[0][7] << 8); + + /* Clear the Bank 0 ready flag on Control OUT */ + pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY; + + /* Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 */ + switch ((bRequest << 8) | bmRequestType) + { + case STD_GET_DESCRIPTOR: + if (wValue>>8 == STD_GET_DESCRIPTOR_DEVICE) + { + /* Return Device Descriptor */ + USB_Write(pCdc->pUsb, devDescriptor, SAM_BA_MIN(sizeof(devDescriptor), wLength), USB_EP_CTRL); + } + else if (wValue>>8 == STD_GET_DESCRIPTOR_CONFIGURATION) + { + /* Return Configuration Descriptor */ + USB_Write(pCdc->pUsb, cfgDescriptor, SAM_BA_MIN(sizeof(cfgDescriptor), wLength), USB_EP_CTRL); + } + else if (wValue>>8 == STD_GET_DESCRIPTOR_STRING) + { + switch ( wValue & 0xff ) + { + case STRING_INDEX_LANGUAGES: { + uint16_t STRING_LANGUAGE[2] = { (STD_GET_DESCRIPTOR_STRING<<8) | 4, 0x0409 }; + + USB_Write(pCdc->pUsb, (const char*)STRING_LANGUAGE, SAM_BA_MIN(sizeof(STRING_LANGUAGE), wLength), USB_EP_CTRL); + } + break; + + case STRING_INDEX_MANUFACTURER: + USB_SendString(pCdc->pUsb, STRING_MANUFACTURER, STRING_MANUFACTURER_LENGTH, wLength ); + break; + + case STRING_INDEX_PRODUCT: + USB_SendString(pCdc->pUsb, STRING_PRODUCT, STRING_PRODUCT_LENGTH, wLength ); + break; + default: + /* Stall the request */ + USB_SendStall(pUsb, true); + break; + } + } + else + { + /* Stall the request */ + USB_SendStall(pUsb, true); + } + break; + + case STD_SET_ADDRESS: + /* Send ZLP */ + USB_SendZlp(pUsb); + /* Set device address to the newly received address from host */ + USB_SetAddress(pCdc->pUsb, wValue); + break; + + case STD_SET_CONFIGURATION: + /* Store configuration */ + pCdc->currentConfiguration = (uint8_t)wValue; + + /* Send ZLP */ + USB_SendZlp(pUsb); + + /* Configure the 3 needed endpoints */ + USB_Configure(pUsb); + break; + + case STD_GET_CONFIGURATION: + /* Return current configuration value */ + USB_Write(pCdc->pUsb, (char *) &(pCdc->currentConfiguration), sizeof(pCdc->currentConfiguration), USB_EP_CTRL); + break; + + case STD_GET_STATUS_ZERO: + wStatus = 0; + USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL); + break; + + case STD_GET_STATUS_INTERFACE: + wStatus = 0; + USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL); + break; + + case STD_GET_STATUS_ENDPOINT: + wStatus = 0; + dir = wIndex & 80; + wIndex &= 0x0F; + if (wIndex <= 3) + { + if (dir) + { + //wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1) ? 1 : 0; + wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<1)) ? 1 : 0; + } + else + { + //wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0) ? 1 : 0; + wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<0)) ? 1 : 0; + } + /* Return current status of endpoint */ + USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL); + } + else + { + /* Stall the request */ + USB_SendStall(pUsb, true); + } + break; + + case STD_SET_FEATURE_ZERO: + /* Stall the request */ + USB_SendStall(pUsb, true); + break; + + case STD_SET_FEATURE_INTERFACE: + /* Send ZLP */ + USB_SendZlp(pUsb); + break; + + case STD_SET_FEATURE_ENDPOINT: + dir = wIndex & 0x80; + wIndex &= 0x0F; + if ((wValue == 0) && wIndex && (wIndex <= 3)) + { + /* Set STALL request for the endpoint */ + if (dir) + { + //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1; + pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.bit.STALLRQ = (1<<1); + } + else + { + //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0; + pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.bit.STALLRQ = (1<<0); + } + + /* Send ZLP */ + USB_SendZlp(pUsb); + } + else + { + /* Stall the request */ + USB_SendStall(pUsb, true); + } + break; + + case STD_SET_INTERFACE: + case STD_CLEAR_FEATURE_ZERO: + /* Stall the request */ + USB_SendStall(pUsb, true); + break; + + case STD_CLEAR_FEATURE_INTERFACE: + /* Send ZLP */ + USB_SendZlp(pUsb); + break; + + case STD_CLEAR_FEATURE_ENDPOINT: + dir = wIndex & 0x80; + wIndex &= 0x0F; + + if ((wValue == 0) && wIndex && (wIndex <= 3)) + { + if (dir) + { + if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<1)) + { + // Remove stall request + //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1; + pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.bit.STALLRQ = (1<<1); + if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL & (1<<1)) + { + pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL = (1<<1); + // The Stall has occurred, then reset data toggle + pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLIN; + } + } + } + else + { + if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<0)) + { + // Remove stall request + //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0; + pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.bit.STALLRQ = (1<<0); + if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL & (1<<0)) + { + pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL = (1<<0); + // The Stall has occurred, then reset data toggle + pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLOUT; + } + } + } + /* Send ZLP */ + USB_SendZlp(pUsb); + } + else + { + USB_SendStall(pUsb, true); + } + break; + + // handle CDC class requests + case SET_LINE_CODING: + /* Send ZLP */ + USB_SendZlp(pUsb); + break; + + case GET_LINE_CODING: + /* Send current line coding */ + USB_Write(pCdc->pUsb, (char *) &line_coding, SAM_BA_MIN(sizeof(usb_cdc_line_coding_t), wLength), USB_EP_CTRL); + break; + + case SET_CONTROL_LINE_STATE: + /* Store the current connection */ + pCdc->currentConnection = wValue; + /* Send ZLP */ + USB_SendZlp(pUsb); + break; + + default: + /* Stall the request */ + USB_SendStall(pUsb, true); + break; + } +} + +/*---------------------------------------------------------------------------- + * \brief + */ +P_USB_CDC usb_init(void) +{ + sam_ba_cdc.pUsb = USB; + + /* Initialize USB */ + USB_Init(); + /* Get the default CDC structure settings */ + USB_Open(&sam_ba_cdc, sam_ba_cdc.pUsb); + + return &sam_ba_cdc; +} + +/*---------------------------------------------------------------------------- + * \brief Send a USB descriptor string. + * + * The input string is plain ASCII but is sent out as UTF-16 with the correct 2-byte prefix. + */ +uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t length, uint8_t maxLength) +{ + uint8_t string_descriptor[255]; // Max USB-allowed string length + uint16_t* unicode_string=(uint16_t*)(string_descriptor+2); // point on 3 bytes of descriptor + int resulting_length; + + string_descriptor[0] = (length<<1) + 2; +//string_descriptor[0] = (strlen(ascii_string)<<1) + 2; + string_descriptor[1] = STD_GET_DESCRIPTOR_STRING; + + for ( resulting_length = 1 ; *ascii_string && (resulting_length>1) ; resulting_length++ ) + { + *unicode_string++ = (uint16_t)(*ascii_string++); + } + + return USB_Write(pUsb, (const char*)string_descriptor, resulting_length<<1, USB_EP_CTRL); +} diff --git a/sparkfun/samd/bootloaders/LilyMini/sam_ba_usb.h b/sparkfun/samd/bootloaders/LilyMini/sam_ba_usb.h new file mode 100644 index 00000000..e2e50484 --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/sam_ba_usb.h @@ -0,0 +1,102 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Atmel Corporation/Thibaut VIARD. 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 +*/ + +#ifndef CDC_ENUMERATE_H +#define CDC_ENUMERATE_H + +#include +#include + +#define USB_EP_CTRL (0u) +#define USB_EP_OUT (2u) +#define USB_EP_OUT_SIZE (0x40u) +#define USB_EP_IN (1u) +#define USB_EP_IN_SIZE (0x40u) +#define USB_EP_COMM (3u) +#define MAX_EP (4u) + +/* USB standard request code */ +#define STD_GET_STATUS_ZERO (0x0080u) +#define STD_GET_STATUS_INTERFACE (0x0081u) +#define STD_GET_STATUS_ENDPOINT (0x0082u) + +#define STD_CLEAR_FEATURE_ZERO (0x0100u) +#define STD_CLEAR_FEATURE_INTERFACE (0x0101u) +#define STD_CLEAR_FEATURE_ENDPOINT (0x0102u) + +#define STD_SET_FEATURE_ZERO (0x0300u) +#define STD_SET_FEATURE_INTERFACE (0x0301u) +#define STD_SET_FEATURE_ENDPOINT (0x0302u) + +#define STD_SET_ADDRESS (0x0500u) +#define STD_GET_DESCRIPTOR (0x0680u) +#define STD_SET_DESCRIPTOR (0x0700u) +#define STD_GET_CONFIGURATION (0x0880u) +#define STD_SET_CONFIGURATION (0x0900u) +#define STD_GET_INTERFACE (0x0A81u) +#define STD_SET_INTERFACE (0x0B01u) +#define STD_SYNCH_FRAME (0x0C82u) + +#define STD_GET_DESCRIPTOR_DEVICE (1u) +#define STD_GET_DESCRIPTOR_CONFIGURATION (2u) +#define STD_GET_DESCRIPTOR_STRING (3u) +#define STD_GET_DESCRIPTOR_INTERFACE (4u) +#define STD_GET_DESCRIPTOR_ENDPOINT (5u) +#define STD_GET_DESCRIPTOR_DEVICE_QUALIFIER (6u) +#define STD_GET_DESCRIPTOR_OTHER_SPEED_CONFIGURATION (7u) +#define STD_GET_DESCRIPTOR_INTERFACE_POWER1 (8u) + +#define FEATURE_ENDPOINT_HALT (0u) +#define FEATURE_DEVICE_REMOTE_WAKEUP (1u) +#define FEATURE_TEST_MODE (2u) + +#define STRING_INDEX_LANGUAGES (0x00u) +#define STRING_INDEX_MANUFACTURER (0x01u) +#define STRING_INDEX_PRODUCT (0x02u) + +#define SAM_BA_MIN(a, b) (((a) < (b)) ? (a) : (b)) + + +typedef struct _USB_CDC +{ + // Private members + Usb *pUsb; + uint8_t currentConfiguration; + uint8_t currentConnection; + // Public Methods: + uint8_t (*IsConfigured)(struct _USB_CDC *pCdc); +// uint32_t (*Write) (Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num); +// uint32_t (*Read) (Usb *pUsb, char *pData, uint32_t length); +} USB_CDC, *P_USB_CDC; + +/** + * \brief Initializes the USB module + * + * \return Pointer to the USB CDC structure + */ +P_USB_CDC usb_init(void); + +void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc); + +uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t length, uint8_t maxLength); +//uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t maxLength); + +extern USB_CDC sam_ba_cdc; + +#endif // CDC_ENUMERATE_H diff --git a/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.atsln b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.atsln new file mode 100644 index 00000000..3a98863a --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.atsln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Atmel Studio Solution File, Format Version 11.00 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "samd11_sam_ba", "samd11_sam_ba.cproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Release|ARM = Release|ARM + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|ARM.ActiveCfg = Debug|ARM + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|ARM.Build.0 = Debug|ARM + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|ARM.ActiveCfg = Release|ARM + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|ARM.Build.0 = Release|ARM + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.bin b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.bin new file mode 100644 index 00000000..7c98b233 Binary files /dev/null and b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.bin differ diff --git a/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.cproj b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.cproj new file mode 100644 index 00000000..980bdb5f --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.cproj @@ -0,0 +1,222 @@ + + + + 2.0 + 7.0 + com.Atmel.ARMGCC.C + dce6c7e3-ee26-4d79-826b-08594b9ad897 + ATSAMD11D14AM + none + Executable + C + $(MSBuildProjectName) + .elf + $(MSBuildProjectDirectory)\$(Configuration) + samd21_sam_ba + samd11_sam_ba + samd21_sam_ba + Native + true + false + false + true + 0x20000000 + + true + exception_table + 2 + 0 + + + + + + + + + + + + + + com.atmel.avrdbg.tool.atmelice + J41800058638 + 0x10030000 + SWD + + + + 2000000 + + SWD + + com.atmel.avrdbg.tool.atmelice + J41800058638 + Atmel-ICE + + 2000000 + + + + + SWD + + com.atmel.avrdbg.tool.edbg + ATML2320040200000259 + EDBG + + + + + 2000000 + + SWD + + com.atmel.avrdbg.tool.jtagice3plus + J30200029813 + JTAGICE3 + + True + False + + + + + True + True + True + True + True + + + NDEBUG + + + Optimize for size (-Os) + True + True + + + libm + + + True + -Tsamd21j18a_flash.ld + + + True + C:\Users\mgrusin\Documents\GitHub\ArduinoCore-samd\bootloaders\LilyMini + all + clean + C:\Users\mgrusin\Documents\GitHub\ArduinoCore-samd\bootloaders\LilyMini\Makefile + + + + + True + True + True + True + True + + + DEBUG + + + Optimize (-O1) + True + Maximum (-g3) + True + + + libm + + + True + -Tsamd21j18a_flash.ld + Default (-g) + Default (-Wa,-g) + + + True + + DEBUG=1 all + clean + Makefile + + + + compile + board_definitions.h + + + compile + + + compile + board_driver_led.c + + + compile + board_driver_led.h + + + compile + board_driver_usb.c + + + compile + board_driver_usb.h + + + compile + board_init.c + + + compile + board_startup.c + + + compile + main.c + + + compile + sam_ba_cdc.c + + + compile + sam_ba_cdc.h + + + compile + sam_ba_monitor.c + + + compile + sam_ba_monitor.h + + + compile + sam_ba_usb.c + + + compile + sam_ba_usb.h + + + + + compile + + + compile + Makefile + + + compile + README.md + + + + \ No newline at end of file diff --git a/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.elf b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.elf new file mode 100644 index 00000000..bd890b8b Binary files /dev/null and b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.elf differ diff --git a/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.hex b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.hex new file mode 100644 index 00000000..f9d03b8c --- /dev/null +++ b/sparkfun/samd/bootloaders/LilyMini/samd11_sam_ba.hex @@ -0,0 +1,246 @@ +:10000000001000204D0500003D05000041050000E6 +:1000100000000000000000000000000000000000E0 +:100020000000000000000000000000004505000086 +:100030000000000000000000490500000000000072 +:1000400010B5064C2378002B07D1054B002B02D0AE +:10005000044800E000BF0123237010BD58000020B9 +:1000600000000000DC0E000008B5084B002B03D098 +:100070000748084900E000BF07480368002B03D089 +:10008000064B002B00D0984708BDC046000000007A +:10009000DC0E00005C000020540000200000000086 +:1000A00070B50368041C988B1A1C0821FF320842A3 +:1000B00028D0988B174D0143802099839872112383 +:1000C00053704021144B917150715E68C0202E40D6 +:1000D000800506435E605E693540284358610F48DD +:1000E00018600F4818615D680E4828408025AD02F1 +:1000F000284358605868800B800358600023517172 +:10010000237105E0137ADA0602D5201C00F0C4FA48 +:10011000207970BDFFFFFF8F840100208400002044 +:1001200004010020FF3F00F0002303714371044BE2 +:10013000016083600B78022213430B707047C04646 +:10014000A100000038B5364B2021DA6901200A43AE +:10015000DA61344B06241A7802431A70324B0F22AC +:100160001978914319701978214319702F490C7827 +:100170002043087019780A401A701A7860210A43DF +:100180001A702B4B2B4A5A805A7852B2002AFBDB4A +:10019000294B01211A780A431A709A78D107FCD4A6 +:1001A00026480268510B1F221140914200D10521BF +:1001B00011408C011D8D2249294021431985046875 +:1001C000A10C0A401F2A00D11D221C8D1F210A40AC +:1001D0008C4322431A8502680721D20D0A408A42C5 +:1001E00000D103220A40188D1103164A02400A4327 +:1001F0001A8519787F220A401A701A780421124849 +:100200000A431A7058621A890C218A431A811A8982 +:1002100001218A431A810021802200F014FE38BD9A +:1002200000040040584400413C440041594400410E +:10023000000C004006400000005000412460800097 +:100240003FF8FFFFFF8FFFFF84010020F7B5141C6C +:10025000234A5F0101971D1CD319061C5869271CEE +:100260004000400F03301033C74006D00F1C8022DF +:10027000596812060A435A6009E02F1C7B1E9F41F1 +:10028000184BBF01FF18381C221C00F0D3FD019948 +:100290001348083542181761131C5269A104920BC8 +:1002A000890C92030A435A6159690F4A02200A4095 +:1002B0005A616B01F318D979032211400143D879AF +:1002C0009043021C0A43DA715979802252420A4350 +:1002D0005A716B01F318DB799A07FAD5201CFEBD21 +:1002E0008401002004010020FF3F00F0F8B51E4EFD +:1002F000041C3378151C002B12D11C4B1C4A1A64A9 +:100300005A6C920B92035A64586C1A4A02405A640F +:10031000A2235B00E25C40200243E25401233370DD +:100320004827FF37E25D012313401AD00F4B5A6C68 +:100330009204920CAA4202D25D6CAD04AD0C081C72 +:100340002A1C0B4900F076FDE25D03231A400121CF +:100350000A43E15D99430B1C1343E35500233370BB +:1003600000E01D1C281CF8BD740000208401002042 +:10037000C4000020FF3F00F0FF30827930239A4311 +:10038000131C2022002900D11022134383717047CF +:100390000C4BFF305A690221920B92035A61027A88 +:1003A00003231A400A43017A99430B1C1343037237 +:1003B000827980235B4213438371037A9A07FCD5C9 +:1003C0007047C0468401002080235B421943C9B2B4 +:1003D0008172704770B5A02303225B00C254134B97 +:1003E000134A5C6CC021144089050C4346255C64AB +:1003F000FF35402444550F4D30261D6490256D0077 +:1004000046555D6B15402943922559636D00802147 +:100410004155094D1D63B0256D0044555C6F224068 +:100420005A67B2235B00C15470BDC04684010020EE +:10043000FFFFFF8FC40000204401002030B5364A82 +:100440001E23516808209943022319435160334900 +:100450008A6902438A613248324A9082908A034311 +:100460009382D3689807FCD52F4B01201870187819 +:10047000C40704D52C48407840B20028F7DB01209F +:100480009860587840B20028FBDB284C264844602E +:10049000587840B20028FBDB82242348E4014480E2 +:1004A000587840B20028FBDB908C8024A0439084D5 +:1004B000D068C506FCD51E4C1A48C462D4681948D9 +:1004C000E506FBD5848C1B4D2C438484D4681548E9 +:1004D000E506FBD5848C02252C438484D068040671 +:1004E000FCD51048C0684506F8D5D068C406FCD5D0 +:1004F00000229A605A7852B2002AFBDB0E480A4A60 +:1005000050605A7852B2002AFBDB00230B724B7208 +:100510008B72CB7230BDC0460040004100040040E9 +:100520000C06000000080040000C0040010501001E +:10053000B805FF7D040A0000000703000EBEFEE7B9 +:100540000DBEFEE705BEFEE702BEFEE70E4A0F48FF +:1005500038B5824204D10E4A0E4B93420ED10AE0C6 +:100560000D4C9442F7D00023D1188842F3D9E558B6 +:1005700004330D60F8E700F011F804E09342FAD27A +:10058000002102C3FAE7FEE7000000205800002027 +:100590008402002058000020E00E000070B5234BBC +:1005A000234A244C9A62802080218022C0050905BC +:1005B000120620250626986099609A6098619961D4 +:1005C0005A615D6026709D611E6A1C1C2E4213D00C +:1005D000194B1D686E1C03D16061A161A2610BE023 +:1005E000A061A161A26185F30888FF22191C9143D3 +:1005F000124A91605B681847FFF720FF62B600F06F +:100600001FF8051C281CAB6898470028FAD08023E7 +:10061000DB05A36180231B06A36180231B056361A7 +:1006200000F07EFA00F0B4FAFCE7C0460044004156 +:10063000004000C0454400410010000000ED00E013 +:1006400010B5054B054C2360FFF77CFD201C21688D +:10065000FFF76AFD201C10BD00500041040200207D +:1006600070B55200C0B06C46023222700322627034 +:100670005B0801240A19013A15786200002D05D1A2 +:1006800069460023FFF7E2FD40B070BD9C42F7DAF7 +:100690006E46B5520134EDE7F7B50468051C201C21 +:1006A000FF30037AAF4A10210B430372AE4F137829 +:1006B000AE493B705378AE4E0B7093783380D1784F +:1006C000338809020B4333801179AA4B1980517981 +:1006D0001F8809020F431F809779A7490F80D2799D +:1006E0000F8812023A430A80402242719F489E4F6F +:1006F0000278387812020243A0480F1C8446181C66 +:10070000624500D1C3E020DC802149008A4200D14B +:1007100085E109DC812A00D193E0822A00D196E0AC +:10072000802A00D07BE18CE081235B009A4200D1DB +:10073000D6E000DA6FE1C0239B009A4200D16EE15F +:100740008F4B9A4200D166E169E190231B019A42E6 +:100750006AD015DCD023DB009A4222D088231B010B +:100760009A426AD0A023DB009A4200D057E1201CB5 +:10077000FFF70EFE3188286889B2FFF725FE52E1A7 +:10078000804B9A4200D146E100DC48E17E4B9A4220 +:1007900000D134E17D4B9A4200D040E133886B7147 +:1007A00039E133881B0A012B08D10B8812222868F3 +:1007B000934201D80A8892B2754928E133881B0A0E +:1007C000022B08D10B8843222868934201D80A885B +:1007D00092B270491BE133881B0A032B00D01EE143 +:1007E0003388DBB2012B17D0002B07D0022B00D0AF +:1007F00015E10B882868DBB2674911E0042201A8E3 +:10080000664900F017FB3B8804222868934201D810 +:100810003A8892B201A9FAE00B8828686049DBB2F5 +:100820000822FFF71DFFFEE03388201C2B71FFF725 +:10083000AFFD201CFFF7CEFDF5E0291C01C9012208 +:10084000E5E0584900230B8028680222E0E0554982 +:1008500000220A80188850221040534A10701E88C7 +:100860000F20304018801888032800D9D7E012786C +:100870001B8808335B01E418A379002A01D09B068A +:1008800000E0DB06DB0F0B8028680222BFE019883E +:100890007F229143444AC9B2117018880F21014048 +:1008A00019803188002900D0B9E01988002900D1C9 +:1008B000B5E01988032900D9B1E012781B88083304 +:1008C0005B01E318002A04D05A7930218A432021A1 +:1008D00003E05A7930218A4310210A435A719AE081 +:1008E00002887F239A43304BD2B21A7001880F22BC +:1008F0000A4002803288002A00D090E00288002A54 +:1009000000D18CE00288032A00D988E01B78002BF4 +:100910004CD0038808335B01E3189B799A0600D416 +:1009200079E00388302108335B01E3181A798A43A0 +:1009300020210A431A71038808335B01E318DB792D +:100940005F0668D50388602108335B01E318DA7914 +:100950008A4340210A43DA710388022208335B018B +:10096000E3184AE0840000207C000020780000208A +:10097000760000207A0000207E00002002030000A4 +:100980000103000021200000A1210000212200001D +:10099000880E0000000000207D0E0000700E000098 +:1009A000740E0000800000208200002003880833BD +:1009B0005B01E3189B79D9062DD5038830210833D4 +:1009C0005B01E3181A798A4310210A431A710388DC +:1009D00008335B01E318DB799A061CD50388602194 +:1009E00008335B01E318DA798A4320210A43DA717C +:1009F0000388012208335B01E3181A710BE00B88AE +:100A000008222868934201D80A8892B20649002336 +:100A1000FFF71CFC07E0201CFFF7BAFC03E0201CDA +:100A20000121FFF7A9FCF7BD4400002007B5054BE5 +:100A30000122019001A91868131CFFF707FC01208F +:100A40000EBDC0460402002013B5054B6C460734AA +:100A50001868211C0122FFF749FC207816BDC0460A +:100A60000402002010B5074C201CFFF719FB031CE3 +:100A70000020834205D022684823FF33D05C012345 +:100A8000184010BD0402002010B5054A0C1C031CC0 +:100A9000191C10680123221CFFF7D8FB201C10BD75 +:100AA0000402002070B5084C061C201C0D1CFFF72A +:100AB000F7FA0023984205D02068311C2A1CFFF762 +:100AC00015FC031C181C70BD04020020F8B50C4C6A +:100AD000051C201C0E1CFFF7E3FA0023271C341C06 +:100AE00098420AD0002C07D0291C221C3868FFF736 +:100AF000FDFB241A2D18F5E7331C181CF8BDC04661 +:100B00000402002008B5031C081C111C984700288B +:100B100003D08022014BD205DA6108BD00440041B8 +:100B2000044A054B1A60054B00221A60044B7A22D6 +:100B30001A7070479C0E00007402002070020020A2 +:100B40001C02002008B50A1C0349031C0968C86878 +:100B5000191CFFF7D7FF08BD740200200A4B802242 +:100B6000D2059A61802212059A61802212069A614A +:100B700072B6EFF30883054A1360036883F30888AD +:100B8000436818477047C04600440041780200207F +:100B9000F0B5974D974C2B6885B01B69201C402100 +:100BA0009847002803D08022934B1205DA61934BBB +:100BB000934A1C60934B002110601960914E904A3B +:100BC00037681068874200D310E18C4C21680A789E +:100BD000FF2A00D101E1232A00D0DAE08A4B1B78FA +:100BE000532B39D1B8421AD9884B01371B680131D0 +:100BF0003760C01B2160864F984201D2386000E008 +:100C00003B60844B3A68186800F014F93B68306820 +:100C100021681A183260CA1822607F4A1370794A14 +:100C200078481268131C013B03602368774A013B34 +:100C30002360794B11681B788B420BD22A68754868 +:100C4000C91A006892699047002803D080226A4B35 +:100C50001205DA61C04696E0522B0ED16D4A2B6820 +:100C600010686A4A5B6911689847002800D18AE0D9 +:100C70008022614BD205DA6185E04F2B05D1654BAF +:100C8000624A1B6812681A707DE0482B05D1614BDF +:100C90005E4A1B6812681A8075E0572B05D15D4BC0 +:100CA0005A4A1B6812681A606DE06F2B03D1594BCA +:100CB0000121186807E0682B08D1564B53481B6880 +:100CC00002211B880360FFF73DFF5CE0772B06D114 +:100CD000504B4E481B6804211B680360F3E7472B09 +:100CE00009D14A4B1868FFF739FF4C4B1B6883F357 +:100CF000088862B647E0562B45D12B684849D8682A +:100D00000722FFF7FFFE2B684649D8680122FFF74C +:100D1000F9FE4549002321603360384A374813689B +:100D20005A1C02601F78002F06D0364A35481268D8 +:100D3000131C01330360F0E72B68324ED868326829 +:100D4000FFF7E0FE2B683749D8680122FFF7DAFE8B +:100D5000364937602160294A1368581C10601B7897 +:100D6000002B03D0336801333360F4E7254A2B6846 +:100D70001268D8680192FFF7C5FE2B682C49D86825 +:100D80000222FFF7BFFE204B7A221A7000221F4B6F +:100D900022E0111C3039C8B21C4B092804D818684D +:100DA00002011143196018E0111C4139052901D8CD +:100DB000373A04E0111C6139052904D8573A1868FC +:100DC00001010A4308E02C2A03D1124A1968116074 +:100DD00001E00D490A7000221A600A4B1A680132BC +:100DE0001A60064B1A6801321A60E7E605B0F0BDDA +:100DF000740200203002002000440041180200204C +:100E000014020020280200201C0200207C02002086 +:100E100080020020700200201002002078020020D2 +:100E2000D20E0000B80E0000BA0E0000C60E000080 +:100E3000CF0E000010B50023934203D0CC5CC45405 +:100E40000133F9E710BD031C8218934202D01970D8 +:100E50000133FAE770470000F8B5C046F8BC08BC9B +:100E60009E467047F8B5C046F8BC08BC9E46704721 +:100E700004030904537061726B46756E004C696C13 +:100E8000794D696E690000001201100102000040F6 +:100E90004F1B000100020102000100002D0A0000AA +:100EA000490A0000650A0000890A0000A50A00003E +:100EB000890A0000CD0A0000200044656320203428 +:100EC00020323031360030313A35393A3433000A85 +:100ED0000D004431312D312E3000000000000000A3 +:100EE00009024300020100803209040000010202ED +:100EF000000005240010010424020005240600015E +:100F00000524010001070583030800FF090401000F +:100F1000020A0000000705810240000007050202E6 +:100F20004000000000C2010000000800690000004D +:080F3000410000000000000078 +:040000030000054DA7 +:00000001FF diff --git a/sparkfun/samd/cores/LilyMini/Arduino.h b/sparkfun/samd/cores/LilyMini/Arduino.h new file mode 100644 index 00000000..3f7e1ae4 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Arduino.h @@ -0,0 +1,129 @@ +/* + Arduino.h - Main include file for the Arduino SDK + Copyright (c) 2014 Arduino LLC. 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 +*/ + +#ifndef Arduino_h +#define Arduino_h + +#include +#include +#include +#include +#include + +typedef bool boolean; +typedef uint8_t byte; +typedef uint16_t word; + +// some libraries and sketches depend on this AVR stuff, +// assuming Arduino.h or WProgram.h automatically includes it... +// +#include "avr/pgmspace.h" +#include "avr/interrupt.h" +#include "avr/io.h" + +#include "binary.h" +#include "itoa.h" + +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus + +// Include Atmel headers +#include "sam.h" + +#include "wiring_constants.h" + +#define clockCyclesPerMicrosecond() ( SystemCoreClock / 1000000L ) +#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) ) +#define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) ) + +void yield( void ) ; + +/* sketch */ +void setup( void ) ; +void loop( void ) ; + +#include "WVariant.h" + +#ifdef __cplusplus +} // extern "C" +#endif + +// The following headers are for C++ only compilation +#ifdef __cplusplus + #include "WCharacter.h" + #include "WString.h" + #include "Tone.h" + #include "WMath.h" + #include "HardwareSerial.h" + #include "pulse.h" +#endif +#include "delay.h" +#ifdef __cplusplus + #include "Uart.h" +#endif + +// Include board variant +#include "variant.h" + +#include "wiring.h" +#include "wiring_digital.h" +#include "wiring_analog.h" +#include "wiring_shift.h" +#include "WInterrupts.h" + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif // abs + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#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)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() __enable_irq() +#define noInterrupts() __disable_irq() + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + +#define bit(b) (1UL << (b)) + +#if (ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606) +// Interrupts +#define digitalPinToInterrupt(P) ( P ) +#endif + +// USB Device +#include "USB/USBDesc.h" +#include "USB/USBCore.h" +#include "USB/USBAPI.h" +//#include "USB/USB_host.h" // removed for SAMD11 + +#endif // Arduino_h diff --git a/sparkfun/samd/cores/LilyMini/Client.h b/sparkfun/samd/cores/LilyMini/Client.h new file mode 100644 index 00000000..b8e5d935 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Client.h @@ -0,0 +1,45 @@ +/* + Client.h - Base class that provides Client + Copyright (c) 2011 Adrian McEwen. 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 +*/ + +#ifndef client_h +#define client_h +#include "Print.h" +#include "Stream.h" +#include "IPAddress.h" + +class Client : public Stream { + +public: + virtual int connect(IPAddress ip, uint16_t port) =0; + virtual int connect(const char *host, uint16_t port) =0; + virtual size_t write(uint8_t) =0; + virtual size_t write(const uint8_t *buf, size_t size) =0; + virtual int available() = 0; + virtual int read() = 0; + virtual int read(uint8_t *buf, size_t size) = 0; + virtual int peek() = 0; + virtual void flush() = 0; + virtual void stop() = 0; + virtual uint8_t connected() = 0; + virtual operator bool() = 0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; + +#endif diff --git a/sparkfun/samd/cores/LilyMini/HardwareSerial.h b/sparkfun/samd/cores/LilyMini/HardwareSerial.h new file mode 100644 index 00000000..62508e78 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/HardwareSerial.h @@ -0,0 +1,84 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#ifndef HardwareSerial_h +#define HardwareSerial_h + +#include + +#include "Stream.h" + +#define HARDSER_PARITY_EVEN (0x1ul) +#define HARDSER_PARITY_ODD (0x2ul) +#define HARDSER_PARITY_NONE (0x3ul) +#define HARDSER_PARITY_MASK (0xFul) + +#define HARDSER_STOP_BIT_1 (0x10ul) +#define HARDSER_STOP_BIT_1_5 (0x20ul) +#define HARDSER_STOP_BIT_2 (0x30ul) +#define HARDSER_STOP_BIT_MASK (0xF0ul) + +#define HARDSER_DATA_5 (0x100ul) +#define HARDSER_DATA_6 (0x200ul) +#define HARDSER_DATA_7 (0x300ul) +#define HARDSER_DATA_8 (0x400ul) +#define HARDSER_DATA_MASK (0xF00ul) + +#define SERIAL_5N1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_NONE | HARDSER_DATA_5) +#define SERIAL_6N1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_NONE | HARDSER_DATA_6) +#define SERIAL_7N1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_NONE | HARDSER_DATA_7) +#define SERIAL_8N1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_NONE | HARDSER_DATA_8) +#define SERIAL_5N2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_NONE | HARDSER_DATA_5) +#define SERIAL_6N2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_NONE | HARDSER_DATA_6) +#define SERIAL_7N2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_NONE | HARDSER_DATA_7) +#define SERIAL_8N2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_NONE | HARDSER_DATA_8) +#define SERIAL_5E1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_EVEN | HARDSER_DATA_5) +#define SERIAL_6E1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_EVEN | HARDSER_DATA_6) +#define SERIAL_7E1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_EVEN | HARDSER_DATA_7) +#define SERIAL_8E1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_EVEN | HARDSER_DATA_8) +#define SERIAL_5E2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_EVEN | HARDSER_DATA_5) +#define SERIAL_6E2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_EVEN | HARDSER_DATA_6) +#define SERIAL_7E2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_EVEN | HARDSER_DATA_7) +#define SERIAL_8E2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_EVEN | HARDSER_DATA_8) +#define SERIAL_5O1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_ODD | HARDSER_DATA_5) +#define SERIAL_6O1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_ODD | HARDSER_DATA_6) +#define SERIAL_7O1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_ODD | HARDSER_DATA_7) +#define SERIAL_8O1 (HARDSER_STOP_BIT_1 | HARDSER_PARITY_ODD | HARDSER_DATA_8) +#define SERIAL_5O2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_ODD | HARDSER_DATA_5) +#define SERIAL_6O2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_ODD | HARDSER_DATA_6) +#define SERIAL_7O2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_ODD | HARDSER_DATA_7) +#define SERIAL_8O2 (HARDSER_STOP_BIT_2 | HARDSER_PARITY_ODD | HARDSER_DATA_8) + +class HardwareSerial : public Stream +{ + public: + virtual void begin(unsigned long); + virtual void begin(unsigned long baudrate, uint16_t config); + virtual void end(); + virtual int available(void) = 0; + virtual int peek(void) = 0; + virtual int read(void) = 0; + virtual void flush(void) = 0; + virtual size_t write(uint8_t) = 0; + using Print::write; // pull in write(str) and write(buf, size) from Print + virtual operator bool() = 0; +}; + +extern void serialEventRun(void) __attribute__((weak)); + +#endif diff --git a/sparkfun/samd/cores/LilyMini/Print.cpp b/sparkfun/samd/cores/LilyMini/Print.cpp new file mode 100644 index 00000000..33ee7210 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Print.cpp @@ -0,0 +1,254 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#include +#include +#include +#include +#include "Arduino.h" + +#include "Print.h" + +// Public Methods ////////////////////////////////////////////////////////////// + +/* default implementation: may be overridden */ +size_t Print::write(const uint8_t *buffer, size_t size) +{ + size_t n = 0; + while (size--) { + if (write(*buffer++)) n++; + else break; + } + return n; +} + +size_t Print::print(const __FlashStringHelper *ifsh) +{ + return print(reinterpret_cast(ifsh)); +} + +size_t Print::print(const String &s) +{ + return write(s.c_str(), s.length()); +} + +size_t Print::print(const char str[]) +{ + return write(str); +} + +size_t Print::print(char c) +{ + return write(c); +} + +size_t Print::print(unsigned char b, int base) +{ + return print((unsigned long) b, base); +} + +size_t Print::print(int n, int base) +{ + return print((long) n, base); +} + +size_t Print::print(unsigned int n, int base) +{ + return print((unsigned long) n, base); +} + +size_t Print::print(long n, int base) +{ + if (base == 0) { + return write(n); + } else if (base == 10) { + if (n < 0) { + int t = print('-'); + n = -n; + return printNumber(n, 10) + t; + } + return printNumber(n, 10); + } else { + return printNumber(n, base); + } +} + +size_t Print::print(unsigned long n, int base) +{ + if (base == 0) return write(n); + else return printNumber(n, base); +} + +size_t Print::print(double n, int digits) +{ + return printFloat(n, digits); +} + +size_t Print::println(const __FlashStringHelper *ifsh) +{ + size_t n = print(ifsh); + n += println(); + return n; +} + +size_t Print::print(const Printable& x) +{ + return x.printTo(*this); +} + +size_t Print::println(void) +{ + return write("\r\n"); +} + +size_t Print::println(const String &s) +{ + size_t n = print(s); + n += println(); + return n; +} + +size_t Print::println(const char c[]) +{ + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(char c) +{ + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(unsigned char b, int base) +{ + size_t n = print(b, base); + n += println(); + return n; +} + +size_t Print::println(int num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(unsigned int num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(long num, int base) +{ + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(unsigned 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); + n += println(); + return n; +} + +size_t Print::println(const Printable& x) +{ + size_t n = print(x); + n += println(); + return n; +} + +// Private Methods ///////////////////////////////////////////////////////////// + +size_t Print::printNumber(unsigned long n, uint8_t base) +{ + char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. + char *str = &buf[sizeof(buf) - 1]; + + *str = '\0'; + + // prevent crash if called with base == 1 + if (base < 2) base = 10; + + do { + char c = n % base; + n /= base; + + *--str = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); + + return write(str); +} + +size_t Print::printFloat(double number, uint8_t digits) +{ + size_t n = 0; + + if (isnan(number)) return print("nan"); + if (isinf(number)) return print("inf"); + if (number > 4294967040.0) return print ("ovf"); // constant determined empirically + if (number <-4294967040.0) return print ("ovf"); // constant determined empirically + + // Handle negative numbers + if (number < 0.0) + { + n += print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i=0; i 0) { + n += print("."); + } + + // Extract digits from the remainder one at a time + while (digits-- > 0) + { + remainder *= 10.0; + unsigned int toPrint = (unsigned int)remainder; + n += print(toPrint); + remainder -= toPrint; + } + + return n; +} diff --git a/sparkfun/samd/cores/LilyMini/Print.h b/sparkfun/samd/cores/LilyMini/Print.h new file mode 100644 index 00000000..9fc26742 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Print.h @@ -0,0 +1,83 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef Print_h +#define Print_h + +#include +#include // for size_t + +#include "WString.h" +#include "Printable.h" + +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 + +class Print +{ + private: + int write_error; + size_t printNumber(unsigned long, uint8_t); + size_t printFloat(double, uint8_t); + protected: + void setWriteError(int err = 1) { write_error = err; } + public: + Print() : write_error(0) {} + + int getWriteError() { return write_error; } + void clearWriteError() { setWriteError(0); } + + virtual size_t write(uint8_t) = 0; + size_t write(const char *str) { + if (str == NULL) return 0; + return write((const uint8_t *)str, strlen(str)); + } + virtual size_t write(const uint8_t *buffer, size_t size); + size_t write(const char *buffer, size_t size) { + return write((const uint8_t *)buffer, size); + } + + size_t print(const __FlashStringHelper *); + size_t print(const String &); + size_t print(const char[]); + size_t print(char); + size_t print(unsigned char, int = DEC); + size_t print(int, int = DEC); + size_t print(unsigned int, int = DEC); + size_t print(long, int = DEC); + size_t print(unsigned long, int = DEC); + size_t print(double, int = 2); + size_t print(const Printable&); + + size_t println(const __FlashStringHelper *); + size_t println(const String &s); + size_t println(const char[]); + size_t println(char); + size_t println(unsigned char, int = DEC); + size_t println(int, int = DEC); + size_t println(unsigned int, int = DEC); + size_t println(long, int = DEC); + size_t println(unsigned long, int = DEC); + size_t println(double, int = 2); + size_t println(const Printable&); + size_t println(void); +}; + +#endif diff --git a/sparkfun/samd/cores/LilyMini/Printable.h b/sparkfun/samd/cores/LilyMini/Printable.h new file mode 100644 index 00000000..34ad5b4d --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Printable.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef Printable_h +#define Printable_h + +#include + +class Print; + +/** The Printable class provides a way for new classes to allow themselves to be printed. + By deriving from Printable and implementing the printTo method, it will then be possible + for users to print out instances of this class by passing them into the usual + Print::print and Print::println methods. +*/ + +class Printable +{ + public: + virtual size_t printTo(Print& p) const = 0; +}; + +#endif + diff --git a/sparkfun/samd/cores/LilyMini/Reset.cpp b/sparkfun/samd/cores/LilyMini/Reset.cpp new file mode 100644 index 00000000..57b36e4c --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Reset.cpp @@ -0,0 +1,74 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include +#include "Reset.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NVM_MEMORY ((volatile uint16_t *)0x000000) +// For 4K bootloader: +#define APP_START 0x00001004 + +static inline bool nvmReady(void) { + return NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY; +} + +__attribute__ ((long_call, section (".ramfunc"))) +static void banzai() { + // Disable all interrupts + __disable_irq(); + + // Erase application + while (!nvmReady()) + ; + NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; + NVMCTRL->ADDR.reg = (uintptr_t)&NVM_MEMORY[APP_START / 4]; + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_ER | NVMCTRL_CTRLA_CMDEX_KEY; + while (!nvmReady()) + ; + + // Reset the device + NVIC_SystemReset() ; + + while (true); +} + +static int ticks = -1; + +void initiateReset(int _ticks) { + ticks = _ticks; +} + +void cancelReset() { + ticks = -1; +} + +void tickReset() { + if (ticks == -1) + return; + ticks--; + if (ticks == 0) + banzai(); +} + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/Reset.h b/sparkfun/samd/cores/LilyMini/Reset.h new file mode 100644 index 00000000..1ddefbf0 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Reset.h @@ -0,0 +1,31 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void initiateReset(int ms); +void tickReset(); +void cancelReset(); + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/RingBuffer.cpp b/sparkfun/samd/cores/LilyMini/RingBuffer.cpp new file mode 100644 index 00000000..d877a6e3 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/RingBuffer.cpp @@ -0,0 +1,86 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#include "RingBuffer.h" +#include + +RingBuffer::RingBuffer( void ) +{ + memset( _aucBuffer, 0, SERIAL_BUFFER_SIZE ) ; + clear(); +} + +void RingBuffer::store_char( uint8_t c ) +{ + int i = nextIndex(_iHead); + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if ( i != _iTail ) + { + _aucBuffer[_iHead] = c ; + _iHead = i ; + } +} + +void RingBuffer::clear() +{ + _iHead = 0; + _iTail = 0; +} + +int RingBuffer::read_char() +{ + if(_iTail == _iHead) + return -1; + + uint8_t value = _aucBuffer[_iTail]; + _iTail = nextIndex(_iTail); + + return value; +} + +int RingBuffer::available() +{ + int delta = _iHead - _iTail; + + if(delta < 0) + return SERIAL_BUFFER_SIZE + delta; + else + return delta; +} + +int RingBuffer::peek() +{ + if(_iTail == _iHead) + return -1; + + return _aucBuffer[_iTail]; +} + +int RingBuffer::nextIndex(int index) +{ + return (uint32_t)(index + 1) % SERIAL_BUFFER_SIZE; +} + +bool RingBuffer::isFull() +{ + return (nextIndex(_iHead) == _iTail); +} diff --git a/sparkfun/samd/cores/LilyMini/RingBuffer.h b/sparkfun/samd/cores/LilyMini/RingBuffer.h new file mode 100644 index 00000000..e212e6b6 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/RingBuffer.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef _RING_BUFFER_ +#define _RING_BUFFER_ + +#include + +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which head is the index of the location +// to which to write the next incoming character and tail is the index of the +// location from which to read. +#define SERIAL_BUFFER_SIZE 64 + +class RingBuffer +{ + public: + uint8_t _aucBuffer[SERIAL_BUFFER_SIZE] ; + int _iHead ; + int _iTail ; + + public: + RingBuffer( void ) ; + void store_char( uint8_t c ) ; + void clear(); + int read_char(); + int available(); + int peek(); + bool isFull(); + + private: + int nextIndex(int index); +} ; + +#endif /* _RING_BUFFER_ */ diff --git a/sparkfun/samd/cores/LilyMini/SERCOM.cpp b/sparkfun/samd/cores/LilyMini/SERCOM.cpp new file mode 100644 index 00000000..cc10cb47 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/SERCOM.cpp @@ -0,0 +1,688 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#include "SERCOM.h" +#include "variant.h" + +SERCOM::SERCOM(Sercom* s) +{ + sercom = s; +} + +/* ========================= + * ===== Sercom UART + * ========================= +*/ +void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) +{ + initClockNVIC(); + resetUART(); + + //Setting the CTRLA register + sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | + SERCOM_USART_CTRLA_SAMPR(sampleRate); + + //Setting the Interrupt register + sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete + SERCOM_USART_INTENSET_ERROR; //All others errors + + if ( mode == UART_INT_CLOCK ) + { + uint16_t sampleRateValue; + + if (sampleRate == SAMPLE_RATE_x16) { + sampleRateValue = 16; + } else { + sampleRateValue = 8; + } + + // Asynchronous fractional mode (Table 24-2 in datasheet) + // BAUD = fref / (sampleRateValue * fbaud) + // (multiply by 8, to calculate fractional piece) + uint32_t baudTimes8 = (SystemCoreClock * 8) / (sampleRateValue * baudrate); + + sercom->USART.BAUD.FRAC.FP = (baudTimes8 % 8); + sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8); + } +} +void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits) +{ + //Setting the CTRLA register + sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) | + dataOrder << SERCOM_USART_CTRLA_DORD_Pos; + + //Setting the CTRLB register + sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_CHSIZE(charSize) | + nbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos | + (parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value +} + +void SERCOM::initPads(SercomUartTXPad txPad, SercomRXPad rxPad) +{ + //Setting the CTRLA register + sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_TXPO(txPad) | + SERCOM_USART_CTRLA_RXPO(rxPad); + + // Enable Transceiver and Receiver + sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ; +} + +void SERCOM::resetUART() +{ + // Start the Software Reset + sercom->USART.CTRLA.bit.SWRST = 1 ; + + while ( sercom->USART.CTRLA.bit.SWRST || sercom->USART.SYNCBUSY.bit.SWRST ) + { + // Wait for both bits Software Reset from CTRLA and SYNCBUSY coming back to 0 + } +} + +void SERCOM::enableUART() +{ + //Setting the enable bit to 1 + sercom->USART.CTRLA.bit.ENABLE = 0x1u; + + //Wait for then enable bit from SYNCBUSY is equal to 0; + while(sercom->USART.SYNCBUSY.bit.ENABLE); +} + +void SERCOM::flushUART() +{ + // Skip checking transmission completion if data register is empty + if(isDataRegisterEmptyUART()) + return; + + // Wait for transmission to complete + while(!sercom->USART.INTFLAG.bit.TXC); +} + +void SERCOM::clearStatusUART() +{ + //Reset (with 0) the STATUS register + sercom->USART.STATUS.reg = SERCOM_USART_STATUS_RESETVALUE; +} + +bool SERCOM::availableDataUART() +{ + //RXC : Receive Complete + return sercom->USART.INTFLAG.bit.RXC; +} + +bool SERCOM::isUARTError() +{ + return sercom->USART.INTFLAG.bit.ERROR; +} + +void SERCOM::acknowledgeUARTError() +{ + sercom->USART.INTFLAG.bit.ERROR = 1; +} + +bool SERCOM::isBufferOverflowErrorUART() +{ + //BUFOVF : Buffer Overflow + return sercom->USART.STATUS.bit.BUFOVF; +} + +bool SERCOM::isFrameErrorUART() +{ + //FERR : Frame Error + return sercom->USART.STATUS.bit.FERR; +} + +bool SERCOM::isParityErrorUART() +{ + //PERR : Parity Error + return sercom->USART.STATUS.bit.PERR; +} + +bool SERCOM::isDataRegisterEmptyUART() +{ + //DRE : Data Register Empty + return sercom->USART.INTFLAG.bit.DRE; +} + +uint8_t SERCOM::readDataUART() +{ + return sercom->USART.DATA.bit.DATA; +} + +int SERCOM::writeDataUART(uint8_t data) +{ + // Wait for data register to be empty + while(!isDataRegisterEmptyUART()); + + //Put data into DATA register + sercom->USART.DATA.reg = (uint16_t)data; + return 1; +} + +/* ========================= + * ===== Sercom SPI + * ========================= +*/ +void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder) +{ + resetSPI(); + initClockNVIC(); + + //Setting the CTRLA register + sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE_SPI_MASTER | + SERCOM_SPI_CTRLA_DOPO(mosi) | + SERCOM_SPI_CTRLA_DIPO(miso) | + dataOrder << SERCOM_SPI_CTRLA_DORD_Pos; + + //Setting the CTRLB register + sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) | + SERCOM_SPI_CTRLB_RXEN; //Active the SPI receiver. + + +} + +void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate) +{ + //Extract data from clockMode + int cpha, cpol; + + if((clockMode & (0x1ul)) == 0 ) + cpha = 0; + else + cpha = 1; + + if((clockMode & (0x2ul)) == 0) + cpol = 0; + else + cpol = 1; + + //Setting the CTRLA register + sercom->SPI.CTRLA.reg |= ( cpha << SERCOM_SPI_CTRLA_CPHA_Pos ) | + ( cpol << SERCOM_SPI_CTRLA_CPOL_Pos ); + + //Synchronous arithmetic + sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(baudrate); +} + +void SERCOM::resetSPI() +{ + //Setting the Software Reset bit to 1 + sercom->SPI.CTRLA.bit.SWRST = 1; + + //Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0 + while(sercom->SPI.CTRLA.bit.SWRST || sercom->SPI.SYNCBUSY.bit.SWRST); +} + +void SERCOM::enableSPI() +{ + //Setting the enable bit to 1 + sercom->SPI.CTRLA.bit.ENABLE = 1; + + while(sercom->SPI.SYNCBUSY.bit.ENABLE) + { + //Waiting then enable bit from SYNCBUSY is equal to 0; + } +} + +void SERCOM::disableSPI() +{ + //Setting the enable bit to 0 + sercom->SPI.CTRLA.bit.ENABLE = 0; + + while(sercom->SPI.SYNCBUSY.bit.ENABLE) + { + //Waiting then enable bit from SYNCBUSY is equal to 0; + } +} + +void SERCOM::setDataOrderSPI(SercomDataOrder dataOrder) +{ + //Register enable-protected + disableSPI(); + + sercom->SPI.CTRLA.bit.DORD = dataOrder; + + enableSPI(); +} + +SercomDataOrder SERCOM::getDataOrderSPI() +{ + return (sercom->SPI.CTRLA.bit.DORD ? LSB_FIRST : MSB_FIRST); +} + +void SERCOM::setBaudrateSPI(uint8_t divider) +{ + //Can't divide by 0 + if(divider == 0) + return; + + //Register enable-protected + disableSPI(); + + sercom->SPI.BAUD.reg = calculateBaudrateSynchronous( SERCOM_FREQ_REF / divider ); + + enableSPI(); +} + +void SERCOM::setClockModeSPI(SercomSpiClockMode clockMode) +{ + int cpha, cpol; + if((clockMode & (0x1ul)) == 0) + cpha = 0; + else + cpha = 1; + + if((clockMode & (0x2ul)) == 0) + cpol = 0; + else + cpol = 1; + + //Register enable-protected + disableSPI(); + + sercom->SPI.CTRLA.bit.CPOL = cpol; + sercom->SPI.CTRLA.bit.CPHA = cpha; + + enableSPI(); +} + +uint8_t SERCOM::transferDataSPI(uint8_t data) +{ + sercom->SPI.DATA.bit.DATA = data; // Writing data into Data register + + while( sercom->SPI.INTFLAG.bit.RXC == 0 ) + { + // Waiting Complete Reception + } + + return sercom->SPI.DATA.bit.DATA; // Reading data +} + +bool SERCOM::isBufferOverflowErrorSPI() +{ + return sercom->SPI.STATUS.bit.BUFOVF; +} + +bool SERCOM::isDataRegisterEmptySPI() +{ + //DRE : Data Register Empty + return sercom->SPI.INTFLAG.bit.DRE; +} + +//bool SERCOM::isTransmitCompleteSPI() +//{ +// //TXC : Transmit complete +// return sercom->SPI.INTFLAG.bit.TXC; +//} +// +//bool SERCOM::isReceiveCompleteSPI() +//{ +// //RXC : Receive complete +// return sercom->SPI.INTFLAG.bit.RXC; +//} + +uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate) +{ + return SERCOM_FREQ_REF / (2 * baudrate) - 1; +} + + +/* ========================= + * ===== Sercom WIRE + * ========================= + */ +void SERCOM::resetWIRE() +{ + //I2CM OR I2CS, no matter SWRST is the same bit. + + //Setting the Software bit to 1 + sercom->I2CM.CTRLA.bit.SWRST = 1; + + //Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0 + while(sercom->I2CM.CTRLA.bit.SWRST || sercom->I2CM.SYNCBUSY.bit.SWRST); +} + +void SERCOM::enableWIRE() +{ + // I2C Master and Slave modes share the ENABLE bit function. + + // Enable the I²C master mode + sercom->I2CM.CTRLA.bit.ENABLE = 1 ; + + while ( sercom->I2CM.SYNCBUSY.bit.ENABLE != 0 ) + { + // Waiting the enable bit from SYNCBUSY is equal to 0; + } + + // Setting bus idle mode + sercom->I2CM.STATUS.bit.BUSSTATE = 1 ; + + while ( sercom->I2CM.SYNCBUSY.bit.SYSOP != 0 ) + { + // Wait the SYSOP bit from SYNCBUSY coming back to 0 + } +} + +void SERCOM::disableWIRE() +{ + // I2C Master and Slave modes share the ENABLE bit function. + + // Enable the I²C master mode + sercom->I2CM.CTRLA.bit.ENABLE = 0 ; + + while ( sercom->I2CM.SYNCBUSY.bit.ENABLE != 0 ) + { + // Waiting the enable bit from SYNCBUSY is equal to 0; + } +} + +void SERCOM::initSlaveWIRE( uint8_t ucAddress ) +{ + // Initialize the peripheral clock and interruption + initClockNVIC() ; + resetWIRE() ; + + // Set slave mode + sercom->I2CS.CTRLA.bit.MODE = I2C_SLAVE_OPERATION ; + + sercom->I2CS.ADDR.reg = SERCOM_I2CS_ADDR_ADDR( ucAddress & 0x7Ful ) | // 0x7F, select only 7 bits + SERCOM_I2CS_ADDR_ADDRMASK( 0x00ul ) ; // 0x00, only match exact address + + // Set the interrupt register + sercom->I2CS.INTENSET.reg = SERCOM_I2CS_INTENSET_PREC | // Stop + SERCOM_I2CS_INTENSET_AMATCH | // Address Match + SERCOM_I2CS_INTENSET_DRDY ; // Data Ready + + while ( sercom->I2CM.SYNCBUSY.bit.SYSOP != 0 ) + { + // Wait the SYSOP bit from SYNCBUSY to come back to 0 + } +} + +void SERCOM::initMasterWIRE( uint32_t baudrate ) +{ + // Initialize the peripheral clock and interruption + initClockNVIC() ; + + resetWIRE() ; + + // Set master mode and enable SCL Clock Stretch mode (stretch after ACK bit) + sercom->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )/* | + SERCOM_I2CM_CTRLA_SCLSM*/ ; + + // Enable Smart mode and Quick Command + //sercom->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN /*| SERCOM_I2CM_CTRLB_QCEN*/ ; + + + // Enable all interrupts +// sercom->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR ; + + // Synchronous arithmetic baudrate + sercom->I2CM.BAUD.bit.BAUD = SystemCoreClock / ( 2 * baudrate) - 1 ; +} + +void SERCOM::prepareNackBitWIRE( void ) +{ + if(isMasterWIRE()) { + // Send a NACK + sercom->I2CM.CTRLB.bit.ACKACT = 1; + } else { + sercom->I2CS.CTRLB.bit.ACKACT = 1; + } +} + +void SERCOM::prepareAckBitWIRE( void ) +{ + if(isMasterWIRE()) { + // Send an ACK + sercom->I2CM.CTRLB.bit.ACKACT = 0; + } else { + sercom->I2CS.CTRLB.bit.ACKACT = 0; + } +} + +void SERCOM::prepareCommandBitsWire(uint8_t cmd) +{ + if(isMasterWIRE()) { + sercom->I2CM.CTRLB.bit.CMD = cmd; + + while(sercom->I2CM.SYNCBUSY.bit.SYSOP) + { + // Waiting for synchronization + } + } else { + sercom->I2CS.CTRLB.bit.CMD = cmd; + } +} + +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() ); + + // Send start and address + sercom->I2CM.ADDR.bit.ADDR = address; + + // Address Transmitted + if ( flag == WIRE_WRITE_FLAG ) // Write mode + { + while( !sercom->I2CM.INTFLAG.bit.MB ) + { + // Wait transmission complete + } + } + else // Read mode + { + while( !sercom->I2CM.INTFLAG.bit.SB ) + { + // If the slave NACKS the address, the MB bit will be set. + // In that case, send a stop condition and return false. + if (sercom->I2CM.INTFLAG.bit.MB) { + 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) + { + return false; + } + else + { + return true; + } +} + +bool SERCOM::sendDataMasterWIRE(uint8_t data) +{ + //Send data + sercom->I2CM.DATA.bit.DATA = 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) { + return false; + } + } + + //Problems on line? nack received? + if(sercom->I2CM.STATUS.bit.RXNACK) + return false; + else + return true; +} + +bool SERCOM::sendDataSlaveWIRE(uint8_t data) +{ + //Send data + sercom->I2CS.DATA.bit.DATA = data; + + //Problems on line? nack received? + if(!sercom->I2CS.INTFLAG.bit.DRDY || sercom->I2CS.STATUS.bit.RXNACK) + return false; + else + return true; +} + +bool SERCOM::isMasterWIRE( void ) +{ + return sercom->I2CS.CTRLA.bit.MODE == I2C_MASTER_OPERATION; +} + +bool SERCOM::isSlaveWIRE( void ) +{ + return sercom->I2CS.CTRLA.bit.MODE == I2C_SLAVE_OPERATION; +} + +bool SERCOM::isBusIdleWIRE( void ) +{ + return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_IDLE_STATE; +} + +bool SERCOM::isBusOwnerWIRE( void ) +{ + return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE; +} + +bool SERCOM::isDataReadyWIRE( void ) +{ + return sercom->I2CS.INTFLAG.bit.DRDY; +} + +bool SERCOM::isStopDetectedWIRE( void ) +{ + return sercom->I2CS.INTFLAG.bit.PREC; +} + +bool SERCOM::isRestartDetectedWIRE( void ) +{ + return sercom->I2CS.STATUS.bit.SR; +} + +bool SERCOM::isAddressMatch( void ) +{ + return sercom->I2CS.INTFLAG.bit.AMATCH; +} + +bool SERCOM::isMasterReadOperationWIRE( void ) +{ + return sercom->I2CS.STATUS.bit.DIR; +} + +bool SERCOM::isRXNackReceivedWIRE( void ) +{ + return sercom->I2CM.STATUS.bit.RXNACK; +} + +int SERCOM::availableWIRE( void ) +{ + if(isMasterWIRE()) + return sercom->I2CM.INTFLAG.bit.SB; + else + return sercom->I2CS.INTFLAG.bit.DRDY; +} + +uint8_t SERCOM::readDataWIRE( void ) +{ + if(isMasterWIRE()) + { + while( sercom->I2CM.INTFLAG.bit.SB == 0 ) + { + // Waiting complete receive + } + + return sercom->I2CM.DATA.bit.DATA ; + } + else + { + return sercom->I2CS.DATA.reg ; + } +} + + +void SERCOM::initClockNVIC( void ) +{ + uint8_t clockId = 0; + IRQn_Type IdNvic=PendSV_IRQn ; // Dummy init to intercept potential error later + + if(sercom == SERCOM0) + { + clockId = GCM_SERCOM0_CORE; + IdNvic = SERCOM0_IRQn; + } + else if(sercom == SERCOM1) + { + clockId = GCM_SERCOM1_CORE; + IdNvic = SERCOM1_IRQn; + } + else if(sercom == SERCOM2) + { + clockId = GCM_SERCOM2_CORE; + IdNvic = SERCOM2_IRQn; + } + +/* + else if(sercom == SERCOM3) + { + clockId = GCM_SERCOM3_CORE; + IdNvic = SERCOM3_IRQn; + } + else if(sercom == SERCOM4) + { + clockId = GCM_SERCOM4_CORE; + IdNvic = SERCOM4_IRQn; + } + else if(sercom == SERCOM5) + { + clockId = GCM_SERCOM5_CORE; + IdNvic = SERCOM5_IRQn; + } +*/ + + if ( IdNvic == PendSV_IRQn ) + { + // We got a problem here + return ; + } + + // Setting NVIC + NVIC_EnableIRQ(IdNvic); + NVIC_SetPriority (IdNvic, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority */ + + //Setting clock + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx) + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_CLKEN ; + + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } +} diff --git a/sparkfun/samd/cores/LilyMini/SERCOM.h b/sparkfun/samd/cores/LilyMini/SERCOM.h new file mode 100644 index 00000000..79249011 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/SERCOM.h @@ -0,0 +1,217 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef _SERCOM_CLASS_ +#define _SERCOM_CLASS_ + +#include "sam.h" + +#define SERCOM_FREQ_REF 48000000 + +typedef enum +{ + UART_EXT_CLOCK = 0, + UART_INT_CLOCK = 0x1u +} SercomUartMode; + +typedef enum +{ + SPI_SLAVE_OPERATION = 0x2u, + SPI_MASTER_OPERATION = 0x3u +} SercomSpiMode; + +typedef enum +{ + I2C_SLAVE_OPERATION = 0x4u, + I2C_MASTER_OPERATION = 0x5u +} SercomI2CMode; + +typedef enum +{ + SERCOM_EVEN_PARITY = 0, + SERCOM_ODD_PARITY, + SERCOM_NO_PARITY +} SercomParityMode; + +typedef enum +{ + SERCOM_STOP_BIT_1 = 0, + SERCOM_STOP_BITS_2 +} SercomNumberStopBit; + +typedef enum +{ + MSB_FIRST = 0, + LSB_FIRST +} SercomDataOrder; + +typedef enum +{ + UART_CHAR_SIZE_8_BITS = 0, + UART_CHAR_SIZE_9_BITS, + UART_CHAR_SIZE_5_BITS = 0x5u, + UART_CHAR_SIZE_6_BITS, + UART_CHAR_SIZE_7_BITS +} SercomUartCharSize; + +typedef enum +{ + SERCOM_RX_PAD_0 = 0, + SERCOM_RX_PAD_1, + SERCOM_RX_PAD_2, + SERCOM_RX_PAD_3 +} SercomRXPad; + +typedef enum +{ + UART_TX_PAD_0 = 0x0ul, // Only for UART + UART_TX_PAD_2 = 0x1ul, // Only for UART + UART_TX_RTS_CTS_PAD_0_2_3 = 0x2ul, // Only for UART with TX on PAD0, RTS on PAD2 and CTS on PAD3 +} SercomUartTXPad; + +typedef enum +{ + SAMPLE_RATE_x16 = 0x1, //Fractional + SAMPLE_RATE_x8 = 0x3, //Fractional +} SercomUartSampleRate; + +typedef enum +{ + SERCOM_SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0 + SERCOM_SPI_MODE_1, // CPOL : 0 | CPHA : 1 + SERCOM_SPI_MODE_2, // CPOL : 1 | CPHA : 0 + SERCOM_SPI_MODE_3 // CPOL : 1 | CPHA : 1 +} SercomSpiClockMode; + +typedef enum +{ + SPI_PAD_0_SCK_1 = 0, + SPI_PAD_2_SCK_3, + SPI_PAD_3_SCK_1, + SPI_PAD_0_SCK_3 +} SercomSpiTXPad; + +typedef enum +{ + SPI_CHAR_SIZE_8_BITS = 0x0ul, + SPI_CHAR_SIZE_9_BITS +} SercomSpiCharSize; + +typedef enum +{ + WIRE_UNKNOWN_STATE = 0x0ul, + WIRE_IDLE_STATE, + WIRE_OWNER_STATE, + WIRE_BUSY_STATE +} SercomWireBusState; + +typedef enum +{ + WIRE_WRITE_FLAG = 0x0ul, + WIRE_READ_FLAG +} SercomWireReadWriteFlag; + +typedef enum +{ + WIRE_MASTER_ACT_NO_ACTION = 0, + WIRE_MASTER_ACT_REPEAT_START, + WIRE_MASTER_ACT_READ, + WIRE_MASTER_ACT_STOP +} SercomMasterCommandWire; + +typedef enum +{ + WIRE_MASTER_ACK_ACTION = 0, + WIRE_MASTER_NACK_ACTION +} SercomMasterAckActionWire; + +class SERCOM +{ + public: + SERCOM(Sercom* s) ; + + /* ========== UART ========== */ + void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0) ; + void initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits) ; + void initPads(SercomUartTXPad txPad, SercomRXPad rxPad) ; + + void resetUART( void ) ; + void enableUART( void ) ; + void flushUART( void ) ; + void clearStatusUART( void ) ; + bool availableDataUART( void ) ; + bool isBufferOverflowErrorUART( void ) ; + bool isFrameErrorUART( void ) ; + bool isParityErrorUART( void ) ; + bool isDataRegisterEmptyUART( void ) ; + uint8_t readDataUART( void ) ; + int writeDataUART(uint8_t data) ; + bool isUARTError() ; + void acknowledgeUARTError() ; + + /* ========== SPI ========== */ + void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder) ; + void initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate) ; + + void resetSPI( void ) ; + void enableSPI( void ) ; + void disableSPI( void ) ; + void setDataOrderSPI(SercomDataOrder dataOrder) ; + SercomDataOrder getDataOrderSPI( void ) ; + void setBaudrateSPI(uint8_t divider) ; + void setClockModeSPI(SercomSpiClockMode clockMode) ; + uint8_t transferDataSPI(uint8_t data) ; + bool isBufferOverflowErrorSPI( void ) ; + bool isDataRegisterEmptySPI( void ) ; + bool isTransmitCompleteSPI( void ) ; + bool isReceiveCompleteSPI( void ) ; + + /* ========== WIRE ========== */ + void initSlaveWIRE(uint8_t address) ; + void initMasterWIRE(uint32_t baudrate) ; + + void resetWIRE( void ) ; + void enableWIRE( void ) ; + void disableWIRE( void ); + void prepareNackBitWIRE( void ) ; + void prepareAckBitWIRE( void ) ; + void prepareCommandBitsWire(uint8_t cmd); + bool startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag) ; + bool sendDataMasterWIRE(uint8_t data) ; + bool sendDataSlaveWIRE(uint8_t data) ; + bool isMasterWIRE( void ) ; + bool isSlaveWIRE( void ) ; + bool isBusIdleWIRE( void ) ; + bool isBusOwnerWIRE( void ) ; + bool isDataReadyWIRE( void ) ; + bool isStopDetectedWIRE( void ) ; + bool isRestartDetectedWIRE( void ) ; + bool isAddressMatch( void ) ; + bool isMasterReadOperationWIRE( void ) ; + bool isRXNackReceivedWIRE( void ) ; + int availableWIRE( void ) ; + uint8_t readDataWIRE( void ) ; + + private: + Sercom* sercom; + uint8_t calculateBaudrateSynchronous(uint32_t baudrate) ; + uint32_t division(uint32_t dividend, uint32_t divisor) ; + void initClockNVIC( void ) ; +}; + +#endif diff --git a/sparkfun/samd/cores/LilyMini/Server.h b/sparkfun/samd/cores/LilyMini/Server.h new file mode 100644 index 00000000..69e3e39f --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Server.h @@ -0,0 +1,30 @@ +/* + Server.h - Base class that provides Server + Copyright (c) 2011 Adrian McEwen. 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 +*/ + +#ifndef server_h +#define server_h + +#include "Print.h" + +class Server : public Print { +public: + virtual void begin() =0; +}; + +#endif diff --git a/sparkfun/samd/cores/LilyMini/Stream.cpp b/sparkfun/samd/cores/LilyMini/Stream.cpp new file mode 100644 index 00000000..f6654653 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Stream.cpp @@ -0,0 +1,319 @@ +/* + Stream.cpp - adds parsing methods to Stream class + Copyright (c) 2008 David A. Mellis. 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 + + Created July 2011 + parsing functions based on TextFinder library by Michael Margolis + + findMulti/findUntil routines written by Jim Leonard/Xuth + */ + +#include "Arduino.h" +#include "Stream.h" + +#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait + +// private method to read stream with timeout +int Stream::timedRead() +{ + int c; + _startMillis = millis(); + do { + c = read(); + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout +} + +// private method to peek stream with timeout +int Stream::timedPeek() +{ + int c; + _startMillis = millis(); + do { + c = peek(); + if (c >= 0) return c; + } while(millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout +} + +// returns peek of the next digit in the stream or -1 if timeout +// discards non-numeric characters +int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) +{ + int c; + while (1) { + c = timedPeek(); + + if( c < 0 || + c == '-' || + (c >= '0' && c <= '9') || + (detectDecimal && c == '.')) return c; + + switch( lookahead ){ + case SKIP_NONE: return -1; // Fail code. + case SKIP_WHITESPACE: + switch( c ){ + case ' ': + case '\t': + case '\r': + case '\n': break; + default: return -1; // Fail code. + } + case SKIP_ALL: + break; + } + read(); // discard non-numeric + } +} + +// Public Methods +////////////////////////////////////////////////////////////// + +void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait +{ + _timeout = timeout; +} + + // find returns true if the target string is found +bool Stream::find(char *target) +{ + return findUntil(target, strlen(target), NULL, 0); +} + +// reads data from the stream until the target string of given length is found +// returns true if target string is found, false if timed out +bool Stream::find(char *target, size_t length) +{ + return findUntil(target, length, NULL, 0); +} + +// as find but search ends if the terminator string is found +bool Stream::findUntil(char *target, char *terminator) +{ + return findUntil(target, strlen(target), terminator, strlen(terminator)); +} + +// reads data from the stream until the target string of the given length is found +// search terminated if the terminator string is found +// returns true if target string is found, false if terminated or timed out +bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) +{ + if (terminator == NULL) { + MultiTarget t[1] = {{target, targetLen, 0}}; + return findMulti(t, 1) == 0 ? true : false; + } else { + MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; + return findMulti(t, 2) == 0 ? true : false; + } +} + +// returns the first valid (long) integer value from the current position. +// lookahead determines how parseInt looks ahead in the stream. +// See LookaheadMode enumeration at the top of the file. +// Lookahead is terminated by the first character that is not a valid part of an integer. +// Once parsing commences, 'ignore' will be skipped in the stream. +long Stream::parseInt(LookaheadMode lookahead, char ignore) +{ + bool isNegative = false; + long value = 0; + int c; + + c = peekNextDigit(lookahead, false); + // ignore non numeric leading characters + if(c < 0) + return 0; // zero returned if timeout + + do{ + if(c == ignore) + ; // ignore this character + else if(c == '-') + isNegative = true; + else if(c >= '0' && c <= '9') // is c a digit? + value = value * 10 + c - '0'; + read(); // consume the character we got with peek + c = timedPeek(); + } + while( (c >= '0' && c <= '9') || c == ignore ); + + if(isNegative) + value = -value; + return value; +} + +// as parseInt but returns a floating point value +float Stream::parseFloat(LookaheadMode lookahead, char ignore) +{ + bool isNegative = false; + bool isFraction = false; + long value = 0; + int c; + float fraction = 1.0; + + c = peekNextDigit(lookahead, true); + // ignore non numeric leading characters + if(c < 0) + return 0; // zero returned if timeout + + do{ + if(c == ignore) + ; // ignore + else if(c == '-') + isNegative = true; + else if (c == '.') + isFraction = true; + else if(c >= '0' && c <= '9') { // is c a digit? + value = value * 10 + c - '0'; + if(isFraction) + fraction *= 0.1; + } + read(); // consume the character we got with peek + c = timedPeek(); + } + while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || c == ignore ); + + if(isNegative) + value = -value; + if(isFraction) + return value * fraction; + else + return value; +} + +// read characters from stream into buffer +// terminates if length characters have been read, or timeout (see setTimeout) +// returns the number of characters placed in the buffer +// the buffer is NOT null terminated. +// +size_t Stream::readBytes(char *buffer, size_t length) +{ + size_t count = 0; + while (count < length) { + int c = timedRead(); + if (c < 0) break; + *buffer++ = (char)c; + count++; + } + return count; +} + + +// as readBytes with terminator character +// terminates if length characters have been read, timeout, or if the terminator character detected +// returns the number of characters placed in the buffer (0 means no valid data found) + +size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) +{ + if (length < 1) return 0; + size_t index = 0; + while (index < length) { + int c = timedRead(); + if (c < 0 || c == terminator) break; + *buffer++ = (char)c; + index++; + } + return index; // return number of characters, not including null terminator +} + +String Stream::readString() +{ + String ret; + int c = timedRead(); + while (c >= 0) + { + ret += (char)c; + c = timedRead(); + } + return ret; +} + +String Stream::readStringUntil(char terminator) +{ + String ret; + int c = timedRead(); + while (c >= 0 && c != terminator) + { + ret += (char)c; + c = timedRead(); + } + return ret; +} + +int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { + // any zero length target string automatically matches and would make + // a mess of the rest of the algorithm. + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + if (t->len <= 0) + return t - targets; + } + + while (1) { + int c = timedRead(); + if (c < 0) + return -1; + + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + // the simple case is if we match, deal with that first. + if (c == t->str[t->index]) { + if (++t->index == t->len) + return t - targets; + else + continue; + } + + // if not we need to walk back and see if we could have matched further + // down the stream (ie '1112' doesn't match the first position in '11112' + // but it will match the second position so we can't just reset the current + // index to 0 when we find a mismatch. + if (t->index == 0) + continue; + + int origIndex = t->index; + do { + --t->index; + // first check if current char works against the new current index + if (c != t->str[t->index]) + continue; + + // if it's the only char then we're good, nothing more to check + if (t->index == 0) { + t->index++; + break; + } + + // otherwise we need to check the rest of the found string + int diff = origIndex - t->index; + size_t i; + for (i = 0; i < t->index; ++i) { + if (t->str[i] != t->str[i + diff]) + break; + } + + // if we successfully got through the previous loop then our current + // index is good. + if (i == t->index) { + t->index++; + break; + } + + // otherwise we just try the next index + } while (t->index); + } + } + // unreachable + return -1; +} diff --git a/sparkfun/samd/cores/LilyMini/Stream.h b/sparkfun/samd/cores/LilyMini/Stream.h new file mode 100644 index 00000000..dd54e8c6 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Stream.h @@ -0,0 +1,130 @@ +/* + Stream.h - base class for character-based streams. + Copyright (c) 2010 David A. Mellis. 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 + + parsing functions based on TextFinder library by Michael Margolis +*/ + +#ifndef Stream_h +#define Stream_h + +#include +#include "Print.h" + +// compatability macros for testing +/* +#define getInt() parseInt() +#define getInt(ignore) parseInt(ignore) +#define getFloat() parseFloat() +#define getFloat(ignore) parseFloat(ignore) +#define getString( pre_string, post_string, buffer, length) +readBytesBetween( pre_string, terminator, buffer, length) +*/ + +// This enumeration provides the lookahead options for parseInt(), parseFloat() +// The rules set out here are used until either the first valid character is found +// or a time out occurs due to lack of input. +enum LookaheadMode{ + SKIP_ALL, // All invalid characters are ignored. + SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. + SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. +}; + +#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field + +class Stream : public Print +{ + protected: + unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout + + public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; + virtual void flush() = 0; + + Stream() {_timeout=1000;} + +// parsing methods + + void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second + unsigned long getTimeout(void) { return _timeout; } + + bool find(char *target); // reads data from the stream until the target string is found + bool find(uint8_t *target) { return find ((char *)target); } + // returns true if target string is found, false if timed out (see setTimeout) + + bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } + // returns true if target string is found, false if timed out + + bool find(char target) { return find (&target, 1); } + + bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found + bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } + + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } + + long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); + // returns the first valid (long) integer value from the current position. + // lookahead determines how parseInt looks ahead in the stream. + // See LookaheadMode enumeration at the top of the file. + // Lookahead is terminated by the first character that is not a valid part of an integer. + // Once parsing commences, 'ignore' will be skipped in the stream. + + float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); + // float version of parseInt + + size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer + size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } + // terminates if length characters have been read or timeout (see setTimeout) + // returns the number of characters placed in the buffer (0 means no valid data found) + + size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character + size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } + // terminates if length characters have been read, timeout, or if the terminator character detected + // returns the number of characters placed in the buffer (0 means no valid data found) + + // Arduino String functions to be added here + String readString(); + String readStringUntil(char terminator); + + protected: + long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } + float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); } + // These overload exists for compatibility with any class that has derived + // Stream and used parseFloat/Int with a custom ignore character. To keep + // the public API simple, these overload remains protected. + + struct MultiTarget { + const char *str; // string you're searching for + size_t len; // length of string you're searching for + size_t index; // index used by the search routine. + }; + + // This allows you to search for an arbitrary number of strings. + // Returns index of the target that is found first or -1 if timeout occurs. + int findMulti(struct MultiTarget *targets, int tCount); +}; + +#undef NO_IGNORE_CHAR +#endif diff --git a/sparkfun/samd/cores/LilyMini/Tone.cpp b/sparkfun/samd/cores/LilyMini/Tone.cpp new file mode 100644 index 00000000..3c24855e --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Tone.cpp @@ -0,0 +1,189 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "Tone.h" +#include "variant.h" + +#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY); + +uint32_t toneMaxFrequency = F_CPU / 2; +uint32_t lastOutputPin = 0xFFFFFFFF; + +volatile uint32_t *portToggleRegister; +volatile uint32_t *portClearRegister; +volatile uint32_t portBitMask; +volatile int64_t toggleCount; +volatile bool toneIsActive = false; +volatile bool firstTimeRunning = false; + +// Use TC1 for tone on SAMD11 (unused by PWM for pins) +#define TONE_TC TC1 +#define TONE_TC_IRQn TC1_IRQn +#define TONE_TC_TOP 0xFFFF +#define TONE_TC_CHANNEL 0 + +void TC1_Handler (void) __attribute__ ((weak, alias("Tone_Handler"))); + +static inline void resetTC (Tc* TCx) +{ + // Disable TCx + TCx->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; + WAIT_TC16_REGS_SYNC(TCx) + + // Reset TCx + TCx->COUNT16.CTRLA.reg = TC_CTRLA_SWRST; + WAIT_TC16_REGS_SYNC(TCx) + while (TCx->COUNT16.CTRLA.bit.SWRST); +} + +void toneAccurateClock (uint32_t accurateSystemCoreClockFrequency) +{ + toneMaxFrequency = accurateSystemCoreClockFrequency / 2; +} + +void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration) +{ + // Configure interrupt request + NVIC_DisableIRQ(TONE_TC_IRQn); + NVIC_ClearPendingIRQ(TONE_TC_IRQn); + + if(!firstTimeRunning) + { + firstTimeRunning = true; + + NVIC_SetPriority(TONE_TC_IRQn, 0); + + // Enable GCLK for TC1 and TC2 + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC1_TC2)); +// GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)); + while (GCLK->STATUS.bit.SYNCBUSY); + } + + if (toneIsActive && (outputPin != lastOutputPin)) + noTone(lastOutputPin); + + // + // Calculate best prescaler divider and comparator value for a 16 bit TC peripheral + // + + uint32_t prescalerConfigBits; + uint32_t ccValue; + + ccValue = toneMaxFrequency / frequency - 1; + prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1; + + uint8_t i = 0; + + while(ccValue > TONE_TC_TOP) + { + ccValue = toneMaxFrequency / frequency / (2< 0 ? frequency * duration * 2 / 1000UL : -1); + + resetTC(TONE_TC); + + uint16_t tmpReg = 0; + tmpReg |= TC_CTRLA_MODE_COUNT16; // Set Timer counter Mode to 16 bits + tmpReg |= TC_CTRLA_WAVEGEN_MFRQ; // Set TONE_TC mode as match frequency + tmpReg |= prescalerConfigBits; + TONE_TC->COUNT16.CTRLA.reg |= tmpReg; + WAIT_TC16_REGS_SYNC(TONE_TC) + + TONE_TC->COUNT16.CC[TONE_TC_CHANNEL].reg = (uint16_t) ccValue; + WAIT_TC16_REGS_SYNC(TONE_TC) + + portToggleRegister = &(PORT->Group[g_APinDescription[outputPin].ulPort].OUTTGL.reg); + portClearRegister = &(PORT->Group[g_APinDescription[outputPin].ulPort].OUTCLR.reg); + portBitMask = (1ul << g_APinDescription[outputPin].ulPin); + + // Enable the TONE_TC interrupt request + TONE_TC->COUNT16.INTENSET.bit.MC0 = 1; + + if (outputPin != lastOutputPin) + { + lastOutputPin = outputPin; + digitalWrite(outputPin, LOW); + pinMode(outputPin, OUTPUT); + toneIsActive = true; + } + + // Enable TONE_TC + TONE_TC->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; + WAIT_TC16_REGS_SYNC(TONE_TC) + + NVIC_EnableIRQ(TONE_TC_IRQn); +} + +void noTone (uint32_t outputPin) +{ + resetTC(TONE_TC); + digitalWrite(outputPin, LOW); + toneIsActive = false; +} + +#ifdef __cplusplus +extern "C" { +#endif + +void Tone_Handler (void) +{ + if (toggleCount != 0) + { + // Toggle the ouput pin + *portToggleRegister = portBitMask; + + if (toggleCount > 0) + --toggleCount; + + // Clear the interrupt + TONE_TC->COUNT16.INTFLAG.bit.MC0 = 1; + } + else + { + resetTC(TONE_TC); + *portClearRegister = portBitMask; + toneIsActive = false; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/Tone.h b/sparkfun/samd/cores/LilyMini/Tone.h new file mode 100644 index 00000000..cf270516 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Tone.h @@ -0,0 +1,28 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#ifdef __cplusplus + +#include "Arduino.h" + +void tone(uint32_t _pin, uint32_t frequency, uint32_t duration = 0); +void noTone(uint32_t _pin); + +#endif diff --git a/sparkfun/samd/cores/LilyMini/USB/CDC.cpp b/sparkfun/samd/cores/LilyMini/USB/CDC.cpp new file mode 100644 index 00000000..3c795f18 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/CDC.cpp @@ -0,0 +1,292 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include +#include // Needed for auto-reset with 1200bps port touch + +#include +#include +#include + +#ifdef CDC_ENABLED + +#define CDC_SERIAL_BUFFER_SIZE 256 + +/* For information purpose only since RTS is not always handled by the terminal application */ +#define CDC_LINESTATE_DTR 0x01 // Data Terminal Ready +#define CDC_LINESTATE_RTS 0x02 // Ready to Send + +#define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR) + +typedef struct { + uint32_t dwDTERate; + uint8_t bCharFormat; + uint8_t bParityType; + uint8_t bDataBits; + uint8_t lineState; +} LineInfo; + +_Pragma("pack(1)") +static volatile LineInfo _usbLineInfo = { + 115200, // dWDTERate + 0x00, // bCharFormat + 0x00, // bParityType + 0x08, // bDataBits + 0x00 // lineState +}; + +static volatile int32_t breakValue = -1; + +static CDCDescriptor _cdcInterface = { + D_IAD(0, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0), + + // CDC communication interface + D_INTERFACE(CDC_ACM_INTERFACE, 1, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0), + D_CDCCS(CDC_HEADER, CDC_V1_10 & 0xFF, (CDC_V1_10>>8) & 0x0FF), // Header (1.10 bcd) + + D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT, 6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported + D_CDCCS(CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 + D_CDCCS(CDC_CALL_MANAGEMENT, 1, 1), // Device handles call management (not) + D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10), + + // CDC data interface + D_INTERFACE(CDC_DATA_INTERFACE, 2, CDC_DATA_INTERFACE_CLASS, 0, 0), + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0), + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0) +}; +_Pragma("pack()") + +const void* _CDC_GetInterface(void) +{ + return &_cdcInterface; +} + +uint32_t _CDC_GetInterfaceLength(void) +{ + return sizeof(_cdcInterface); +} + +int CDC_GetInterface(uint8_t* interfaceNum) +{ + interfaceNum[0] += 2; // uses 2 + return USBDevice.sendControl(&_cdcInterface,sizeof(_cdcInterface)); +} + +bool CDC_Setup(USBSetup& setup) +{ + uint8_t requestType = setup.bmRequestType; + uint8_t r = setup.bRequest; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (r == CDC_GET_LINE_CODING) + { + USBDevice.sendControl((void*)&_usbLineInfo, 7); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (r == CDC_SET_LINE_CODING) + { + USBDevice.recvControl((void*)&_usbLineInfo, 7); + } + + if (r == CDC_SET_CONTROL_LINE_STATE) + { + _usbLineInfo.lineState = setup.wValueL; + } + + if (r == CDC_SET_LINE_CODING || r == CDC_SET_CONTROL_LINE_STATE) + { + // auto-reset into the bootloader is triggered when the port, already + // open at 1200 bps, is closed. We check DTR state to determine if host + // port is open (bit 0 of lineState). + if (_usbLineInfo.dwDTERate == 1200 && (_usbLineInfo.lineState & 0x01) == 0) + { + initiateReset(250); + } + else + { + cancelReset(); + } + return false; + } + + if (CDC_SEND_BREAK == r) + { + breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; + return false; + } + } + return false; +} + +void Serial_::begin(uint32_t /* baud_count */) +{ + // uart config is ignored in USB-CDC +} + +void Serial_::begin(uint32_t /* baud_count */, uint8_t /* config */) +{ + // uart config is ignored in USB-CDC +} + +void Serial_::end(void) +{ +} + +int Serial_::available(void) +{ + return usb.available(CDC_ENDPOINT_OUT); +} + +int Serial_::availableForWrite(void) +{ + // return the number of bytes left in the current bank, + // always EP size - 1, because bank is flushed on every write + return (EPX_SIZE - 1); +} + +int _serialPeek = -1; + +int Serial_::peek(void) +{ + if (_serialPeek != -1) + return _serialPeek; + _serialPeek = read(); + return _serialPeek; +} + +int Serial_::read(void) +{ + if (_serialPeek != -1) { + int res = _serialPeek; + _serialPeek = -1; + return res; + } + return usb.recv(CDC_ENDPOINT_OUT); +} + +size_t Serial_::readBytes(char *buffer, size_t length) +{ + size_t count = 0; + _startMillis = millis(); + while (count < length) + { + uint32_t n = usb.recv(CDC_ENDPOINT_OUT, buffer+count, length-count); + if (n == 0 && (millis() - _startMillis) >= _timeout) + break; + count += n; + } + return count; +} + +void Serial_::flush(void) +{ + usb.flush(CDC_ENDPOINT_IN); +} + +size_t Serial_::write(const uint8_t *buffer, size_t size) +{ + uint32_t r = usb.send(CDC_ENDPOINT_IN, buffer, size); + + if (r > 0) { + return r; + } else { + setWriteError(); + return 0; + } +} + +size_t Serial_::write(uint8_t c) { + return write(&c, 1); +} + +// This operator is a convenient way for a sketch to check whether the +// port has actually been configured and opened by the host (as opposed +// to just being connected to the host). It can be used, for example, in +// setup() before printing to ensure that an application on the host is +// actually ready to receive and display the data. +// We add a short delay before returning to fix a bug observed by Federico +// where the port is configured (lineState != 0) but not quite opened. +Serial_::operator bool() +{ + // this is here to avoid spurious opening after upload + if (millis() < 500) + return false; + + bool result = false; + + if (_usbLineInfo.lineState > 0) + { + result = true; + } + + delay(10); + 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_ SerialUSB(USBDevice); + +#endif diff --git a/sparkfun/samd/cores/LilyMini/USB/PluggableUSB.cpp b/sparkfun/samd/cores/LilyMini/USB/PluggableUSB.cpp new file mode 100644 index 00000000..4c52c1fa --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/PluggableUSB.cpp @@ -0,0 +1,116 @@ +/* + PluggableUSB.cpp + Copyright (c) 2015 Arduino LLC + + 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 +*/ + +#include "USBAPI.h" +#include "USBDesc.h" +#include "USBCore.h" +#include "PluggableUSB.h" + +#if defined(USBCON) +#ifdef PLUGGABLE_USB_ENABLED + +extern uint32_t EndPoints[]; + +int PluggableUSB_::getInterface(uint8_t* interfaceCount) +{ + int sent = 0; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) { + int res = node->getInterface(interfaceCount); + if (res < 0) + return -1; + sent += res; + } + return sent; +} + +int PluggableUSB_::getDescriptor(USBSetup& setup) +{ + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) { + int ret = node->getDescriptor(setup); + // ret!=0 -> request has been processed + if (ret) + return ret; + } + return 0; +} + +void PluggableUSB_::getShortName(char *iSerialNum) +{ + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) { + iSerialNum += node->getShortName(iSerialNum); + } + *iSerialNum = 0; +} + +bool PluggableUSB_::setup(USBSetup& setup) +{ + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) { + if (node->setup(setup)) { + return true; + } + } + return false; +} + +bool PluggableUSB_::plug(PluggableUSBModule *node) +{ + if ((lastEp + node->numEndpoints) > USB_ENDPOINTS) { + return false; + } + + if (!rootNode) { + rootNode = node; + } else { + PluggableUSBModule *current = rootNode; + while (current->next) { + current = current->next; + } + current->next = node; + } + + node->pluggedInterface = lastIf; + node->pluggedEndpoint = lastEp; + lastIf += node->numInterfaces; + for (uint8_t i = 0; i < node->numEndpoints; i++) { + EndPoints[lastEp] = node->endpointType[i]; + lastEp++; + } + return true; + // restart USB layer??? +} + +PluggableUSB_& PluggableUSB() +{ + static PluggableUSB_ obj; + return obj; +} + +PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT), + lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT), + rootNode(NULL) +{ + // Empty +} + +#endif +#endif \ No newline at end of file diff --git a/sparkfun/samd/cores/LilyMini/USB/PluggableUSB.h b/sparkfun/samd/cores/LilyMini/USB/PluggableUSB.h new file mode 100644 index 00000000..4e08e5df --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/PluggableUSB.h @@ -0,0 +1,74 @@ +/* + PluggableUSB.h + Copyright (c) 2015 Arduino LLC + + 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 +*/ + +#ifndef PUSB_h +#define PUSB_h + +#include "USBAPI.h" +#include + +#if defined(USBCON) + +class PluggableUSBModule { +public: + PluggableUSBModule(uint8_t numEps, uint8_t numIfs, uint32_t *epType) : + numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType) + { } + +protected: + virtual bool setup(USBSetup& setup) = 0; + virtual int getInterface(uint8_t* interfaceCount) = 0; + virtual int getDescriptor(USBSetup& setup) = 0; + virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; } + + uint8_t pluggedInterface; + uint8_t pluggedEndpoint; + + const uint8_t numEndpoints; + const uint8_t numInterfaces; + const uint32_t *endpointType; + + PluggableUSBModule *next = NULL; + + friend class PluggableUSB_; +}; + +class PluggableUSB_ { +public: + PluggableUSB_(); + bool plug(PluggableUSBModule *node); + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + void getShortName(char *iSerialNum); + +private: + uint8_t lastIf; + uint8_t lastEp; + PluggableUSBModule* rootNode; +}; + +// Replacement for global singleton. +// This function prevents static-initialization-order-fiasco +// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use +PluggableUSB_& PluggableUSB(); + +#endif + +#endif diff --git a/sparkfun/samd/cores/LilyMini/USB/SAMD21_USBDevice.h b/sparkfun/samd/cores/LilyMini/USB/SAMD21_USBDevice.h new file mode 100644 index 00000000..f053c76c --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/SAMD21_USBDevice.h @@ -0,0 +1,395 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#include + +#include +#include +#include + +typedef uint8_t ep_t; + +class USBDevice_SAMD21G18x { +public: + USBDevice_SAMD21G18x() : usb(USB->DEVICE) { + // Empty + } + + // USB Device function mapping + // --------------------------- + + // Reset USB Device + void reset(); + + // Enable + inline void enable() { usb.CTRLA.bit.ENABLE = 1; } + inline void disable() { usb.CTRLA.bit.ENABLE = 0; } + + // USB mode (device/host) + inline void setUSBDeviceMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val; } +// inline void setUSBHostMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_HOST_Val; } + + inline void runInStandby() { usb.CTRLA.bit.RUNSTDBY = 1; } + inline void noRunInStandby() { usb.CTRLA.bit.RUNSTDBY = 0; } + + // USB speed + inline void setFullSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val; } + inline void setLowSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_LS_Val; } + inline void setHiSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HS_Val; } + inline void setHiSpeedTestMode() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HSTM_Val; } + + // Authorize attach if Vbus is present + inline void attach() { usb.CTRLB.bit.DETACH = 0; } + inline void detach() { usb.CTRLB.bit.DETACH = 1; } + + // USB Interrupts + inline bool isEndOfResetInterrupt() { return usb.INTFLAG.bit.EORST; } + inline void ackEndOfResetInterrupt() { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; } + inline void enableEndOfResetInterrupt() { usb.INTENSET.bit.EORST = 1; } + inline void disableEndOfResetInterrupt() { usb.INTENCLR.bit.EORST = 1; } + + inline bool isStartOfFrameInterrupt() { return usb.INTFLAG.bit.SOF; } + inline void ackStartOfFrameInterrupt() { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; } + inline void enableStartOfFrameInterrupt() { usb.INTENSET.bit.SOF = 1; } + inline void disableStartOfFrameInterrupt() { usb.INTENCLR.bit.SOF = 1; } + + // USB Address + inline void setAddress(uint32_t addr) { usb.DADD.bit.DADD = addr; usb.DADD.bit.ADDEN = 1; } + inline void unsetAddress() { usb.DADD.bit.DADD = 0; usb.DADD.bit.ADDEN = 0; } + + // Frame number + inline uint16_t frameNumber() { return usb.FNUM.bit.FNUM; } + + // Load calibration values + void calibrate(); + + // USB Device Endpoints function mapping + // ------------------------------------- + + // Config + inline void epBank0SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE0 = type; } + inline void epBank1SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE1 = type; } + + // Interrupts + inline uint16_t epInterruptSummary() { return usb.EPINTSMRY.reg; } + + inline bool epBank0IsSetupReceived(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.RXSTP; } + inline bool epBank0IsStalled(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL0; } + inline bool epBank1IsStalled(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL1; } + inline bool epBank0IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0; } + inline bool epBank1IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT1; } + + inline void epBank0AckSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP; } + inline void epBank0AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(1); } + inline void epBank1AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(2); } + inline void epBank0AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(1); } + inline void epBank1AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(2); } + + inline void epBank0EnableSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.RXSTP = 1; } + inline void epBank0EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL0 = 1; } + inline void epBank1EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL1 = 1; } + inline void epBank0EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; } + inline void epBank1EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; } + + inline void epBank0DisableSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.RXSTP = 1; } + inline void epBank0DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL0 = 1; } + inline void epBank1DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL1 = 1; } + inline void epBank0DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT0 = 1; } + inline void epBank1DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT1 = 1; } + + // Status + inline bool epBank0IsReady(ep_t ep) { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK0RDY; } + inline bool epBank1IsReady(ep_t ep) { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK1RDY; } + inline void epBank0SetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK0RDY = 1; } + inline void epBank1SetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK1RDY = 1; } + inline void epBank0ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK0RDY = 1; } + inline void epBank1ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK1RDY = 1; } + + inline void epBank0SetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ0 = 1; } + inline void epBank1SetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ1 = 1; } + inline void epBank0ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ0 = 1; } + inline void epBank1ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ1 = 1; } + + // Packet + inline uint16_t epBank0ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT; } + inline uint16_t epBank1ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT; } + inline void epBank0SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = bc; } + inline void epBank1SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = bc; } + inline void epBank0SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = s; } + inline void epBank1SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = s; } + + inline void epBank0SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)addr; } + inline void epBank1SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[1].ADDR.reg = (uint32_t)addr; } + inline void epBank0SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); } + inline void epBank1SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); } + inline uint8_t EP_PCKSIZE_SIZE(uint16_t size) { + switch (size) { + case 8: return 0; + case 16: return 1; + case 32: return 2; + case 64: return 3; + case 128: return 4; + case 256: return 5; + case 512: return 6; + case 1023: return 7; + default: return 0; + } + } + + inline void epBank0DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 0; } + inline void epBank1DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 0; } + inline void epBank0EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 1; } + inline void epBank1EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 1; } + +private: + // USB Device registers + UsbDevice &usb; + + // Endpoints descriptors table + __attribute__((__aligned__(4))) UsbDeviceDescriptor EP[USB_EPT_NUM]; +}; + +void USBDevice_SAMD21G18x::reset() { + usb.CTRLA.bit.SWRST = 1; + memset(EP, 0, sizeof(EP)); + while (usb.SYNCBUSY.bit.SWRST) {} + usb.DESCADD.reg = (uint32_t)(&EP); +} + +void USBDevice_SAMD21G18x::calibrate() { + // Load Pad Calibration data from non-volatile memory + uint32_t *pad_transn_p = (uint32_t *) USB_FUSES_TRANSN_ADDR; + uint32_t *pad_transp_p = (uint32_t *) USB_FUSES_TRANSP_ADDR; + uint32_t *pad_trim_p = (uint32_t *) USB_FUSES_TRIM_ADDR; + + uint32_t pad_transn = (*pad_transn_p & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos; + uint32_t pad_transp = (*pad_transp_p & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos; + uint32_t pad_trim = (*pad_trim_p & USB_FUSES_TRIM_Msk ) >> USB_FUSES_TRIM_Pos; + + if (pad_transn == 0x1F) // maximum value (31) + pad_transn = 5; + if (pad_transp == 0x1F) // maximum value (31) + pad_transp = 29; + if (pad_trim == 0x7) // maximum value (7) + pad_trim = 3; + + usb.PADCAL.bit.TRANSN = pad_transn; + usb.PADCAL.bit.TRANSP = pad_transp; + usb.PADCAL.bit.TRIM = pad_trim; +} + +/* + * Synchronization primitives. + * TODO: Move into a separate header file and make an API out of it + */ + +class __Guard { +public: + __Guard() : primask(__get_PRIMASK()), loops(1) { + __disable_irq(); + } + ~__Guard() { + if (primask == 0) { + __enable_irq(); + // http://infocenter.arm.com/help/topic/com.arm.doc.dai0321a/BIHBFEIB.html + __ISB(); + } + } + uint32_t enter() { return loops--; } +private: + uint32_t primask; + uint32_t loops; +}; + +#define synchronized for (__Guard __guard; __guard.enter(); ) + + +/* + * USB EP generic handlers. + */ + +class EPHandler { +public: + virtual void handleEndpoint() = 0; + virtual uint32_t recv(void *_data, uint32_t len) = 0; + virtual uint32_t available() const = 0; +}; + +class DoubleBufferedEPOutHandler : public EPHandler { +public: + DoubleBufferedEPOutHandler(USBDevice_SAMD21G18x &usbDev, uint32_t endPoint, uint32_t bufferSize) : + usbd(usbDev), + ep(endPoint), size(bufferSize), + current(0), incoming(0), + first0(0), last0(0), ready0(false), + first1(0), last1(0), ready1(false), + notify(false) + { + data0 = reinterpret_cast(malloc(size)); + data1 = reinterpret_cast(malloc(size)); + + usbd.epBank0SetSize(ep, 64); + usbd.epBank0SetType(ep, 3); // BULK OUT + + usbd.epBank0SetAddress(ep, const_cast(data0)); + + release(); + } + + virtual uint32_t recv(void *_data, uint32_t len) + { + uint8_t *data = reinterpret_cast(_data); + + // R/W: current, first0/1, ready0/1, notify + // R : last0/1, data0/1 + if (current == 0) { + synchronized { + if (!ready0) { + return 0; + } + } + // when ready0==true the buffer is not being filled and last0 is constant + uint32_t i; + for (i=0; i(data1)); + ready0 = true; + synchronized { + if (ready1) { + notify = true; + return; + } + notify = false; + } + } else { + last1 = usbd.epBank0ByteCount(ep); + incoming = 0; + usbd.epBank0SetAddress(ep, const_cast(data0)); + synchronized { + ready1 = true; + if (ready0) { + notify = true; + return; + } + notify = false; + } + } + release(); + } + } + + // Returns how many bytes are stored in the buffers + virtual uint32_t available() const { + if (current == 0) { + bool ready = false; + synchronized { + ready = ready0; + } + return ready ? (last0 - first0) : 0; + } else { + bool ready = false; + synchronized { + ready = ready1; + } + return ready ? (last1 - first1) : 0; + } + } + + void release() { + // Release OUT EP + usbd.epBank0EnableTransferComplete(ep); + usbd.epBank0SetMultiPacketSize(ep, size); + usbd.epBank0SetByteCount(ep, 0); + usbd.epBank0ResetReady(ep); + } + +private: + USBDevice_SAMD21G18x &usbd; + + const uint32_t ep; + const uint32_t size; + uint32_t current, incoming; + + volatile uint8_t *data0; + uint32_t first0; + volatile uint32_t last0; + volatile bool ready0; + + volatile uint8_t *data1; + uint32_t first1; + volatile uint32_t last1; + volatile bool ready1; + + volatile bool notify; +}; + diff --git a/sparkfun/samd/cores/LilyMini/USB/SAMD21_USBDevice.h.bak b/sparkfun/samd/cores/LilyMini/USB/SAMD21_USBDevice.h.bak new file mode 100644 index 00000000..31b9e965 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/SAMD21_USBDevice.h.bak @@ -0,0 +1,395 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#include + +#include +#include +#include + +typedef uint8_t ep_t; + +class USBDevice_SAMD21G18x { +public: + USBDevice_SAMD21G18x() : usb(USB->DEVICE) { + // Empty + } + + // USB Device function mapping + // --------------------------- + + // Reset USB Device + void reset(); + + // Enable + inline void enable() { usb.CTRLA.bit.ENABLE = 1; } + inline void disable() { usb.CTRLA.bit.ENABLE = 0; } + + // USB mode (device/host) + inline void setUSBDeviceMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val; } + inline void setUSBHostMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_HOST_Val; } + + inline void runInStandby() { usb.CTRLA.bit.RUNSTDBY = 1; } + inline void noRunInStandby() { usb.CTRLA.bit.RUNSTDBY = 0; } + + // USB speed + inline void setFullSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val; } + inline void setLowSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_LS_Val; } + inline void setHiSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HS_Val; } + inline void setHiSpeedTestMode() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HSTM_Val; } + + // Authorize attach if Vbus is present + inline void attach() { usb.CTRLB.bit.DETACH = 0; } + inline void detach() { usb.CTRLB.bit.DETACH = 1; } + + // USB Interrupts + inline bool isEndOfResetInterrupt() { return usb.INTFLAG.bit.EORST; } + inline void ackEndOfResetInterrupt() { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; } + inline void enableEndOfResetInterrupt() { usb.INTENSET.bit.EORST = 1; } + inline void disableEndOfResetInterrupt() { usb.INTENCLR.bit.EORST = 1; } + + inline bool isStartOfFrameInterrupt() { return usb.INTFLAG.bit.SOF; } + inline void ackStartOfFrameInterrupt() { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; } + inline void enableStartOfFrameInterrupt() { usb.INTENSET.bit.SOF = 1; } + inline void disableStartOfFrameInterrupt() { usb.INTENCLR.bit.SOF = 1; } + + // USB Address + inline void setAddress(uint32_t addr) { usb.DADD.bit.DADD = addr; usb.DADD.bit.ADDEN = 1; } + inline void unsetAddress() { usb.DADD.bit.DADD = 0; usb.DADD.bit.ADDEN = 0; } + + // Frame number + inline uint16_t frameNumber() { return usb.FNUM.bit.FNUM; } + + // Load calibration values + void calibrate(); + + // USB Device Endpoints function mapping + // ------------------------------------- + + // Config + inline void epBank0SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE0 = type; } + inline void epBank1SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE1 = type; } + + // Interrupts + inline uint16_t epInterruptSummary() { return usb.EPINTSMRY.reg; } + + inline bool epBank0IsSetupReceived(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.RXSTP; } + inline bool epBank0IsStalled(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL0; } + inline bool epBank1IsStalled(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL1; } + inline bool epBank0IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0; } + inline bool epBank1IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT1; } + + inline void epBank0AckSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP; } + inline void epBank0AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(1); } + inline void epBank1AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(2); } + inline void epBank0AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(1); } + inline void epBank1AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(2); } + + inline void epBank0EnableSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.RXSTP = 1; } + inline void epBank0EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL0 = 1; } + inline void epBank1EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL1 = 1; } + inline void epBank0EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; } + inline void epBank1EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; } + + inline void epBank0DisableSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.RXSTP = 1; } + inline void epBank0DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL0 = 1; } + inline void epBank1DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL1 = 1; } + inline void epBank0DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT0 = 1; } + inline void epBank1DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT1 = 1; } + + // Status + inline bool epBank0IsReady(ep_t ep) { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK0RDY; } + inline bool epBank1IsReady(ep_t ep) { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK1RDY; } + inline void epBank0SetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK0RDY = 1; } + inline void epBank1SetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK1RDY = 1; } + inline void epBank0ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK0RDY = 1; } + inline void epBank1ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK1RDY = 1; } + + inline void epBank0SetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ0 = 1; } + inline void epBank1SetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ1 = 1; } + inline void epBank0ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ0 = 1; } + inline void epBank1ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ1 = 1; } + + // Packet + inline uint16_t epBank0ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT; } + inline uint16_t epBank1ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT; } + inline void epBank0SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = bc; } + inline void epBank1SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = bc; } + inline void epBank0SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = s; } + inline void epBank1SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = s; } + + inline void epBank0SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)addr; } + inline void epBank1SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[1].ADDR.reg = (uint32_t)addr; } + inline void epBank0SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); } + inline void epBank1SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); } + inline uint8_t EP_PCKSIZE_SIZE(uint16_t size) { + switch (size) { + case 8: return 0; + case 16: return 1; + case 32: return 2; + case 64: return 3; + case 128: return 4; + case 256: return 5; + case 512: return 6; + case 1023: return 7; + default: return 0; + } + } + + inline void epBank0DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 0; } + inline void epBank1DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 0; } + inline void epBank0EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 1; } + inline void epBank1EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 1; } + +private: + // USB Device registers + UsbDevice &usb; + + // Endpoints descriptors table + __attribute__((__aligned__(4))) UsbDeviceDescriptor EP[USB_EPT_NUM]; +}; + +void USBDevice_SAMD21G18x::reset() { + usb.CTRLA.bit.SWRST = 1; + memset(EP, 0, sizeof(EP)); + while (usb.SYNCBUSY.bit.SWRST) {} + usb.DESCADD.reg = (uint32_t)(&EP); +} + +void USBDevice_SAMD21G18x::calibrate() { + // Load Pad Calibration data from non-volatile memory + uint32_t *pad_transn_p = (uint32_t *) USB_FUSES_TRANSN_ADDR; + uint32_t *pad_transp_p = (uint32_t *) USB_FUSES_TRANSP_ADDR; + uint32_t *pad_trim_p = (uint32_t *) USB_FUSES_TRIM_ADDR; + + uint32_t pad_transn = (*pad_transn_p & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos; + uint32_t pad_transp = (*pad_transp_p & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos; + uint32_t pad_trim = (*pad_trim_p & USB_FUSES_TRIM_Msk ) >> USB_FUSES_TRIM_Pos; + + if (pad_transn == 0x1F) // maximum value (31) + pad_transn = 5; + if (pad_transp == 0x1F) // maximum value (31) + pad_transp = 29; + if (pad_trim == 0x7) // maximum value (7) + pad_trim = 3; + + usb.PADCAL.bit.TRANSN = pad_transn; + usb.PADCAL.bit.TRANSP = pad_transp; + usb.PADCAL.bit.TRIM = pad_trim; +} + +/* + * Synchronization primitives. + * TODO: Move into a separate header file and make an API out of it + */ + +class __Guard { +public: + __Guard() : primask(__get_PRIMASK()), loops(1) { + __disable_irq(); + } + ~__Guard() { + if (primask == 0) { + __enable_irq(); + // http://infocenter.arm.com/help/topic/com.arm.doc.dai0321a/BIHBFEIB.html + __ISB(); + } + } + uint32_t enter() { return loops--; } +private: + uint32_t primask; + uint32_t loops; +}; + +#define synchronized for (__Guard __guard; __guard.enter(); ) + + +/* + * USB EP generic handlers. + */ + +class EPHandler { +public: + virtual void handleEndpoint() = 0; + virtual uint32_t recv(void *_data, uint32_t len) = 0; + virtual uint32_t available() const = 0; +}; + +class DoubleBufferedEPOutHandler : public EPHandler { +public: + DoubleBufferedEPOutHandler(USBDevice_SAMD21G18x &usbDev, uint32_t endPoint, uint32_t bufferSize) : + usbd(usbDev), + ep(endPoint), size(bufferSize), + current(0), incoming(0), + first0(0), last0(0), ready0(false), + first1(0), last1(0), ready1(false), + notify(false) + { + data0 = reinterpret_cast(malloc(size)); + data1 = reinterpret_cast(malloc(size)); + + usbd.epBank0SetSize(ep, 64); + usbd.epBank0SetType(ep, 3); // BULK OUT + + usbd.epBank0SetAddress(ep, const_cast(data0)); + + release(); + } + + virtual uint32_t recv(void *_data, uint32_t len) + { + uint8_t *data = reinterpret_cast(_data); + + // R/W: current, first0/1, ready0/1, notify + // R : last0/1, data0/1 + if (current == 0) { + synchronized { + if (!ready0) { + return 0; + } + } + // when ready0==true the buffer is not being filled and last0 is constant + uint32_t i; + for (i=0; i(data1)); + ready0 = true; + synchronized { + if (ready1) { + notify = true; + return; + } + notify = false; + } + } else { + last1 = usbd.epBank0ByteCount(ep); + incoming = 0; + usbd.epBank0SetAddress(ep, const_cast(data0)); + synchronized { + ready1 = true; + if (ready0) { + notify = true; + return; + } + notify = false; + } + } + release(); + } + } + + // Returns how many bytes are stored in the buffers + virtual uint32_t available() const { + if (current == 0) { + bool ready = false; + synchronized { + ready = ready0; + } + return ready ? (last0 - first0) : 0; + } else { + bool ready = false; + synchronized { + ready = ready1; + } + return ready ? (last1 - first1) : 0; + } + } + + void release() { + // Release OUT EP + usbd.epBank0EnableTransferComplete(ep); + usbd.epBank0SetMultiPacketSize(ep, size); + usbd.epBank0SetByteCount(ep, 0); + usbd.epBank0ResetReady(ep); + } + +private: + USBDevice_SAMD21G18x &usbd; + + const uint32_t ep; + const uint32_t size; + uint32_t current, incoming; + + volatile uint8_t *data0; + uint32_t first0; + volatile uint32_t last0; + volatile bool ready0; + + volatile uint8_t *data1; + uint32_t first1; + volatile uint32_t last1; + volatile bool ready1; + + volatile bool notify; +}; + diff --git a/sparkfun/samd/cores/LilyMini/USB/USBAPI.h b/sparkfun/samd/cores/LilyMini/USB/USBAPI.h new file mode 100644 index 00000000..53c249a4 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/USBAPI.h @@ -0,0 +1,200 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#define HSTPIPCFG_PTYPE_BLK 1 +#define HSTPIPCFG_PTOKEN_IN 2 +#define HSTPIPCFG_PTOKEN_OUT 3 +#define HSTPIPCFG_PBK_1_BANK 4 +#define HSTPIPCFG_PTYPE_INTRPT 5 + +#define EP0 0 +#define EPX_SIZE 64 // 64 for Full Speed, EPT size max is 1024 + +#if defined __cplusplus + +#include "Stream.h" +#include "RingBuffer.h" + +//================================================================================ +// USB + +// Low level API +typedef struct { + union { + uint8_t bmRequestType; + struct { + uint8_t direction : 5; + uint8_t type : 2; + uint8_t transferDirection : 1; + }; + }; + uint8_t bRequest; + uint8_t wValueL; + uint8_t wValueH; + uint16_t wIndex; + uint16_t wLength; +} USBSetup; + +class USBDeviceClass { +public: + USBDeviceClass() {}; + + // USB Device API + void init(); + bool attach(); + bool detach(); + void setAddress(uint32_t addr); + + bool configured(); + bool connected(); + + // Setup API + bool handleClassInterfaceSetup(USBSetup &setup); + bool handleStandardSetup(USBSetup &setup); + bool sendDescriptor(USBSetup &setup); + + // Control EndPoint API + uint32_t sendControl(const void *data, uint32_t len); + 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); + void initControl(int end); + uint8_t SendInterfaces(uint32_t* total); + void packMessages(bool val); + + // Generic EndPoint API + void initEndpoints(void); + void initEP(uint32_t ep, uint32_t type); + void handleEndpoint(uint8_t ep); + + uint32_t send(uint32_t ep, const void *data, uint32_t len); + void sendZlp(uint32_t ep); + uint32_t recv(uint32_t ep, void *data, uint32_t len); + int recv(uint32_t ep); + uint32_t available(uint32_t ep); + void flush(uint32_t ep); + void stall(uint32_t ep); + + // private? + uint32_t armSend(uint32_t ep, const void *data, uint32_t len); + uint8_t armRecv(uint32_t ep); + uint8_t armRecvCtrlOUT(uint32_t ep); + + void ISRHandler(); + +private: + bool initialized; +}; + +extern USBDeviceClass USBDevice; + +//================================================================================ +// Serial over CDC (Serial1 is the physical port) + +class Serial_ : public Stream +{ +public: + Serial_(USBDeviceClass &_usb) : usb(_usb), stalled(false) { } + void begin(uint32_t baud_count); + void begin(unsigned long, uint8_t); + void end(void); + + virtual int available(void); + virtual int availableForWrite(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buffer, size_t size); + using Print::write; // pull in write(str) from Print + operator bool(); + + size_t readBytes(char *buffer, size_t length); + + // This method allows processing "SEND_BREAK" requests sent by + // the USB host. Those requests indicate that the host wants to + // send a BREAK signal and are accompanied by a single uint16_t + // value, specifying the duration of the break. The value 0 + // means to end any current break, while the value 0xffff means + // to start an indefinite break. + // readBreak() will return the value of the most recent break + // request, but will return it at most once, returning -1 when + // readBreak() is called again (until another break request is + // received, which is again returned once). + // This also mean that if two break requests are received + // without readBreak() being called in between, the value of the + // first request is lost. + // Note that the value returned is a long, so it can return + // 0-0xffff as well as -1. + int32_t readBreak(); + + // These return the settings specified by the USB host for the + // serial port. These aren't really used, but are offered here + // in case a sketch wants to act on these settings. + uint32_t baud(); + uint8_t stopbits(); + uint8_t paritytype(); + uint8_t numbits(); + bool dtr(); + bool rts(); + enum { + ONE_STOP_BIT = 0, + ONE_AND_HALF_STOP_BIT = 1, + TWO_STOP_BITS = 2, + }; + enum { + NO_PARITY = 0, + ODD_PARITY = 1, + EVEN_PARITY = 2, + MARK_PARITY = 3, + SPACE_PARITY = 4, + }; + +private: + int availableForStore(void); + + USBDeviceClass &usb; + RingBuffer *_cdc_rx_buffer; + bool stalled; +}; +extern Serial_ SerialUSB; + +//================================================================================ +//================================================================================ +// MSC 'Driver' + +uint32_t MSC_GetInterface(uint8_t* interfaceNum); +uint32_t MSC_GetDescriptor(uint32_t i); +bool MSC_Setup(USBSetup& setup); +bool MSC_Data(uint8_t rx,uint8_t tx); + +//================================================================================ +//================================================================================ +// CDC 'Driver' + +int CDC_GetInterface(uint8_t* interfaceNum); +const void* _CDC_GetInterface(void); +uint32_t _CDC_GetInterfaceLength(void); +uint32_t CDC_GetOtherInterface(uint8_t* interfaceNum); +uint32_t CDC_GetDescriptor(uint32_t i); +bool CDC_Setup(USBSetup& setup); + +#endif // __cplusplus diff --git a/sparkfun/samd/cores/LilyMini/USB/USBCore.cpp b/sparkfun/samd/cores/LilyMini/USB/USBCore.cpp new file mode 100644 index 00000000..5ba11192 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/USBCore.cpp @@ -0,0 +1,960 @@ +/* + Copyright (c) 2016 Arduino LLC. 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 +*/ + +#include + +#include "SAMD21_USBDevice.h" +#include "PluggableUSB.h" + +#include +#include +#include +#include + +USBDevice_SAMD21G18x usbd; + +/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ +#define TX_RX_LED_PULSE_MS 100 +#ifdef PIN_LED_TXL +static volatile uint8_t txLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ +#endif +#ifdef PIN_LED_RXL +static volatile uint8_t rxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ +#endif +static char isRemoteWakeUpEnabled = 0; +static char isEndpointHalt = 0; + +extern void (*gpf_isr)(void); + + +static void (*usb_isr)(void) = NULL; + +void USB_Handler(void) +{ + if (usb_isr) + usb_isr(); +} + +void USB_SetHandler(void (*new_usb_isr)(void)) +{ + usb_isr = new_usb_isr; +} + + +// USB_Handler ISR +extern "C" void UDD_Handler(void) { + USBDevice.ISRHandler(); +} + +const uint16_t STRING_LANGUAGE[2] = { + (3<<8) | (2+2), + 0x0409 // English +}; + +#ifndef USB_PRODUCT +// If no product is provided, use USB IO Board +#define USB_PRODUCT "USB IO Board" +#endif + +const uint8_t STRING_PRODUCT[] = USB_PRODUCT; + +#if USB_VID == 0x2341 +# if defined(USB_MANUFACTURER) +# undef USB_MANUFACTURER +# endif +# define USB_MANUFACTURER "Arduino LLC" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +# define USB_MANUFACTURER "Unknown" +#endif + +const uint8_t STRING_MANUFACTURER[] = USB_MANUFACTURER; + + +// DEVICE DESCRIPTOR +const DeviceDescriptor USB_DeviceDescriptorB = D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, ISERIAL, 1); +const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, ISERIAL, 1); + +//================================================================== + +volatile uint32_t _usbConfiguration = 0; +volatile uint32_t _usbSetInterface = 0; + +static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0"))) +uint8_t udd_ep_out_cache_buffer[7][64]; + +static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0"))) +uint8_t udd_ep_in_cache_buffer[7][64]; + +// Some EP are handled using EPHanlders. +// Possibly all the sparse EP handling subroutines will be +// converted into reusable EPHandlers in the future. +static EPHandler *epHandlers[7]; + +//================================================================== + +// 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) +{ + if (maxlen < 2) + return false; + + uint8_t buffer[maxlen]; + buffer[0] = strlen((const char*)string) * 2 + 2; + buffer[1] = 0x03; + + uint8_t i; + for (i = 2; i < maxlen && *string; i++) { + buffer[i++] = *string++; + if (i == maxlen) break; + buffer[i] = 0; + } + + return USBDevice.sendControl(buffer, i); +} + +bool _dry_run = false; +bool _pack_message = false; +uint16_t _pack_size = 0; +uint8_t _pack_buffer[256]; + +void USBDeviceClass::packMessages(bool val) +{ + if (val) { + _pack_message = true; + _pack_size = 0; + } else { + _pack_message = false; + sendControl(_pack_buffer, _pack_size); + } +} + +uint8_t USBDeviceClass::SendInterfaces(uint32_t* total) +{ + uint8_t interfaces = 0; + +#if defined(CDC_ENABLED) + total[0] += CDC_GetInterface(&interfaces); +#endif + +#ifdef PLUGGABLE_USB_ENABLED + total[0] += PluggableUSB().getInterface(&interfaces); +#endif + + return interfaces; +} + +// Construct a dynamic configuration descriptor +// This really needs dynamic endpoint allocation etc +uint32_t USBDeviceClass::sendConfiguration(uint32_t maxlen) +{ + uint32_t total = 0; + // Count and measure interfaces + _dry_run = true; + uint8_t interfaces = SendInterfaces(&total); + + _Pragma("pack(1)") + ConfigDescriptor config = D_CONFIG((uint16_t)(total + sizeof(ConfigDescriptor)), interfaces); + _Pragma("pack()") + + // Now send them + _dry_run = false; + + if (maxlen == sizeof(ConfigDescriptor)) { + sendControl(&config, sizeof(ConfigDescriptor)); + return true; + } + + total = 0; + + packMessages(true); + sendControl(&config, sizeof(ConfigDescriptor)); + SendInterfaces(&total); + packMessages(false); + + return true; +} + +bool USBDeviceClass::sendDescriptor(USBSetup &setup) +{ + uint8_t t = setup.wValueH; + uint8_t desc_length = 0; + bool _cdcComposite; + int ret; + const uint8_t *desc_addr = 0; + + if (t == USB_CONFIGURATION_DESCRIPTOR_TYPE) + { + return USBDevice.sendConfiguration(setup.wLength); + } + +#ifdef PLUGGABLE_USB_ENABLED + ret = PluggableUSB().getDescriptor(setup); + if (ret != 0) { + return (ret > 0 ? true : false); + } +#endif + + if (t == USB_DEVICE_DESCRIPTOR_TYPE) + { + if (setup.wLength == 8) + _cdcComposite = 1; + + desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptorB : (const uint8_t*)&USB_DeviceDescriptor; + + if (*desc_addr > setup.wLength) { + desc_length = setup.wLength; + } + } + else if (USB_STRING_DESCRIPTOR_TYPE == t) + { + if (setup.wValueL == 0) { + desc_addr = (const uint8_t*)&STRING_LANGUAGE; + } + else if (setup.wValueL == IPRODUCT) { + return sendStringDescriptor(STRING_PRODUCT, setup.wLength); + } + else if (setup.wValueL == IMANUFACTURER) { + return sendStringDescriptor(STRING_MANUFACTURER, setup.wLength); + } + else if (setup.wValueL == ISERIAL) { +#ifdef PLUGGABLE_USB_ENABLED + char name[ISERIAL_MAX_LEN]; + PluggableUSB().getShortName(name); + return sendStringDescriptor((uint8_t*)name, setup.wLength); +#endif + } + else { + return false; + } + if (*desc_addr > setup.wLength) { + desc_length = setup.wLength; + } + } + else + { + } + + if (desc_addr == 0) { + return false; + } + + if (desc_length == 0) { + desc_length = *desc_addr; + } + + sendControl(desc_addr, desc_length); + + return true; +} + +void USBDeviceClass::handleEndpoint(uint8_t ep) +{ +#if defined(CDC_ENABLED) + if (ep == CDC_ENDPOINT_IN) + { + // NAK on endpoint IN, the bank is not yet filled in. + usbd.epBank1ResetReady(CDC_ENDPOINT_IN); + usbd.epBank1AckTransferComplete(CDC_ENDPOINT_IN); + } + if (ep == CDC_ENDPOINT_ACM) + { + // NAK on endpoint IN, the bank is not yet filled in. + usbd.epBank1ResetReady(CDC_ENDPOINT_ACM); + usbd.epBank1AckTransferComplete(CDC_ENDPOINT_ACM); + } +#endif + +#if defined(PLUGGABLE_USB_ENABLED) + // Empty +#endif +} + +void USBDeviceClass::init() +{ +#ifdef PIN_LED_TXL + txLEDPulse = 0; + pinMode(PIN_LED_TXL, OUTPUT); + digitalWrite(PIN_LED_TXL, HIGH); +#endif + +#ifdef PIN_LED_RXL + rxLEDPulse = 0; + pinMode(PIN_LED_RXL, OUTPUT); + digitalWrite(PIN_LED_RXL, HIGH); +#endif + + // Enable USB clock + PM->APBBMASK.reg |= PM_APBBMASK_USB; + + // Set up the USB DP/DN pins + PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u))); + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u)); + PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u))); + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u)); + + // Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference) + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | // Generic Clock Multiplexer 6 + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY) + ; + + USB_SetHandler(&UDD_Handler); + + // Reset USB Device + usbd.reset(); + + usbd.calibrate(); + usbd.setUSBDeviceMode(); + usbd.runInStandby(); + usbd.setFullSpeed(); + + // Configure interrupts + NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL); + NVIC_EnableIRQ((IRQn_Type) USB_IRQn); + + usbd.enable(); + + initialized = true; +} + +bool USBDeviceClass::attach() +{ + if (!initialized) + return false; + + usbd.attach(); + usbd.enableEndOfResetInterrupt(); + usbd.enableStartOfFrameInterrupt(); + + _usbConfiguration = 0; + return true; +} + +void USBDeviceClass::setAddress(uint32_t addr) +{ + usbd.epBank1SetByteCount(0, 0); + usbd.epBank1AckTransferComplete(0); + + // RAM buffer is full, we can send data (IN) + usbd.epBank1SetReady(0); + + // Wait for transfer to complete + while (!usbd.epBank1IsTransferComplete(0)) {} + + // Set USB address to addr + USB->DEVICE.DADD.bit.DADD = addr; // Address + USB->DEVICE.DADD.bit.ADDEN = 1; // Enable +} + +bool USBDeviceClass::detach() +{ + if (!initialized) + return false; + usbd.detach(); + return true; +} + +bool USBDeviceClass::configured() +{ + return _usbConfiguration != 0; +} + +bool USBDeviceClass::handleClassInterfaceSetup(USBSetup& setup) +{ + uint8_t i = setup.wIndex; + + #if defined(CDC_ENABLED) + if (CDC_ACM_INTERFACE == i) + { + if (CDC_Setup(setup) == false) { + sendZlp(0); + } + return true; + } + #endif + + #if defined(PLUGGABLE_USB_ENABLED) + bool ret = PluggableUSB().setup(setup); + if ( ret == false) { + sendZlp(0); + } + return ret; + #endif + + return false; +} + +uint32_t EndPoints[] = +{ + USB_ENDPOINT_TYPE_CONTROL, + +#ifdef CDC_ENABLED + USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_ACM + USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0), // CDC_ENDPOINT_OUT + USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_IN +#endif + +#ifdef PLUGGABLE_USB_ENABLED + //allocate 6 endpoints and remove const so they can be changed by the user + 0, + 0, + 0, + 0, + 0, + 0, +#endif +}; + +void USBDeviceClass::initEndpoints() { + for (uint8_t i = 1; i < sizeof(EndPoints) && EndPoints[i] != 0; i++) { + initEP(i, EndPoints[i]); + } +} + +void USBDeviceClass::initEP(uint32_t ep, uint32_t config) +{ + if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0))) + { + usbd.epBank1SetSize(ep, 64); + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + usbd.epBank1SetType(ep, 4); // INTERRUPT IN + } + else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0))) + { + epHandlers[ep] = new DoubleBufferedEPOutHandler(usbd, ep, 256); + } + else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0))) + { + usbd.epBank1SetSize(ep, 64); + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + + // NAK on endpoint IN, the bank is not yet filled in. + usbd.epBank1ResetReady(ep); + + usbd.epBank1SetType(ep, 3); // BULK IN + } + else if (config == USB_ENDPOINT_TYPE_CONTROL) + { + // Setup Control OUT + usbd.epBank0SetSize(ep, 64); + usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]); + usbd.epBank0SetType(ep, 1); // CONTROL OUT / SETUP + + // Setup Control IN + usbd.epBank1SetSize(ep, 64); + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[0]); + usbd.epBank1SetType(ep, 1); // CONTROL IN + + // Release OUT EP + usbd.epBank0SetMultiPacketSize(ep, 64); + usbd.epBank0SetByteCount(ep, 0); + + // NAK on endpoint OUT, the bank is full. + usbd.epBank0SetReady(ep); + } +} + +void USBDeviceClass::flush(uint32_t ep) +{ + if (available(ep)) { + // RAM buffer is full, we can send data (IN) + usbd.epBank1SetReady(ep); + + // Clear the transfer complete flag + usbd.epBank1AckTransferComplete(ep); + } +} + +void USBDeviceClass::stall(uint32_t ep) +{ + // TODO: test + // TODO: use .bit. notation + + // Stall endpoint + USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ(2); +} + +bool USBDeviceClass::connected() +{ + // Count frame numbers + uint8_t f = USB->DEVICE.FNUM.bit.FNUM; + //delay(3); + return f != USB->DEVICE.FNUM.bit.FNUM; +} + + +uint32_t USBDeviceClass::recvControl(void *_data, uint32_t len) +{ + uint8_t *data = reinterpret_cast(_data); + + // The RAM Buffer is empty: we can receive data + usbd.epBank0ResetReady(0); + + //usbd.epBank0AckSetupReceived(0); + uint32_t read = armRecvCtrlOUT(0); + if (read > len) + read = len; + //while (!usbd.epBank0AckTransferComplete(0)) {} + uint8_t *buffer = udd_ep_out_cache_buffer[0]; + for (uint32_t i=0; iavailable(); + } else { + return usbd.epBank0ByteCount(ep); + } +} + +// Non Blocking receive +// Return number of bytes read +uint32_t USBDeviceClass::recv(uint32_t ep, void *_data, uint32_t len) +{ + if (!_usbConfiguration) + return -1; + +#ifdef PIN_LED_RXL + if (rxLEDPulse == 0) + digitalWrite(PIN_LED_RXL, LOW); + + rxLEDPulse = TX_RX_LED_PULSE_MS; +#endif + + if (epHandlers[ep]) { + return epHandlers[ep]->recv(_data, len); + } + + if (available(ep) < len) + len = available(ep); + + armRecv(ep); + + usbd.epBank0DisableTransferComplete(ep); + + memcpy(_data, udd_ep_out_cache_buffer[ep], len); + + // release empty buffer + if (len && !available(ep)) { + // The RAM Buffer is empty: we can receive data + usbd.epBank0ResetReady(ep); + + // Clear Transfer complete 0 flag + usbd.epBank0AckTransferComplete(ep); + + // Enable Transfer complete 0 interrupt + usbd.epBank0EnableTransferComplete(ep); + } + + return len; +} + +// Recv 1 byte if ready +int USBDeviceClass::recv(uint32_t ep) +{ + uint8_t c; + if (recv(ep, &c, 1) != 1) { + return -1; + } else { + return c; + } +} + +uint8_t USBDeviceClass::armRecvCtrlOUT(uint32_t ep) +{ + // Get endpoint configuration from setting register + usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]); + usbd.epBank0SetMultiPacketSize(ep, 8); + usbd.epBank0SetByteCount(ep, 0); + + usbd.epBank0ResetReady(ep); + + // Wait OUT + while (!usbd.epBank0IsReady(ep)) {} + while (!usbd.epBank0IsTransferComplete(ep)) {} + return usbd.epBank0ByteCount(ep); +} + +uint8_t USBDeviceClass::armRecv(uint32_t ep) +{ + uint16_t count = usbd.epBank0ByteCount(ep); + if (count >= 64) { + usbd.epBank0SetByteCount(ep, count - 64); + } else { + usbd.epBank0SetByteCount(ep, 0); + } + return usbd.epBank0ByteCount(ep); +} + +// Timeout for sends +#define TX_TIMEOUT_MS 70 + +static char LastTransmitTimedOut[7] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0 +}; + +// Blocking Send of data to an endpoint +uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len) +{ + uint32_t written = 0; + uint32_t length = 0; + + if (!_usbConfiguration) + return -1; + if (len > 16384) + return -1; + +#ifdef PIN_LED_TXL + if (txLEDPulse == 0) + digitalWrite(PIN_LED_TXL, LOW); + + txLEDPulse = TX_RX_LED_PULSE_MS; +#endif + + // Flash area + while (len != 0) + { + if (usbd.epBank1IsReady(ep)) { + // previous transfer is still not complete + + // convert the timeout from microseconds to a number of times through + // the wait loop; it takes (roughly) 23 clock cycles per iteration. + uint32_t timeout = microsecondsToClockCycles(TX_TIMEOUT_MS * 1000) / 23; + + // Wait for (previous) transfer to complete + // inspired by Paul Stoffregen's work on Teensy + while (!usbd.epBank1IsTransferComplete(ep)) { + if (LastTransmitTimedOut[ep] || timeout-- == 0) { + LastTransmitTimedOut[ep] = 1; + + // set byte count to zero, so that ZLP is sent + // instead of stale data + usbd.epBank1SetByteCount(ep, 0); + return -1; + } + } + } + + LastTransmitTimedOut[ep] = 0; + + if (len >= EPX_SIZE) { + length = EPX_SIZE - 1; + } else { + length = len; + } + + /* memcopy could be safer in multi threaded environment */ + memcpy(&udd_ep_in_cache_buffer[ep], data, length); + + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + usbd.epBank1SetByteCount(ep, length); + + // Clear the transfer complete flag + usbd.epBank1AckTransferComplete(ep); + + // RAM buffer is full, we can send data (IN) + usbd.epBank1SetReady(ep); + + written += length; + len -= length; + data = (char *)data + length; + } + return written; +} + +uint32_t USBDeviceClass::armSend(uint32_t ep, const void* data, uint32_t len) +{ + memcpy(&udd_ep_in_cache_buffer[ep], data, len); + + // Get endpoint configuration from setting register + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + usbd.epBank1SetMultiPacketSize(ep, 0); + usbd.epBank1SetByteCount(ep, len); + + return len; +} + +uint32_t USBDeviceClass::sendControl(const void* _data, uint32_t len) +{ + const uint8_t *data = reinterpret_cast(_data); + uint32_t length = len; + uint32_t sent = 0; + uint32_t pos = 0; + + if (_dry_run == true) + return length; + + if (_pack_message == true) { + memcpy(&_pack_buffer[_pack_size], data, len); + _pack_size += len; + return length; + } + + while (len > 0) + { + sent = armSend(EP0, data + pos, len); + pos += sent; + len -= sent; + } + + return length; +} + +void USBDeviceClass::sendZlp(uint32_t ep) +{ + // Set the byte count as zero + usbd.epBank1SetByteCount(ep, 0); +} + +bool USBDeviceClass::handleStandardSetup(USBSetup &setup) +{ + switch (setup.bRequest) { + case GET_STATUS: + if (setup.bmRequestType == 0) // device + { + // Send the device status + // TODO: Check current configuration for power mode (if device is configured) + // TODO: Check if remote wake-up is enabled + uint8_t buff[] = { 0, 0 }; + armSend(0, buff, 2); + return true; + } + // if( setup.bmRequestType == 2 ) // Endpoint: + else + { + // Send the endpoint status + // Check if the endpoint if currently halted + uint8_t buff[] = { 0, 0 }; + if (isEndpointHalt == 1) + buff[0] = 1; + armSend(0, buff, 2); + return true; + } + + case CLEAR_FEATURE: + // Check which is the selected feature + if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP + { + // Enable remote wake-up and send a ZLP + uint8_t buff[] = { 0, 0 }; + if (isRemoteWakeUpEnabled == 1) + buff[0] = 1; + armSend(0, buff, 2); + return true; + } + else // if( setup.wValueL == 0) // ENDPOINTHALT + { + isEndpointHalt = 0; + sendZlp(0); + return true; + } + + case SET_FEATURE: + // Check which is the selected feature + if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP + { + // Enable remote wake-up and send a ZLP + isRemoteWakeUpEnabled = 1; + uint8_t buff[] = { 0 }; + armSend(0, buff, 1); + return true; + } + if (setup.wValueL == 0) // ENDPOINTHALT + { + // Halt endpoint + isEndpointHalt = 1; + sendZlp(0); + return true; + } + + case SET_ADDRESS: + setAddress(setup.wValueL); + return true; + + case GET_DESCRIPTOR: + return sendDescriptor(setup); + + case SET_DESCRIPTOR: + return false; + + case GET_CONFIGURATION: + armSend(0, (void*)&_usbConfiguration, 1); + return true; + + case SET_CONFIGURATION: + if (REQUEST_DEVICE == (setup.bmRequestType & REQUEST_RECIPIENT)) { + + initEndpoints(); + _usbConfiguration = setup.wValueL; + + #if defined(CDC_ENABLED) + // Enable interrupt for CDC reception from host (OUT packet) + usbd.epBank1EnableTransferComplete(CDC_ENDPOINT_ACM); + usbd.epBank0EnableTransferComplete(CDC_ENDPOINT_OUT); + #endif + + sendZlp(0); + return true; + } else { + return false; + } + + case GET_INTERFACE: + armSend(0, (void*)&_usbSetInterface, 1); + return true; + + case SET_INTERFACE: + _usbSetInterface = setup.wValueL; + sendZlp(0); + return true; + + default: + return true; + } +} + +void USBDeviceClass::ISRHandler() +{ + + if (_pack_message == true) { + return; + } + // End-Of-Reset + if (usbd.isEndOfResetInterrupt()) + { + // Configure EP 0 + initEP(0, USB_ENDPOINT_TYPE_CONTROL); + + // Enable Setup-Received interrupt + usbd.epBank0EnableSetupReceived(0); + + _usbConfiguration = 0; + + usbd.ackEndOfResetInterrupt(); + } + + // Start-Of-Frame + if (usbd.isStartOfFrameInterrupt()) + { + usbd.ackStartOfFrameInterrupt(); + + // check whether the one-shot period has elapsed. if so, turn off the LED +#ifdef PIN_LED_TXL + if (txLEDPulse > 0) { + txLEDPulse--; + if (txLEDPulse == 0) + digitalWrite(PIN_LED_TXL, HIGH); + } +#endif + +#ifdef PIN_LED_RXL + if (rxLEDPulse > 0) { + rxLEDPulse--; + if (rxLEDPulse == 0) + digitalWrite(PIN_LED_RXL, HIGH); + } +#endif + } + + // Endpoint 0 Received Setup interrupt + if (usbd.epBank0IsSetupReceived(0)) + { + usbd.epBank0AckSetupReceived(0); + + USBSetup *setup = reinterpret_cast(udd_ep_out_cache_buffer[0]); + + /* Clear the Bank 0 ready flag on Control OUT */ + // The RAM Buffer is empty: we can receive data + usbd.epBank0ResetReady(0); + + bool ok; + if (REQUEST_STANDARD == (setup->bmRequestType & REQUEST_TYPE)) { + // Standard Requests + ok = handleStandardSetup(*setup); + } else { + // Class Interface Requests + ok = handleClassInterfaceSetup(*setup); + } + + if (ok) { + usbd.epBank1SetReady(0); + } else { + stall(0); + } + + if (usbd.epBank1IsStalled(0)) + { + usbd.epBank1AckStalled(0); + + // Remove stall request + usbd.epBank1DisableStalled(0); + } + + } // end Received Setup handler + + uint8_t i=0; + uint8_t ept_int = usbd.epInterruptSummary() & 0xFE; // Remove endpoint number 0 (setup) + while (ept_int != 0) + { + // Check if endpoint has a pending interrupt + if ((ept_int & (1 << i)) != 0) + { + // Endpoint Transfer Complete (0/1) Interrupt + if (usbd.epBank0IsTransferComplete(i) || + usbd.epBank1IsTransferComplete(i)) + { + if (epHandlers[i]) { + epHandlers[i]->handleEndpoint(); + } else { + handleEndpoint(i); + } + } + ept_int &= ~(1 << i); + } + i++; + if (i > USB_EPT_NUM) + break; // fire exit + } +} + +/* + * USB Device instance + * ------------------- + */ + +// USBDevice class instance +USBDeviceClass USBDevice; + diff --git a/sparkfun/samd/cores/LilyMini/USB/USBCore.cpp.bak b/sparkfun/samd/cores/LilyMini/USB/USBCore.cpp.bak new file mode 100644 index 00000000..14390bcc --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/USBCore.cpp.bak @@ -0,0 +1,945 @@ +/* + Copyright (c) 2016 Arduino LLC. 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 +*/ + +#include + +#include "SAMD21_USBDevice.h" +#include "PluggableUSB.h" + +#include +#include +#include +#include + +USBDevice_SAMD21G18x usbd; + +/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ +#define TX_RX_LED_PULSE_MS 100 +#ifdef PIN_LED_TXL +static volatile uint8_t txLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ +#endif +#ifdef PIN_LED_RXL +static volatile uint8_t rxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ +#endif +static char isRemoteWakeUpEnabled = 0; +static char isEndpointHalt = 0; + +extern void (*gpf_isr)(void); + +// USB_Handler ISR +extern "C" void UDD_Handler(void) { + USBDevice.ISRHandler(); +} + +const uint16_t STRING_LANGUAGE[2] = { + (3<<8) | (2+2), + 0x0409 // English +}; + +#ifndef USB_PRODUCT +// If no product is provided, use USB IO Board +#define USB_PRODUCT "USB IO Board" +#endif + +const uint8_t STRING_PRODUCT[] = USB_PRODUCT; + +#if USB_VID == 0x2341 +# if defined(USB_MANUFACTURER) +# undef USB_MANUFACTURER +# endif +# define USB_MANUFACTURER "Arduino LLC" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +# define USB_MANUFACTURER "Unknown" +#endif + +const uint8_t STRING_MANUFACTURER[] = USB_MANUFACTURER; + + +// DEVICE DESCRIPTOR +const DeviceDescriptor USB_DeviceDescriptorB = D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, ISERIAL, 1); +const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, ISERIAL, 1); + +//================================================================== + +volatile uint32_t _usbConfiguration = 0; +volatile uint32_t _usbSetInterface = 0; + +static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0"))) +uint8_t udd_ep_out_cache_buffer[7][64]; + +static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0"))) +uint8_t udd_ep_in_cache_buffer[7][64]; + +// Some EP are handled using EPHanlders. +// Possibly all the sparse EP handling subroutines will be +// converted into reusable EPHandlers in the future. +static EPHandler *epHandlers[7]; + +//================================================================== + +// 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) +{ + if (maxlen < 2) + return false; + + uint8_t buffer[maxlen]; + buffer[0] = strlen((const char*)string) * 2 + 2; + buffer[1] = 0x03; + + uint8_t i; + for (i = 2; i < maxlen && *string; i++) { + buffer[i++] = *string++; + if (i == maxlen) break; + buffer[i] = 0; + } + + return USBDevice.sendControl(buffer, i); +} + +bool _dry_run = false; +bool _pack_message = false; +uint16_t _pack_size = 0; +uint8_t _pack_buffer[256]; + +void USBDeviceClass::packMessages(bool val) +{ + if (val) { + _pack_message = true; + _pack_size = 0; + } else { + _pack_message = false; + sendControl(_pack_buffer, _pack_size); + } +} + +uint8_t USBDeviceClass::SendInterfaces(uint32_t* total) +{ + uint8_t interfaces = 0; + +#if defined(CDC_ENABLED) + total[0] += CDC_GetInterface(&interfaces); +#endif + +#ifdef PLUGGABLE_USB_ENABLED + total[0] += PluggableUSB().getInterface(&interfaces); +#endif + + return interfaces; +} + +// Construct a dynamic configuration descriptor +// This really needs dynamic endpoint allocation etc +uint32_t USBDeviceClass::sendConfiguration(uint32_t maxlen) +{ + uint32_t total = 0; + // Count and measure interfaces + _dry_run = true; + uint8_t interfaces = SendInterfaces(&total); + + _Pragma("pack(1)") + ConfigDescriptor config = D_CONFIG((uint16_t)(total + sizeof(ConfigDescriptor)), interfaces); + _Pragma("pack()") + + // Now send them + _dry_run = false; + + if (maxlen == sizeof(ConfigDescriptor)) { + sendControl(&config, sizeof(ConfigDescriptor)); + return true; + } + + total = 0; + + packMessages(true); + sendControl(&config, sizeof(ConfigDescriptor)); + SendInterfaces(&total); + packMessages(false); + + return true; +} + +bool USBDeviceClass::sendDescriptor(USBSetup &setup) +{ + uint8_t t = setup.wValueH; + uint8_t desc_length = 0; + bool _cdcComposite; + int ret; + const uint8_t *desc_addr = 0; + + if (t == USB_CONFIGURATION_DESCRIPTOR_TYPE) + { + return USBDevice.sendConfiguration(setup.wLength); + } + +#ifdef PLUGGABLE_USB_ENABLED + ret = PluggableUSB().getDescriptor(setup); + if (ret != 0) { + return (ret > 0 ? true : false); + } +#endif + + if (t == USB_DEVICE_DESCRIPTOR_TYPE) + { + if (setup.wLength == 8) + _cdcComposite = 1; + + desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptorB : (const uint8_t*)&USB_DeviceDescriptor; + + if (*desc_addr > setup.wLength) { + desc_length = setup.wLength; + } + } + else if (USB_STRING_DESCRIPTOR_TYPE == t) + { + if (setup.wValueL == 0) { + desc_addr = (const uint8_t*)&STRING_LANGUAGE; + } + else if (setup.wValueL == IPRODUCT) { + return sendStringDescriptor(STRING_PRODUCT, setup.wLength); + } + else if (setup.wValueL == IMANUFACTURER) { + return sendStringDescriptor(STRING_MANUFACTURER, setup.wLength); + } + else if (setup.wValueL == ISERIAL) { +#ifdef PLUGGABLE_USB_ENABLED + char name[ISERIAL_MAX_LEN]; + PluggableUSB().getShortName(name); + return sendStringDescriptor((uint8_t*)name, setup.wLength); +#endif + } + else { + return false; + } + if (*desc_addr > setup.wLength) { + desc_length = setup.wLength; + } + } + else + { + } + + if (desc_addr == 0) { + return false; + } + + if (desc_length == 0) { + desc_length = *desc_addr; + } + + sendControl(desc_addr, desc_length); + + return true; +} + +void USBDeviceClass::handleEndpoint(uint8_t ep) +{ +#if defined(CDC_ENABLED) + if (ep == CDC_ENDPOINT_IN) + { + // NAK on endpoint IN, the bank is not yet filled in. + usbd.epBank1ResetReady(CDC_ENDPOINT_IN); + usbd.epBank1AckTransferComplete(CDC_ENDPOINT_IN); + } + if (ep == CDC_ENDPOINT_ACM) + { + // NAK on endpoint IN, the bank is not yet filled in. + usbd.epBank1ResetReady(CDC_ENDPOINT_ACM); + usbd.epBank1AckTransferComplete(CDC_ENDPOINT_ACM); + } +#endif + +#if defined(PLUGGABLE_USB_ENABLED) + // Empty +#endif +} + +void USBDeviceClass::init() +{ +#ifdef PIN_LED_TXL + txLEDPulse = 0; + pinMode(PIN_LED_TXL, OUTPUT); + digitalWrite(PIN_LED_TXL, HIGH); +#endif + +#ifdef PIN_LED_RXL + rxLEDPulse = 0; + pinMode(PIN_LED_RXL, OUTPUT); + digitalWrite(PIN_LED_RXL, HIGH); +#endif + + // Enable USB clock + PM->APBBMASK.reg |= PM_APBBMASK_USB; + + // Set up the USB DP/DN pins + PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u))); + PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u)); + PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1; + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u))); + PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u)); + + // Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference) + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | // Generic Clock Multiplexer 6 + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY) + ; + + USB_SetHandler(&UDD_Handler); + + // Reset USB Device + usbd.reset(); + + usbd.calibrate(); + usbd.setUSBDeviceMode(); + usbd.runInStandby(); + usbd.setFullSpeed(); + + // Configure interrupts + NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL); + NVIC_EnableIRQ((IRQn_Type) USB_IRQn); + + usbd.enable(); + + initialized = true; +} + +bool USBDeviceClass::attach() +{ + if (!initialized) + return false; + + usbd.attach(); + usbd.enableEndOfResetInterrupt(); + usbd.enableStartOfFrameInterrupt(); + + _usbConfiguration = 0; + return true; +} + +void USBDeviceClass::setAddress(uint32_t addr) +{ + usbd.epBank1SetByteCount(0, 0); + usbd.epBank1AckTransferComplete(0); + + // RAM buffer is full, we can send data (IN) + usbd.epBank1SetReady(0); + + // Wait for transfer to complete + while (!usbd.epBank1IsTransferComplete(0)) {} + + // Set USB address to addr + USB->DEVICE.DADD.bit.DADD = addr; // Address + USB->DEVICE.DADD.bit.ADDEN = 1; // Enable +} + +bool USBDeviceClass::detach() +{ + if (!initialized) + return false; + usbd.detach(); + return true; +} + +bool USBDeviceClass::configured() +{ + return _usbConfiguration != 0; +} + +bool USBDeviceClass::handleClassInterfaceSetup(USBSetup& setup) +{ + uint8_t i = setup.wIndex; + + #if defined(CDC_ENABLED) + if (CDC_ACM_INTERFACE == i) + { + if (CDC_Setup(setup) == false) { + sendZlp(0); + } + return true; + } + #endif + + #if defined(PLUGGABLE_USB_ENABLED) + bool ret = PluggableUSB().setup(setup); + if ( ret == false) { + sendZlp(0); + } + return ret; + #endif + + return false; +} + +uint32_t EndPoints[] = +{ + USB_ENDPOINT_TYPE_CONTROL, + +#ifdef CDC_ENABLED + USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_ACM + USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0), // CDC_ENDPOINT_OUT + USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_IN +#endif + +#ifdef PLUGGABLE_USB_ENABLED + //allocate 6 endpoints and remove const so they can be changed by the user + 0, + 0, + 0, + 0, + 0, + 0, +#endif +}; + +void USBDeviceClass::initEndpoints() { + for (uint8_t i = 1; i < sizeof(EndPoints) && EndPoints[i] != 0; i++) { + initEP(i, EndPoints[i]); + } +} + +void USBDeviceClass::initEP(uint32_t ep, uint32_t config) +{ + if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0))) + { + usbd.epBank1SetSize(ep, 64); + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + usbd.epBank1SetType(ep, 4); // INTERRUPT IN + } + else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0))) + { + epHandlers[ep] = new DoubleBufferedEPOutHandler(usbd, ep, 256); + } + else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0))) + { + usbd.epBank1SetSize(ep, 64); + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + + // NAK on endpoint IN, the bank is not yet filled in. + usbd.epBank1ResetReady(ep); + + usbd.epBank1SetType(ep, 3); // BULK IN + } + else if (config == USB_ENDPOINT_TYPE_CONTROL) + { + // Setup Control OUT + usbd.epBank0SetSize(ep, 64); + usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]); + usbd.epBank0SetType(ep, 1); // CONTROL OUT / SETUP + + // Setup Control IN + usbd.epBank1SetSize(ep, 64); + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[0]); + usbd.epBank1SetType(ep, 1); // CONTROL IN + + // Release OUT EP + usbd.epBank0SetMultiPacketSize(ep, 64); + usbd.epBank0SetByteCount(ep, 0); + + // NAK on endpoint OUT, the bank is full. + usbd.epBank0SetReady(ep); + } +} + +void USBDeviceClass::flush(uint32_t ep) +{ + if (available(ep)) { + // RAM buffer is full, we can send data (IN) + usbd.epBank1SetReady(ep); + + // Clear the transfer complete flag + usbd.epBank1AckTransferComplete(ep); + } +} + +void USBDeviceClass::stall(uint32_t ep) +{ + // TODO: test + // TODO: use .bit. notation + + // Stall endpoint + USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ(2); +} + +bool USBDeviceClass::connected() +{ + // Count frame numbers + uint8_t f = USB->DEVICE.FNUM.bit.FNUM; + //delay(3); + return f != USB->DEVICE.FNUM.bit.FNUM; +} + + +uint32_t USBDeviceClass::recvControl(void *_data, uint32_t len) +{ + uint8_t *data = reinterpret_cast(_data); + + // The RAM Buffer is empty: we can receive data + usbd.epBank0ResetReady(0); + + //usbd.epBank0AckSetupReceived(0); + uint32_t read = armRecvCtrlOUT(0); + if (read > len) + read = len; + //while (!usbd.epBank0AckTransferComplete(0)) {} + uint8_t *buffer = udd_ep_out_cache_buffer[0]; + for (uint32_t i=0; iavailable(); + } else { + return usbd.epBank0ByteCount(ep); + } +} + +// Non Blocking receive +// Return number of bytes read +uint32_t USBDeviceClass::recv(uint32_t ep, void *_data, uint32_t len) +{ + if (!_usbConfiguration) + return -1; + +#ifdef PIN_LED_RXL + if (rxLEDPulse == 0) + digitalWrite(PIN_LED_RXL, LOW); + + rxLEDPulse = TX_RX_LED_PULSE_MS; +#endif + + if (epHandlers[ep]) { + return epHandlers[ep]->recv(_data, len); + } + + if (available(ep) < len) + len = available(ep); + + armRecv(ep); + + usbd.epBank0DisableTransferComplete(ep); + + memcpy(_data, udd_ep_out_cache_buffer[ep], len); + + // release empty buffer + if (len && !available(ep)) { + // The RAM Buffer is empty: we can receive data + usbd.epBank0ResetReady(ep); + + // Clear Transfer complete 0 flag + usbd.epBank0AckTransferComplete(ep); + + // Enable Transfer complete 0 interrupt + usbd.epBank0EnableTransferComplete(ep); + } + + return len; +} + +// Recv 1 byte if ready +int USBDeviceClass::recv(uint32_t ep) +{ + uint8_t c; + if (recv(ep, &c, 1) != 1) { + return -1; + } else { + return c; + } +} + +uint8_t USBDeviceClass::armRecvCtrlOUT(uint32_t ep) +{ + // Get endpoint configuration from setting register + usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]); + usbd.epBank0SetMultiPacketSize(ep, 8); + usbd.epBank0SetByteCount(ep, 0); + + usbd.epBank0ResetReady(ep); + + // Wait OUT + while (!usbd.epBank0IsReady(ep)) {} + while (!usbd.epBank0IsTransferComplete(ep)) {} + return usbd.epBank0ByteCount(ep); +} + +uint8_t USBDeviceClass::armRecv(uint32_t ep) +{ + uint16_t count = usbd.epBank0ByteCount(ep); + if (count >= 64) { + usbd.epBank0SetByteCount(ep, count - 64); + } else { + usbd.epBank0SetByteCount(ep, 0); + } + return usbd.epBank0ByteCount(ep); +} + +// Timeout for sends +#define TX_TIMEOUT_MS 70 + +static char LastTransmitTimedOut[7] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0 +}; + +// Blocking Send of data to an endpoint +uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len) +{ + uint32_t written = 0; + uint32_t length = 0; + + if (!_usbConfiguration) + return -1; + if (len > 16384) + return -1; + +#ifdef PIN_LED_TXL + if (txLEDPulse == 0) + digitalWrite(PIN_LED_TXL, LOW); + + txLEDPulse = TX_RX_LED_PULSE_MS; +#endif + + // Flash area + while (len != 0) + { + if (usbd.epBank1IsReady(ep)) { + // previous transfer is still not complete + + // convert the timeout from microseconds to a number of times through + // the wait loop; it takes (roughly) 23 clock cycles per iteration. + uint32_t timeout = microsecondsToClockCycles(TX_TIMEOUT_MS * 1000) / 23; + + // Wait for (previous) transfer to complete + // inspired by Paul Stoffregen's work on Teensy + while (!usbd.epBank1IsTransferComplete(ep)) { + if (LastTransmitTimedOut[ep] || timeout-- == 0) { + LastTransmitTimedOut[ep] = 1; + + // set byte count to zero, so that ZLP is sent + // instead of stale data + usbd.epBank1SetByteCount(ep, 0); + return -1; + } + } + } + + LastTransmitTimedOut[ep] = 0; + + if (len >= EPX_SIZE) { + length = EPX_SIZE - 1; + } else { + length = len; + } + + /* memcopy could be safer in multi threaded environment */ + memcpy(&udd_ep_in_cache_buffer[ep], data, length); + + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + usbd.epBank1SetByteCount(ep, length); + + // Clear the transfer complete flag + usbd.epBank1AckTransferComplete(ep); + + // RAM buffer is full, we can send data (IN) + usbd.epBank1SetReady(ep); + + written += length; + len -= length; + data = (char *)data + length; + } + return written; +} + +uint32_t USBDeviceClass::armSend(uint32_t ep, const void* data, uint32_t len) +{ + memcpy(&udd_ep_in_cache_buffer[ep], data, len); + + // Get endpoint configuration from setting register + usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]); + usbd.epBank1SetMultiPacketSize(ep, 0); + usbd.epBank1SetByteCount(ep, len); + + return len; +} + +uint32_t USBDeviceClass::sendControl(const void* _data, uint32_t len) +{ + const uint8_t *data = reinterpret_cast(_data); + uint32_t length = len; + uint32_t sent = 0; + uint32_t pos = 0; + + if (_dry_run == true) + return length; + + if (_pack_message == true) { + memcpy(&_pack_buffer[_pack_size], data, len); + _pack_size += len; + return length; + } + + while (len > 0) + { + sent = armSend(EP0, data + pos, len); + pos += sent; + len -= sent; + } + + return length; +} + +void USBDeviceClass::sendZlp(uint32_t ep) +{ + // Set the byte count as zero + usbd.epBank1SetByteCount(ep, 0); +} + +bool USBDeviceClass::handleStandardSetup(USBSetup &setup) +{ + switch (setup.bRequest) { + case GET_STATUS: + if (setup.bmRequestType == 0) // device + { + // Send the device status + // TODO: Check current configuration for power mode (if device is configured) + // TODO: Check if remote wake-up is enabled + uint8_t buff[] = { 0, 0 }; + armSend(0, buff, 2); + return true; + } + // if( setup.bmRequestType == 2 ) // Endpoint: + else + { + // Send the endpoint status + // Check if the endpoint if currently halted + uint8_t buff[] = { 0, 0 }; + if (isEndpointHalt == 1) + buff[0] = 1; + armSend(0, buff, 2); + return true; + } + + case CLEAR_FEATURE: + // Check which is the selected feature + if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP + { + // Enable remote wake-up and send a ZLP + uint8_t buff[] = { 0, 0 }; + if (isRemoteWakeUpEnabled == 1) + buff[0] = 1; + armSend(0, buff, 2); + return true; + } + else // if( setup.wValueL == 0) // ENDPOINTHALT + { + isEndpointHalt = 0; + sendZlp(0); + return true; + } + + case SET_FEATURE: + // Check which is the selected feature + if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP + { + // Enable remote wake-up and send a ZLP + isRemoteWakeUpEnabled = 1; + uint8_t buff[] = { 0 }; + armSend(0, buff, 1); + return true; + } + if (setup.wValueL == 0) // ENDPOINTHALT + { + // Halt endpoint + isEndpointHalt = 1; + sendZlp(0); + return true; + } + + case SET_ADDRESS: + setAddress(setup.wValueL); + return true; + + case GET_DESCRIPTOR: + return sendDescriptor(setup); + + case SET_DESCRIPTOR: + return false; + + case GET_CONFIGURATION: + armSend(0, (void*)&_usbConfiguration, 1); + return true; + + case SET_CONFIGURATION: + if (REQUEST_DEVICE == (setup.bmRequestType & REQUEST_RECIPIENT)) { + + initEndpoints(); + _usbConfiguration = setup.wValueL; + + #if defined(CDC_ENABLED) + // Enable interrupt for CDC reception from host (OUT packet) + usbd.epBank1EnableTransferComplete(CDC_ENDPOINT_ACM); + usbd.epBank0EnableTransferComplete(CDC_ENDPOINT_OUT); + #endif + + sendZlp(0); + return true; + } else { + return false; + } + + case GET_INTERFACE: + armSend(0, (void*)&_usbSetInterface, 1); + return true; + + case SET_INTERFACE: + _usbSetInterface = setup.wValueL; + sendZlp(0); + return true; + + default: + return true; + } +} + +void USBDeviceClass::ISRHandler() +{ + + if (_pack_message == true) { + return; + } + // End-Of-Reset + if (usbd.isEndOfResetInterrupt()) + { + // Configure EP 0 + initEP(0, USB_ENDPOINT_TYPE_CONTROL); + + // Enable Setup-Received interrupt + usbd.epBank0EnableSetupReceived(0); + + _usbConfiguration = 0; + + usbd.ackEndOfResetInterrupt(); + } + + // Start-Of-Frame + if (usbd.isStartOfFrameInterrupt()) + { + usbd.ackStartOfFrameInterrupt(); + + // check whether the one-shot period has elapsed. if so, turn off the LED +#ifdef PIN_LED_TXL + if (txLEDPulse > 0) { + txLEDPulse--; + if (txLEDPulse == 0) + digitalWrite(PIN_LED_TXL, HIGH); + } +#endif + +#ifdef PIN_LED_RXL + if (rxLEDPulse > 0) { + rxLEDPulse--; + if (rxLEDPulse == 0) + digitalWrite(PIN_LED_RXL, HIGH); + } +#endif + } + + // Endpoint 0 Received Setup interrupt + if (usbd.epBank0IsSetupReceived(0)) + { + usbd.epBank0AckSetupReceived(0); + + USBSetup *setup = reinterpret_cast(udd_ep_out_cache_buffer[0]); + + /* Clear the Bank 0 ready flag on Control OUT */ + // The RAM Buffer is empty: we can receive data + usbd.epBank0ResetReady(0); + + bool ok; + if (REQUEST_STANDARD == (setup->bmRequestType & REQUEST_TYPE)) { + // Standard Requests + ok = handleStandardSetup(*setup); + } else { + // Class Interface Requests + ok = handleClassInterfaceSetup(*setup); + } + + if (ok) { + usbd.epBank1SetReady(0); + } else { + stall(0); + } + + if (usbd.epBank1IsStalled(0)) + { + usbd.epBank1AckStalled(0); + + // Remove stall request + usbd.epBank1DisableStalled(0); + } + + } // end Received Setup handler + + uint8_t i=0; + uint8_t ept_int = usbd.epInterruptSummary() & 0xFE; // Remove endpoint number 0 (setup) + while (ept_int != 0) + { + // Check if endpoint has a pending interrupt + if ((ept_int & (1 << i)) != 0) + { + // Endpoint Transfer Complete (0/1) Interrupt + if (usbd.epBank0IsTransferComplete(i) || + usbd.epBank1IsTransferComplete(i)) + { + if (epHandlers[i]) { + epHandlers[i]->handleEndpoint(); + } else { + handleEndpoint(i); + } + } + ept_int &= ~(1 << i); + } + i++; + if (i > USB_EPT_NUM) + break; // fire exit + } +} + +/* + * USB Device instance + * ------------------- + */ + +// USBDevice class instance +USBDeviceClass USBDevice; + diff --git a/sparkfun/samd/cores/LilyMini/USB/USBCore.h b/sparkfun/samd/cores/LilyMini/USB/USBCore.h new file mode 100644 index 00000000..269218d4 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/USBCore.h @@ -0,0 +1,290 @@ +/* + Copyright (c) 2014 Arduino LLC. 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 +*/ + +#ifndef __USBCORE_H__ +#define __USBCORE_H__ + +// Standard requests +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 +#define SET_FEATURE 3 +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define SET_DESCRIPTOR 7 +#define GET_CONFIGURATION 8 +#define SET_CONFIGURATION 9 +#define GET_INTERFACE 10 +#define SET_INTERFACE 11 + +// bEndpointAddress in Endpoint Descriptor +#define USB_ENDPOINT_DIRECTION_MASK 0x80 +#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) +#define USB_ENDPOINT_IN(addr) ((addr) | 0x80) + +#define USB_ENDPOINTS 7 + +#define USB_ENDPOINT_TYPE_MASK 0x03 +#define USB_ENDPOINT_TYPE_CONTROL 0x00 +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_TYPE_BULK 0x02 +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 + +// bmRequestType +#define REQUEST_HOSTTODEVICE 0x00 +#define REQUEST_DEVICETOHOST 0x80 +#define REQUEST_DIRECTION 0x80 + +#define REQUEST_STANDARD 0x00 +#define REQUEST_CLASS 0x20 +#define REQUEST_VENDOR 0x40 +#define REQUEST_TYPE 0x60 + +#define REQUEST_DEVICE 0x00 +#define REQUEST_INTERFACE 0x01 +#define REQUEST_ENDPOINT 0x02 +#define REQUEST_OTHER 0x03 +#define REQUEST_RECIPIENT 0x1F + +#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) +// Class requests + +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 + +#define MSC_RESET 0xFF +#define MSC_GET_MAX_LUN 0xFE + +// Descriptors + +// #define USB_DEVICE_DESC_SIZE 18 +// #define USB_CONFIGUARTION_DESC_SIZE 9 +// #define USB_INTERFACE_DESC_SIZE 9 +// #define USB_ENDPOINT_DESC_SIZE 7 + +#define USB_DEVICE_DESCRIPTOR_TYPE 1 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2 +#define USB_STRING_DESCRIPTOR_TYPE 3 +#define USB_INTERFACE_DESCRIPTOR_TYPE 4 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 5 +#define USB_DEVICE_QUALIFIER 6 +#define USB_OTHER_SPEED_CONFIGURATION 7 + +#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#define USB_DEVICE_CLASS_STORAGE 0x08 +#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF + +#define USB_CONFIG_POWERED_MASK 0x40 +#define USB_CONFIG_BUS_POWERED 0x80 +#define USB_CONFIG_SELF_POWERED 0xC0 +#define USB_CONFIG_REMOTE_WAKEUP 0x20 + +// bMaxPower in Configuration Descriptor +#define USB_CONFIG_POWER_MA(mA) ((mA)/2) + +#define CDC_V1_10 0x0110 +#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 + +#define CDC_CALL_MANAGEMENT 0x01 +#define CDC_ABSTRACT_CONTROL_MODEL 0x02 +#define CDC_HEADER 0x00 +#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 +#define CDC_UNION 0x06 +#define CDC_CS_INTERFACE 0x24 +#define CDC_CS_ENDPOINT 0x25 +#define CDC_DATA_INTERFACE_CLASS 0x0A + +#define MSC_SUBCLASS_SCSI 0x06 +#define MSC_PROTOCOL_BULK_ONLY 0x50 + +_Pragma("pack(1)") + +// Device +typedef struct { + uint8_t len; // 18 + uint8_t dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE + uint16_t usbVersion; // 0x200 + uint8_t deviceClass; + uint8_t deviceSubClass; + uint8_t deviceProtocol; + uint8_t packetSize0; // Packet 0 + uint16_t idVendor; + uint16_t idProduct; + uint16_t deviceVersion; // 0x100 + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} DeviceDescriptor; + +// Config +typedef struct { + uint8_t len; // 9 + uint8_t dtype; // 2 + uint16_t clen; // total length + uint8_t numInterfaces; + uint8_t config; + uint8_t iconfig; + uint8_t attributes; + uint8_t maxPower; +} ConfigDescriptor; + +// String + +// Interface +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 4 + uint8_t number; + uint8_t alternate; + uint8_t numEndpoints; + uint8_t interfaceClass; + uint8_t interfaceSubClass; + uint8_t protocol; + uint8_t iInterface; +} InterfaceDescriptor; + +// Endpoint +typedef struct +{ + uint8_t len; // 7 + uint8_t dtype; // 5 + uint8_t addr; + uint8_t attr; + uint16_t packetSize; + uint8_t interval; +} EndpointDescriptor; + +// Interface Association Descriptor +// Used to bind 2 interfaces together in CDC compostite device +typedef struct +{ + uint8_t len; // 8 + uint8_t dtype; // 11 + uint8_t firstInterface; + uint8_t interfaceCount; + uint8_t functionClass; + uint8_t funtionSubClass; + uint8_t functionProtocol; + uint8_t iInterface; +} IADDescriptor; + +// CDC CS interface descriptor +typedef struct +{ + uint8_t len; // 5 + uint8_t dtype; // 0x24 + uint8_t subtype; + uint8_t d0; + uint8_t d1; +} CDCCSInterfaceDescriptor; + +typedef struct +{ + uint8_t len; // 4 + uint8_t dtype; // 0x24 + uint8_t subtype; + uint8_t d0; +} CDCCSInterfaceDescriptor4; + +typedef struct +{ + uint8_t len; + uint8_t dtype; // 0x24 + uint8_t subtype; // 1 + uint8_t bmCapabilities; + uint8_t bDataInterface; +} CMFunctionalDescriptor; + +typedef struct +{ + uint8_t len; + uint8_t dtype; // 0x24 + uint8_t subtype; // 1 + uint8_t bmCapabilities; +} ACMFunctionalDescriptor; + +typedef struct +{ + // IAD + IADDescriptor iad; // Only needed on compound device + // Control + InterfaceDescriptor cif; + CDCCSInterfaceDescriptor header; + ACMFunctionalDescriptor controlManagement; // ACM + CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION + CMFunctionalDescriptor callManagement; // Call Management + EndpointDescriptor cifin; + + // Data + InterfaceDescriptor dif; + EndpointDescriptor in; + EndpointDescriptor out; +} CDCDescriptor; + +typedef struct +{ + InterfaceDescriptor msc; + EndpointDescriptor in; + EndpointDescriptor out; +} MSCDescriptor; + +_Pragma("pack()") + +#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ + { 18, 1, 0x0110, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } +// 0x0110 = USB 1.1 +// { 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } +/* Table 9-8. Standard Device Descriptor + * bLength, bDescriptorType, bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0, + * idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber, bNumConfigurations */ + +#define D_CONFIG(_totalLength,_interfaces) \ + { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) } +/* Table 9-10. Standard Configuration Descriptor + * bLength, bDescriptorType, wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration + * bmAttributes, bMaxPower */ + +#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ + { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } +/* Table 9-12. Standard Interface Descriptor + * bLength, bDescriptorType, bInterfaceNumber, bAlternateSetting, bNumEndpoints, bInterfaceClass, + * bInterfaceSubClass, bInterfaceProtocol, iInterface */ + +#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \ + { 7, 5, _addr,_attr,_packetSize, _interval } +/* Table 9-13. Standard Endpoint Descriptor + * bLength, bDescriptorType, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval */ + +#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ + { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } +/* iadclasscode_r10.pdf, Table 9\96Z. Standard Interface Association Descriptor + * bLength, bDescriptorType, bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol, iFunction */ + +// Functional Descriptor General Format +#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } +#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } +/* bFunctionLength, bDescriptorType, bDescriptorSubtype, function specific data0, functional specific data N-1 + * CS_INTERFACE 24h */ + +#endif diff --git a/sparkfun/samd/cores/LilyMini/USB/USBCore.h.bak b/sparkfun/samd/cores/LilyMini/USB/USBCore.h.bak new file mode 100644 index 00000000..1b575f91 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/USBCore.h.bak @@ -0,0 +1,288 @@ +/* + Copyright (c) 2014 Arduino LLC. 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 +*/ + +#ifndef __USBCORE_H__ +#define __USBCORE_H__ + +// Standard requests +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 +#define SET_FEATURE 3 +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define SET_DESCRIPTOR 7 +#define GET_CONFIGURATION 8 +#define SET_CONFIGURATION 9 +#define GET_INTERFACE 10 +#define SET_INTERFACE 11 + +// bEndpointAddress in Endpoint Descriptor +#define USB_ENDPOINT_DIRECTION_MASK 0x80 +#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) +#define USB_ENDPOINT_IN(addr) ((addr) | 0x80) + +#define USB_ENDPOINTS 7 + +#define USB_ENDPOINT_TYPE_MASK 0x03 +#define USB_ENDPOINT_TYPE_CONTROL 0x00 +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_TYPE_BULK 0x02 +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 + +// bmRequestType +#define REQUEST_HOSTTODEVICE 0x00 +#define REQUEST_DEVICETOHOST 0x80 +#define REQUEST_DIRECTION 0x80 + +#define REQUEST_STANDARD 0x00 +#define REQUEST_CLASS 0x20 +#define REQUEST_VENDOR 0x40 +#define REQUEST_TYPE 0x60 + +#define REQUEST_DEVICE 0x00 +#define REQUEST_INTERFACE 0x01 +#define REQUEST_ENDPOINT 0x02 +#define REQUEST_OTHER 0x03 +#define REQUEST_RECIPIENT 0x1F + +#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) +// Class requests + +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 + +#define MSC_RESET 0xFF +#define MSC_GET_MAX_LUN 0xFE + +// Descriptors + +// #define USB_DEVICE_DESC_SIZE 18 +// #define USB_CONFIGUARTION_DESC_SIZE 9 +// #define USB_INTERFACE_DESC_SIZE 9 +// #define USB_ENDPOINT_DESC_SIZE 7 + +#define USB_DEVICE_DESCRIPTOR_TYPE 1 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2 +#define USB_STRING_DESCRIPTOR_TYPE 3 +#define USB_INTERFACE_DESCRIPTOR_TYPE 4 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 5 +#define USB_DEVICE_QUALIFIER 6 +#define USB_OTHER_SPEED_CONFIGURATION 7 + +#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#define USB_DEVICE_CLASS_STORAGE 0x08 +#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF + +#define USB_CONFIG_POWERED_MASK 0x40 +#define USB_CONFIG_BUS_POWERED 0x80 +#define USB_CONFIG_SELF_POWERED 0xC0 +#define USB_CONFIG_REMOTE_WAKEUP 0x20 + +// bMaxPower in Configuration Descriptor +#define USB_CONFIG_POWER_MA(mA) ((mA)/2) + +#define CDC_V1_10 0x0110 +#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 + +#define CDC_CALL_MANAGEMENT 0x01 +#define CDC_ABSTRACT_CONTROL_MODEL 0x02 +#define CDC_HEADER 0x00 +#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 +#define CDC_UNION 0x06 +#define CDC_CS_INTERFACE 0x24 +#define CDC_CS_ENDPOINT 0x25 +#define CDC_DATA_INTERFACE_CLASS 0x0A + +#define MSC_SUBCLASS_SCSI 0x06 +#define MSC_PROTOCOL_BULK_ONLY 0x50 + +_Pragma("pack(1)") + +// Device +typedef struct { + uint8_t len; // 18 + uint8_t dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE + uint16_t usbVersion; // 0x200 + uint8_t deviceClass; + uint8_t deviceSubClass; + uint8_t deviceProtocol; + uint8_t packetSize0; // Packet 0 + uint16_t idVendor; + uint16_t idProduct; + uint16_t deviceVersion; // 0x100 + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} DeviceDescriptor; + +// Config +typedef struct { + uint8_t len; // 9 + uint8_t dtype; // 2 + uint16_t clen; // total length + uint8_t numInterfaces; + uint8_t config; + uint8_t iconfig; + uint8_t attributes; + uint8_t maxPower; +} ConfigDescriptor; + +// String + +// Interface +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 4 + uint8_t number; + uint8_t alternate; + uint8_t numEndpoints; + uint8_t interfaceClass; + uint8_t interfaceSubClass; + uint8_t protocol; + uint8_t iInterface; +} InterfaceDescriptor; + +// Endpoint +typedef struct +{ + uint8_t len; // 7 + uint8_t dtype; // 5 + uint8_t addr; + uint8_t attr; + uint16_t packetSize; + uint8_t interval; +} EndpointDescriptor; + +// Interface Association Descriptor +// Used to bind 2 interfaces together in CDC compostite device +typedef struct +{ + uint8_t len; // 8 + uint8_t dtype; // 11 + uint8_t firstInterface; + uint8_t interfaceCount; + uint8_t functionClass; + uint8_t funtionSubClass; + uint8_t functionProtocol; + uint8_t iInterface; +} IADDescriptor; + +// CDC CS interface descriptor +typedef struct +{ + uint8_t len; // 5 + uint8_t dtype; // 0x24 + uint8_t subtype; + uint8_t d0; + uint8_t d1; +} CDCCSInterfaceDescriptor; + +typedef struct +{ + uint8_t len; // 4 + uint8_t dtype; // 0x24 + uint8_t subtype; + uint8_t d0; +} CDCCSInterfaceDescriptor4; + +typedef struct +{ + uint8_t len; + uint8_t dtype; // 0x24 + uint8_t subtype; // 1 + uint8_t bmCapabilities; + uint8_t bDataInterface; +} CMFunctionalDescriptor; + +typedef struct +{ + uint8_t len; + uint8_t dtype; // 0x24 + uint8_t subtype; // 1 + uint8_t bmCapabilities; +} ACMFunctionalDescriptor; + +typedef struct +{ + // IAD + IADDescriptor iad; // Only needed on compound device + // Control + InterfaceDescriptor cif; + CDCCSInterfaceDescriptor header; + ACMFunctionalDescriptor controlManagement; // ACM + CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION + CMFunctionalDescriptor callManagement; // Call Management + EndpointDescriptor cifin; + + // Data + InterfaceDescriptor dif; + EndpointDescriptor in; + EndpointDescriptor out; +} CDCDescriptor; + +typedef struct +{ + InterfaceDescriptor msc; + EndpointDescriptor in; + EndpointDescriptor out; +} MSCDescriptor; + +_Pragma("pack()") + +#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ + { 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } +/* Table 9-8. Standard Device Descriptor + * bLength, bDescriptorType, bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0, + * idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber, bNumConfigurations */ + +#define D_CONFIG(_totalLength,_interfaces) \ + { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) } +/* Table 9-10. Standard Configuration Descriptor + * bLength, bDescriptorType, wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration + * bmAttributes, bMaxPower */ + +#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ + { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } +/* Table 9-12. Standard Interface Descriptor + * bLength, bDescriptorType, bInterfaceNumber, bAlternateSetting, bNumEndpoints, bInterfaceClass, + * bInterfaceSubClass, bInterfaceProtocol, iInterface */ + +#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \ + { 7, 5, _addr,_attr,_packetSize, _interval } +/* Table 9-13. Standard Endpoint Descriptor + * bLength, bDescriptorType, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval */ + +#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ + { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } +/* iadclasscode_r10.pdf, Table 9\96Z. Standard Interface Association Descriptor + * bLength, bDescriptorType, bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol, iFunction */ + +// Functional Descriptor General Format +#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } +#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } +/* bFunctionLength, bDescriptorType, bDescriptorSubtype, function specific data0, functional specific data N-1 + * CS_INTERFACE 24h */ + +#endif diff --git a/sparkfun/samd/cores/LilyMini/USB/USBDesc.h b/sparkfun/samd/cores/LilyMini/USB/USBDesc.h new file mode 100644 index 00000000..e4335aa9 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/USB/USBDesc.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2014 Arduino LLC. 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 +*/ + +#ifndef __USBDESC_H__ +#define __USBDESC_H__ + +// CDC or HID can be enabled together. +#define CDC_ENABLED +#define PLUGGABLE_USB_ENABLED + +#ifdef CDC_ENABLED +#define CDC_INTERFACE_COUNT 2 +#define CDC_ENPOINT_COUNT 3 +#endif + +// CDC +#define CDC_ACM_INTERFACE 0 // CDC ACM +#define CDC_DATA_INTERFACE 1 // CDC Data +#define CDC_FIRST_ENDPOINT 1 +#define CDC_ENDPOINT_ACM 1 +#define CDC_ENDPOINT_OUT 2 +#define CDC_ENDPOINT_IN 3 + +#ifdef CDC_ENABLED +#define CDC_RX CDC_ENDPOINT_OUT +#define CDC_TX CDC_ENDPOINT_IN +#endif + +#define ISERIAL_MAX_LEN 20 + +// Defined string description +#define IMANUFACTURER 1 +#define IPRODUCT 2 +#define ISERIAL 3 + +#endif /* __USBDESC_H__ */ diff --git a/sparkfun/samd/cores/LilyMini/Uart.cpp b/sparkfun/samd/cores/LilyMini/Uart.cpp new file mode 100644 index 00000000..13e0ebaa --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Uart.cpp @@ -0,0 +1,148 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "Uart.h" +#include "Arduino.h" +#include "wiring_private.h" + +Uart::Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, SercomUartTXPad _padTX) +{ + sercom = _s; + uc_pinRX = _pinRX; + uc_pinTX = _pinTX; + uc_padRX=_padRX ; + uc_padTX=_padTX; +} + +void Uart::begin(unsigned long baudrate) +{ + begin(baudrate, (uint8_t)SERIAL_8N1); +} + +void Uart::begin(unsigned long baudrate, uint16_t config) +{ + pinPeripheral(uc_pinRX, g_APinDescription[uc_pinRX].ulPinType); + pinPeripheral(uc_pinTX, g_APinDescription[uc_pinTX].ulPinType); + + sercom->initUART(UART_INT_CLOCK, SAMPLE_RATE_x16, baudrate); + sercom->initFrame(extractCharSize(config), LSB_FIRST, extractParity(config), extractNbStopBit(config)); + sercom->initPads(uc_padTX, uc_padRX); + + sercom->enableUART(); +} + +void Uart::end() +{ + sercom->resetUART(); + rxBuffer.clear(); +} + +void Uart::flush() +{ + sercom->flushUART(); +} + +void Uart::IrqHandler() +{ + if (sercom->availableDataUART()) { + rxBuffer.store_char(sercom->readDataUART()); + } + + if (sercom->isUARTError()) { + sercom->acknowledgeUARTError(); + // TODO: if (sercom->isBufferOverflowErrorUART()) .... + // TODO: if (sercom->isFrameErrorUART()) .... + // TODO: if (sercom->isParityErrorUART()) .... + sercom->clearStatusUART(); + } +} + +int Uart::available() +{ + return rxBuffer.available(); +} + +int Uart::availableForWrite() +{ + return (sercom->isDataRegisterEmptyUART() ? 1 : 0); +} + +int Uart::peek() +{ + return rxBuffer.peek(); +} + +int Uart::read() +{ + return rxBuffer.read_char(); +} + +size_t Uart::write(const uint8_t data) +{ + sercom->writeDataUART(data); + return 1; +} + +SercomNumberStopBit Uart::extractNbStopBit(uint16_t config) +{ + switch(config & HARDSER_STOP_BIT_MASK) + { + case HARDSER_STOP_BIT_1: + default: + return SERCOM_STOP_BIT_1; + + case HARDSER_STOP_BIT_2: + return SERCOM_STOP_BITS_2; + } +} + +SercomUartCharSize Uart::extractCharSize(uint16_t config) +{ + switch(config & HARDSER_DATA_MASK) + { + case HARDSER_DATA_5: + return UART_CHAR_SIZE_5_BITS; + + case HARDSER_DATA_6: + return UART_CHAR_SIZE_6_BITS; + + case HARDSER_DATA_7: + return UART_CHAR_SIZE_7_BITS; + + case HARDSER_DATA_8: + default: + return UART_CHAR_SIZE_8_BITS; + + } +} + +SercomParityMode Uart::extractParity(uint16_t config) +{ + switch(config & HARDSER_PARITY_MASK) + { + case HARDSER_PARITY_NONE: + default: + return SERCOM_NO_PARITY; + + case HARDSER_PARITY_EVEN: + return SERCOM_EVEN_PARITY; + + case HARDSER_PARITY_ODD: + return SERCOM_ODD_PARITY; + } +} diff --git a/sparkfun/samd/cores/LilyMini/Uart.h b/sparkfun/samd/cores/LilyMini/Uart.h new file mode 100644 index 00000000..02d30bd4 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/Uart.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#include "HardwareSerial.h" +#include "SERCOM.h" +#include "RingBuffer.h" + +#include + +class Uart : public HardwareSerial +{ + public: + Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, SercomUartTXPad _padTX); + void begin(unsigned long baudRate); + void begin(unsigned long baudrate, uint16_t config); + void end(); + int available(); + int availableForWrite(); + int peek(); + int read(); + void flush(); + size_t write(const uint8_t data); + using Print::write; // pull in write(str) and write(buf, size) from Print + + void IrqHandler(); + + operator bool() { return true; } + + private: + SERCOM *sercom; + RingBuffer rxBuffer; + + uint8_t uc_pinRX; + uint8_t uc_pinTX; + SercomRXPad uc_padRX; + SercomUartTXPad uc_padTX; + + SercomNumberStopBit extractNbStopBit(uint16_t config); + SercomUartCharSize extractCharSize(uint16_t config); + SercomParityMode extractParity(uint16_t config); +}; diff --git a/sparkfun/samd/cores/LilyMini/WCharacter.h b/sparkfun/samd/cores/LilyMini/WCharacter.h new file mode 100644 index 00000000..c0cbec7a --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WCharacter.h @@ -0,0 +1,179 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef Character_h +#define Character_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// WCharacter.h prototypes +#if defined ( __GNUC__ ) +inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); +inline boolean isAlpha(int c) __attribute__((always_inline)); +inline boolean isAscii(int c) __attribute__((always_inline)); +inline boolean isWhitespace(int c) __attribute__((always_inline)); +inline boolean isControl(int c) __attribute__((always_inline)); +inline boolean isDigit(int c) __attribute__((always_inline)); +inline boolean isGraph(int c) __attribute__((always_inline)); +inline boolean isLowerCase(int c) __attribute__((always_inline)); +inline boolean isPrintable(int c) __attribute__((always_inline)); +inline boolean isPunct(int c) __attribute__((always_inline)); +inline boolean isSpace(int c) __attribute__((always_inline)); +inline boolean isUpperCase(int c) __attribute__((always_inline)); +inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); +inline int toAscii(int c) __attribute__((always_inline)); +inline int toLowerCase(int c) __attribute__((always_inline)); +inline int toUpperCase(int c)__attribute__((always_inline)); +#elif defined ( __ICCARM__ ) +#endif + +// Checks for an alphanumeric character. +// It is equivalent to (isalpha(c) || isdigit(c)). +inline boolean isAlphaNumeric(int c) +{ + return ( isalnum(c) == 0 ? false : true); +} + + +// Checks for an alphabetic character. +// It is equivalent to (isupper(c) || islower(c)). +inline boolean isAlpha(int c) +{ + return ( isalpha(c) == 0 ? false : true); +} + + +// Checks whether c is a 7-bit unsigned char value +// that fits into the ASCII character set. +inline boolean isAscii(int c) +{ +/* return ( isascii(c) == 0 ? false : true); */ + return ( (c & ~0x7f) != 0 ? false : true); +} + + +// Checks for a blank character, that is, a space or a tab. +inline boolean isWhitespace(int c) +{ + return ( isblank (c) == 0 ? false : true); +} + + +// Checks for a control character. +inline boolean isControl(int c) +{ + return ( iscntrl (c) == 0 ? false : true); +} + + +// Checks for a digit (0 through 9). +inline boolean isDigit(int c) +{ + return ( isdigit (c) == 0 ? false : true); +} + + +// Checks for any printable character except space. +inline boolean isGraph(int c) +{ + return ( isgraph (c) == 0 ? false : true); +} + + +// Checks for a lower-case character. +inline boolean isLowerCase(int c) +{ + return (islower (c) == 0 ? false : true); +} + + +// Checks for any printable character including space. +inline boolean isPrintable(int c) +{ + return ( isprint (c) == 0 ? false : true); +} + + +// Checks for any printable character which is not a space +// or an alphanumeric character. +inline boolean isPunct(int c) +{ + return ( ispunct (c) == 0 ? false : true); +} + + +// Checks for white-space characters. For the avr-libc library, +// these are: space, formfeed ('\f'), newline ('\n'), carriage +// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). +inline boolean isSpace(int c) +{ + return ( isspace (c) == 0 ? false : true); +} + + +// Checks for an uppercase letter. +inline boolean isUpperCase(int c) +{ + return ( isupper (c) == 0 ? false : true); +} + + +// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 +// 8 9 a b c d e f A B C D E F. +inline boolean isHexadecimalDigit(int c) +{ + return ( isxdigit (c) == 0 ? false : true); +} + + +// Converts c to a 7-bit unsigned char value that fits into the +// ASCII character set, by clearing the high-order bits. +inline int toAscii(int c) +{ +/* return toascii (c); */ + return (c & 0x7f); +} + + +// Warning: +// Many people will be unhappy if you use this function. +// This function will convert accented letters into random +// characters. + +// Converts the letter c to lower case, if possible. +inline int toLowerCase(int c) +{ + return tolower (c); +} + + +// Converts the letter c to upper case, if possible. +inline int toUpperCase(int c) +{ + return toupper (c); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkfun/samd/cores/LilyMini/WInterrupts.c b/sparkfun/samd/cores/LilyMini/WInterrupts.c new file mode 100644 index 00000000..f0fc37d8 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WInterrupts.c @@ -0,0 +1,156 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "Arduino.h" +#include "wiring_private.h" + +#include + +static voidFuncPtr callbacksInt[EXTERNAL_NUM_INTERRUPTS]; + +/* Configure I/O interrupt sources */ +static void __initialize() +{ + memset(callbacksInt, 0, sizeof(callbacksInt)); + + NVIC_DisableIRQ(EIC_IRQn); + NVIC_ClearPendingIRQ(EIC_IRQn); + NVIC_SetPriority(EIC_IRQn, 0); + NVIC_EnableIRQ(EIC_IRQn); + + // Enable GCLK for EIC (External Interrupt Controller) + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC)); + +/* Shall we do that? + // Do a software reset on EIC + EIC->CTRL.SWRST.bit = 1 ; + while ((EIC->CTRL.SWRST.bit == 1) && (EIC->STATUS.SYNCBUSY.bit == 1)) { } +*/ + + // Enable EIC + EIC->CTRL.bit.ENABLE = 1; + while (EIC->STATUS.bit.SYNCBUSY == 1) { } +} + +/* + * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs. + * Replaces any previous function that was attached to the interrupt. + */ +void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) +{ + static int enabled = 0; + uint32_t config; + uint32_t pos; + +#if ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606 + EExt_Interrupts in = g_APinDescription[pin].ulExtInt; +#else + EExt_Interrupts in = digitalPinToInterrupt(pin); +#endif + if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI) + return; + + if (!enabled) { + __initialize(); + enabled = 1; + } + + // Enable wakeup capability on pin in case being used during sleep + EIC->WAKEUP.reg |= (1 << in); + + // Assign pin to EIC + pinPeripheral(pin, PIO_EXTINT); + + // Assign callback to interrupt + callbacksInt[in] = callback; + + // Look for right CONFIG register to be addressed + if (in > EXTERNAL_INT_7) { + config = 1; + } else { + config = 0; + } + + // Configure the interrupt mode + pos = (in - (8 * config)) << 2; + switch (mode) + { + case LOW: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos; + break; + + case HIGH: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos; + break; + + case CHANGE: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos; + break; + + case FALLING: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos; + break; + + case RISING: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos; + break; + } + + // Enable the interrupt + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << in); +} + +/* + * \brief Turns off the given interrupt. + */ +void detachInterrupt(uint32_t pin) +{ +#if (ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606) + EExt_Interrupts in = g_APinDescription[pin].ulExtInt; +#else + EExt_Interrupts in = digitalPinToInterrupt(pin); +#endif + if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI) + return; + + EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << in); + + // Disable wakeup capability on pin during sleep + EIC->WAKEUP.reg &= ~(1 << in); +} + +/* + * External Interrupt Controller NVIC Interrupt Handler + */ +void EIC_Handler(void) +{ + // Test the 16 normal interrupts + for (uint32_t i=EXTERNAL_INT_0; i<=EXTERNAL_INT_15; i++) + { + if ((EIC->INTFLAG.reg & (1 << i)) != 0) + { + // Call the callback function if assigned + if (callbacksInt[i]) { + callbacksInt[i](); + } + + // Clear the interrupt + EIC->INTFLAG.reg = 1 << i; + } + } +} diff --git a/sparkfun/samd/cores/LilyMini/WInterrupts.h b/sparkfun/samd/cores/LilyMini/WInterrupts.h new file mode 100644 index 00000000..5d2b24a0 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WInterrupts.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#ifndef _WIRING_INTERRUPTS_ +#define _WIRING_INTERRUPTS_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// LOW 0 +// HIGH 1 +#define CHANGE 2 +#define FALLING 3 +#define RISING 4 + +#define DEFAULT 1 +#define EXTERNAL 0 + +typedef void (*voidFuncPtr)(void); + +/* + * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs. + * Replaces any previous function that was attached to the interrupt. + */ +void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); + +/* + * \brief Turns off the given interrupt. + */ +void detachInterrupt(uint32_t pin); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sparkfun/samd/cores/LilyMini/WMath.cpp b/sparkfun/samd/cores/LilyMini/WMath.cpp new file mode 100644 index 00000000..55caddd6 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WMath.cpp @@ -0,0 +1,68 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +extern "C" { + #include "stdlib.h" + #include "stdint.h" +} +#include "WMath.h" + +extern void randomSeed( uint32_t dwSeed ) +{ + if ( dwSeed != 0 ) + { + srand( dwSeed ) ; + } +} + +extern long random( long howbig ) +{ + if ( howbig == 0 ) + { + return 0 ; + } + + return rand() % howbig; +} + +extern long random( long howsmall, long howbig ) +{ + if (howsmall >= howbig) + { + return howsmall; + } + + long diff = howbig - howsmall; + + return random(diff) + howsmall; +} + +extern long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +extern uint16_t makeWord( uint16_t w ) +{ + return w ; +} + +extern uint16_t makeWord( uint8_t h, uint8_t l ) +{ + return (h << 8) | l ; +} diff --git a/sparkfun/samd/cores/LilyMini/WMath.h b/sparkfun/samd/cores/LilyMini/WMath.h new file mode 100644 index 00000000..1893955c --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WMath.h @@ -0,0 +1,33 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef _WIRING_MATH_ +#define _WIRING_MATH_ + +extern long random( long ) ; +extern long random( long, long ) ; +extern void randomSeed( uint32_t dwSeed ) ; +extern long map( long, long, long, long, long ) ; + +extern uint16_t makeWord( uint16_t w ) ; +extern uint16_t makeWord( uint8_t h, uint8_t l ) ; + +#define word(...) makeWord(__VA_ARGS__) + + +#endif /* _WIRING_MATH_ */ diff --git a/sparkfun/samd/cores/LilyMini/WString.cpp b/sparkfun/samd/cores/LilyMini/WString.cpp new file mode 100644 index 00000000..71bbc07d --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WString.cpp @@ -0,0 +1,752 @@ +/* + WString.cpp - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... + Copyright (c) 2009-10 Hernando Barragan. All rights reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com + + 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 +*/ + +#include "WString.h" +#include "itoa.h" +#include "avr/dtostrf.h" + +/*********************************************/ +/* Constructors */ +/*********************************************/ + +String::String(const char *cstr) +{ + init(); + if (cstr) copy(cstr, strlen(cstr)); +} + +String::String(const String &value) +{ + init(); + *this = value; +} + +String::String(const __FlashStringHelper *pstr) +{ + init(); + *this = pstr; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) +String::String(String &&rval) +{ + init(); + move(rval); +} +String::String(StringSumHelper &&rval) +{ + init(); + move(rval); +} +#endif + +String::String(char c) +{ + init(); + char buf[2]; + buf[0] = c; + buf[1] = 0; + *this = buf; +} + +String::String(unsigned char value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned char)]; + utoa(value, buf, base); + *this = buf; +} + +String::String(int value, unsigned char base) +{ + init(); + char buf[2 + 8 * sizeof(int)]; + itoa(value, buf, base); + *this = buf; +} + +String::String(unsigned int value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned int)]; + utoa(value, buf, base); + *this = buf; +} + +String::String(long value, unsigned char base) +{ + init(); + char buf[2 + 8 * sizeof(long)]; + ltoa(value, buf, base); + *this = buf; +} + +String::String(unsigned long value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned long)]; + ultoa(value, buf, base); + *this = buf; +} + +String::String(float value, unsigned char decimalPlaces) +{ + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); +} + +String::String(double value, unsigned char decimalPlaces) +{ + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); +} + +String::~String() +{ + free(buffer); +} + +/*********************************************/ +/* Memory Management */ +/*********************************************/ + +inline void String::init(void) +{ + buffer = NULL; + capacity = 0; + len = 0; +} + +void String::invalidate(void) +{ + if (buffer) free(buffer); + buffer = NULL; + capacity = len = 0; +} + +unsigned char String::reserve(unsigned int size) +{ + if (buffer && capacity >= size) return 1; + if (changeBuffer(size)) { + if (len == 0) buffer[0] = 0; + return 1; + } + return 0; +} + +unsigned char String::changeBuffer(unsigned int maxStrLen) +{ + char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); + if (newbuffer) { + buffer = newbuffer; + capacity = maxStrLen; + return 1; + } + return 0; +} + +/*********************************************/ +/* Copy and Move */ +/*********************************************/ + +String & String::copy(const char *cstr, unsigned int length) +{ + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy(buffer, cstr); + return *this; +} + +String & String::copy(const __FlashStringHelper *pstr, unsigned int length) +{ + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy_P(buffer, (PGM_P)pstr); + return *this; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) +void String::move(String &rhs) +{ + if (buffer) { + if (rhs && capacity >= rhs.len) { + strcpy(buffer, rhs.buffer); + len = rhs.len; + rhs.len = 0; + return; + } else { + free(buffer); + } + } + buffer = rhs.buffer; + capacity = rhs.capacity; + len = rhs.len; + rhs.buffer = NULL; + rhs.capacity = 0; + rhs.len = 0; +} +#endif + +String & String::operator = (const String &rhs) +{ + if (this == &rhs) return *this; + + if (rhs.buffer) copy(rhs.buffer, rhs.len); + else invalidate(); + + return *this; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) +String & String::operator = (String &&rval) +{ + if (this != &rval) move(rval); + return *this; +} + +String & String::operator = (StringSumHelper &&rval) +{ + if (this != &rval) move(rval); + return *this; +} +#endif + +String & String::operator = (const char *cstr) +{ + if (cstr) copy(cstr, strlen(cstr)); + else invalidate(); + + return *this; +} + +String & String::operator = (const __FlashStringHelper *pstr) +{ + if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); + else invalidate(); + + return *this; +} + +/*********************************************/ +/* concat */ +/*********************************************/ + +unsigned char String::concat(const String &s) +{ + return concat(s.buffer, s.len); +} + +unsigned char String::concat(const char *cstr, unsigned int length) +{ + unsigned int newlen = len + length; + if (!cstr) return 0; + if (length == 0) return 1; + if (!reserve(newlen)) return 0; + strcpy(buffer + len, cstr); + len = newlen; + return 1; +} + +unsigned char String::concat(const char *cstr) +{ + if (!cstr) return 0; + return concat(cstr, strlen(cstr)); +} + +unsigned char String::concat(char c) +{ + char buf[2]; + buf[0] = c; + buf[1] = 0; + return concat(buf, 1); +} + +unsigned char String::concat(unsigned char num) +{ + char buf[1 + 3 * sizeof(unsigned char)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(int num) +{ + char buf[2 + 3 * sizeof(int)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned int num) +{ + char buf[1 + 3 * sizeof(unsigned int)]; + utoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(long num) +{ + char buf[2 + 3 * sizeof(long)]; + ltoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned long num) +{ + char buf[1 + 3 * sizeof(unsigned long)]; + ultoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(float num) +{ + char buf[20]; + char* string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); +} + +unsigned char String::concat(double num) +{ + char buf[20]; + char* string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); +} + +unsigned char String::concat(const __FlashStringHelper * str) +{ + if (!str) return 0; + int length = strlen_P((const char *) str); + if (length == 0) return 1; + unsigned int newlen = len + length; + if (!reserve(newlen)) return 0; + strcpy_P(buffer + len, (const char *) str); + len = newlen; + return 1; +} + +/*********************************************/ +/* Concatenate */ +/*********************************************/ + +StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) +{ + StringSumHelper &a = const_cast(lhs); + if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, char c) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(c)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, float num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, double num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs)) a.invalidate(); + return a; +} + +/*********************************************/ +/* Comparison */ +/*********************************************/ + +int String::compareTo(const String &s) const +{ + if (!buffer || !s.buffer) { + if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; + if (buffer && len > 0) return *(unsigned char *)buffer; + return 0; + } + return strcmp(buffer, s.buffer); +} + +unsigned char String::equals(const String &s2) const +{ + return (len == s2.len && compareTo(s2) == 0); +} + +unsigned char String::equals(const char *cstr) const +{ + if (len == 0) return (cstr == NULL || *cstr == 0); + if (cstr == NULL) return buffer[0] == 0; + return strcmp(buffer, cstr) == 0; +} + +unsigned char String::operator<(const String &rhs) const +{ + return compareTo(rhs) < 0; +} + +unsigned char String::operator>(const String &rhs) const +{ + return compareTo(rhs) > 0; +} + +unsigned char String::operator<=(const String &rhs) const +{ + return compareTo(rhs) <= 0; +} + +unsigned char String::operator>=(const String &rhs) const +{ + return compareTo(rhs) >= 0; +} + +unsigned char String::equalsIgnoreCase( const String &s2 ) const +{ + if (this == &s2) return 1; + if (len != s2.len) return 0; + if (len == 0) return 1; + const char *p1 = buffer; + const char *p2 = s2.buffer; + while (*p1) { + if (tolower(*p1++) != tolower(*p2++)) return 0; + } + return 1; +} + +unsigned char String::startsWith( const String &s2 ) const +{ + if (len < s2.len) return 0; + return startsWith(s2, 0); +} + +unsigned char String::startsWith( const String &s2, unsigned int offset ) const +{ + if (offset > len - s2.len || !buffer || !s2.buffer) return 0; + return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; +} + +unsigned char String::endsWith( const String &s2 ) const +{ + if ( len < s2.len || !buffer || !s2.buffer) return 0; + return strcmp(&buffer[len - s2.len], s2.buffer) == 0; +} + +/*********************************************/ +/* Character Access */ +/*********************************************/ + +char String::charAt(unsigned int loc) const +{ + return operator[](loc); +} + +void String::setCharAt(unsigned int loc, char c) +{ + if (loc < len) buffer[loc] = c; +} + +char & String::operator[](unsigned int index) +{ + static char dummy_writable_char; + if (index >= len || !buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return buffer[index]; +} + +char String::operator[]( unsigned int index ) const +{ + if (index >= len || !buffer) return 0; + return buffer[index]; +} + +void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const +{ + if (!bufsize || !buf) return; + if (index >= len) { + buf[0] = 0; + return; + } + unsigned int n = bufsize - 1; + if (n > len - index) n = len - index; + strncpy((char *)buf, buffer + index, n); + buf[n] = 0; +} + +/*********************************************/ +/* Search */ +/*********************************************/ + +int String::indexOf(char c) const +{ + return indexOf(c, 0); +} + +int String::indexOf( char ch, unsigned int fromIndex ) const +{ + if (fromIndex >= len) return -1; + const char* temp = strchr(buffer + fromIndex, ch); + if (temp == NULL) return -1; + return temp - buffer; +} + +int String::indexOf(const String &s2) const +{ + return indexOf(s2, 0); +} + +int String::indexOf(const String &s2, unsigned int fromIndex) const +{ + if (fromIndex >= len) return -1; + const char *found = strstr(buffer + fromIndex, s2.buffer); + if (found == NULL) return -1; + return found - buffer; +} + +int String::lastIndexOf( char theChar ) const +{ + return lastIndexOf(theChar, len - 1); +} + +int String::lastIndexOf(char ch, unsigned int fromIndex) const +{ + if (fromIndex >= len) return -1; + char tempchar = buffer[fromIndex + 1]; + buffer[fromIndex + 1] = '\0'; + char* temp = strrchr( buffer, ch ); + buffer[fromIndex + 1] = tempchar; + if (temp == NULL) return -1; + return temp - buffer; +} + +int String::lastIndexOf(const String &s2) const +{ + return lastIndexOf(s2, len - s2.len); +} + +int String::lastIndexOf(const String &s2, unsigned int fromIndex) const +{ + if (s2.len == 0 || len == 0 || s2.len > len) return -1; + if (fromIndex >= len) fromIndex = len - 1; + int found = -1; + for (char *p = buffer; p <= buffer + fromIndex; p++) { + p = strstr(p, s2.buffer); + if (!p) break; + if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; + } + return found; +} + +String String::substring(unsigned int left, unsigned int right) const +{ + if (left > right) { + unsigned int temp = right; + right = left; + left = temp; + } + String out; + if (left >= len) return out; + if (right > len) right = len; + char temp = buffer[right]; // save the replaced character + buffer[right] = '\0'; + out = buffer + left; // pointer arithmetic + buffer[right] = temp; //restore character + return out; +} + +/*********************************************/ +/* Modification */ +/*********************************************/ + +void String::replace(char find, char replace) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + if (*p == find) *p = replace; + } +} + +void String::replace(const String& find, const String& replace) +{ + if (len == 0 || find.len == 0) return; + int diff = replace.len - find.len; + char *readFrom = buffer; + char *foundAt; + if (diff == 0) { + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + memcpy(foundAt, replace.buffer, replace.len); + readFrom = foundAt + replace.len; + } + } else if (diff < 0) { + char *writeTo = buffer; + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + unsigned int n = foundAt - readFrom; + memcpy(writeTo, readFrom, n); + writeTo += n; + memcpy(writeTo, replace.buffer, replace.len); + writeTo += replace.len; + readFrom = foundAt + find.len; + len += diff; + } + strcpy(writeTo, readFrom); + } else { + unsigned int size = len; // compute size needed for result + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + readFrom = foundAt + find.len; + size += diff; + } + if (size == len) return; + if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! + int index = len - 1; + while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { + readFrom = buffer + index + find.len; + memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); + len += diff; + buffer[len] = 0; + memcpy(buffer + index, replace.buffer, replace.len); + index--; + } + } +} + +void String::remove(unsigned int index){ + // Pass the biggest integer as the count. The remove method + // below will take care of truncating it at the end of the + // string. + remove(index, (unsigned int)-1); +} + +void String::remove(unsigned int index, unsigned int count){ + if (index >= len) { return; } + if (count <= 0) { return; } + if (count > len - index) { count = len - index; } + char *writeTo = buffer + index; + len = len - count; + strncpy(writeTo, buffer + index + count,len - index); + buffer[len] = 0; +} + +void String::toLowerCase(void) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + *p = tolower(*p); + } +} + +void String::toUpperCase(void) +{ + if (!buffer) return; + for (char *p = buffer; *p; p++) { + *p = toupper(*p); + } +} + +void String::trim(void) +{ + if (!buffer || len == 0) return; + char *begin = buffer; + while (isspace(*begin)) begin++; + char *end = buffer + len - 1; + while (isspace(*end) && end >= begin) end--; + len = end + 1 - begin; + if (begin > buffer) memcpy(buffer, begin, len); + buffer[len] = 0; +} + +/*********************************************/ +/* Parsing / Conversion */ +/*********************************************/ + +long String::toInt(void) const +{ + if (buffer) return atol(buffer); + return 0; +} + +float String::toFloat(void) const +{ + return float(toDouble()); +} + +double String::toDouble(void) const +{ + if (buffer) return atof(buffer); + return 0; +} diff --git a/sparkfun/samd/cores/LilyMini/WString.h b/sparkfun/samd/cores/LilyMini/WString.h new file mode 100644 index 00000000..77709c3b --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WString.h @@ -0,0 +1,229 @@ +/* + WString.h - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... + Copyright (c) 2009-10 Hernando Barragan. All right reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com + + 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 +*/ + +#ifndef String_class_h +#define String_class_h +#ifdef __cplusplus + +#include +#include +#include +#include + +// When compiling programs with this class, the following gcc parameters +// dramatically increase performance and memory (RAM) efficiency, typically +// with little or no increase in code size. +// -felide-constructors +// -std=c++0x + +class __FlashStringHelper; +#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) + +// An inherited class for holding the result of a concatenation. These +// result objects are assumed to be writable by subsequent concatenations. +class StringSumHelper; + +// The string class +class String +{ + // use a function pointer to allow for "if (s)" without the + // complications of an operator bool(). for more information, see: + // http://www.artima.com/cppsource/safebool.html + typedef void (String::*StringIfHelperType)() const; + void StringIfHelper() const {} + +public: + // constructors + // creates a copy of the initial value. + // if the initial value is null or invalid, or if memory allocation + // fails, the string will be marked as invalid (i.e. "if (s)" will + // be false). + String(const char *cstr = ""); + String(const String &str); + String(const __FlashStringHelper *str); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + String(String &&rval); + String(StringSumHelper &&rval); + #endif + explicit String(char c); + explicit String(unsigned char, unsigned char base=10); + explicit String(int, unsigned char base=10); + explicit String(unsigned int, unsigned char base=10); + explicit String(long, unsigned char base=10); + explicit String(unsigned long, unsigned char base=10); + explicit String(float, unsigned char decimalPlaces=2); + explicit String(double, unsigned char decimalPlaces=2); + ~String(void); + + // memory management + // return true on success, false on failure (in which case, the string + // is left unchanged). reserve(0), if successful, will validate an + // invalid string (i.e., "if (s)" will be true afterwards) + unsigned char reserve(unsigned int size); + inline unsigned int length(void) const {return len;} + + // creates a copy of the assigned value. if the value is null or + // invalid, or if the memory allocation fails, the string will be + // marked as invalid ("if (s)" will be false). + String & operator = (const String &rhs); + String & operator = (const char *cstr); + String & operator = (const __FlashStringHelper *str); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + String & operator = (String &&rval); + String & operator = (StringSumHelper &&rval); + #endif + + // concatenate (works w/ built-in types) + + // returns true on success, false on failure (in which case, the string + // is left unchanged). if the argument is null or invalid, the + // concatenation is considered unsucessful. + unsigned char concat(const String &str); + unsigned char concat(const char *cstr); + unsigned char concat(char c); + unsigned char concat(unsigned char c); + unsigned char concat(int num); + unsigned char concat(unsigned int num); + unsigned char concat(long num); + unsigned char concat(unsigned long num); + unsigned char concat(float num); + unsigned char concat(double num); + unsigned char concat(const __FlashStringHelper * str); + + // if there's not enough memory for the concatenated value, the string + // will be left unchanged (but this isn't signalled in any way) + String & operator += (const String &rhs) {concat(rhs); return (*this);} + String & operator += (const char *cstr) {concat(cstr); return (*this);} + String & operator += (char c) {concat(c); return (*this);} + String & operator += (unsigned char num) {concat(num); return (*this);} + String & operator += (int num) {concat(num); return (*this);} + String & operator += (unsigned int num) {concat(num); return (*this);} + String & operator += (long num) {concat(num); return (*this);} + String & operator += (unsigned long num) {concat(num); return (*this);} + String & operator += (float num) {concat(num); return (*this);} + String & operator += (double num) {concat(num); return (*this);} + String & operator += (const __FlashStringHelper *str){concat(str); return (*this);} + + friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); + friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); + + // comparison (only works w/ Strings and "strings") + operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } + int compareTo(const String &s) const; + unsigned char equals(const String &s) const; + unsigned char equals(const char *cstr) const; + unsigned char operator == (const String &rhs) const {return equals(rhs);} + unsigned char operator == (const char *cstr) const {return equals(cstr);} + unsigned char operator != (const String &rhs) const {return !equals(rhs);} + unsigned char operator != (const char *cstr) const {return !equals(cstr);} + unsigned char operator < (const String &rhs) const; + unsigned char operator > (const String &rhs) const; + unsigned char operator <= (const String &rhs) const; + unsigned char operator >= (const String &rhs) const; + unsigned char equalsIgnoreCase(const String &s) const; + unsigned char startsWith( const String &prefix) const; + unsigned char startsWith(const String &prefix, unsigned int offset) const; + unsigned char endsWith(const String &suffix) const; + + // character acccess + char charAt(unsigned int index) const; + void setCharAt(unsigned int index, char c); + char operator [] (unsigned int index) const; + char& operator [] (unsigned int index); + void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; + void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const + { getBytes((unsigned char *)buf, bufsize, index); } + const char* c_str() const { return buffer; } + char* begin() { return buffer; } + char* end() { return buffer + length(); } + const char* begin() const { return c_str(); } + const char* end() const { return c_str() + length(); } + + // search + int indexOf( char ch ) const; + int indexOf( char ch, unsigned int fromIndex ) const; + int indexOf( const String &str ) const; + int indexOf( const String &str, unsigned int fromIndex ) const; + int lastIndexOf( char ch ) const; + int lastIndexOf( char ch, unsigned int fromIndex ) const; + int lastIndexOf( const String &str ) const; + int lastIndexOf( const String &str, unsigned int fromIndex ) const; + String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); }; + String substring( unsigned int beginIndex, unsigned int endIndex ) const; + + // modification + void replace(char find, char replace); + void replace(const String& find, const String& replace); + void remove(unsigned int index); + void remove(unsigned int index, unsigned int count); + void toLowerCase(void); + void toUpperCase(void); + void trim(void); + + // parsing/conversion + long toInt(void) const; + float toFloat(void) const; + double toDouble(void) const; + +protected: + char *buffer; // the actual char array + unsigned int capacity; // the array length minus one (for the '\0') + unsigned int len; // the String length (not counting the '\0') +protected: + void init(void); + void invalidate(void); + unsigned char changeBuffer(unsigned int maxStrLen); + unsigned char concat(const char *cstr, unsigned int length); + + // copy and move + String & copy(const char *cstr, unsigned int length); + String & copy(const __FlashStringHelper *pstr, unsigned int length); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + void move(String &rhs); + #endif +}; + +class StringSumHelper : public String +{ +public: + StringSumHelper(const String &s) : String(s) {} + StringSumHelper(const char *p) : String(p) {} + StringSumHelper(char c) : String(c) {} + StringSumHelper(unsigned char num) : String(num) {} + StringSumHelper(int num) : String(num) {} + StringSumHelper(unsigned int num) : String(num) {} + StringSumHelper(long num) : String(num) {} + StringSumHelper(unsigned long num) : String(num) {} + StringSumHelper(float num) : String(num) {} + StringSumHelper(double num) : String(num) {} +}; + +#endif // __cplusplus +#endif // String_class_h diff --git a/sparkfun/samd/cores/LilyMini/WVariant.h b/sparkfun/samd/cores/LilyMini/WVariant.h new file mode 100644 index 00000000..146b3785 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/WVariant.h @@ -0,0 +1,235 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#include +#include "sam.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Definitions and types for pins */ +typedef enum _EAnalogChannel +{ + No_ADC_Channel=-1, + ADC_Channel0=0, + ADC_Channel1=1, + ADC_Channel2=2, + ADC_Channel3=3, + ADC_Channel4=4, + ADC_Channel5=5, + ADC_Channel6=6, + ADC_Channel7=7, + ADC_Channel8=8, + ADC_Channel9=9, +/* + ADC_Channel10=10, + ADC_Channel11=11, + ADC_Channel12=12, + ADC_Channel13=13, + ADC_Channel14=14, + ADC_Channel15=15, + ADC_Channel16=16, + ADC_Channel17=17, + ADC_Channel18=18, + ADC_Channel19=19, +*/ + DAC_Channel0, +} EAnalogChannel ; + +// Definitions for TC channels +typedef enum _ETCChannel +{ + NOT_ON_TIMER=-1, + TCC0_CH0 = (0<<8)|(0), // 0 + TCC0_CH1 = (0<<8)|(1), // 1 + TCC0_CH2 = (0<<8)|(2), // 2 + TCC0_CH3 = (0<<8)|(3), // 3 + TC1_CH0 = (1<<8)|(0), // 256 1 + TC1_CH1 = (1<<8)|(1), // 257 1 + TC2_CH0 = (2<<8)|(0), // 512 2 + TC2_CH1 = (2<<8)|(1), // 513 2 +} ETCChannel ; + +extern const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM] ; + +#define GetTCNumber( x ) ( (x) >> 8 ) +#define GetTCChannelNumber( x ) ( (x) & 0xff ) +#define GetTC( x ) ( g_apTCInstances[(x) >> 8] ) + +// Definitions for PWM channels +typedef enum _EPWMChannel +{ + NOT_ON_PWM=-1, + PWM0_CH0=TCC0_CH0, + PWM0_CH1=TCC0_CH1, + PWM0_CH2=TCC0_CH2, + PWM0_CH3=TCC0_CH3, + PWM1_CH0=TC1_CH0, + PWM1_CH1=TC1_CH1, + PWM2_CH0=TC2_CH0, + PWM2_CH1=TC2_CH1, +} EPWMChannel ; + +typedef enum _EPortType +{ + NOT_A_PORT=-1, + PORTA=0, + PORTB=1, + PORTC=2, +} EPortType ; + +typedef enum +{ + EXTERNAL_INT_0 = 0, + EXTERNAL_INT_1, + EXTERNAL_INT_2, + EXTERNAL_INT_3, + EXTERNAL_INT_4, + EXTERNAL_INT_5, + EXTERNAL_INT_6, + EXTERNAL_INT_7, + EXTERNAL_INT_8, + EXTERNAL_INT_9, + EXTERNAL_INT_10, + EXTERNAL_INT_11, + EXTERNAL_INT_12, + EXTERNAL_INT_13, + EXTERNAL_INT_14, + EXTERNAL_INT_15, + EXTERNAL_INT_NMI, + EXTERNAL_NUM_INTERRUPTS, + NOT_AN_INTERRUPT = -1, + EXTERNAL_INT_NONE = NOT_AN_INTERRUPT, +} EExt_Interrupts ; + +//A B C D E F G H +//EIC REF ADC AC PTC DAC SERCOM SERCOM_ALT TC/TCC TCC COM AC/GCLK + +typedef enum _EPioType +{ + PIO_NOT_A_PIN=-1, /* Not under control of a peripheral. */ + PIO_EXTINT=0, /* The pin is controlled by the associated signal of peripheral A. */ + PIO_ANALOG, /* The pin is controlled by the associated signal of peripheral B. */ + PIO_SERCOM, /* The pin is controlled by the associated signal of peripheral C. */ + PIO_SERCOM_ALT, /* The pin is controlled by the associated signal of peripheral D. */ + PIO_TIMER, /* The pin is controlled by the associated signal of peripheral E. */ + PIO_TIMER_ALT, /* The pin is controlled by the associated signal of peripheral F. */ + PIO_COM, /* The pin is controlled by the associated signal of peripheral G. */ + PIO_AC_CLK, /* The pin is controlled by the associated signal of peripheral H. */ + PIO_DIGITAL, /* The pin is controlled by PORT. */ + PIO_INPUT, /* The pin is controlled by PORT and is an input. */ + PIO_INPUT_PULLUP, /* The pin is controlled by PORT and is an input with internal pull-up resistor enabled. */ + PIO_OUTPUT, /* The pin is controlled by PORT and is an output. */ + + PIO_PWM=PIO_TIMER, + PIO_PWM_ALT=PIO_TIMER_ALT, +} EPioType ; + +/** + * Pin Attributes to be OR-ed + */ + +#define PIN_ATTR_NONE (0UL<<0) +#define PIN_ATTR_COMBO (1UL<<0) +#define PIN_ATTR_ANALOG (1UL<<1) +#define PIN_ATTR_DIGITAL (1UL<<2) +#define PIN_ATTR_PWM (1UL<<3) +#define PIN_ATTR_TIMER (1UL<<4) +#define PIN_ATTR_TIMER_ALT (1UL<<5) +#define PIN_ATTR_EXTINT (1UL<<6) + +/* Types used for the table below */ +typedef struct _PinDescription +{ + EPortType ulPort ; + uint32_t ulPin ; + EPioType ulPinType ; + uint32_t ulPinAttribute ; + EAnalogChannel ulADCChannelNumber ; /* ADC Channel number in the SAM device */ + EPWMChannel ulPWMChannel ; + ETCChannel ulTCChannel ; + EExt_Interrupts ulExtInt ; +} PinDescription ; + +/* Pins table to be instantiated into variant.cpp */ +extern const PinDescription g_APinDescription[] ; + +/* Generic Clock Multiplexer IDs */ +#define GCM_DFLL48M_REF (0x00U) +#define GCM_FDPLL96M_INPUT (0x01U) +#define GCM_FDPLL96M_32K (0x02U) +#define GCM_WDT (0x03U) +#define GCM_RTC (0x04U) +#define GCM_EIC (0x05U) +#define GCM_USB (0x06U) +#define GCM_EVSYS_CHANNEL_0 (0x07U) +#define GCM_EVSYS_CHANNEL_1 (0x08U) +#define GCM_EVSYS_CHANNEL_2 (0x09U) +#define GCM_EVSYS_CHANNEL_3 (0x0AU) +#define GCM_EVSYS_CHANNEL_4 (0x0BU) +#define GCM_EVSYS_CHANNEL_5 (0x0CU) + +#if defined(__SAMD11D14AM__) || defined(__SAMD11C14A__) || defined(__SAMD11D14AS__) + +#define GCM_SERCOMx_SLOW (0x0DU) +#define GCM_SERCOM0_CORE (0x0EU) +#define GCM_SERCOM1_CORE (0x0FU) +#define GCM_SERCOM2_CORE (0x10U) +#define GCM_TCC0 (0x11U) +#define GCM_TC1_TC2 (0x12U) +#define GCM_ADC (0x13U) +#define GCM_AC_DIG (0x14U) +#define GCM_AC_ANA (0x15U) +#define GCM_DAC (0x16U) +#define GCM_PTC (0x17U) + +#else + +#define GCM_EVSYS_CHANNEL_6 (0x0DU) +#define GCM_EVSYS_CHANNEL_7 (0x0EU) +#define GCM_EVSYS_CHANNEL_8 (0x0FU) +#define GCM_EVSYS_CHANNEL_9 (0x10U) +#define GCM_EVSYS_CHANNEL_10 (0x11U) +#define GCM_EVSYS_CHANNEL_11 (0x12U) +#define GCM_SERCOMx_SLOW (0x13U) +#define GCM_SERCOM0_CORE (0x14U) +#define GCM_SERCOM1_CORE (0x15U) +#define GCM_SERCOM2_CORE (0x16U) +#define GCM_SERCOM3_CORE (0x17U) +#define GCM_SERCOM4_CORE (0x18U) +#define GCM_SERCOM5_CORE (0x19U) +#define GCM_TCC0_TCC1 (0x1AU) +#define GCM_TCC2_TC3 (0x1BU) +#define GCM_TC4_TC5 (0x1CU) +#define GCM_TC6_TC7 (0x1DU) +#define GCM_ADC (0x1EU) +#define GCM_AC_DIG (0x1FU) +#define GCM_AC_ANA (0x20U) +#define GCM_DAC (0x21U) +#define GCM_PTC (0x22U) +#define GCM_I2S_0 (0x23U) +#define GCM_I2S_1 (0x24U) + +#endif + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/sparkfun/samd/cores/LilyMini/abi.cpp b/sparkfun/samd/cores/LilyMini/abi.cpp new file mode 100644 index 00000000..bd2f43ad --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/abi.cpp @@ -0,0 +1,37 @@ +/* + Copyright (c) 2014 Arduino LLC. 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 +*/ + +#include + +extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); +extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); + +void __cxa_pure_virtual(void) { + // We might want to write some diagnostics to uart in this case + //std::terminate(); + while (1) + ; +} + +void __cxa_deleted_virtual(void) { + // We might want to write some diagnostics to uart in this case + //std::terminate(); + while (1) + ; +} + diff --git a/sparkfun/samd/cores/LilyMini/avr/dtostrf.c b/sparkfun/samd/cores/LilyMini/avr/dtostrf.c new file mode 100644 index 00000000..de164277 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/avr/dtostrf.c @@ -0,0 +1,30 @@ +/* + dtostrf - Emulation for dtostrf function from avr-libc + Copyright (c) 2015 Arduino LLC. All rights 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 +*/ + +#include + +char *dtostrf (double val, signed char width, unsigned char prec, char *sout) { + asm(".global _printf_float"); + + char fmt[20]; + sprintf(fmt, "%%%d.%df", width, prec); + sprintf(sout, fmt, val); + return sout; +} + diff --git a/sparkfun/samd/cores/LilyMini/avr/dtostrf.h b/sparkfun/samd/cores/LilyMini/avr/dtostrf.h new file mode 100644 index 00000000..762a8864 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/avr/dtostrf.h @@ -0,0 +1,30 @@ +/* + dtostrf - Emulation for dtostrf function from avr-libc + Copyright (c) 2015 Arduino LLC. All rights 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 +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +char *dtostrf(double val, signed char width, unsigned char prec, char *sout); + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/avr/interrupt.h b/sparkfun/samd/cores/LilyMini/avr/interrupt.h new file mode 100644 index 00000000..950509dd --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/avr/interrupt.h @@ -0,0 +1,23 @@ +/* + Copyright (c) 2015 Arduino LCC. 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 +*/ + +/* + Empty file. + This file is here to allow compatibility with sketches (made for AVR) + that includes +*/ diff --git a/sparkfun/samd/cores/LilyMini/avr/io.h b/sparkfun/samd/cores/LilyMini/avr/io.h new file mode 100644 index 00000000..33d20cdd --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/avr/io.h @@ -0,0 +1,32 @@ +/* + io.h - Definitions for compatibility with AVR io macros + + Copyright (c) 2016 Arduino LLC + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE +*/ + +#ifndef _IO_H_ +#define _IO_H_ + +#define RAMSTART (HMCRAMC0_ADDR) +#define RAMSIZE (HMCRAMC0_SIZE) +#define RAMEND (RAMSTART + RAMSIZE - 1) + +#endif diff --git a/sparkfun/samd/cores/LilyMini/avr/pgmspace.h b/sparkfun/samd/cores/LilyMini/avr/pgmspace.h new file mode 100644 index 00000000..0f732bba --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/avr/pgmspace.h @@ -0,0 +1,122 @@ +/* + pgmspace.h - Definitions for compatibility with AVR pgmspace macros + + Copyright (c) 2015 Arduino LLC + + Based on work of Paul Stoffregen on Teensy 3 (http://pjrc.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE +*/ + +#ifndef __PGMSPACE_H_ +#define __PGMSPACE_H_ 1 + +#include + +#define PROGMEM +#define PGM_P const char * +#define PSTR(str) (str) + +#define _SFR_BYTE(n) (n) + +typedef void prog_void; +typedef char prog_char; +typedef unsigned char prog_uchar; +typedef int8_t prog_int8_t; +typedef uint8_t prog_uint8_t; +typedef int16_t prog_int16_t; +typedef uint16_t prog_uint16_t; +typedef int32_t prog_int32_t; +typedef uint32_t prog_uint32_t; +typedef int64_t prog_int64_t; +typedef uint64_t prog_uint64_t; + +typedef const void* int_farptr_t; +typedef const void* uint_farptr_t; + +#define memchr_P(s, c, n) memchr((s), (c), (n)) +#define memcmp_P(s1, s2, n) memcmp((s1), (s2), (n)) +#define memccpy_P(dest, src, c, n) memccpy((dest), (src), (c), (n)) +#define memcpy_P(dest, src, n) memcpy((dest), (src), (n)) +#define memmem_P(haystack, haystacklen, needle, needlelen) memmem((haystack), (haystacklen), (needle), (needlelen)) +#define memrchr_P(s, c, n) memrchr((s), (c), (n)) +#define strcat_P(dest, src) strcat((dest), (src)) +#define strchr_P(s, c) strchr((s), (c)) +#define strchrnul_P(s, c) strchrnul((s), (c)) +#define strcmp_P(a, b) strcmp((a), (b)) +#define strcpy_P(dest, src) strcpy((dest), (src)) +#define strcasecmp_P(s1, s2) strcasecmp((s1), (s2)) +#define strcasestr_P(haystack, needle) strcasestr((haystack), (needle)) +#define strcspn_P(s, accept) strcspn((s), (accept)) +#define strlcat_P(s1, s2, n) strlcat((s1), (s2), (n)) +#define strlcpy_P(s1, s2, n) strlcpy((s1), (s2), (n)) +#define strlen_P(a) strlen((a)) +#define strnlen_P(s, n) strnlen((s), (n)) +#define strncmp_P(s1, s2, n) strncmp((s1), (s2), (n)) +#define strncasecmp_P(s1, s2, n) strncasecmp((s1), (s2), (n)) +#define strncat_P(s1, s2, n) strncat((s1), (s2), (n)) +#define strncpy_P(s1, s2, n) strncpy((s1), (s2), (n)) +#define strpbrk_P(s, accept) strpbrk((s), (accept)) +#define strrchr_P(s, c) strrchr((s), (c)) +#define strsep_P(sp, delim) strsep((sp), (delim)) +#define strspn_P(s, accept) strspn((s), (accept)) +#define strstr_P(a, b) strstr((a), (b)) +#define strtok_P(s, delim) strtok((s), (delim)) +#define strtok_rP(s, delim, last) strtok((s), (delim), (last)) + +#define strlen_PF(a) strlen((a)) +#define strnlen_PF(src, len) strnlen((src), (len)) +#define memcpy_PF(dest, src, len) memcpy((dest), (src), (len)) +#define strcpy_PF(dest, src) strcpy((dest), (src)) +#define strncpy_PF(dest, src, len) strncpy((dest), (src), (len)) +#define strcat_PF(dest, src) strcat((dest), (src)) +#define strlcat_PF(dest, src, len) strlcat((dest), (src), (len)) +#define strncat_PF(dest, src, len) strncat((dest), (src), (len)) +#define strcmp_PF(s1, s2) strcmp((s1), (s2)) +#define strncmp_PF(s1, s2, n) strncmp((s1), (s2), (n)) +#define strcasecmp_PF(s1, s2) strcasecmp((s1), (s2)) +#define strncasecmp_PF(s1, s2, n) strncasecmp((s1), (s2), (n)) +#define strstr_PF(s1, s2) strstr((s1), (s2)) +#define strlcpy_PF(dest, src, n) strlcpy((dest), (src), (n)) +#define memcmp_PF(s1, s2, n) memcmp((s1), (s2), (n)) + +#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__) +#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__) + +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#define pgm_read_word(addr) (*(const unsigned short *)(addr)) +#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#define pgm_read_float(addr) (*(const float *)(addr)) +#define pgm_read_ptr(addr) (*(const void *)(addr)) + +#define pgm_read_byte_near(addr) pgm_read_byte(addr) +#define pgm_read_word_near(addr) pgm_read_word(addr) +#define pgm_read_dword_near(addr) pgm_read_dword(addr) +#define pgm_read_float_near(addr) pgm_read_float(addr) +#define pgm_read_ptr_near(addr) pgm_read_ptr(addr) + +#define pgm_read_byte_far(addr) pgm_read_byte(addr) +#define pgm_read_word_far(addr) pgm_read_word(addr) +#define pgm_read_dword_far(addr) pgm_read_dword(addr) +#define pgm_read_float_far(addr) pgm_read_float(addr) +#define pgm_read_ptr_far(addr) pgm_read_ptr(addr) + +#define pgm_get_far_address(addr) (&(addr)) + +#endif diff --git a/sparkfun/samd/cores/LilyMini/binary.h b/sparkfun/samd/cores/LilyMini/binary.h new file mode 100644 index 00000000..aec4c733 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/binary.h @@ -0,0 +1,534 @@ +/* + binary.h - Definitions for binary constants + Copyright (c) 2006 David A. Mellis. 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 +*/ + +#ifndef Binary_h +#define Binary_h + +#define B0 0 +#define B00 0 +#define B000 0 +#define B0000 0 +#define B00000 0 +#define B000000 0 +#define B0000000 0 +#define B00000000 0 +#define B1 1 +#define B01 1 +#define B001 1 +#define B0001 1 +#define B00001 1 +#define B000001 1 +#define B0000001 1 +#define B00000001 1 +#define B10 2 +#define B010 2 +#define B0010 2 +#define B00010 2 +#define B000010 2 +#define B0000010 2 +#define B00000010 2 +#define B11 3 +#define B011 3 +#define B0011 3 +#define B00011 3 +#define B000011 3 +#define B0000011 3 +#define B00000011 3 +#define B100 4 +#define B0100 4 +#define B00100 4 +#define B000100 4 +#define B0000100 4 +#define B00000100 4 +#define B101 5 +#define B0101 5 +#define B00101 5 +#define B000101 5 +#define B0000101 5 +#define B00000101 5 +#define B110 6 +#define B0110 6 +#define B00110 6 +#define B000110 6 +#define B0000110 6 +#define B00000110 6 +#define B111 7 +#define B0111 7 +#define B00111 7 +#define B000111 7 +#define B0000111 7 +#define B00000111 7 +#define B1000 8 +#define B01000 8 +#define B001000 8 +#define B0001000 8 +#define B00001000 8 +#define B1001 9 +#define B01001 9 +#define B001001 9 +#define B0001001 9 +#define B00001001 9 +#define B1010 10 +#define B01010 10 +#define B001010 10 +#define B0001010 10 +#define B00001010 10 +#define B1011 11 +#define B01011 11 +#define B001011 11 +#define B0001011 11 +#define B00001011 11 +#define B1100 12 +#define B01100 12 +#define B001100 12 +#define B0001100 12 +#define B00001100 12 +#define B1101 13 +#define B01101 13 +#define B001101 13 +#define B0001101 13 +#define B00001101 13 +#define B1110 14 +#define B01110 14 +#define B001110 14 +#define B0001110 14 +#define B00001110 14 +#define B1111 15 +#define B01111 15 +#define B001111 15 +#define B0001111 15 +#define B00001111 15 +#define B10000 16 +#define B010000 16 +#define B0010000 16 +#define B00010000 16 +#define B10001 17 +#define B010001 17 +#define B0010001 17 +#define B00010001 17 +#define B10010 18 +#define B010010 18 +#define B0010010 18 +#define B00010010 18 +#define B10011 19 +#define B010011 19 +#define B0010011 19 +#define B00010011 19 +#define B10100 20 +#define B010100 20 +#define B0010100 20 +#define B00010100 20 +#define B10101 21 +#define B010101 21 +#define B0010101 21 +#define B00010101 21 +#define B10110 22 +#define B010110 22 +#define B0010110 22 +#define B00010110 22 +#define B10111 23 +#define B010111 23 +#define B0010111 23 +#define B00010111 23 +#define B11000 24 +#define B011000 24 +#define B0011000 24 +#define B00011000 24 +#define B11001 25 +#define B011001 25 +#define B0011001 25 +#define B00011001 25 +#define B11010 26 +#define B011010 26 +#define B0011010 26 +#define B00011010 26 +#define B11011 27 +#define B011011 27 +#define B0011011 27 +#define B00011011 27 +#define B11100 28 +#define B011100 28 +#define B0011100 28 +#define B00011100 28 +#define B11101 29 +#define B011101 29 +#define B0011101 29 +#define B00011101 29 +#define B11110 30 +#define B011110 30 +#define B0011110 30 +#define B00011110 30 +#define B11111 31 +#define B011111 31 +#define B0011111 31 +#define B00011111 31 +#define B100000 32 +#define B0100000 32 +#define B00100000 32 +#define B100001 33 +#define B0100001 33 +#define B00100001 33 +#define B100010 34 +#define B0100010 34 +#define B00100010 34 +#define B100011 35 +#define B0100011 35 +#define B00100011 35 +#define B100100 36 +#define B0100100 36 +#define B00100100 36 +#define B100101 37 +#define B0100101 37 +#define B00100101 37 +#define B100110 38 +#define B0100110 38 +#define B00100110 38 +#define B100111 39 +#define B0100111 39 +#define B00100111 39 +#define B101000 40 +#define B0101000 40 +#define B00101000 40 +#define B101001 41 +#define B0101001 41 +#define B00101001 41 +#define B101010 42 +#define B0101010 42 +#define B00101010 42 +#define B101011 43 +#define B0101011 43 +#define B00101011 43 +#define B101100 44 +#define B0101100 44 +#define B00101100 44 +#define B101101 45 +#define B0101101 45 +#define B00101101 45 +#define B101110 46 +#define B0101110 46 +#define B00101110 46 +#define B101111 47 +#define B0101111 47 +#define B00101111 47 +#define B110000 48 +#define B0110000 48 +#define B00110000 48 +#define B110001 49 +#define B0110001 49 +#define B00110001 49 +#define B110010 50 +#define B0110010 50 +#define B00110010 50 +#define B110011 51 +#define B0110011 51 +#define B00110011 51 +#define B110100 52 +#define B0110100 52 +#define B00110100 52 +#define B110101 53 +#define B0110101 53 +#define B00110101 53 +#define B110110 54 +#define B0110110 54 +#define B00110110 54 +#define B110111 55 +#define B0110111 55 +#define B00110111 55 +#define B111000 56 +#define B0111000 56 +#define B00111000 56 +#define B111001 57 +#define B0111001 57 +#define B00111001 57 +#define B111010 58 +#define B0111010 58 +#define B00111010 58 +#define B111011 59 +#define B0111011 59 +#define B00111011 59 +#define B111100 60 +#define B0111100 60 +#define B00111100 60 +#define B111101 61 +#define B0111101 61 +#define B00111101 61 +#define B111110 62 +#define B0111110 62 +#define B00111110 62 +#define B111111 63 +#define B0111111 63 +#define B00111111 63 +#define B1000000 64 +#define B01000000 64 +#define B1000001 65 +#define B01000001 65 +#define B1000010 66 +#define B01000010 66 +#define B1000011 67 +#define B01000011 67 +#define B1000100 68 +#define B01000100 68 +#define B1000101 69 +#define B01000101 69 +#define B1000110 70 +#define B01000110 70 +#define B1000111 71 +#define B01000111 71 +#define B1001000 72 +#define B01001000 72 +#define B1001001 73 +#define B01001001 73 +#define B1001010 74 +#define B01001010 74 +#define B1001011 75 +#define B01001011 75 +#define B1001100 76 +#define B01001100 76 +#define B1001101 77 +#define B01001101 77 +#define B1001110 78 +#define B01001110 78 +#define B1001111 79 +#define B01001111 79 +#define B1010000 80 +#define B01010000 80 +#define B1010001 81 +#define B01010001 81 +#define B1010010 82 +#define B01010010 82 +#define B1010011 83 +#define B01010011 83 +#define B1010100 84 +#define B01010100 84 +#define B1010101 85 +#define B01010101 85 +#define B1010110 86 +#define B01010110 86 +#define B1010111 87 +#define B01010111 87 +#define B1011000 88 +#define B01011000 88 +#define B1011001 89 +#define B01011001 89 +#define B1011010 90 +#define B01011010 90 +#define B1011011 91 +#define B01011011 91 +#define B1011100 92 +#define B01011100 92 +#define B1011101 93 +#define B01011101 93 +#define B1011110 94 +#define B01011110 94 +#define B1011111 95 +#define B01011111 95 +#define B1100000 96 +#define B01100000 96 +#define B1100001 97 +#define B01100001 97 +#define B1100010 98 +#define B01100010 98 +#define B1100011 99 +#define B01100011 99 +#define B1100100 100 +#define B01100100 100 +#define B1100101 101 +#define B01100101 101 +#define B1100110 102 +#define B01100110 102 +#define B1100111 103 +#define B01100111 103 +#define B1101000 104 +#define B01101000 104 +#define B1101001 105 +#define B01101001 105 +#define B1101010 106 +#define B01101010 106 +#define B1101011 107 +#define B01101011 107 +#define B1101100 108 +#define B01101100 108 +#define B1101101 109 +#define B01101101 109 +#define B1101110 110 +#define B01101110 110 +#define B1101111 111 +#define B01101111 111 +#define B1110000 112 +#define B01110000 112 +#define B1110001 113 +#define B01110001 113 +#define B1110010 114 +#define B01110010 114 +#define B1110011 115 +#define B01110011 115 +#define B1110100 116 +#define B01110100 116 +#define B1110101 117 +#define B01110101 117 +#define B1110110 118 +#define B01110110 118 +#define B1110111 119 +#define B01110111 119 +#define B1111000 120 +#define B01111000 120 +#define B1111001 121 +#define B01111001 121 +#define B1111010 122 +#define B01111010 122 +#define B1111011 123 +#define B01111011 123 +#define B1111100 124 +#define B01111100 124 +#define B1111101 125 +#define B01111101 125 +#define B1111110 126 +#define B01111110 126 +#define B1111111 127 +#define B01111111 127 +#define B10000000 128 +#define B10000001 129 +#define B10000010 130 +#define B10000011 131 +#define B10000100 132 +#define B10000101 133 +#define B10000110 134 +#define B10000111 135 +#define B10001000 136 +#define B10001001 137 +#define B10001010 138 +#define B10001011 139 +#define B10001100 140 +#define B10001101 141 +#define B10001110 142 +#define B10001111 143 +#define B10010000 144 +#define B10010001 145 +#define B10010010 146 +#define B10010011 147 +#define B10010100 148 +#define B10010101 149 +#define B10010110 150 +#define B10010111 151 +#define B10011000 152 +#define B10011001 153 +#define B10011010 154 +#define B10011011 155 +#define B10011100 156 +#define B10011101 157 +#define B10011110 158 +#define B10011111 159 +#define B10100000 160 +#define B10100001 161 +#define B10100010 162 +#define B10100011 163 +#define B10100100 164 +#define B10100101 165 +#define B10100110 166 +#define B10100111 167 +#define B10101000 168 +#define B10101001 169 +#define B10101010 170 +#define B10101011 171 +#define B10101100 172 +#define B10101101 173 +#define B10101110 174 +#define B10101111 175 +#define B10110000 176 +#define B10110001 177 +#define B10110010 178 +#define B10110011 179 +#define B10110100 180 +#define B10110101 181 +#define B10110110 182 +#define B10110111 183 +#define B10111000 184 +#define B10111001 185 +#define B10111010 186 +#define B10111011 187 +#define B10111100 188 +#define B10111101 189 +#define B10111110 190 +#define B10111111 191 +#define B11000000 192 +#define B11000001 193 +#define B11000010 194 +#define B11000011 195 +#define B11000100 196 +#define B11000101 197 +#define B11000110 198 +#define B11000111 199 +#define B11001000 200 +#define B11001001 201 +#define B11001010 202 +#define B11001011 203 +#define B11001100 204 +#define B11001101 205 +#define B11001110 206 +#define B11001111 207 +#define B11010000 208 +#define B11010001 209 +#define B11010010 210 +#define B11010011 211 +#define B11010100 212 +#define B11010101 213 +#define B11010110 214 +#define B11010111 215 +#define B11011000 216 +#define B11011001 217 +#define B11011010 218 +#define B11011011 219 +#define B11011100 220 +#define B11011101 221 +#define B11011110 222 +#define B11011111 223 +#define B11100000 224 +#define B11100001 225 +#define B11100010 226 +#define B11100011 227 +#define B11100100 228 +#define B11100101 229 +#define B11100110 230 +#define B11100111 231 +#define B11101000 232 +#define B11101001 233 +#define B11101010 234 +#define B11101011 235 +#define B11101100 236 +#define B11101101 237 +#define B11101110 238 +#define B11101111 239 +#define B11110000 240 +#define B11110001 241 +#define B11110010 242 +#define B11110011 243 +#define B11110100 244 +#define B11110101 245 +#define B11110110 246 +#define B11110111 247 +#define B11111000 248 +#define B11111001 249 +#define B11111010 250 +#define B11111011 251 +#define B11111100 252 +#define B11111101 253 +#define B11111110 254 +#define B11111111 255 + +#endif diff --git a/sparkfun/samd/cores/LilyMini/cortex_handlers.c b/sparkfun/samd/cores/LilyMini/cortex_handlers.c new file mode 100644 index 00000000..3186f1ba --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/cortex_handlers.c @@ -0,0 +1,193 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include +#include +#include + +/* RTOS Hooks */ +extern void svcHook(void); +extern void pendSVHook(void); +extern int sysTickHook(void); + +/* Default empty handler */ +void Dummy_Handler(void) +{ +#if defined DEBUG + __BKPT(3); +#endif + for (;;) { } +} + +/* Cortex-M0+ core handlers */ +void HardFault_Handler(void) __attribute__ ((weak, alias("Dummy_Handler"))); +void Reset_Handler (void); +void NMI_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SVC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void PendSV_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SysTick_Handler (void); + +/* Peripherals handlers */ +void PM_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SYSCTRL_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void WDT_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void RTC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void EIC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void NVMCTRL_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void DMAC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void USB_Handler (void) __attribute__ ((weak)); +void EVSYS_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SERCOM0_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SERCOM1_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SERCOM2_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SERCOM3_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SERCOM4_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void SERCOM5_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void TCC0_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +//void TCC1_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +//void TCC2_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void TC1_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void TC2_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +//void TC3_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +//void TC4_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +//void TC5_Handler (void) __attribute__ ((weak)); // Used in Tone.cpp +//void TC6_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +//void TC7_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void ADC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void AC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void DAC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +void PTC_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); +//void I2S_Handler (void) __attribute__ ((weak, alias("Dummy_Handler"))); + +/* Initialize segments */ +extern uint32_t __etext; +extern uint32_t __data_start__; +extern uint32_t __data_end__; +extern uint32_t __bss_start__; +extern uint32_t __bss_end__; +extern uint32_t __StackTop; + +/* Exception Table */ +__attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table = +{ + /* Configure Initial Stack Pointer, using linker-generated symbols */ + (void*) (&__StackTop), + + (void*) Reset_Handler, + (void*) NMI_Handler, + (void*) HardFault_Handler, + (void*) (0UL), /* Reserved */ + (void*) (0UL), /* Reserved */ + (void*) (0UL), /* Reserved */ + (void*) (0UL), /* Reserved */ + (void*) (0UL), /* Reserved */ + (void*) (0UL), /* Reserved */ + (void*) (0UL), /* Reserved */ + (void*) SVC_Handler, + (void*) (0UL), /* Reserved */ + (void*) (0UL), /* Reserved */ + (void*) PendSV_Handler, + (void*) SysTick_Handler, + + /* Configurable interrupts */ + (void*) PM_Handler, /* 0 Power Manager */ + (void*) SYSCTRL_Handler, /* 1 System Control */ + (void*) WDT_Handler, /* 2 Watchdog Timer */ + (void*) RTC_Handler, /* 3 Real-Time Counter */ + (void*) EIC_Handler, /* 4 External Interrupt Controller */ + (void*) NVMCTRL_Handler, /* 5 Non-Volatile Memory Controller */ + (void*) DMAC_Handler, /* 6 Direct Memory Access Controller */ + (void*) USB_Handler, /* 7 Universal Serial Bus */ + (void*) EVSYS_Handler, /* 8 Event System Interface */ + (void*) SERCOM0_Handler, /* 9 Serial Communication Interface 0 */ + (void*) SERCOM1_Handler, /* 10 Serial Communication Interface 1 */ + (void*) SERCOM2_Handler, /* 11 Serial Communication Interface 2 */ + (void*) TCC0_Handler, /* 12 Timer Counter Control 0 */ + (void*) TC1_Handler, /* 13 Basic Timer Counter 1 */ + (void*) TC2_Handler, /* 14 Basic Timer Counter 2 */ + (void*) ADC_Handler, /* 15 Analog Digital Converter */ + (void*) AC_Handler, /* 16 Analog Comparators */ + (void*) DAC_Handler, /* 17 Digital Analog Converter */ + (void*) PTC_Handler, /* 18 Peripheral Touch Controller */ +// (void*) TC4_Handler, /* 19 Basic Timer Counter 1 */ +// (void*) TC5_Handler, /* 20 Basic Timer Counter 2 */ +// (void*) TC6_Handler, /* 21 Basic Timer Counter 3 */ +// (void*) TC7_Handler, /* 22 Basic Timer Counter 4 */ +// (void*) ADC_Handler, /* 23 Analog Digital Converter */ +// (void*) AC_Handler, /* 24 Analog Comparators */ +// (void*) DAC_Handler, /* 25 Digital Analog Converter */ +// (void*) PTC_Handler, /* 26 Peripheral Touch Controller */ +// (void*) I2S_Handler, /* 27 Inter-IC Sound Interface */ +// (void*) (0UL), /* Reserved */ +}; + +extern int main(void); +extern void __libc_init_array(void); + +/* This is called on processor reset to initialize the device and call main() */ +void Reset_Handler(void) +{ + uint32_t *pSrc, *pDest; + + /* Initialize the initialized data section */ + pSrc = &__etext; + pDest = &__data_start__; + + if ((&__data_start__ != &__data_end__) && (pSrc != pDest)) { + for (; pDest < &__data_end__; pDest++, pSrc++) + *pDest = *pSrc; + } + + /* Clear the zero section */ + if ((&__data_start__ != &__data_end__) && (pSrc != pDest)) { + for (pDest = &__bss_start__; pDest < &__bss_end__; pDest++) + *pDest = 0; + } + + /* Initialize the C library */ + __libc_init_array(); + SystemInit(); + + main(); + + while (1) + ; +} + +/* Default Arduino systick handler */ +extern void SysTick_DefaultHandler(void); + +void SysTick_Handler(void) +{ + if (sysTickHook()) + return; + SysTick_DefaultHandler(); +} + +//static void (*usb_isr)(void) = NULL; + +//void USB_Handler(void) +//{ +// if (usb_isr) +// usb_isr(); +//} + +//void USB_SetHandler(void (*new_usb_isr)(void)) +//{ +// usb_isr = new_usb_isr; +//} diff --git a/sparkfun/samd/cores/LilyMini/delay.c b/sparkfun/samd/cores/LilyMini/delay.c new file mode 100644 index 00000000..ea000abb --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/delay.c @@ -0,0 +1,90 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "delay.h" +#include "Arduino.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Tick Counter united by ms */ +static volatile uint32_t _ulTickCount=0 ; + +uint32_t millis( void ) +{ +// todo: ensure no interrupts + return _ulTickCount ; +} + +// Interrupt-compatible version of micros +// Theory: repeatedly take readings of SysTick counter, millis counter and SysTick interrupt pending flag. +// When it appears that millis counter and pending is stable and SysTick hasn't rolled over, use these +// values to calculate micros. If there is a pending SysTick, add one to the millis counter in the calculation. +uint32_t micros( void ) +{ + uint32_t ticks, ticks2; + uint32_t pend, pend2; + uint32_t count, count2; + + ticks2 = SysTick->VAL; + pend2 = !!(SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) ; + count2 = _ulTickCount ; + + do + { + ticks=ticks2; + pend=pend2; + count=count2; + ticks2 = SysTick->VAL; + pend2 = !!(SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) ; + count2 = _ulTickCount ; + } while ((pend != pend2) || (count != count2) || (ticks < ticks2)); + + return ((count+pend) * 1000) + (((SysTick->LOAD - ticks)*(1048576/(VARIANT_MCK/1000000)))>>20) ; + // this is an optimization to turn a runtime division into two compile-time divisions and + // a runtime multiplication and shift, saving a few cycles +} + +void delay( uint32_t ms ) +{ + if ( ms == 0 ) + { + return ; + } + + uint32_t start = _ulTickCount ; + + do + { + yield() ; + } while ( _ulTickCount - start < ms ) ; +} + +#include "Reset.h" // for tickReset() + +void SysTick_DefaultHandler(void) +{ + // Increment tick count each ms + _ulTickCount++; + tickReset(); +} + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/delay.h b/sparkfun/samd/cores/LilyMini/delay.h new file mode 100644 index 00000000..1df845bd --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/delay.h @@ -0,0 +1,104 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#ifndef _DELAY_ +#define _DELAY_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "variant.h" + +/** + * \brief Returns the number of milliseconds since the Arduino board began running the current program. + * + * This number will overflow (go back to zero), after approximately 50 days. + * + * \return Number of milliseconds since the program started (uint32_t) + */ +extern uint32_t millis( void ) ; + +/** + * \brief Returns the number of microseconds since the Arduino board began running the current program. + * + * This number will overflow (go back to zero), after approximately 70 minutes. On 16 MHz Arduino boards + * (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is + * always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution + * of eight microseconds. + * + * \note There are 1,000 microseconds in a millisecond and 1,000,000 microseconds in a second. + */ +extern uint32_t micros( void ) ; + +/** + * \brief Pauses the program for the amount of time (in miliseconds) specified as parameter. + * (There are 1000 milliseconds in a second.) + * + * \param dwMs the number of milliseconds to pause (uint32_t) + */ +extern void delay( uint32_t dwMs ) ; + +/** + * \brief Pauses the program for the amount of time (in microseconds) specified as parameter. + * + * \param dwUs the number of microseconds to pause (uint32_t) + */ +static __inline__ void delayMicroseconds( uint32_t ) __attribute__((always_inline, unused)) ; +static __inline__ void delayMicroseconds( uint32_t usec ) +{ + if ( usec == 0 ) + { + return ; + } + + /* + * The following loop: + * + * for (; ul; ul--) { + * __asm__ volatile(""); + * } + * + * produce the following assembly code: + * + * loop: + * subs r3, #1 // 1 Core cycle + * bne.n loop // 1 Core cycle + 1 if branch is taken + */ + + // VARIANT_MCK / 1000000 == cycles needed to delay 1uS + // 3 == cycles used in a loop + uint32_t n = usec * (VARIANT_MCK / 1000000) / 3; + __asm__ __volatile__( + "1: \n" + " sub %0, #1 \n" // substract 1 from %0 (n) + " bne 1b \n" // if result is not 0 jump to 1 + : "+r" (n) // '%0' is n variable with RW constraints + : // no input + : // no clobber + ); + // https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html + // https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile +} + +#ifdef __cplusplus +} +#endif + +#endif /* _DELAY_ */ diff --git a/sparkfun/samd/cores/LilyMini/hooks.c b/sparkfun/samd/cores/LilyMini/hooks.c new file mode 100644 index 00000000..f87c2044 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/hooks.c @@ -0,0 +1,58 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +/** + * Empty yield() hook. + * + * This function is intended to be used by library writers to build + * libraries or sketches that supports cooperative threads. + * + * Its defined as a weak symbol and it can be redefined to implement a + * real cooperative scheduler. + */ +static void __empty() { + // Empty +} +void yield(void) __attribute__ ((weak, alias("__empty"))); + +/** + * SysTick hook + * + * This function is called from SysTick handler, before the default + * handler provided by Arduino. + */ +static int __false() { + // Return false + return 0; +} +int sysTickHook(void) __attribute__ ((weak, alias("__false"))); + +/** + * SVC hook + * PendSV hook + * + * These functions are called from SVC handler, and PensSV handler. + * Default action is halting. + */ +static void __halt() { + // Halts + while (1) + ; +} +void svcHook(void) __attribute__ ((weak, alias("__halt"))); +void pendSVHook(void) __attribute__ ((weak, alias("__halt"))); diff --git a/sparkfun/samd/cores/LilyMini/itoa.c b/sparkfun/samd/cores/LilyMini/itoa.c new file mode 100644 index 00000000..55a80e78 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/itoa.c @@ -0,0 +1,170 @@ +/* + Copyright (c) 2014 Arduino LLC. 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 +*/ + +#include "itoa.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* reverse: reverse string s in place */ +/* +static void reverse( char s[] ) +{ + int i, j ; + char c ; + + for ( i = 0, j = strlen(s)-1 ; i < j ; i++, j-- ) + { + c = s[i] ; + s[i] = s[j] ; + s[j] = c ; + } +} +*/ + +/* itoa: convert n to characters in s */ +/* +extern void itoa( int n, char s[] ) +{ + int i, sign ; + + if ( (sign = n) < 0 ) // record sign + { + n = -n; // make n positive + } + + i = 0; + do + { // generate digits in reverse order + s[i++] = n % 10 + '0'; // get next digit + } while ((n /= 10) > 0) ; // delete it + + if (sign < 0 ) + { + s[i++] = '-'; + } + + s[i] = '\0'; + + reverse( s ) ; +} +*/ + +extern char* itoa( int value, char *string, int radix ) +{ + return ltoa( value, string, radix ) ; +} + +extern char* ltoa( long value, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if ( string == NULL ) + { + return 0 ; + } + + if (radix > 36 || radix <= 1) + { + return 0 ; + } + + sign = (radix == 10 && value < 0); + if (sign) + { + v = -value; + } + else + { + v = (unsigned long)value; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + + return string; +} + +extern char* utoa( unsigned long value, char *string, int radix ) +{ + return ultoa( value, string, radix ) ; +} + +extern char* ultoa( unsigned long value, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if ( string == NULL ) + { + return 0; + } + + if (radix > 36 || radix <= 1) + { + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + + return string; +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/sparkfun/samd/cores/LilyMini/itoa.h b/sparkfun/samd/cores/LilyMini/itoa.h new file mode 100644 index 00000000..9e4f48d7 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/itoa.h @@ -0,0 +1,35 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#ifdef __cplusplus +extern "C"{ +#endif + +//extern void itoa( int n, char s[] ) ; + +extern char* itoa( int value, char *string, int radix ) ; +extern char* ltoa( long value, char *string, int radix ) ; +extern char* utoa( unsigned long value, char *string, int radix ) ; +extern char* ultoa( unsigned long value, char *string, int radix ) ; + +#ifdef __cplusplus +} // extern "C" +#endif + diff --git a/sparkfun/samd/cores/LilyMini/main.cpp b/sparkfun/samd/cores/LilyMini/main.cpp new file mode 100644 index 00000000..c66e7281 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/main.cpp @@ -0,0 +1,255 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#define ARDUINO_MAIN +#include "Arduino.h" + +void __sleepIRQ(); +void __wakeIRQ(); + +// Weak empty variant initialization function. +// May be redefined by variant files. +// void initVariant() __attribute__((weak)); + +volatile uint8_t __sleeping; + +void __voltageFade(uint8_t fadeout) +// Sleep entry/exit indicator for RGB LED +// If parameter fadeout is true, fades from on to off. If false, fades from off to on. +// Fade the RGB LED up or down in a specific color chosen by measuring the battery voltage +// Green if above threshold ("good battery") or red if below threshold ("empty battery") +// Does not use PWM or millis() to work within IRQ +{ + int pin,bright,pwm,x; + + pinMode(PIN_LED_RED,OUTPUT); + pinMode(PIN_LED_GREEN,OUTPUT); + pinMode(PIN_LED_BLUE,OUTPUT); + + digitalWrite(PIN_LED_RED,LOW); + digitalWrite(PIN_LED_GREEN,LOW); + digitalWrite(PIN_LED_BLUE,LOW); + + if (analogReadBattVolts() < 250) // < 2.50V, see macro in variant.h + pin = PIN_LED_RED; + else + pin = PIN_LED_GREEN; + +#define __FADESPEED 80 // larger is slower + + if (fadeout) + { + digitalWrite(pin,HIGH); + for (bright = 0; bright <= (__FADESPEED*200); bright++) __asm__ __volatile__(""); + + for (bright = 255; bright >= 0; bright--) + { + for (x = 0; x < __FADESPEED; x++) + { + digitalWrite(pin,HIGH); + for (pwm = 0; pwm <= bright; pwm++) __asm__ __volatile__(""); + digitalWrite(pin,LOW); + for (pwm = 0; pwm <= (255-bright); pwm++) __asm__ __volatile__(""); + } + } + } + else // fade in + { + for (bright = 0; bright <= 255; bright++) + { + for (x = 0; x < __FADESPEED; x++) + { + digitalWrite(pin,HIGH); + for (pwm = 0; pwm <= bright; pwm++) __asm__ __volatile__(""); + digitalWrite(pin,LOW); + for (pwm = 0; pwm <= (255-bright); pwm++) __asm__ __volatile__(""); + } + } + + digitalWrite(pin,HIGH); + for (bright = 0; bright <= (__FADESPEED*200); bright++) __asm__ __volatile__(""); + } + + digitalWrite(PIN_LED_RED,LOW); + digitalWrite(PIN_LED_GREEN,LOW); + digitalWrite(PIN_LED_BLUE,LOW); + + pinMode(PIN_LED_RED,INPUT); + pinMode(PIN_LED_GREEN,INPUT); + pinMode(PIN_LED_BLUE,INPUT); +} + +void __powerButtonIRQ() +// IRQ for asychronous sleep/wake +// Depends on global __sleeping variable preinitialized to false (make static local?) +{ + static uint32_t DIR,OUT,INTENAB,x; + static uint8_t PINCFG1,PINCFG2,PINCFG3,PINCFG4,PINCFG5,PINCFG6,PINCFG7,PINCFG8; + + if (__sleeping) // wake up + { + __sleeping = false; + + // Clear "sleep on exit" + SCB->SCR &= (~SCB_SCR_SLEEPONEXIT_Msk); + + SYSCTRL->VREF.reg |= (SYSCTRL_VREF_BGOUTEN | SYSCTRL_VREF_TSEN); + + // Enable preexisting input pullups only + //PORT->Group[0].OUT.reg = (OUT & (~DIR)); + //PORT->Group[0].PINCFG[14].reg |= (PINCFG1 & 0X02); + //PORT->Group[0].PINCFG[15].reg |= (PINCFG2 & 0X02); + //PORT->Group[0].PINCFG[7].reg |= (PINCFG3 & 0X02); + //PORT->Group[0].PINCFG[6].reg |= (PINCFG4 & 0X02); + //PORT->Group[0].PINCFG[30].reg |= (PINCFG5 & 0X02); + //PORT->Group[0].PINCFG[27].reg |= (PINCFG6 & 0X02); + //PORT->Group[0].PINCFG[31].reg |= (PINCFG7 & 0X02); + //PORT->Group[0].PINCFG[2].reg |= (PINCFG8 & 0X02); + + // Wait for ADC system to recover and pullups to charge input pin caps + for (x = 0; x < 2400000; x++) __asm__ __volatile__(""); // 50ms + + // RGB wake indicator + __voltageFade(false); + + // Restore pin configs +// PORT->Group[0].OUT.reg = OUT; //(OUT & (~DIR)); // Enable preexisting input pullups only + PORT->Group[0].PINCFG[14].reg = PINCFG1; + PORT->Group[0].PINCFG[15].reg = PINCFG2; + PORT->Group[0].PINCFG[7].reg = PINCFG3; + PORT->Group[0].PINCFG[6].reg = PINCFG4; + PORT->Group[0].PINCFG[30].reg = PINCFG5; + PORT->Group[0].PINCFG[27].reg = PINCFG6; + PORT->Group[0].PINCFG[31].reg = PINCFG7; + PORT->Group[0].PINCFG[2].reg = PINCFG8; + + PORT->Group[0].DIR.reg = DIR; + PORT->Group[0].OUT.reg = OUT; + + // Clear any pending interrupts + EIC->INTFLAG.reg = 0; + // Restore interrupts + EIC->INTENSET.reg = INTENAB; + + // Restore USB connection + USBDevice.init(); + USBDevice.attach(); + } + else // go to sleep + { + __sleeping = true; + + // Turn off USB + USBDevice.detach(); + + // Save enabled interrupts + INTENAB = EIC->INTENCLR.reg; + // Disable external interrupts except this one + EIC->INTENCLR.reg = 0b11011111; + + // Save pin values to restore on wake + DIR = PORT->Group[0].DIR.reg; // Save all pin directions + OUT = PORT->Group[0].OUT.reg; // Save all pin states + PINCFG1 = PORT->Group[0].PINCFG[14].reg; // Save individual pin configs + PINCFG2 = PORT->Group[0].PINCFG[15].reg; + PINCFG3 = PORT->Group[0].PINCFG[7].reg; + PINCFG4 = PORT->Group[0].PINCFG[6].reg; + PINCFG5 = PORT->Group[0].PINCFG[30].reg; + PINCFG6 = PORT->Group[0].PINCFG[27].reg; + PINCFG7 = PORT->Group[0].PINCFG[31].reg; + PINCFG8 = PORT->Group[0].PINCFG[2].reg; + + // Set all pins to lowest power state + + // Disable all pins except power + PORT->Group[0].DIR.reg = 0; // Set all pins to be inputs + PORT->Group[0].OUT.reg = 0x00008020; // Turn off all outputs except power ######## AND BUTTON pullups + PORT->Group[0].WRCONFIG.reg = 0x40007FDF; // Disable pullups, lower 16 pins except A5 ############### AND A15 (REMOVE!) +// PORT->Group[0].WRCONFIG.reg = 0x4000FFDF; // Disable pullups, lower 16 pins except A5 + PORT->Group[0].WRCONFIG.reg = 0xC000FFFF; // Disable pullups, upper 16 pins + + // If pins are outputs, disable the pullup + // Keep pullups active for inputs, disable for former outputs (avoid LED glow through pullup) + //if (DIR & (1<<14)) /* output */ PORT->Group[0].PINCFG[14].reg = 0; + //if (DIR & (1<<15)) /* output */ PORT->Group[0].PINCFG[15].reg = 0; + //if (DIR & (1<<7)) /* output */ PORT->Group[0].PINCFG[7].reg = 0; + //if (DIR & (1<<6)) /* output */ PORT->Group[0].PINCFG[6].reg = 0; + //if (DIR & (1<<30)) /* output */ PORT->Group[0].PINCFG[30].reg = 0; + //if (DIR & (1<<27)) /* output */ PORT->Group[0].PINCFG[27].reg = 0; + //if (DIR & (1<<31)) /* output */ PORT->Group[0].PINCFG[31].reg = 0; + //if (DIR & (1<<2)) /* output */ PORT->Group[0].PINCFG[2].reg = 0; + + // Wait for voltage to stabilize before ADC read +// for (x = 0; x < 2400000; x++) __asm__ __volatile__(""); // 50ms + __voltageFade(true); + + // Misc low-power settings +// NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_WAKEUPINSTANT_Val; + // Turn off bandgap reference and temperature sensor (ADC internal sources) + SYSCTRL->VREF.reg &= ~(SYSCTRL_VREF_BGOUTEN | SYSCTRL_VREF_TSEN); + + // Set deep sleep + sleep on exit: system will WFI after IRQ exits + SCB->SCR |= (SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk); + + } +} + +void initVariant() +{ + // Preset onboard RGB LED to outputs/off + pinMode(PIN_LED_RED,OUTPUT); + pinMode(PIN_LED_GREEN,OUTPUT); + pinMode(PIN_LED_BLUE,OUTPUT); + digitalWrite(PIN_LED_RED,LOW); + digitalWrite(PIN_LED_GREEN,LOW); + digitalWrite(PIN_LED_BLUE,LOW); + + // Set up power button for sleep / wake + __sleeping = false; + pinMode(PIN_BUTTON,INPUT_PULLUP); + attachInterrupt(PIN_BUTTON,__powerButtonIRQ,LOW); + + // Turn on "+" sewtab + pinMode(PIN_POWER,OUTPUT); + digitalWrite(PIN_POWER,HIGH); +} + +/* + * \brief Main entry point of Arduino application + */ +int main( void ) +{ + init(); + initVariant(); + + delay(1); +#if defined(USBCON) + USBDevice.init(); + USBDevice.attach(); +#endif + + setup(); + + for (;;) + { + loop(); + if (serialEventRun) serialEventRun(); + } + + return 0; +} diff --git a/sparkfun/samd/cores/LilyMini/new.cpp b/sparkfun/samd/cores/LilyMini/new.cpp new file mode 100644 index 00000000..f1897758 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/new.cpp @@ -0,0 +1,36 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#include + +void *operator new(size_t size) { + return malloc(size); +} + +void *operator new[](size_t size) { + return malloc(size); +} + +void operator delete(void * ptr) { + free(ptr); +} + +void operator delete[](void * ptr) { + free(ptr); +} + diff --git a/sparkfun/samd/cores/LilyMini/pulse.c b/sparkfun/samd/cores/LilyMini/pulse.c new file mode 100644 index 00000000..2dd03bf4 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/pulse.c @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include + +// See pulse_asm.S +extern unsigned long countPulseASM(const volatile uint32_t *port, uint32_t bit, uint32_t stateMask, unsigned long maxloops); + +/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH + * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds + * to 3 minutes in length, but must be called at least a few dozen microseconds + * before the start of the pulse. */ +uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout) +{ + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + PinDescription p = g_APinDescription[pin]; + uint32_t bit = 1 << p.ulPin; + uint32_t stateMask = state ? bit : 0; + + // convert the timeout from microseconds to a number of times through + // the initial loop; it takes (roughly) 13 clock cycles per iteration. + uint32_t maxloops = microsecondsToClockCycles(timeout) / 13; + + uint32_t width = countPulseASM(&(PORT->Group[p.ulPort].IN.reg), bit, stateMask, maxloops); + + // convert the reading to microseconds. The loop has been determined + // to be 13 clock cycles long and have about 16 clocks between the edge + // and the start of the loop. There will be some error introduced by + // the interrupt handlers. + if (width) + return clockCyclesToMicroseconds(width * 13 + 16); + else + return 0; +} + diff --git a/sparkfun/samd/cores/LilyMini/pulse.h b/sparkfun/samd/cores/LilyMini/pulse.h new file mode 100644 index 00000000..9c620f12 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/pulse.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * \brief Measures the length (in microseconds) of a pulse on the pin; state is HIGH + * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds + * to 3 minutes in length, but must be called at least a few dozen microseconds + * before the start of the pulse. + */ +uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout); + +#ifdef __cplusplus +// Provides a version of pulseIn with a default argument (C++ only) +uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout = 1000000L); + +} // extern "C" +#endif + diff --git a/sparkfun/samd/cores/LilyMini/pulse_asm.S b/sparkfun/samd/cores/LilyMini/pulse_asm.S new file mode 100644 index 00000000..7b94f158 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/pulse_asm.S @@ -0,0 +1,175 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +/* + +The following function has been compiled to ASM with gcc + + unsigned long countPulseASM(const volatile uint32_t *port, uint32_t bit, uint32_t stateMask, unsigned long maxloops) + { + unsigned long width = 0; + + // wait for any previous pulse to end + while ((*port & bit) == stateMask) + if (--maxloops == 0) + return 0; + + // wait for the pulse to start + while ((*port & bit) != stateMask) + if (--maxloops == 0) + return 0; + + // wait for the pulse to stop + while ((*port & bit) == stateMask) { + if (++width == maxloops) + return 0; + } + return width; + } + +using the command line: + + arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -c -Os -W -ffunction-sections -fdata-sections \ + -nostdlib --param max-inline-insns-single=500 -fno-exceptions -MMD \ + -DF_CPU=48000000L -DARDUINO=10602 -DARDUINO_SAMD_ZERO -DARDUINO_ARCH_SAMD \ + -D__SAMD21G18A__ -DUSB_VID=0x2341 -DUSB_PID=0x004d -DUSBCON \ + -DUSB_MANUFACTURER="Arduino LLC" -DUSB_PRODUCT="Arduino Zero" \ + -I/Code/arduino/build/linux/work/hardware/tools/CMSIS/CMSIS/Include/ \ + -I/Code/arduino/build/linux/work/hardware/tools/CMSIS/Device/ATMEL/ \ + -I/Code/arduino/build/linux/work/hardware/arduino/samd/cores/arduino \ + -I/Code/arduino/build/linux/work/hardware/arduino/samd/variants/arduino_zero \ + count.c -Wa,-ahlmsd=output.lst -dp -fverbose-asm -S + +The result has been slightly edited to increase readability. + +*/ + + .cpu cortex-m0plus + .fpu softvfp + .eabi_attribute 20, 1 @ Tag_ABI_FP_denormal + .eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions + .eabi_attribute 23, 3 @ Tag_ABI_FP_number_model + .eabi_attribute 24, 1 @ Tag_ABI_align8_needed + .eabi_attribute 25, 1 @ Tag_ABI_align8_preserved + .eabi_attribute 26, 1 @ Tag_ABI_enum_size + .eabi_attribute 30, 4 @ Tag_ABI_optimization_goals + .eabi_attribute 34, 0 @ Tag_CPU_unaligned_access + .eabi_attribute 18, 4 @ Tag_ABI_PCS_wchar_t + .file "count.c" +@ GNU C (GNU Tools for ARM Embedded Processors (Arduino build)) version 4.8.3 20140228 (release) [ARM/embedded-4_8-branch revision 208322] (arm-none-eabi) +@ compiled by GNU C version 4.3.2, GMP version 4.3.2, MPFR version 2.4.2, MPC version 0.8.1 +@ GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 +@ options passed: +@ -I /Code/arduino/build/linux/work/hardware/tools/CMSIS/CMSIS/Include/ +@ -I /Code/arduino/build/linux/work/hardware/tools/CMSIS/Device/ATMEL/ +@ -I /Code/arduino/build/linux/work/hardware/arduino/samd/cores/arduino +@ -I /Code/arduino/build/linux/work/hardware/arduino/samd/variants/arduino_zero +@ -imultilib armv6-m +@ -iprefix /Code/arduino/build/linux/work/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/ +@ -isysroot /Code/arduino/build/linux/work/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/../arm-none-eabi +@ -MMD count.d -D__USES_INITFINI__ -D F_CPU=48000000L -D ARDUINO=10602 +@ -D ARDUINO_SAMD_ZERO -D ARDUINO_ARCH_SAMD -D __SAMD21G18A__ +@ -D USB_VID=0x2341 -D USB_PID=0x004d -D USBCON +@ -D USB_MANUFACTURER=Arduino LLC -D USB_PRODUCT=Arduino Zero count.c +@ -mcpu=cortex-m0plus -mthumb -Os -Wextra -ffunction-sections +@ -fdata-sections -fno-exceptions -fverbose-asm +@ --param max-inline-insns-single=500 +@ options enabled: -faggressive-loop-optimizations -fauto-inc-dec +@ -fbranch-count-reg -fcaller-saves -fcombine-stack-adjustments -fcommon +@ -fcompare-elim -fcprop-registers -fcrossjumping -fcse-follow-jumps +@ -fdata-sections -fdefer-pop -fdelete-null-pointer-checks -fdevirtualize +@ -fdwarf2-cfi-asm -fearly-inlining -feliminate-unused-debug-types +@ -fexpensive-optimizations -fforward-propagate -ffunction-cse +@ -ffunction-sections -fgcse -fgcse-lm -fgnu-runtime +@ -fguess-branch-probability -fhoist-adjacent-loads -fident -fif-conversion +@ -fif-conversion2 -findirect-inlining -finline -finline-atomics +@ -finline-functions -finline-functions-called-once +@ -finline-small-functions -fipa-cp -fipa-profile -fipa-pure-const +@ -fipa-reference -fipa-sra -fira-hoist-pressure -fira-share-save-slots +@ -fira-share-spill-slots -fivopts -fkeep-static-consts +@ -fleading-underscore -fmath-errno -fmerge-constants -fmerge-debug-strings +@ -fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls +@ -fpartial-inlining -fpeephole -fpeephole2 -fprefetch-loop-arrays +@ -freg-struct-return -fregmove -freorder-blocks -freorder-functions +@ -frerun-cse-after-loop -fsched-critical-path-heuristic +@ -fsched-dep-count-heuristic -fsched-group-heuristic -fsched-interblock +@ -fsched-last-insn-heuristic -fsched-pressure -fsched-rank-heuristic +@ -fsched-spec -fsched-spec-insn-heuristic -fsched-stalled-insns-dep +@ -fschedule-insns2 -fsection-anchors -fshow-column -fshrink-wrap +@ -fsigned-zeros -fsplit-ivs-in-unroller -fsplit-wide-types +@ -fstrict-aliasing -fstrict-overflow -fstrict-volatile-bitfields +@ -fsync-libcalls -fthread-jumps -ftoplevel-reorder -ftrapping-math +@ -ftree-bit-ccp -ftree-builtin-call-dce -ftree-ccp -ftree-ch +@ -ftree-coalesce-vars -ftree-copy-prop -ftree-copyrename -ftree-cselim +@ -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre +@ -ftree-loop-if-convert -ftree-loop-im -ftree-loop-ivcanon +@ -ftree-loop-optimize -ftree-parallelize-loops= -ftree-phiprop -ftree-pre +@ -ftree-pta -ftree-reassoc -ftree-scev-cprop -ftree-sink +@ -ftree-slp-vectorize -ftree-slsr -ftree-sra -ftree-switch-conversion +@ -ftree-tail-merge -ftree-ter -ftree-vect-loop-version -ftree-vrp +@ -funit-at-a-time -fverbose-asm -fzero-initialized-in-bss -mlittle-endian +@ -mpic-data-is-text-relative -msched-prolog -mthumb +@ -mvectorize-with-neon-quad + + .section .text.countPulseASM,"ax",%progbits + .align 1 + .global countPulseASM + .code 16 + .thumb_func + .type countPulseASM, %function +countPulseASM: + push {r4, r5, lr} @ @ 112 *push_multi [length = 2] +.L2: + ldr r4, [r0] @ D.11539, *port_7(D) @ 22 *thumb1_movsi_insn/7 [length = 2] + and r4, r1 @ D.11539, bit @ 24 *thumb1_andsi3_insn [length = 2] + cmp r4, r2 @ D.11539, stateMask @ 25 cbranchsi4_insn/1 [length = 4] + bne .L5 @, + sub r3, r3, #1 @ maxloops, @ 17 *thumb1_addsi3/2 [length = 2] + cmp r3, #0 @ maxloops, @ 18 cbranchsi4_insn/1 [length = 4] + bne .L2 @, + b .L10 @ @ 127 *thumb_jump [length = 2] +.L6: + sub r3, r3, #1 @ maxloops, @ 30 *thumb1_addsi3/2 [length = 2] + cmp r3, #0 @ maxloops, @ 31 cbranchsi4_insn/1 [length = 4] + beq .L10 @, +.L5: + ldr r4, [r0] @ D.11539, *port_7(D) @ 35 *thumb1_movsi_insn/7 [length = 2] + and r4, r1 @ D.11539, bit @ 37 *thumb1_andsi3_insn [length = 2] + cmp r4, r2 @ D.11539, stateMask @ 38 cbranchsi4_insn/1 [length = 4] + bne .L6 @, + mov r4, #0 @ width, @ 7 *thumb1_movsi_insn/2 [length = 2] +.L7: + ldr r5, [r0] @ D.11539, *port_7(D) @ 48 *thumb1_movsi_insn/7 [length = 2] + and r5, r1 @ D.11539, bit @ 50 *thumb1_andsi3_insn [length = 2] + cmp r5, r2 @ D.11539, stateMask @ 51 cbranchsi4_insn/1 [length = 4] + bne .L13 @, + add r4, r4, #1 @ width, @ 43 *thumb1_addsi3/1 [length = 2] + cmp r4, r3 @ width, maxloops @ 44 cbranchsi4_insn/1 [length = 4] + bne .L7 @, + mov r0, #0 @ D.11539, @ 11 *thumb1_movsi_insn/2 [length = 2] + b .L3 @ @ 130 *thumb_jump [length = 2] +.L13: + mov r0, r4 @ D.11539, width @ 9 *thumb1_movsi_insn/1 [length = 2] + b .L3 @ @ 132 *thumb_jump [length = 2] +.L10: + mov r0, r3 @ D.11539, maxloops @ 8 *thumb1_movsi_insn/1 [length = 2] +.L3: + @ sp needed @ @ 115 force_register_use [length = 0] + pop {r4, r5, pc} + .size countPulseASM, .-countPulseASM + .ident "GCC: (GNU Tools for ARM Embedded Processors (Arduino build)) 4.8.3 20140228 (release) [ARM/embedded-4_8-branch revision 208322]" diff --git a/sparkfun/samd/cores/LilyMini/startup.c b/sparkfun/samd/cores/LilyMini/startup.c new file mode 100644 index 00000000..c93780a2 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/startup.c @@ -0,0 +1,217 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "sam.h" +#include "variant.h" + +#include + +/** + * \brief SystemInit() configures the needed clocks and according Flash Read Wait States. + * At reset: + * - OSC8M clock source is enabled with a divider by 8 (1MHz). + * - Generic Clock Generator 0 (GCLKMAIN) is using OSC8M as source. + * We need to: + * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator), will be used as DFLL48M reference. + * 2) Put XOSC32K as source of Generic Clock Generator 1 + * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) + * 4) Enable DFLL48M clock + * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. + * 6) Modify PRESCaler value of OSCM to have 8MHz + * 7) Put OSC8M as source for Generic Clock Generator 3 + */ +// Constants for Clock generators +#define GENERIC_CLOCK_GENERATOR_MAIN (0u) +#define GENERIC_CLOCK_GENERATOR_XOSC32K (1u) +#define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */ +#define GENERIC_CLOCK_GENERATOR_OSC8M (3u) +// Constants for Clock multiplexers +#define GENERIC_CLOCK_MULTIPLEXER_DFLL48M (0u) + +void waitForSync( void ) +{ + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } +} + +void waitForDFLL( void ) +{ + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) + { + /* Wait for synchronization */ + } +} + +void SystemInit( void ) +{ + /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */ + NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ; + + /* Turn on the digital interface clock */ + PM->APBAMASK.reg |= PM_APBAMASK_GCLK ; + + /* ---------------------------------------------------------------------------------------------- + * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator) + */ + SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */ + SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ; + SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */ + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 ) + { + /* Wait for oscillator stabilization */ + } + + /* Software reset the module to ensure it is re-initialized correctly */ + /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete. + * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1 + */ + GCLK->CTRL.reg = GCLK_CTRL_SWRST ; + + while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) ) + { + /* Wait for reset to complete */ + } + + /* ---------------------------------------------------------------------------------------------- + * 2) Put XOSC32K as source of Generic Clock Generator 1 + */ + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1 + + waitForSync(); + + /* Write Generic Clock Generator 1 configuration */ + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1 + GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator +// GCLK_GENCTRL_OE | // Output clock to a pin for tests + GCLK_GENCTRL_GENEN ; + + waitForSync(); + + /* ---------------------------------------------------------------------------------------------- + * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) + */ + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0 + GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source + GCLK_CLKCTRL_CLKEN ; + + waitForSync(); + + /* ---------------------------------------------------------------------------------------------- + * 4) Enable DFLL48M clock + */ + + /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */ + + /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */ + SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0 ; + + waitForDFLL(); + + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value + SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value + SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK/VARIANT_MAINOSC) ) ; // External 32KHz is the reference + + waitForDFLL(); + + /* Write full configuration to DFLL control register */ + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */ + SYSCTRL_DFLLCTRL_WAITLOCK | + SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */ + + waitForDFLL(); + + /* Enable the DFLL */ + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ; + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 || + (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 ) + { + /* Wait for locks flags */ + } + + waitForDFLL(); + + /* ---------------------------------------------------------------------------------------------- + * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. + */ + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0 + + waitForSync(); + + /* Write Generic Clock Generator 0 configuration */ + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0 + GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz +// GCLK_GENCTRL_OE | // Output clock to a pin for tests + GCLK_GENCTRL_IDC | // Set 50/50 duty cycle + GCLK_GENCTRL_GENEN ; + + waitForSync(); + + /* ---------------------------------------------------------------------------------------------- + * 6) Modify PRESCaler value of OSC8M to have 8MHz + */ + SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_1_Val ; + SYSCTRL->OSC8M.bit.ONDEMAND = 0 ; + + /* ---------------------------------------------------------------------------------------------- + * 7) Put OSC8M as source for Generic Clock Generator 3 + */ + GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) ; // Generic Clock Generator 3 + + /* Write Generic Clock Generator 3 configuration */ + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3 + GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset) +// GCLK_GENCTRL_OE | // Output clock to a pin for tests + GCLK_GENCTRL_GENEN ; + + waitForSync(); + + /* + * Now that all system clocks are configured, we can set CPU and APBx BUS clocks. + * There values are normally the one present after Reset. + */ + PM->CPUSEL.reg = PM_CPUSEL_CPUDIV_DIV1 ; + PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val ; + PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val ; + PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val ; + + SystemCoreClock=VARIANT_MCK ; + + /* ---------------------------------------------------------------------------------------------- + * 8) Load ADC factory calibration values + */ + + // ADC Bias Calibration + uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos; + + // ADC Linearity bits 4:0 + uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos; + + // ADC Linearity bits 7:5 + linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5; + + ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity); + + /* + * 9) Disable automatic NVM write operations + */ + NVMCTRL->CTRLB.bit.MANW = 1; +} diff --git a/sparkfun/samd/cores/LilyMini/wiring.c b/sparkfun/samd/cores/LilyMini/wiring.c new file mode 100644 index 00000000..545b54b2 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring.c @@ -0,0 +1,143 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "Arduino.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * System Core Clock is at 1MHz (8MHz/8) at Reset. + * It is switched to 48MHz in the Reset Handler (startup.c) + */ +uint32_t SystemCoreClock=1000000ul ; + +/* +void calibrateADC() +{ + volatile uint32_t valeur = 0; + + for(int i = 0; i < 5; ++i) + { + ADC->SWTRIG.bit.START = 1; + while( ADC->INTFLAG.bit.RESRDY == 0 || ADC->STATUS.bit.SYNCBUSY == 1 ) + { + // Waiting for a complete conversion and complete synchronization + } + + valeur += ADC->RESULT.bit.RESULT; + } + + valeur = valeur/5; +}*/ + +/* + * Arduino Zero board initialization + * + * Good to know: + * - At reset, ResetHandler did the system clock configuration. Core is running at 48MHz. + * - Watchdog is disabled by default, unless someone plays with NVM User page + * - During reset, all PORT lines are configured as inputs with input buffers, output buffers and pull disabled. + */ +void init( void ) +{ + uint32_t ul ; + + // Set Systick to 1ms interval, common to all Cortex-M variants + if ( SysTick_Config( SystemCoreClock / 1000 ) ) + { + // Capture error + while ( 1 ) ; + } + NVIC_SetPriority (SysTick_IRQn, (1 << __NVIC_PRIO_BITS) - 2); /* set Priority for Systick Interrupt (2nd lowest) */ + + // Clock PORT for Digital I/O +// PM->APBBMASK.reg |= PM_APBBMASK_PORT ; +// +// // Clock EIC for I/O interrupts +// PM->APBAMASK.reg |= PM_APBAMASK_EIC ; + + // Clock SERCOM for Serial + PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 ; + + // Clock TC/TCC for Pulse and Analog + PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TC1 | PM_APBCMASK_TC2 ; + + // Clock ADC/DAC for Analog + PM->APBCMASK.reg |= PM_APBCMASK_ADC; // | PM_APBCMASK_DAC ; + + //PORT->Group[0].OUTCLR.reg = 0xFFFF; // Outputs off or pullups down + //PORT->Group[0].DIRCLR.reg = 0xFFFF; // Set all pins to be inputs + //PORT->Group[0].WRCONFIG.reg = 0x4000FFFF; // Disable pullups, lower 16 pins + //PORT->Group[0].WRCONFIG.reg = 0xC000FFFF; // Disable pullups, upper 16 pins + + // Setup all pins (digital and analog) in INPUT mode (default is nothing) + for ( ul = 0 ; ul < PINS_COUNT ; ul++ ) // nee NUM_DIGITAL_PINS + { + pinMode( ul, INPUT ) ; + } + + // Initialize Analog Controller + // Setting clock + while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); + + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_CLKEN ; + + while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains + + ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 | // Divide Clock by 512. + ADC_CTRLB_RESSEL_16BIT; // 16 bits resolution for averaging + + ADC->SAMPCTRL.reg = 0x3f; // Set max Sampling Time Length + + while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains + + ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND; // No Negative input (Internal Ground) + + // Averaging (see datasheet table in AVGCTRL register description) + ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_4 | // Average over 4 samples + ADC_AVGCTRL_ADJRES(4); // Shift right by 4 to get 10 bits + + analogReference( AR_DEFAULT ) ; // See wiring_analog.c + + // Initialize DAC + // Setting clock +// while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ); +// GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock DAC +// GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source +// GCLK_CLKCTRL_CLKEN ; +// +// while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains +// DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference +// DAC_CTRLB_EOEN ; // External Output Enable (Vout) + + // Turn on bandgap reference and temperature sensor (ADC internal sources) + + SYSCTRL->VREF.reg |= (SYSCTRL_VREF_BGOUTEN | SYSCTRL_VREF_TSEN); + + // Shut down VREG in sleep, ensure power is reduced before sleeping + +// SYSCTRL->VREG.bit.RUNSTDBY = 0; // Not in CMSIS? +} + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/wiring.h b/sparkfun/samd/cores/LilyMini/wiring.h new file mode 100644 index 00000000..55e4e6a8 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring.h @@ -0,0 +1,29 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +extern void init(void); + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/wiring_analog.c b/sparkfun/samd/cores/LilyMini/wiring_analog.c new file mode 100644 index 00000000..c232c3ba --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_analog.c @@ -0,0 +1,342 @@ +/* + Copyright (c) 2014 Arduino LLC. 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 +*/ + +#include "Arduino.h" +#include "wiring_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static int _readResolution = 10; +static int _ADCResolution = 10; +static int _writeResolution = 8; + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncADC() __attribute__((always_inline, unused)); +static void syncADC() { + while (ADC->STATUS.bit.SYNCBUSY == 1) + ; +} + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncDAC() __attribute__((always_inline, unused)); +static void syncDAC() { + while (DAC->STATUS.bit.SYNCBUSY == 1) + ; +} + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncTC_8(Tc* TCx) __attribute__((always_inline, unused)); +static void syncTC_8(Tc* TCx) { + while (TCx->COUNT8.STATUS.bit.SYNCBUSY); +} + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused)); +static void syncTCC(Tcc* TCCx) { + while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK); +} + +//void analogReadResolution( int res ) +//{ +// _readResolution = res ; +// if (res > 10) +// { +// ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val; +// _ADCResolution = 12; +// } +// else if (res > 8) +// { +// ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val; +// _ADCResolution = 10; +// } +// else +// { +// ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val; +// _ADCResolution = 8; +// } +// syncADC(); +//} + +//void analogWriteResolution( int res ) +//{ +// _writeResolution = res ; +//} + +//static inline uint32_t mapResolution( uint32_t value, uint32_t from, uint32_t to ) +//{ +// if ( from == to ) +// { +// return value ; +// } +// +// if ( from > to ) +// { +// return value >> (from-to) ; +// } +// else +// { +// return value << (to-from) ; +// } +//} + +/* + * Internal Reference is at 1.0v + * External Reference should be between 1v and VDDANA-0.6v=2.7v + * + * Warning : On Arduino Zero board the input/output voltage for SAMD21G18 is 3.3 volts maximum + */ +void analogReference(eAnalogReference mode) +{ + syncADC(); + switch (mode) + { + case AR_INTERNAL: + case AR_INTERNAL2V23: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 1/1.48 VDDANA = 1/1.48* 3V3 = 2.2297 + break; + + case AR_EXTERNAL: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val; + break; + + case AR_INTERNAL1V0: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val; // 1.0V voltage reference + break; + + case AR_INTERNAL1V65: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain Factor Selection + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V + break; + + case AR_DEFAULT: + default: + ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val; + ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V + break; + } + analogRead(0); // Do a dummy conversion, necessary after reference change +} + +uint32_t analogRead(uint32_t pin) +{ + uint32_t valueRead = 0; + uint32_t channel; + + if ((pin >= 0x18)&&(pin <= 0x1C)) // Internal ADC sources + { + channel = pin; // Grab source directly from parameter + } + else // External ADC source + { + if ((pin > PINS_COUNT)||(g_APinDescription[pin].ulPinType == PIO_NOT_A_PIN)||(g_APinDescription[pin].ulADCChannelNumber == No_ADC_Channel)) + { + return 0; + } + + // Mux pin to ADC + pinPeripheral(pin, PIO_ANALOG); + +/* + if (pin == A0) // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled + { + syncDAC(); + DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC + //DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off. + syncDAC(); + } +*/ + channel = g_APinDescription[pin].ulADCChannelNumber; // Input selection + } + + // Postpone IRQ past the ADC read to preserve the conversion (ADC hardware is depowered in sleep) + __disable_irq(); + + syncADC(); + ADC->INPUTCTRL.bit.MUXPOS = channel; + //ADC->INPUTCTRL.bit.MUXNEG = ADC_INPUTCTRL_MUXNEG_GND_Val; // Ground reference was set in init(); + + // Control A + /* + * Bit 1 ENABLE: Enable + * 0: The ADC is disabled. + * 1: The ADC is enabled. + * Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The + * value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register + * (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete. + * + * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be + * configured. The first conversion after the reference is changed must not be used. + */ + syncADC(); + ADC->CTRLA.bit.ENABLE = 1; // Enable ADC + +/* + // Start conversion + syncADC(); + ADC->SWTRIG.bit.START = 1; + + syncADC(); + // Clear the Data Ready flag +// ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY; + ADC->INTFLAG.bit.RESRDY = 1; + + // Start conversion again, since The first conversion after the reference is changed must not be used. +*/ + + syncADC(); + ADC->SWTRIG.bit.START = 1; + + // Store the value + while (ADC->INTFLAG.bit.RESRDY == 0); // Waiting for conversion to complete + valueRead = ADC->RESULT.reg; + + syncADC(); + ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC + syncADC(); // needed? + + __enable_irq(); + +// return mapResolution(valueRead, _ADCResolution, _readResolution); + return valueRead; +} + + +// Right now, PWM output only works on the pins with +// hardware support. These are defined in the appropriate +// pins_*.c file. For the rest of the pins, we default +// to digital output. +void analogWrite(uint32_t pin, uint32_t value) +{ + PinDescription pinDesc = g_APinDescription[pin]; + uint32_t attr = pinDesc.ulPinAttribute; + +// DAC removed in LilyMini for space / simplicity (use PWM) + +// value = mapResolution(value, _writeResolution, 8); + + if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM) + { + if (attr & PIN_ATTR_TIMER) { + #if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603) + // Compatibility for cores based on SAMD core <=1.6.2 + if (g_APinDescription[pin].ulPinType == PIO_TIMER_ALT) { + pinPeripheral(pin, PIO_TIMER_ALT); + } else + #endif + { + pinPeripheral(pin, PIO_TIMER); + } + } else { + // We suppose that attr has PIN_ATTR_TIMER_ALT bit set... + pinPeripheral(pin, PIO_TIMER_ALT); + } + + Tc* TCx = 0 ; + Tcc* TCCx = 0 ; + uint8_t Channelx = GetTCChannelNumber( g_APinDescription[pin].ulPWMChannel ) ; + if ( GetTCNumber( g_APinDescription[pin].ulPWMChannel ) >= TCC_INST_NUM ) + { + TCx = (Tc*) GetTC( g_APinDescription[pin].ulPWMChannel ) ; + } + else + { + TCCx = (Tcc*) GetTC( g_APinDescription[pin].ulPWMChannel ) ; + } + + // Enable clocks according to TCCx instance to use + switch ( GetTCNumber( g_APinDescription[pin].ulPWMChannel ) ) + { + case 0: // TCC0 + // Enable GCLK for TCC0 (timer counter input clock) + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0 )) ; + break ; + + case 1: // TC1 + case 2: // TC2 + // Enable GCLK for TC1 and TC2 (timer counter input clock) + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC1_TC2 )) ; + break ; + } + + while (GCLK->STATUS.bit.SYNCBUSY == 1); + + // Set PORT + if ( TCx ) + { + // -- Configure TC + + // Disable TCx + TCx->COUNT8.CTRLA.reg &= ~TC_CTRLA_ENABLE; + syncTC_8(TCx); + // Set Timer counter Mode to 8 bits + TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8; + // Set TCx as normal PWM + TCx->COUNT8.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM; + // Set TCx in waveform mode Normal PWM + TCx->COUNT8.CC[Channelx].reg = (uint8_t) value; + syncTC_8(TCx); + // Set PER to maximum counter value (resolution : 0xFF) + TCx->COUNT8.PER.reg = 0xFF; + syncTC_8(TCx); + // Enable TCx + TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE; + syncTC_8(TCx); + } + else + { + // -- Configure TCC + // Disable TCCx + TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + syncTCC(TCCx); + // Set TCx as normal PWM + TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; + syncTCC(TCCx); + // Set TCx in waveform mode Normal PWM + TCCx->CC[Channelx].reg = (uint32_t)value; + syncTCC(TCCx); + // Set PER to maximum counter value (resolution : 0xFF) + TCCx->PER.reg = 0xFF; + syncTCC(TCCx); + // Enable TCCx + TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; + syncTCC(TCCx); + } + return; + } + + // -- Defaults to digital write + pinMode(pin, OUTPUT); + + if (value < 128) + { + digitalWrite(pin, LOW); + } + else + { + digitalWrite(pin, HIGH); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/wiring_analog.h b/sparkfun/samd/cores/LilyMini/wiring_analog.h new file mode 100644 index 00000000..cca46359 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_analog.h @@ -0,0 +1,84 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * \brief SAMD products have only one reference for ADC + */ +typedef enum _eAnalogReference +{ + AR_DEFAULT, + AR_INTERNAL, + AR_EXTERNAL, + AR_INTERNAL1V0, + AR_INTERNAL1V65, + AR_INTERNAL2V23 +} eAnalogReference ; + + +/* + * \brief Configures the reference voltage used for analog input (i.e. the value used as the top of the input range). + * This function is kept only for compatibility with existing AVR based API. + * + * \param ulMmode Should be set to AR_DEFAULT. + */ +extern void analogReference( eAnalogReference ulMode ) ; + +/* + * \brief Writes an analog value (PWM wave) to a pin. + * + * \param ulPin + * \param ulValue + */ +extern void analogWrite( uint32_t ulPin, uint32_t ulValue ) ; + +/* + * \brief Reads the value from the specified analog pin. + * + * \param ulPin + * + * \return Read value from selected pin, if no error. + */ +extern uint32_t analogRead( uint32_t ulPin ) ; + +/* + * \brief Set the resolution of analogRead return values. Default is 10 bits (range from 0 to 1023). + * + * \param res + */ +extern void analogReadResolution(int res); + +/* + * \brief Set the resolution of analogWrite parameters. Default is 8 bits (range from 0 to 255). + * + * \param res + */ +extern void analogWriteResolution(int res); + +extern void analogOutputInit( void ) ; + +#ifdef __cplusplus +} +#endif diff --git a/sparkfun/samd/cores/LilyMini/wiring_constants.h b/sparkfun/samd/cores/LilyMini/wiring_constants.h new file mode 100644 index 00000000..e8573aed --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_constants.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef _WIRING_CONSTANTS_ +#define _WIRING_CONSTANTS_ + +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus + +#define LOW (0x0) +#define HIGH (0x1) + +#define INPUT (0x0) +#define OUTPUT (0x1) +#define INPUT_PULLUP (0x2) +#define INPUT_PULLDOWN (0x3) + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 +#define EULER 2.718281828459045235360287471352 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +enum BitOrder { + LSBFIRST = 0, + MSBFIRST = 1 +}; + +// moved to WInterrupts.h +//// LOW 0 +//// HIGH 1 +//#define CHANGE 2 +//#define FALLING 3 +//#define RISING 4 +// +//#define DEFAULT 1 +//#define EXTERNAL 0 + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif /* _WIRING_CONSTANTS_ */ diff --git a/sparkfun/samd/cores/LilyMini/wiring_digital.c b/sparkfun/samd/cores/LilyMini/wiring_digital.c new file mode 100644 index 00000000..0490d1b3 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_digital.c @@ -0,0 +1,136 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "Arduino.h" + +#ifdef __cplusplus + extern "C" { +#endif + +void pinMode( uint32_t ulPin, uint32_t ulMode ) +{ + // Handle the case the pin isn't usable as PIO + if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN ) + { + return ; + } + + // 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<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<Group[g_APinDescription[ulPin].ulPort].OUTSET.reg = (uint32_t)(1<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<Group[g_APinDescription[ulPin].ulPort].OUTCLR.reg = (uint32_t)(1<Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].bit.INEN = 1 ; + + // disable pullups + PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].bit.PULLEN = 0 ; + + // Set pin to output mode + PORT->Group[g_APinDescription[ulPin].ulPort].DIRSET.reg = (uint32_t)(1<Group[port].DIRSET.reg & pinMask) == 0 ) { + // the pin is not an output, disable pull-up if val is LOW, otherwise enable pull-up + PORT->Group[port].PINCFG[pin].bit.PULLEN = ((ulVal == LOW) ? 0 : 1) ; + } + + // Handle reversed RGB LED pins + if ((ulPin == PIN_LED_RED) || (ulPin == PIN_LED_GREEN) || (ulPin == PIN_LED_BLUE)) + { + if (ulVal) + ulVal = 0L; + else + ulVal = 1L; + } + + switch ( ulVal ) + { + case LOW: + PORT->Group[port].OUTCLR.reg = pinMask; + break ; + + default: + PORT->Group[port].OUTSET.reg = pinMask; + break ; + } + + return ; +} + +int digitalRead( uint32_t ulPin ) +{ + // Handle the case the pin isn't usable as PIO + if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN ) + { + return LOW ; + } + + if ( (PORT->Group[g_APinDescription[ulPin].ulPort].IN.reg & (1ul << g_APinDescription[ulPin].ulPin)) != 0 ) + { + return HIGH ; + } + + return LOW ; +} + +#ifdef __cplusplus +} +#endif + diff --git a/sparkfun/samd/cores/LilyMini/wiring_digital.h b/sparkfun/samd/cores/LilyMini/wiring_digital.h new file mode 100644 index 00000000..9895390f --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_digital.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef _WIRING_DIGITAL_ +#define _WIRING_DIGITAL_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "WVariant.h" + +/** + * \brief Configures the specified pin to behave either as an input or an output. See the description of digital pins for details. + * + * \param ulPin The number of the pin whose mode you wish to set + * \param ulMode Can be INPUT, OUTPUT, INPUT_PULLUP or INPUT_PULLDOWN + */ +extern void pinMode( uint32_t dwPin, uint32_t dwMode ) ; + +/** + * \brief Write a HIGH or a LOW value to a digital pin. + * + * If the pin has been configured as an OUTPUT with pinMode(), its voltage will be set to the + * corresponding value: 5V (or 3.3V on 3.3V boards) for HIGH, 0V (ground) for LOW. + * + * If the pin is configured as an INPUT, writing a HIGH value with digitalWrite() will enable an internal + * 20K pullup resistor (see the tutorial on digital pins). Writing LOW will disable the pullup. The pullup + * resistor is enough to light an LED dimly, so if LEDs appear to work, but very dimly, this is a likely + * cause. The remedy is to set the pin to an output with the pinMode() function. + * + * \note Digital pin PIN_LED is harder to use as a digital input than the other digital pins because it has an LED + * and resistor attached to it that's soldered to the board on most boards. If you enable its internal 20k pull-up + * resistor, it will hang at around 1.7 V instead of the expected 5V because the onboard LED and series resistor + * pull the voltage level down, meaning it always returns LOW. If you must use pin PIN_LED as a digital input, use an + * external pull down resistor. + * + * \param dwPin the pin number + * \param dwVal HIGH or LOW + */ +extern void digitalWrite( uint32_t dwPin, uint32_t dwVal ) ; + +/** + * \brief Reads the value from a specified digital pin, either HIGH or LOW. + * + * \param ulPin The number of the digital pin you want to read (int) + * + * \return HIGH or LOW + */ +extern int digitalRead( uint32_t ulPin ) ; + +#ifdef __cplusplus +} +#endif + +#endif /* _WIRING_DIGITAL_ */ diff --git a/sparkfun/samd/cores/LilyMini/wiring_private.c b/sparkfun/samd/cores/LilyMini/wiring_private.c new file mode 100644 index 00000000..a5aaba42 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_private.c @@ -0,0 +1,118 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#include "Arduino.h" +#include "wiring_private.h" + +int pinPeripheral( uint32_t ulPin, EPioType ulPeripheral ) +{ + // Handle the case the pin isn't usable as PIO + if ( g_APinDescription[ulPin].ulPinType == PIO_NOT_A_PIN ) + { + return -1 ; + } + + switch ( ulPeripheral ) + { + case PIO_DIGITAL: + case PIO_INPUT: + case PIO_INPUT_PULLUP: + case PIO_OUTPUT: + // Disable peripheral muxing, done in pinMode +// PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].bit.PMUXEN = 0 ; + + // Configure pin mode, if requested + if ( ulPeripheral == PIO_INPUT ) + { + pinMode( ulPin, INPUT ) ; + } + else + { + if ( ulPeripheral == PIO_INPUT_PULLUP ) + { + pinMode( ulPin, INPUT_PULLUP ) ; + } + else + { + if ( ulPeripheral == PIO_OUTPUT ) + { + pinMode( ulPin, OUTPUT ) ; + } + else + { + // PIO_DIGITAL, do we have to do something as all cases are covered? + } + } + } + break ; + + case PIO_ANALOG: + case PIO_SERCOM: + case PIO_SERCOM_ALT: + case PIO_TIMER: + case PIO_TIMER_ALT: + case PIO_EXTINT: + case PIO_COM: + case PIO_AC_CLK: +#if 0 + // Is the pio pin in the lower 16 ones? + // The WRCONFIG register allows update of only 16 pin max out of 32 + if ( g_APinDescription[ulPin].ulPin < 16 ) + { + PORT->Group[g_APinDescription[ulPin].ulPort].WRCONFIG.reg = PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_PMUXEN | PORT_WRCONFIG_PMUX( ulPeripheral ) | + PORT_WRCONFIG_WRPINCFG | + PORT_WRCONFIG_PINMASK( g_APinDescription[ulPin].ulPin ) ; + } + else + { + PORT->Group[g_APinDescription[ulPin].ulPort].WRCONFIG.reg = PORT_WRCONFIG_HWSEL | + PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_PMUXEN | PORT_WRCONFIG_PMUX( ulPeripheral ) | + PORT_WRCONFIG_WRPINCFG | + PORT_WRCONFIG_PINMASK( g_APinDescription[ulPin].ulPin - 16 ) ; + } +#else + if ( g_APinDescription[ulPin].ulPin & 1 ) // is pin odd? + { + uint32_t temp ; + + // Get whole current setup for both odd and even pins and remove odd one + temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXE( 0xF ) ; + // Set new muxing + PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXO( ulPeripheral ) ; + // Enable port mux + PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ; + } + else // even pin + { + uint32_t temp ; + + temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXO( 0xF ) ; + PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXE( ulPeripheral ) ; + PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ; // Enable port mux + } +#endif + break ; + + case PIO_NOT_A_PIN: + return -1l ; + break ; + } + + return 0l ; +} + diff --git a/sparkfun/samd/cores/LilyMini/wiring_private.h b/sparkfun/samd/cores/LilyMini/wiring_private.h new file mode 100644 index 00000000..ce64e2de --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_private.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2015 Arduino LLC. 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 +*/ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Includes Atmel CMSIS +#include "sam.h" + +#include "wiring_constants.h" + +int pinPeripheral( uint32_t ulPin, EPioType ulPeripheral ); + +#ifdef __cplusplus +} // extern "C" + +#include "HardwareSerial.h" + +#endif diff --git a/sparkfun/samd/cores/LilyMini/wiring_shift.c b/sparkfun/samd/cores/LilyMini/wiring_shift.c new file mode 100644 index 00000000..3260d2b1 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_shift.c @@ -0,0 +1,74 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#include +#include "wiring_shift.h" +#include "wiring_digital.h" +#include "wiring_private.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder ) +{ + uint8_t value = 0 ; + uint8_t i ; + + for ( i=0 ; i < 8 ; ++i ) + { + digitalWrite( ulClockPin, HIGH ) ; + + if ( ulBitOrder == LSBFIRST ) + { + value |= digitalRead( ulDataPin ) << i ; + } + else + { + value |= digitalRead( ulDataPin ) << (7 - i) ; + } + + digitalWrite( ulClockPin, LOW ) ; + } + + return value ; +} + +void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal ) +{ + uint8_t i ; + + for ( i=0 ; i < 8 ; i++ ) + { + if ( ulBitOrder == LSBFIRST ) + { + digitalWrite( ulDataPin, !!(ulVal & (1 << i)) ) ; + } + else + { + digitalWrite( ulDataPin, !!(ulVal & (1 << (7 - i))) ) ; + } + + digitalWrite( ulClockPin, HIGH ) ; + digitalWrite( ulClockPin, LOW ) ; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/sparkfun/samd/cores/LilyMini/wiring_shift.h b/sparkfun/samd/cores/LilyMini/wiring_shift.h new file mode 100644 index 00000000..6026bdc6 --- /dev/null +++ b/sparkfun/samd/cores/LilyMini/wiring_shift.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2014 Arduino. 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 +*/ + +#ifndef _WIRING_SHIFT_ +#define _WIRING_SHIFT_ + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * \brief + */ +extern uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder ) ; + + +/* + * \brief + */ +extern void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal ) ; + + +#ifdef __cplusplus +} +#endif + +#endif /* _WIRING_SHIFT_ */ diff --git a/sparkfun/samd/cores/arduino/Arduino.h b/sparkfun/samd/cores/arduino/Arduino.h index b6fd4e73..e645743b 100644 --- a/sparkfun/samd/cores/arduino/Arduino.h +++ b/sparkfun/samd/cores/arduino/Arduino.h @@ -55,6 +55,10 @@ extern "C"{ void yield( void ) ; +/* system functions */ +int main( void ); +void init( void ); + /* sketch */ void setup( void ) ; void loop( void ) ; diff --git a/sparkfun/samd/cores/arduino/Reset.cpp b/sparkfun/samd/cores/arduino/Reset.cpp index 8809907e..053d7c5f 100644 --- a/sparkfun/samd/cores/arduino/Reset.cpp +++ b/sparkfun/samd/cores/arduino/Reset.cpp @@ -24,7 +24,15 @@ extern "C" { #endif #define NVM_MEMORY ((volatile uint16_t *)0x000000) + +#if (ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10610) + +extern const uint32_t __text_start__; +#define APP_START ((volatile uint32_t)(&__text_start__) + 4) + +#else #define APP_START 0x00002004 +#endif static inline bool nvmReady(void) { return NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY; @@ -35,6 +43,13 @@ static void banzai() { // Disable all interrupts __disable_irq(); + // Avoid erasing the application if APP_START is < than the minimum bootloader size + // This could happen if without_bootloader linker script was chosen + // Minimum bootloader size in SAMD21 family is 512bytes (RM section 22.6.5) + if (APP_START < (0x200 + 4)) { + goto reset; + } + // Erase application while (!nvmReady()) ; @@ -44,6 +59,7 @@ static void banzai() { while (!nvmReady()) ; +reset: // Reset the device NVIC_SystemReset() ; diff --git a/sparkfun/samd/cores/arduino/SERCOM.cpp b/sparkfun/samd/cores/arduino/SERCOM.cpp index bfcf813a..44d2fbc2 100644 --- a/sparkfun/samd/cores/arduino/SERCOM.cpp +++ b/sparkfun/samd/cores/arduino/SERCOM.cpp @@ -240,13 +240,13 @@ void SERCOM::enableSPI() void SERCOM::disableSPI() { - //Setting the enable bit to 0 - sercom->SPI.CTRLA.bit.ENABLE = 0; while(sercom->SPI.SYNCBUSY.bit.ENABLE) { //Waiting then enable bit from SYNCBUSY is equal to 0; } + //Setting the enable bit to 0 + sercom->SPI.CTRLA.bit.ENABLE = 0; } void SERCOM::setDataOrderSPI(SercomDataOrder dataOrder) diff --git a/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h b/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h index 31b9e965..c8fafb40 100644 --- a/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h +++ b/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h @@ -48,6 +48,7 @@ class USBDevice_SAMD21G18x { inline void runInStandby() { usb.CTRLA.bit.RUNSTDBY = 1; } inline void noRunInStandby() { usb.CTRLA.bit.RUNSTDBY = 0; } + inline void wakeupHost() { usb.CTRLB.bit.UPRSM = 1; } // USB speed inline void setFullSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val; } @@ -106,8 +107,7 @@ class USBDevice_SAMD21G18x { inline void epBank0EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL0 = 1; } inline void epBank1EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL1 = 1; } inline void epBank0EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; } - inline void epBank1EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; } - + inline void epBank1EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT1 = 1; } inline void epBank0DisableSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.RXSTP = 1; } inline void epBank0DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL0 = 1; } inline void epBank1DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL1 = 1; } @@ -318,21 +318,24 @@ class DoubleBufferedEPOutHandler : public EPHandler { usbd.epBank0AckTransferComplete(ep); //usbd.epBank0AckTransferFailed(ep); // XXX - // Update counters and swap banks + // Update counters and swap banks for non-ZLP's if (incoming == 0) { last0 = usbd.epBank0ByteCount(ep); + if (last0 != 0) { incoming = 1; usbd.epBank0SetAddress(ep, const_cast(data1)); - ready0 = true; synchronized { + ready0 = true; if (ready1) { notify = true; return; } notify = false; } + } } else { last1 = usbd.epBank0ByteCount(ep); + if (last1 != 0) { incoming = 0; usbd.epBank0SetAddress(ep, const_cast(data0)); synchronized { @@ -344,6 +347,7 @@ class DoubleBufferedEPOutHandler : public EPHandler { notify = false; } } + } release(); } } diff --git a/sparkfun/samd/cores/arduino/USB/USBAPI.h b/sparkfun/samd/cores/arduino/USB/USBAPI.h index 53c249a4..690488b7 100644 --- a/sparkfun/samd/cores/arduino/USB/USBAPI.h +++ b/sparkfun/samd/cores/arduino/USB/USBAPI.h @@ -65,6 +65,8 @@ class USBDeviceClass { bool configured(); bool connected(); + void standby(); + // Setup API bool handleClassInterfaceSetup(USBSetup &setup); bool handleStandardSetup(USBSetup &setup); diff --git a/sparkfun/samd/cores/arduino/USB/USBCore.cpp b/sparkfun/samd/cores/arduino/USB/USBCore.cpp index 14390bcc..6f983c0a 100644 --- a/sparkfun/samd/cores/arduino/USB/USBCore.cpp +++ b/sparkfun/samd/cores/arduino/USB/USBCore.cpp @@ -250,6 +250,11 @@ bool USBDeviceClass::sendDescriptor(USBSetup &setup) return true; } +void USBDeviceClass::standby() { + usbd.noRunInStandby(); +} + + void USBDeviceClass::handleEndpoint(uint8_t ep) { #if defined(CDC_ENABLED) diff --git a/sparkfun/samd/cores/arduino/USB/USBCore.h b/sparkfun/samd/cores/arduino/USB/USBCore.h index 1b575f91..cba8089a 100644 --- a/sparkfun/samd/cores/arduino/USB/USBCore.h +++ b/sparkfun/samd/cores/arduino/USB/USBCore.h @@ -258,7 +258,7 @@ _Pragma("pack()") * idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber, bNumConfigurations */ #define D_CONFIG(_totalLength,_interfaces) \ - { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) } + { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(500) } /* Table 9-10. Standard Configuration Descriptor * bLength, bDescriptorType, wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration * bmAttributes, bMaxPower */ diff --git a/sparkfun/samd/cores/arduino/USB/USBDesc.h b/sparkfun/samd/cores/arduino/USB/USBDesc.h index e4335aa9..6088ee08 100644 --- a/sparkfun/samd/cores/arduino/USB/USBDesc.h +++ b/sparkfun/samd/cores/arduino/USB/USBDesc.h @@ -41,7 +41,7 @@ #define CDC_TX CDC_ENDPOINT_IN #endif -#define ISERIAL_MAX_LEN 20 +#define ISERIAL_MAX_LEN 33 // Defined string description #define IMANUFACTURER 1 diff --git a/sparkfun/samd/cores/arduino/Uart.cpp b/sparkfun/samd/cores/arduino/Uart.cpp index 13e0ebaa..37b6e690 100644 --- a/sparkfun/samd/cores/arduino/Uart.cpp +++ b/sparkfun/samd/cores/arduino/Uart.cpp @@ -31,7 +31,7 @@ Uart::Uart(SERCOM *_s, uint8_t _pinRX, uint8_t _pinTX, SercomRXPad _padRX, Serco void Uart::begin(unsigned long baudrate) { - begin(baudrate, (uint8_t)SERIAL_8N1); + begin(baudrate, SERIAL_8N1); } void Uart::begin(unsigned long baudrate, uint16_t config) diff --git a/sparkfun/samd/cores/arduino/Udp.h b/sparkfun/samd/cores/arduino/Udp.h index dc5644b9..d0524465 100644 --- a/sparkfun/samd/cores/arduino/Udp.h +++ b/sparkfun/samd/cores/arduino/Udp.h @@ -42,6 +42,7 @@ class UDP : public Stream { public: virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure virtual void stop() =0; // Finish with the UDP socket // Sending UDP packets diff --git a/sparkfun/samd/cores/arduino/itoa.c b/sparkfun/samd/cores/arduino/itoa.c index 55a80e78..cb30a47c 100644 --- a/sparkfun/samd/cores/arduino/itoa.c +++ b/sparkfun/samd/cores/arduino/itoa.c @@ -122,7 +122,7 @@ extern char* ltoa( long value, char *string, int radix ) return string; } -extern char* utoa( unsigned long value, char *string, int radix ) +extern char* utoa( unsigned int value, char *string, int radix ) { return ultoa( value, string, radix ) ; } diff --git a/sparkfun/samd/cores/arduino/itoa.h b/sparkfun/samd/cores/arduino/itoa.h index 9e4f48d7..1057d11a 100644 --- a/sparkfun/samd/cores/arduino/itoa.h +++ b/sparkfun/samd/cores/arduino/itoa.h @@ -26,7 +26,7 @@ extern "C"{ extern char* itoa( int value, char *string, int radix ) ; extern char* ltoa( long value, char *string, int radix ) ; -extern char* utoa( unsigned long value, char *string, int radix ) ; +extern char* utoa( unsigned int value, char *string, int radix ) ; extern char* ultoa( unsigned long value, char *string, int radix ) ; #ifdef __cplusplus diff --git a/sparkfun/samd/cores/arduino/startup.c b/sparkfun/samd/cores/arduino/startup.c index 3e01e79a..9e77bd9d 100644 --- a/sparkfun/samd/cores/arduino/startup.c +++ b/sparkfun/samd/cores/arduino/startup.c @@ -38,6 +38,7 @@ // Constants for Clock generators #define GENERIC_CLOCK_GENERATOR_MAIN (0u) #define GENERIC_CLOCK_GENERATOR_XOSC32K (1u) +#define GENERIC_CLOCK_GENERATOR_OSC32K (1u) #define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */ #define GENERIC_CLOCK_GENERATOR_OSC8M (3u) // Constants for Clock multiplexers @@ -51,6 +52,24 @@ void SystemInit( void ) /* Turn on the digital interface clock */ PM->APBAMASK.reg |= PM_APBAMASK_GCLK ; + +#if defined(CRYSTALLESS) + + /* ---------------------------------------------------------------------------------------------- + * 1) Enable OSC32K clock (Internal 32.768Hz oscillator) + */ + + uint32_t calib = (*((uint32_t *) FUSES_OSC32K_CAL_ADDR) & FUSES_OSC32K_CAL_Msk) >> FUSES_OSC32K_CAL_Pos; + + SYSCTRL->OSC32K.reg = SYSCTRL_OSC32K_CALIB(calib) | + SYSCTRL_OSC32K_STARTUP( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6 + SYSCTRL_OSC32K_EN32K | + SYSCTRL_OSC32K_ENABLE; + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY) == 0 ); // Wait for oscillator stabilization + +#else // has crystal + /* ---------------------------------------------------------------------------------------------- * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator) */ @@ -63,6 +82,8 @@ void SystemInit( void ) /* Wait for oscillator stabilization */ } +#endif + /* Software reset the module to ensure it is re-initialized correctly */ /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete. * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1 @@ -85,8 +106,12 @@ void SystemInit( void ) } /* Write Generic Clock Generator 1 configuration */ - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1 + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1 +#if defined(CRYSTALLESS) + GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator +#else GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator +#endif // GCLK_GENCTRL_OE | // Output clock to a pin for tests GCLK_GENCTRL_GENEN ; @@ -130,6 +155,41 @@ void SystemInit( void ) /* Wait for synchronization */ } +#if defined(CRYSTALLESS) + + #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58 + #define NVM_SW_CALIB_DFLL48M_FINE_VAL 64 + + // Turn on DFLL + uint32_t coarse =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32) ) + & ((1 << 6) - 1); + if (coarse == 0x3f) { + coarse = 0x1f; + } + uint32_t fine =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32) ) + & ((1 << 10) - 1); + if (fine == 0x3ff) { + fine = 0x1ff; + } + + SYSCTRL->DFLLVAL.bit.COARSE = coarse; + SYSCTRL->DFLLVAL.bit.FINE = fine; + /* Write full configuration to DFLL control register */ + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */ + SYSCTRL_DFLLCTRL_CCDIS | + SYSCTRL_DFLLCTRL_WAITLOCK | + SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */ + + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) + { + /* Wait for synchronization */ + } + + /* Enable the DFLL */ + SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ; + +#else // has crystal + /* Write full configuration to DFLL control register */ SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */ SYSCTRL_DFLLCTRL_WAITLOCK | @@ -149,6 +209,8 @@ void SystemInit( void ) /* Wait for locks flags */ } +#endif + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) { /* Wait for synchronization */ @@ -179,7 +241,7 @@ void SystemInit( void ) /* ---------------------------------------------------------------------------------------------- * 6) Modify PRESCaler value of OSC8M to have 8MHz */ - SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_1_Val ; + SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_0_Val ; //CMSIS 4.5 changed the prescaler defines SYSCTRL->OSC8M.bit.ONDEMAND = 0 ; /* ---------------------------------------------------------------------------------------------- diff --git a/sparkfun/samd/cores/arduino/wiring.c b/sparkfun/samd/cores/arduino/wiring.c index fca81bfb..ce12d32c 100644 --- a/sparkfun/samd/cores/arduino/wiring.c +++ b/sparkfun/samd/cores/arduino/wiring.c @@ -57,8 +57,6 @@ void calibrateADC() */ void init( void ) { - uint32_t ul ; - // Set Systick to 1ms interval, common to all Cortex-M variants if ( SysTick_Config( SystemCoreClock / 1000 ) ) { @@ -83,7 +81,7 @@ void init( void ) PM->APBCMASK.reg |= PM_APBCMASK_ADC | PM_APBCMASK_DAC ; // Setup all pins (digital and analog) in INPUT mode (default is nothing) - for ( ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ ) + for (uint32_t ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ ) { pinMode( ul, INPUT ) ; } diff --git a/sparkfun/samd/cores/arduino/wiring_digital.c b/sparkfun/samd/cores/arduino/wiring_digital.c index 001c77b0..026af80d 100644 --- a/sparkfun/samd/cores/arduino/wiring_digital.c +++ b/sparkfun/samd/cores/arduino/wiring_digital.c @@ -58,11 +58,8 @@ void pinMode( uint32_t ulPin, uint32_t ulMode ) break ; case OUTPUT: - // enable input, to support reading back values - PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].bit.INEN = 1 ; - - // disable pullups - PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].bit.PULLEN = 0 ; + // 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) ; // Set pin to output mode PORT->Group[g_APinDescription[ulPin].ulPort].DIRSET.reg = (uint32_t)(1< +sentence=Examples for the LilyMini Programming Guide +paragraph= +category=Other +url=https://learn.sparkfun.com/tutorials/intro-to-arduino-with-lilymini-protosnap +architectures=* + diff --git a/sparkfun/samd/libraries/LilyMini_Guide/src/LilyMini_Guide.cpp b/sparkfun/samd/libraries/LilyMini_Guide/src/LilyMini_Guide.cpp new file mode 100644 index 00000000..e69de29b diff --git a/sparkfun/samd/libraries/LilyMini_Guide/src/LilyMini_Guide.h b/sparkfun/samd/libraries/LilyMini_Guide/src/LilyMini_Guide.h new file mode 100644 index 00000000..e69de29b diff --git a/sparkfun/samd/platform.txt b/sparkfun/samd/platform.txt index 51399dd8..0404ce09 100644 --- a/sparkfun/samd/platform.txt +++ b/sparkfun/samd/platform.txt @@ -20,7 +20,7 @@ # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification name=SparkFun SAMD (32-bits ARM Cortex-M0+) Boards -version=1.3.2 +version=1.4.0 # Compile variables # ----------------- @@ -37,18 +37,20 @@ compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -s compiler.c.elf.cmd=arm-none-eabi-gcc compiler.c.elf.flags=-Os -Wl,--gc-sections -save-temps compiler.S.cmd=arm-none-eabi-gcc -compiler.S.flags=-c -g -x assembler-with-cpp +compiler.S.flags=-c -g -x assembler-with-cpp -MMD compiler.cpp.cmd=arm-none-eabi-g++ compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD compiler.ar.cmd=arm-none-eabi-ar compiler.ar.flags=rcs compiler.objcopy.cmd=arm-none-eabi-objcopy compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 -compiler.elf2hex.flags=-O binary +compiler.elf2hex.bin.flags=-O binary +compiler.elf2hex.hex.flags=-O ihex -R .eeprom compiler.elf2hex.cmd=arm-none-eabi-objcopy compiler.ldflags=-mcpu={build.mcu} -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align compiler.size.cmd=arm-none-eabi-size compiler.define=-DARDUINO= +compiler.readelf.cmd=arm-none-eabi-readelf # this can be overriden in boards.txt build.extra_flags= @@ -62,8 +64,8 @@ compiler.S.extra_flags= compiler.ar.extra_flags= compiler.elf2hex.extra_flags= -compiler.arm.cmsis.c.flags="-I{runtime.tools.CMSIS.path}/CMSIS/Include/" "-I{runtime.tools.CMSIS-Atmel.path}/CMSIS/Device/ATMEL/" -compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS.path}/CMSIS/Lib/GCC/" -larm_cortexM0l_math +compiler.arm.cmsis.c.flags="-I{runtime.tools.CMSIS-4.5.0.path}/CMSIS/Include/" "-I{runtime.tools.CMSIS-Atmel-1.1.0.path}/CMSIS/Device/ATMEL/" +compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-4.5.0.path}/CMSIS/Lib/GCC/" -larm_cortexM0l_math # USB Flags # --------- @@ -95,11 +97,16 @@ recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compil recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nano.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} -Wl,--start-group {compiler.arm.cmsis.ldflags} -lm "{build.path}/{archive_file}" -Wl,--end-group ## Create output (bin file) -recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin" +recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.bin.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin" + +## Create output (hex file) +recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" + +build.preferred_out_format=bin ## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin +recipe.output.tmp_file={build.project_name}.{build.preferred_out_format} +recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_out_format} ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" @@ -109,6 +116,20 @@ recipe.size.regex=\.text\s+([0-9]+).* # Uploader tools # -------------- +# +# AVRDUDE +# +tools.avrdude.path={runtime.tools.avrdude.path} +tools.avrdude.cmd={path}/bin/avrdude +tools.avrdude.config.path={path}/etc/avrdude.conf + +tools.avrdude.upload.params.verbose=-v -v +tools.avrdude.upload.params.quiet=-q -q +tools.avrdude.upload.params.noverify=-V +tools.avrdude.upload.pattern="{cmd}" "-C{config.path}" {upload.verbose} -p{build.emu.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} "-Uflash:w:{build.path}/{build.project_name}.hex:i" + +tools.avrdude_remote.upload.pattern="openocd --version 2>&1 | grep 2016 && if opkg update; then opkg upgrade openocd; exit 1; else echo 'Please connect your board to the Internet in order to upgrade tools' >&2; exit 1; fi || /usr/bin/run-avrdude /tmp/sketch.hex" + # # BOSSA # @@ -122,18 +143,25 @@ tools.bossac.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port. tools.bossac_remote.upload.pattern=/usr/bin/run-bossac {upload.verbose} --port=ttyATH0 -U {upload.native_usb} -e -w -v /tmp/sketch.bin -R +tools.bossac.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA +tools.bossac.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b + # # OpenOCD sketch upload # -tools.openocd.path={runtime.tools.openocd-0.9.0-arduino.path} +tools.openocd.path={runtime.tools.openocd-0.9.0-arduino6-static.path} tools.openocd.cmd=bin/openocd tools.openocd.cmd.windows=bin/openocd.exe tools.openocd.upload.params.verbose=-d2 tools.openocd.upload.params.quiet=-d0 -tools.openocd.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.bin}} verify reset 0x00002000; shutdown" +tools.openocd.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.bin}} verify reset 0x2000; shutdown" + +tools.openocd.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA +tools.openocd.upload.network_pattern={network_cmd} -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b +# Program flashes the binary at 0x0000, so use the linker script without_bootloader tools.openocd.program.params.verbose=-d2 tools.openocd.program.params.quiet=-d0 tools.openocd.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.elf}} verify reset; shutdown" @@ -145,3 +173,29 @@ tools.openocd.erase.pattern= tools.openocd.bootloader.params.verbose=-d2 tools.openocd.bootloader.params.quiet=-d0 tools.openocd.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{{runtime.platform.path}/bootloaders/{bootloader.file}}} verify reset; shutdown" + +# +# OpenOCD sketch upload - version with configurable bootloader size +# FIXME: this programmer is a workaround for default options being overwritten by uploadUsingPreferences +# + +tools.openocd-withbootsize.path={runtime.tools.openocd-0.9.0-arduino6-static.path} +tools.openocd-withbootsize.cmd=bin/openocd +tools.openocd-withbootsize.cmd.windows=bin/openocd.exe + +tools.openocd-withbootsize.upload.params.verbose=-d2 +tools.openocd-withbootsize.upload.params.quiet=-d0 +tools.openocd-withbootsize.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.bin}} verify reset {bootloader.size}; shutdown" + +# Program flashes the binary at 0x0000, so use the linker script without_bootloader +tools.openocd-withbootsize.program.params.verbose=-d2 +tools.openocd-withbootsize.program.params.quiet=-d0 +tools.openocd-withbootsize.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.elf}} verify reset; shutdown" + +tools.openocd-withbootsize.erase.params.verbose=-d3 +tools.openocd-withbootsize.erase.params.quiet=-d0 +tools.openocd-withbootsize.erase.pattern= + +tools.openocd-withbootsize.bootloader.params.verbose=-d2 +tools.openocd-withbootsize.bootloader.params.quiet=-d0 +tools.openocd-withbootsize.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{{runtime.platform.path}/bootloaders/{bootloader.file}}} verify reset; shutdown" diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/debug_scripts/variant.gdb b/sparkfun/samd/variants/SparkFun_LilyMini/debug_scripts/variant.gdb new file mode 100644 index 00000000..3c37ffde --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/debug_scripts/variant.gdb @@ -0,0 +1,31 @@ +# +# Arduino Zero OpenOCD script. +# +# Copyright (c) 2014-2015 Arduino LLC. 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 +# + +# Define 'reset' command +define reset + +info reg + +break main + +# End of 'reset' command +end + +target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log" diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_with_4kbootloader.ld b/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_with_4kbootloader.ld new file mode 100644 index 00000000..54802de2 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_with_4kbootloader.ld @@ -0,0 +1,211 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. 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 +*/ + +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000+0x1000, LENGTH = 0x00004000-0x1000 /* First 4KB used by bootloader */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00001000 +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + __ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_with_bootloader.ld.bak b/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_with_bootloader.ld.bak new file mode 100644 index 00000000..4475f951 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_with_bootloader.ld.bak @@ -0,0 +1,211 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. 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 +*/ + +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + __ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_without_bootloader.ld b/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_without_bootloader.ld new file mode 100644 index 00000000..0162f077 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/linker_scripts/gcc/flash_without_bootloader.ld @@ -0,0 +1,212 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. 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 +*/ + +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __ram_end__ + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM) ; + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + __ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/openocd_scripts/arduino_zero.cfg b/sparkfun/samd/variants/SparkFun_LilyMini/openocd_scripts/arduino_zero.cfg new file mode 100644 index 00000000..36c65c32 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/openocd_scripts/arduino_zero.cfg @@ -0,0 +1,30 @@ +# +# Arduino Zero OpenOCD script. +# +# Copyright (c) 2014-2015 Arduino LLC. 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 +# + +source [find interface/cmsis-dap.cfg] + +# chip name +set CHIPNAME at91samd21g18 +set ENDIAN little + +# choose a port here +set telnet_port 0 + +source [find target/at91samdXX.cfg] diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/pins_arduino.h b/sparkfun/samd/variants/SparkFun_LilyMini/pins_arduino.h new file mode 100644 index 00000000..db0e40c3 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/pins_arduino.h @@ -0,0 +1,21 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. 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 +*/ + +// API compatibility +#include "variant.h" + diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/variant.cpp b/sparkfun/samd/variants/SparkFun_LilyMini/variant.cpp new file mode 100644 index 00000000..9e52582f --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/variant.cpp @@ -0,0 +1,60 @@ +/* + SparkFul LilyMini Configuration File + + Based on Arduino SAMD21 configuration files, + Copyright (c) 2014-2015 Arduino LLC. 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 +*/ + +#include "variant.h" + +/* + * Pin descriptions + */ +const PinDescription g_APinDescription[]= +{ +// Pin array starts at 0, but LilyMini sewtaps start at 1, so duplicate pin 0 = pin 1 +/* sewtap 0*/{ PORTA, 14, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_EXTINT), ADC_Channel6, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // 0 +/* sewtap 1*/{ PORTA, 14, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_EXTINT), ADC_Channel6, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // 1 +/* sewtap 2*/{ PORTA, 15, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_EXTINT), ADC_Channel7, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_1 }, // 2 +/* sewtap 3*/{ PORTA, 7, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_EXTINT), ADC_Channel5, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_7 }, // 3 +/* sewtap 4*/{ PORTA, 6, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_EXTINT), ADC_Channel4, PWM0_CH2, TCC0_CH2, EXTERNAL_INT_6 }, // 4 +/*red LED 5*/{ PORTA, 30, PIO_OUTPUT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM2_CH0, TC2_CH0, EXTERNAL_INT_NONE },// 5 +/*grn LED 6*/{ PORTA, 27, PIO_OUTPUT, (PIN_ATTR_DIGITAL/*|PIN_ATTR_PWM*/), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },// 6 +/*blu LED 7*/{ PORTA, 31, PIO_OUTPUT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM2_CH1, TC2_CH1, EXTERNAL_INT_NONE },// 7 +/*sewtap+ 8*/{ PORTA, 2, PIO_OUTPUT, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL/*|PIN_ATTR_PWM*/), ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },// 8 +/*USB DM 9*/{ PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 9 +/*USB DP 10*/{ PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 10 +/*button 11*/{ PORTA, 5, PIO_DIGITAL, (PIN_ATTR_EXTINT), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // 11 +/*unused 12*/{ NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 12 +/*red LED 13*/{ PORTA, 30, PIO_OUTPUT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM),No_ADC_Channel,PWM2_CH0,TC2_CH0,EXTERNAL_INT_NONE }, // 13 +// Note that pin 13 is mapped to red LED to support example code that uses pin 13 +} ; + +const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TC1, TC2 } ; + +// Multi-serial objects instantiation +SERCOM sercom0( SERCOM0 ) ; +SERCOM sercom1( SERCOM1 ) ; +SERCOM sercom2( SERCOM2 ) ; + +Uart Serial0( &sercom0, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ; + +void SERCOM0_Handler() +{ + Serial0.IrqHandler(); +} + diff --git a/sparkfun/samd/variants/SparkFun_LilyMini/variant.h b/sparkfun/samd/variants/SparkFun_LilyMini/variant.h new file mode 100644 index 00000000..48a5858f --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_LilyMini/variant.h @@ -0,0 +1,196 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. 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 +*/ + +#ifndef _VARIANT_SPARKFUN_LILYMINI_ +#define _VARIANT_SPARKFUN_LILYMINI_ + +// The definitions here needs a SAMD core >=1.6.3 +#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10603 + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** Frequency of the board main oscillator */ +#define VARIANT_MAINOSC (32768ul) + +/** Master clock frequency */ +#define VARIANT_MCK (48000000ul) + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#ifdef __cplusplus +#include "SERCOM.h" +#include "Uart.h" +#endif // __cplusplus + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*---------------------------------------------------------------------------- + * Pins + *----------------------------------------------------------------------------*/ + +// Number of pins defined in PinDescription array +#define PINS_COUNT (13u) +#define NUM_DIGITAL_PINS (10u) +#define NUM_ANALOG_INPUTS (6u) +#define NUM_ANALOG_OUTPUTS (0u) + +#define digitalPinToPort(P) ( &(PORT->Group[g_APinDescription[P].ulPort]) ) +#define digitalPinToBitMask(P) ( 1 << g_APinDescription[P].ulPin ) +#define portOutputRegister(port) ( &(port->OUT.reg) ) +#define portInputRegister(port) ( &(port->IN.reg) ) +#define portModeRegister(port) ( &(port->DIR.reg) ) +#define digitalPinHasPWM(P) ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER ) + +/* + * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD + * architecture. If you need to check if a pin supports PWM you must + * use digitalPinHasPWM(..). + * + * https://github.com/arduino/Arduino/issues/1833 + */ +// #define digitalPinToTimer(P) + +// Interrupts +#define digitalPinToInterrupt(P) ( g_APinDescription[P].ulExtInt ) + +// Digital pins +#define LED_RED (5u) +#define LED_GREEN (6u) +#define LED_BLUE (7u) +#define LED_BUILTIN (5u) // Introduced in Arduino 1.8, tied to red LED + +#define PIN_LED_RED (5u) +#define PIN_LED_GREEN (6u) +#define PIN_LED_BLUE (7u) +#define PIN_POWER (8u) +#define PIN_BUTTON (11u) + +// Analog pins +#define PIN_A0 (1ul) +#define PIN_A1 (1ul) +#define PIN_A2 (2ul) +#define PIN_A3 (3ul) +#define PIN_A4 (4ul) + +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +#define ADC_RESOLUTION 10 + +// Internal "pins" +#define PIN_BATT (ADC_INPUTCTRL_MUXPOS_SCALEDIOVCC_Val) +#define PIN_1V (ADC_INPUTCTRL_MUXPOS_BANDGAP_Val) +#define PIN_TEMP (ADC_INPUTCTRL_MUXPOS_TEMP_Val) + +#define analogReadBattVolts() ((analogRead(PIN_BATT)*4000)/((analogRead(PIN_1V)*100)/11)) // will be e.g. 199 for 1.99V +#define analogReadVolts(pin) ((analogRead(pin)*1000)/((analogRead(PIN_1V)*100)/11)) // will be e.g. 199 for 1.99V + +// Serial (SERCOM0) +#define PIN_SERIAL_RX (3ul) +#define PIN_SERIAL_TX (4ul) +#define PAD_SERIAL_TX (UART_TX_PAD_0) +#define PAD_SERIAL_RX (SERCOM_RX_PAD_1) + +// SPI +#define SPI_INTERFACES_COUNT 1 +#define PIN_SPI_MISO (4u) +#define PIN_SPI_MOSI (1u) +#define PIN_SPI_SCK (2u) +#define PIN_SPI_SS (3u) +#define PERIPH_SPI sercom1 +// Pad Map: 0 1 2 3 +// MOSI (TX) SCK SS MOSI (RX) +#define PAD_SPI_TX SPI_PAD_0_SCK_1 +#define PAD_SPI_RX SERCOM_RX_PAD_3 + +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +// I2C (wire) +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (1u) +#define PIN_WIRE_SCL (2u) +#define PERIPH_WIRE sercom2 +#define WIRE_IT_HANDLER SERCOM2_Handler + +// USB +#define PIN_USB_DM (9ul) +#define PIN_USB_DP (10ul) + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#ifdef __cplusplus + +/* ========================= + * ===== SERCOM DEFINITION + * ========================= +*/ +extern SERCOM sercom0; +extern SERCOM sercom1; +extern SERCOM sercom2; + +extern Uart Serial0; + +#endif + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_USBVIRTUAL SerialUSB +#define SERIAL_PORT_MONITOR Serial0 +// Serial has no physical pins broken out, so it's not listed as HARDWARE port +#define SERIAL_PORT_HARDWARE Serial0 +#define SERIAL_PORT_HARDWARE_OPEN Serial0 + +#define Serial SerialUSB +#define SerialPins Serial0 + +#endif /* _VARIANT_SPARKFUN_LILYMINI_ */ + diff --git a/sparkfunboards.png b/sparkfunboards.png new file mode 100644 index 00000000..cd5ec8af Binary files /dev/null and b/sparkfunboards.png differ