diff --git a/fw/HackSpaceCon_AS7/.vs/HackSpaceCon_AS7/v14/.atsuo b/fw/HackSpaceCon_AS7/.vs/HackSpaceCon_AS7/v14/.atsuo
new file mode 100644
index 0000000..30334cc
Binary files /dev/null and b/fw/HackSpaceCon_AS7/.vs/HackSpaceCon_AS7/v14/.atsuo differ
diff --git a/fw/HackSpaceCon_AS7/Arduino/Arduino.componentinfo.xml b/fw/HackSpaceCon_AS7/Arduino/Arduino.componentinfo.xml
new file mode 100644
index 0000000..30cec97
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/Arduino.componentinfo.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ Device
+ Startup
+
+
+ Atmel
+ 1.10.0
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs
+
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\include\
+
+ include
+ C
+
+
+ include/
+
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\include\avr\iotn402.h
+
+ header
+ C
+ g0XngzH9uwBI0kp8K6DswA==
+
+ include/avr/iotn402.h
+
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\templates\library.c
+ template
+ source
+ C Lib
+ VjSGq44t/3IHSL1ATPOBng==
+
+ templates/library.c
+ Main file (.c)
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\templates\library.cpp
+ template
+ source
+ C Lib
+ W2Pmq0e0Z2LqDTKNsfzUmA==
+
+ templates/library.cpp
+ Main file (.cpp)
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402
+
+ libraryPrefix
+ GCC
+
+
+ gcc/dev/attiny402
+
+
+
+
+ ATtiny_DFP
+ C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATtiny_DFP/1.10.348/Atmel.ATtiny_DFP.pdsc
+ 1.10.348
+ true
+ ATtiny402
+
+
+
+ Resolved
+ Fixed
+ true
+
+
+
\ No newline at end of file
diff --git a/fw/HackSpaceCon_AS7/Arduino/Arduino.cppproj b/fw/HackSpaceCon_AS7/Arduino/Arduino.cppproj
new file mode 100644
index 0000000..836b6a0
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/Arduino.cppproj
@@ -0,0 +1,323 @@
+
+
+
+ 2.0
+ 7.0
+ com.Atmel.AVRGCC8.CPP
+ {47694d30-4990-4f03-a1f7-e94eb79783f0}
+ ATtiny402
+ none
+ StaticLibrary
+ CPP
+ lib$(MSBuildProjectName)
+ .a
+ $(MSBuildProjectDirectory)\$(Configuration)
+
+
+ Arduino
+ Arduino
+ Arduino
+ Native
+ true
+ false
+ true
+ true
+ 0x20000000
+
+ true
+ exception_table
+ 2
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -mmcu=attiny402 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402"
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+
+
+ NDEBUG
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+
+
+ Optimize for size (-Os)
+ True
+ True
+ True
+ True
+ True
+
+
+ NDEBUG
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+
+
+ Optimize for size (-Os)
+ True
+ True
+ True
+
+
+ libm
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+
+
+
+
+
+
+
+
+ -mmcu=attiny402 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402"
+ True
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+
+
+ DEBUG
+ ARDUINO=108019
+ ARDUINO_AVR_ATtinyxy2
+ ARDUINO_attinyxy2
+ F_CPU=8000000UL
+ MEGATINYCORE="2.6.10"
+ MEGATINYCORE_MAJOR=2UL
+ MEGATINYCORE_MINOR=6UL
+ MEGATINYCORE_PATCH=10UL
+ MEGATINYCORE_RELEASED=1
+ MILLIS_USE_TIMERA0
+ CLOCK_SOURCE=0
+ LTODISABLED
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+ ../megatinycore
+ ../variants/txy2
+ ../arduino_libraries/tinyNeoPixel_static
+
+
+ Optimize for size (-Os)
+ True
+ True
+ Maximum (-g3)
+ True
+ -std=gnu11
+ True
+ True
+
+
+ DEBUG
+ ARDUINO=108019
+ ARDUINO_AVR_ATtinyxy2
+ ARDUINO_attinyxy2
+ F_CPU=8000000UL
+ MEGATINYCORE="2.6.10"
+ MEGATINYCORE_MAJOR=2UL
+ MEGATINYCORE_MINOR=6UL
+ MEGATINYCORE_PATCH=10UL
+ MEGATINYCORE_RELEASED=1
+ MILLIS_USE_TIMERA0
+ CLOCK_SOURCE=0
+ TWI_MORS
+ LTODISABLED
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+ ../megatinycore
+ ../variants/txy2
+ ../arduino_libraries/tinyNeoPixel_static
+
+
+ Optimize for size (-Os)
+ -fno-threadsafe-statics
+ True
+ True
+ Maximum (-g3)
+ True
+ -std=gnu++17
+
+
+ libm
+
+
+ -Os -fuse-linker-plugin
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+
+
+ Default (-Wa,-g)
+
+
+
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+
+
+
+
+
+
+
+
+
+
+ compile
+
+
+
+
\ No newline at end of file
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/LICENSE.md b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/LICENSE.md
new file mode 100644
index 0000000..d57ff94
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/LICENSE.md
@@ -0,0 +1,168 @@
+# tinyNeoPixel_Static License
+The tinyNeoPixel_Static library is derived from tinyNeoPixel, which is in turn derived from adafruitNeoPixel, which is released under the terms of the LGPL 3, unlike the rest of the core which is released under LGPL 2.1.
+The license was previously in a file named "COPYING". It has been renamed for consistency and prefaced for clarity.
+
+## GNU Lesser General Public License, Version 3
+```legalese
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+```
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/README.md b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/README.md
new file mode 100644
index 0000000..aee1c43
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/README.md
@@ -0,0 +1,15 @@
+# tinyNeoPixel documentation is elsewhere
+tinyNeoPixel is a tweaked version of adafruitNeoPixel, supporting more clock speeds and correcting some improperly specified constraints, but should be code compatible excepting the change to the class name. This core also includes tinyNeoPixel_Static, which has been modified further to reduce the flash footprint. It is recommended to read the first one first, as it gives brief summaries of the API, before and discusses supported parts and particularly common issues relating to addressable LEDs, both specific to these parts and in general (including specific hazards that they can expose the user to if used improperly.
+* [Summary and changes specific to tinyNeoPixel_Static](https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/tinyNeoPixel.md) - both normal and static versions use the same documentation.
+* [Full class reference from Adafruit](https://adafruit.github.io/Adafruit_NeoPixel/html/class_adafruit___neo_pixel.html)
+
+In the event that a function listed in that class reference is not defined in tinyNeoPixel, or in the event of differences in behavior between adafruitNeoPixel and tinyNeoPixel (except as noted in the first documentation link above), that is a bug, and is likely unknown to the maintainer of megaTinyCore - please report it via github issue (preferred) or by emailing SpenceKonde@gmail.com
+
+## Licensing
+**tinyNeoPixel is LGPL 3 not LGPL 2.1**
+It is derived from Adafruit's adafruitNeoPixel library, which is licenced under LGPL 3.
+See [LICENSE.md for the library](LICENSE.md)
+
+The rest of this core (except where noted) is LGPL 2.1.
+
+This distinction is rarely relevant, but consult with a legal professional if in doubt.
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/buttoncycler/buttoncycler.ino b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/buttoncycler/buttoncycler.ino
new file mode 100644
index 0000000..dc18b00
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/buttoncycler/buttoncycler.ino
@@ -0,0 +1,186 @@
+// This is a demonstration on how to use an input device to trigger changes on your neo pixels.
+// You should wire a momentary push button to connect from ground to a digital IO pin. When you
+// press the button it will change to a new pixel animation. Note that you need to press the
+// button once to start the first animation!
+
+#include
+
+#define BUTTON_PIN PIN_PA2 // Digital IO pin connected to the button. This will be
+// driven with a pull-up resistor so the switch should
+// pull the pin to ground momentarily. On a high -> low
+// transition the button press logic will execute.
+// These pins were chosen because they are present on all parts; this sketch is used for automated testing.
+// Since 8-pin parts with UPDI enabled have only 5 available IO pins (PA1, 2, 3, 6, and 7), and PA3 is the
+// external clock pin (we detect and give an error when using external clock source if you try to use the
+// clock pin for anything else, since that doesn't work). Serial in turn is on either PA6/7 or PA1/2 (alt) so unless we
+// want to make life hard on people modifying the sketch and maybe adding serial debug logging, PA1 and PA2 are the best
+// choices for the pin in this sketch as an example and automated testing sketch.
+
+
+#define PIXEL_PIN PIN_PA1 // Digital IO pin connected to the NeoPixels
+
+#define PIXEL_COUNT 16
+
+
+// Since this is for the static version of the library, we need to supply the pixel array
+// This saves space by eliminating use of malloc() and free(), and makes the RAM used for
+// the frame buffer show up when the sketch is compiled.
+
+byte pixels[PIXEL_COUNT * 3];
+// It is strongly recommended to have one variable or #define for the number of pixels, and then
+// multiply that by 3 (for RGB) or 4 (for RGBW) when declaring the pixel array, as is done here
+// to avoid the need for double-entry bookkeeping.
+
+
+// Parameter 1 = number of pixels in strip,
+// Parameter 2 = pin number (most are valid)
+// Parameter 3 = color order (NEO_RGB, NEO_GRB, etc).
+// Parameter 4 = pixel buffer declared above
+// Unlike the Adafruit library there's no 400 kHz option. I don't think I have ever seen 400 kHz pixels, and they may no longer be made.
+// Because the optimizer's hands are tied when working with classes it would impose undue burdens on all users to support it, plus it would
+// need the asm routines adapted to every supported clock speed... all for the sake of a part that seems extinct in the wild.
+
+tinyNeoPixel strip = tinyNeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB, pixels);
+
+bool oldState = HIGH;
+int showType = 0;
+
+void setup() {
+ pinMode(BUTTON_PIN, INPUT_PULLUP);
+ pinMode(PIXEL_PIN, OUTPUT);
+ // strip.begin();
+ strip.show(); // Initialize all pixels to 'off'
+}
+
+void loop() {
+ // Get current button state.
+ bool newState = digitalRead(BUTTON_PIN);
+
+ // Check if state changed from high to low (button press).
+ if (newState == LOW && oldState == HIGH) {
+ // Short delay to debounce button.
+ delay(20);
+ // Check if button is still low after debounce.
+ newState = digitalRead(BUTTON_PIN);
+ if (newState == LOW) {
+ showType++;
+ if (showType > 9) {
+ showType = 0;
+ }
+ startShow(showType);
+ }
+ }
+
+ // Set the last button state to the old state.
+ oldState = newState;
+}
+
+void startShow(int i) {
+ switch (i) {
+ case 0: colorWipe(strip.Color(0, 0, 0), 50); // Black/off
+ break;
+ case 1: colorWipe(strip.Color(255, 0, 0), 50); // Red
+ break;
+ case 2: colorWipe(strip.Color(0, 255, 0), 50); // Green
+ break;
+ case 3: colorWipe(strip.Color(0, 0, 255), 50); // Blue
+ break;
+ case 4: theaterChase(strip.Color(127, 127, 127), 50); // White
+ break;
+ case 5: theaterChase(strip.Color(127, 0, 0), 50); // Red
+ break;
+ case 6: theaterChase(strip.Color(0, 0, 127), 50); // Blue
+ break;
+ case 7: rainbow(20);
+ break;
+ case 8: rainbowCycle(20);
+ break;
+ case 9: theaterChaseRainbow(50);
+ break;
+ }
+}
+
+// Fill the dots one after the other with a color
+void colorWipe(uint32_t c, uint8_t wait) {
+ for (uint16_t i = 0; i < strip.numPixels(); i++) {
+ strip.setPixelColor(i, c);
+ strip.show();
+ delay(wait);
+ }
+}
+
+void rainbow(uint8_t wait) {
+ uint16_t i, j;
+
+ for (j = 0; j < 256; j++) {
+ for (i = 0; i < strip.numPixels(); i++) {
+ strip.setPixelColor(i, Wheel((i + j) & 255));
+ }
+ strip.show();
+ delay(wait);
+ }
+}
+
+// Slightly different, this makes the rainbow equally distributed throughout
+void rainbowCycle(uint8_t wait) {
+ uint16_t i, j;
+
+ for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
+ for (i = 0; i < strip.numPixels(); i++) {
+ strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
+ }
+ strip.show();
+ delay(wait);
+ }
+}
+
+// Theatre-style crawling lights.
+void theaterChase(uint32_t c, uint8_t wait) {
+ for (int j = 0; j < 10; j++) { // do 10 cycles of chasing
+ for (int q = 0; q < 3; q++) {
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, c); // turn every third pixel on
+ }
+ strip.show();
+
+ delay(wait);
+
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, 0); // turn every third pixel off
+ }
+ }
+ }
+}
+
+// Theatre-style crawling lights with rainbow effect
+void theaterChaseRainbow(uint8_t wait) {
+ for (int j = 0; j < 256; j++) { // cycle all 256 colors in the wheel
+ for (int q = 0; q < 3; q++) {
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, Wheel((i + j) % 255)); // turn every third pixel on
+ }
+ strip.show();
+
+ delay(wait);
+
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, 0); // turn every third pixel off
+ }
+ }
+ }
+}
+
+// Input a value 0 to 255 to get a color value.
+// The colours are a transition r - g - b - back to r.
+uint32_t Wheel(byte WheelPos) {
+ WheelPos = 255 - WheelPos;
+ if (WheelPos < 85) {
+ return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
+ }
+ if (WheelPos < 170) {
+ WheelPos -= 85;
+ return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
+ }
+ WheelPos -= 170;
+ return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/simple/simple.ino b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/simple/simple.ino
new file mode 100644
index 0000000..4b9cd09
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/simple/simple.ino
@@ -0,0 +1,56 @@
+// NeoPixel simple sketch (c) 2013 Shae Erisson, adapted to tinyNeoPixel library by Spence Konde 2019.
+// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library
+
+#include
+
+
+// Which pin on the Arduino is connected to the NeoPixels?
+#define PIN 3
+
+// How many NeoPixels are attached to the Arduino?
+#define NUMPIXELS 16
+
+// Since this is for the static version of the library, we need to supply the pixel array
+// This saves space by eliminating use of malloc() and free(), and makes the RAM used for
+// the frame buffer show up when the sketch is compiled.
+
+byte pixels[NUMPIXELS * 3];
+
+// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
+// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
+// example for more information on possible values.
+
+tinyNeoPixel leds = tinyNeoPixel(NUMPIXELS, PIN, NEO_GRB, pixels);
+
+int delayval = 500; // delay for half a second
+
+void setup() {
+ pinMode(PIN, OUTPUT);
+ // with tinyNeoPixel_Static, you need to set pinMode yourself. This means you can eliminate pinMode()
+ // and replace with direct port writes to save a couple hundred bytes in sketch size (note that this
+ // savings is only present when you eliminate *all* references to pinMode).
+ // leds.begin() not needed on tinyNeoPixel
+}
+
+void loop() {
+
+ // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.
+
+ for (int i = 0; i < NUMPIXELS; i++) {
+
+ // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
+ leds.setPixelColor(i, leds.Color(0, 150, 0)); // Moderately bright green color.
+
+ leds.show(); // This sends the updated pixel color to the hardware.
+
+ delay(delayval); // Delay for a period of time (in milliseconds).
+ }
+ // with tinyNeoPixel_Static, since we have the pixel array, we can also directly manipulate it - this sacrifices the correction for the pixel order, and the clarity of setColor to save a tiny amount of flash and time.
+ for (int i = 0; i < (NUMPIXELS * 3); i++) {
+ pixels[i] = 150; // set byte i of array (this is channel (i%3) of led (i/3) (respectively, i%4 and i/4 for RGBW leds)
+ leds.show(); // show
+ delay(delayval); // delay for a period of time
+ pixels[i] = 0; // turn off the above pixel
+ // result is that each pixel will cycle through each of the primary colors (green, red, blue for most LEDs) in turn, and only one LED will be on at a time.
+ }
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/strandtest/strandtest.ino b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/strandtest/strandtest.ino
new file mode 100644
index 0000000..cc8e7f9
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/examples/strandtest/strandtest.ino
@@ -0,0 +1,136 @@
+#include
+
+#define PIN 3
+
+// Parameter 1 = number of pixels in strip
+// Parameter 2 = Arduino pin number (most are valid)
+// Parameter 3 = pixel type flags, add together as needed:
+// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
+// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
+// Parameter 4 = array to store pixel data in
+
+#define NUMPIXELS 60
+
+// Since this is for the static version of the library, we need to supply the pixel array
+// This saves space by eliminating use of malloc() and free(), and makes the RAM used for
+// the frame buffer show up when the sketch is compiled.
+
+byte pixels[NUMPIXELS * 3];
+
+// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
+// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
+// example for more information on possible values. Finally, for the 4th argument we pass the array we
+// defined above.
+
+tinyNeoPixel strip = tinyNeoPixel(NUMPIXELS, PIN, NEO_GRB, pixels);
+
+// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
+// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
+// and minimize distance between Arduino and first pixel. Avoid connecting
+// on a live circuit...if you must, connect GND first.
+
+void setup() {
+ pinMode(PIN, OUTPUT); // set pin output - this is not done internally by the library for Static version of library
+ // strip.begin(); // Static version does not use this.
+ strip.show(); // Initialize all pixels to 'off'
+}
+
+void loop() {
+ // Some example procedures showing how to display to the pixels:
+ colorWipe(strip.Color(255, 0, 0), 50); // Red
+ colorWipe(strip.Color(0, 255, 0), 50); // Green
+ colorWipe(strip.Color(0, 0, 255), 50); // Blue
+ // Send a theater pixel chase in...
+ theaterChase(strip.Color(127, 127, 127), 50); // White
+ theaterChase(strip.Color(127, 0, 0), 50); // Red
+ theaterChase(strip.Color(0, 0, 127), 50); // Blue
+
+ rainbow(20);
+ rainbowCycle(20);
+ theaterChaseRainbow(50);
+}
+
+// Fill the dots one after the other with a color
+void colorWipe(uint32_t c, uint8_t wait) {
+ for (uint16_t i = 0; i < strip.numPixels(); i++) {
+ strip.setPixelColor(i, c);
+ strip.show();
+ delay(wait);
+ }
+}
+
+void rainbow(uint8_t wait) {
+ uint16_t i, j;
+
+ for (j = 0; j < 256; j++) {
+ for (i = 0; i < strip.numPixels(); i++) {
+ strip.setPixelColor(i, Wheel((i + j) & 255));
+ }
+ strip.show();
+ delay(wait);
+ }
+}
+
+// Slightly different, this makes the rainbow equally distributed throughout
+void rainbowCycle(uint8_t wait) {
+ uint16_t i, j;
+
+ for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
+ for (i = 0; i < strip.numPixels(); i++) {
+ strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
+ }
+ strip.show();
+ delay(wait);
+ }
+}
+
+// Theatre-style crawling lights.
+void theaterChase(uint32_t c, uint8_t wait) {
+ for (int j = 0; j < 10; j++) { // do 10 cycles of chasing
+ for (int q = 0; q < 3; q++) {
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, c); // turn every third pixel on
+ }
+ strip.show();
+
+ delay(wait);
+
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, 0); // turn every third pixel off
+ }
+ }
+ }
+}
+
+// Theatre-style crawling lights with rainbow effect
+void theaterChaseRainbow(uint8_t wait) {
+ for (int j = 0; j < 256; j++) { // cycle all 256 colors in the wheel
+ for (int q = 0; q < 3; q++) {
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, Wheel((i + j) % 255)); // turn every third pixel on
+ }
+ strip.show();
+
+ delay(wait);
+
+ for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
+ strip.setPixelColor(i + q, 0); // turn every third pixel off
+ }
+ }
+ }
+}
+
+// Input a value 0 to 255 to get a color value.
+// The colours are a transition r - g - b - back to r.
+uint32_t Wheel(byte WheelPos) {
+ WheelPos = 255 - WheelPos;
+ if (WheelPos < 85) {
+ return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
+ }
+ if (WheelPos < 170) {
+ WheelPos -= 85;
+ return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
+ }
+ WheelPos -= 170;
+ return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/keywords.txt b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/keywords.txt
new file mode 100644
index 0000000..edcdcb5
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/keywords.txt
@@ -0,0 +1,64 @@
+#######################################
+# Syntax Coloring Map For tinyNeopixel_Static
+#######################################
+# Class
+#######################################
+
+tinyNeoPixel KEYWORD1
+
+#######################################
+# Methods and Functions
+#######################################
+
+setPixelColor KEYWORD2
+getPixelColor KEYWORD2
+setPin KEYWORD2
+getPin KEYWORD2
+setBrightness KEYWORD2
+getBrightness KEYWORD2
+numPixels KEYWORD2
+getPixels KEYWORD2
+show KEYWORD2
+clear KEYWORD2
+fill KEYWORD2
+Color KEYWORD2
+ColorHSV KEYWORD2
+gamma8 KEYWORD2
+sine8 KEYWORD2
+gamma32 KEYWORD2
+
+#######################################
+# Constants
+#######################################
+
+NEO_GRB LITERAL1
+NEO_RGB LITERAL1
+NEO_RBG LITERAL1
+NEO_GRB LITERAL1
+NEO_GBR LITERAL1
+NEO_BRG LITERAL1
+NEO_BGR LITERAL1
+NEO_WRGB LITERAL1
+NEO_WRBG LITERAL1
+NEO_WGRB LITERAL1
+NEO_WGBR LITERAL1
+NEO_WBRG LITERAL1
+NEO_WBGR LITERAL1
+NEO_RWGB LITERAL1
+NEO_RWBG LITERAL1
+NEO_RGWB LITERAL1
+NEO_RGBW LITERAL1
+NEO_RBWG LITERAL1
+NEO_RBGW LITERAL1
+NEO_GWRB LITERAL1
+NEO_GWBR LITERAL1
+NEO_GRWB LITERAL1
+NEO_GRBW LITERAL1
+NEO_GBWR LITERAL1
+NEO_GBRW LITERAL1
+NEO_BWRG LITERAL1
+NEO_BWGR LITERAL1
+NEO_BRWG LITERAL1
+NEO_BRGW LITERAL1
+NEO_BGWR LITERAL1
+NEO_BGRW LITERAL1
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/library.properties b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/library.properties
new file mode 100644
index 0000000..a436cc1
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/library.properties
@@ -0,0 +1,9 @@
+name=tinyNeoPixel Static
+version=2.0.7
+author=Adafruit (modified by Spence Konde)
+maintainer=Spence Konde
+sentence=Arduino library for controlling single-wire-based LED pixels and strip for all modern (post 2016) AVR microcontrollers, and distributed with megaTinyCore and DxCore.
+paragraph=This library is closely based on the original Adafruit_NeoPixel library. It has been modified to account for the improved ST performance on the tinyAVR 0-series, tinyAVR 1-series and megaAVR 0-series, and add support for speeds from 4 MHz to 48 MHz. No specific actions to choose the port the port at any speed (enabled by ST improvements). Please refer to the documentation for more information.
2.0.7 - Fix critical defect in 10 and 12 MHz implementations which would output the first bit only.
2.0.6 - correct naming of labels in asm to conform with our naming policy. Add show(number), which will show up to the first (number) leds. This allows the static allocation version to light up a varying number of LEDs. 2.0.5 - correct some timing and compile issues at certain speeds.
2.0.4 - Add support for operation at speeds as low as 4 MHz. Ensure that the inline assembly is specified correctly.
2.0.3 - Fix issue when millis is disabled.
+category=Display
+url=https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/tinyNeoPixel.md
+architectures=megaavr
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/tinyNeoPixel_Static.cpp b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/tinyNeoPixel_Static.cpp
new file mode 100644
index 0000000..7e511bd
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/tinyNeoPixel_Static.cpp
@@ -0,0 +1,1410 @@
+/*-------------------------------------------------------------------------
+ Arduino library to control a wide variety of WS2811- and WS2812-based RGB
+ LED devices such as Adafruit FLORA RGB Smart Pixels and NeoPixel strips.
+
+ Currently handles 800 KHz bitstreams on 8, 10, 12, 16, and 20 MHz ATtiny
+ MCUs with ATTinyCore 1.30+, 8, 10, 12, 16, 20, 24, 28, and 32 MHz AVRxt
+ tinyAVR 0/1/2-series parts with megaTinyCore 1.0.3+ and those speeds
+ plus the ridiculously overclocked 36, 40, 44, and 48 MHz speeds with
+ AVR Dx-series parts. Note that the highest speeds have not been tested
+ and it would be surprising if the parts could be pushed that far.
+
+ Like the Adafruit original version, it supports LEDs wired
+ for various color orders. 400 kHz support was never included.
+ Nobody has ever asked about it, nor have I seen any 400 kHz LEDs for sale.
+ Ever.
+
+ Written by Phil Burgess / Paint Your Dragon for Adafruit Industries,
+ contributions by PJRC, Michael Miller and other members of the open
+ source community.
+
+ Extensive porting to additional parts and different clock speeds by
+ Spence Konde.
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing products
+ from Adafruit!
+
+ Same goes for Spence too!
+
+ -------------------------------------------------------------------------
+ This file is part of the tinyNeoPixel library derived from
+ Adafruit_NeoPixel.
+
+ NeoPixel 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 3 of
+ the License, or (at your option) any later version.
+
+ NeoPixel 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 NeoPixel. If not, see
+ .
+ -------------------------------------------------------------------------*/
+
+#include "tinyNeoPixel_Static.h"
+
+// Constructor when length, pin and type are known at compile-time:
+tinyNeoPixel::tinyNeoPixel(uint16_t n, uint8_t p, neoPixelType t, uint8_t *pxl) :
+ latchTime(50), brightness(0), pixels(pxl), endTime(0) {
+ // boolean oldThreeBytesPerPixel = (wOffset == rOffset); // false if RGBW
+ wOffset = (t >> 6) & 0b11; // See notes in header file
+ rOffset = (t >> 4) & 0b11; // regarding R/G/B/W offsets
+ gOffset = (t >> 2) & 0b11;
+ bOffset = t & 0b11;
+ numBytes = n * ((wOffset == rOffset) ? 3 : 4);
+ numLEDs = n;
+ pin = p;
+ port = portOutputRegister(digitalPinToPort(p));
+ pinMask = digitalPinToBitMask(p);
+}
+
+
+
+tinyNeoPixel::~tinyNeoPixel() {
+ // if (pixels) free(pixels);
+ // if (pin >= 0) pinMode(pin, INPUT);
+}
+void tinyNeoPixel::updateLatch(uint16_t us) {
+ /* New feature - to extend the latch interlock to all varieties of LEDs turns out to not be costly at all. */
+ latchTime = (us < 6 ? 6 : us); // there are no devices in production with a shorter latch waiting time, and thus is the shortest reasonable latch delay.
+}
+// *INDENT-OFF* astyle don't like assembly
+#if (PROGMEM_SIZE > 4096UL)
+
+void tinyNeoPixel::show(void) {
+ show(0);
+}
+void tinyNeoPixel::show(uint16_t leds) {
+ volatile uint16_t i = numBytes;;
+ if (!(numLEDs <= leds || !leds)) {
+ if (wOffset == rOffset) {
+ i = leds + leds + leds;
+ } else {
+ i = leds << 2;
+ }
+ }
+ if ((!pixels) || pin >= NUM_DIGITAL_PINS) {
+ return;
+ }
+#else
+ void tinyNeoPixel::show(void) {
+ volatile uint16_t i = numBytes; // Loop counter
+#endif
+ // Data latch = 50+ microsecond pause in the output stream. Rather than
+ // put a delay at the end of the function, the ending time is noted and
+ // the function will simply hold off (if needed) on issuing the
+ // subsequent round of data until the latch time has elapsed. This
+ // allows the mainline code to start generating the next frame of data
+ // rather than stalling for the latch.
+ while (!canShow());
+ // endTime is a private member (rather than global var) so that multiple
+ // instances on different pins can be quickly issued in succession (each
+ // instance doesn't delay the next).
+
+ // In order to make this code runtime-configurable to work with any pin,
+ // SBI/CBI instructions are eschewed in favor of full PORT writes via the
+ // OUT or ST instructions. It relies on two facts: that peripheral
+ // functions (such as PWM) take precedence on output pins, so our PORT-
+ // wide writes won't interfere, and that interrupts are globally disabled
+ // while data is being issued to the LEDs, so no other code will be
+ // accessing the PORT. The code takes an initial 'snapshot' of the PORT
+ // state, computes 'pin high' and 'pin low' values, and writes these back
+ // to the PORT register as needed.
+ // Notes (Spence 2/2022):
+ // OUTs suck, because they force duplication of the routine to handle
+ // different ports. Luckily we don't need them here - modern AVRs are
+ // based on the AVRxt core, and ST takes only 1 clock.
+ // Actually, it is possible to do that on the classic AVR version of
+ // these routines too... I'm not sure why it wasn't done, other than
+ // a strict adherence to the official datasheet, unhindered by any
+ // actual testing of how the parts behave (a LOW of only 6 us is
+ // enough to trigger the latch, that is the only limit on the length
+ // of a LOW, (hence if any bit takes longer than 5 bytes are supposed
+ // to, it won't work :-P)), and the length of a 1 is limited by the
+ // fact that it will get "signal reshaped" an "ideal length". If this
+ // results in the following LOW exceeding the latch limit, it breaks.
+ //
+ // So, having timing that's not strictly speaking correct located in
+ // anywhere that won't make a 0 look like a 1 or the other way around,
+ // you can kind of get away with a lot.
+ //
+ // This code manages to avoid having having to do that all the way down
+ // to 4-5 MHz one. which takes 1400 us to run for 6 bits and 1600 for the
+ // last two.
+ //
+ // Over the years a bunch of faster speeds have been added, so it could
+ // be used even on highly overclocked modern AVRs.
+ //
+ // Finally, some of the constraints were incorrect, and this only ever
+ // worked because classes are kryptonite to the optimizer.
+ // * [ptr] was declared read only. No, it is not. The register is
+ // register contaains the address being pointed to. We read with
+ // postincrement, so this is read-write.
+ // * Conversely, [port], another pointer, is never written. The thing that
+ // [port] points *to* is changed, but [port] is not.
+ // * b (bit number for speeds that don't have to unroll the loop)
+ // is given constraint "+r", which can assign it to any register.
+ // But the code uses LDI on it. LDI doesn't work on every register,
+ // it must have the "+d" constraint to guarantee an upper register.
+
+ noInterrupts(); // Need 100% focus on instruction timing
+
+
+ // AVRxt MCUs -- tinyAVR 0/1/2, megaAVR 0, AVR Dx ----------------------
+ // with extended maximum speeds to support vigorously overclocked
+ // Dx-series parts. This is by no means intended to imply that they will
+ // run at those speeds, only that - if they do - you can control WS2812s
+ // with them.
+
+
+ volatile uint8_t
+ *ptr = pixels, // Pointer to next byte
+ b = *ptr++, // Current byte value
+ hi, // PORT w/output bit set high
+ lo; // PORT w/output bit set low
+
+ // Hand-tuned assembly code issues data to the LED drivers at a specific
+ // rate. There's separate code for different CPU speeds (8, 12, 16 MHz)
+ // for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The
+ // datastream timing for the LED drivers allows a little wiggle room each
+ // way (listed in the datasheets), so the conditions for compiling each
+ // case are set up for a range of frequencies rather than just the exact
+ // 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on
+ // devices (e.g. 16.5 MHz DigiSpark). The ranges were arrived at based
+ // on the datasheet figures and have not been extensively tested outside
+ // the canonical 8/12/16 MHz speeds; there's no guarantee these will work
+ // close to the extremes (or possibly they could be pushed further).
+ // Keep in mind only one CPU speed case actually gets compiled; the
+ // resulting program isn't as massive as it might look from source here.
+
+
+ // 5ish MHz(ish) AVRxt
+ #if (F_CPU >= 400000UL) && (F_CPU <= 5600000UL)
+
+ volatile uint8_t n1, n2 = 0; // First, next bits out
+
+ // At this dreadfully slow clock speed, we struggle to meet the constraints.
+ // The best I can come up with is this. At 5 MHz, the bits are 1.4 us lonng.
+ // The last two bits are 1.6 us long.
+ // and if you were to crank it back to 4 MHz, well... it might actually still just barely work.
+ // The ones would be way longser
+
+ // 7 instruction clocks per bit: HxxxxLL H:1 x:4 L:2
+ // OUT instructions: ^^ ^ (T=0,2,5)
+ // 200 ns zero bit - barely legal.
+ // 800 ns highs - legal.
+ // 400 ns lows minimum
+ //
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ n1 = lo;
+ if (b & 0x80) n1 = hi;
+
+ // Dirty trick: RJMPs proceeding to the next instruction are used
+ // to delay two clock cycles in one instruction word (rather than
+ // using two NOPs). This was necessary in order to squeeze the
+ // loop down to exactly 64 words -- the maximum possible for a
+ // relative branch.
+
+ asm volatile(
+ "_head5:" "\n\t" // Clk Pseudocode
+ // Bit 7:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "sbrc %[byte] , 6" "\n\t" // 1-2 if (b & 0x40)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "nop" "\n\t" // 1 nop total 7 clocks
+ // Bit 6:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "sbrc %[byte] , 5" "\n\t" // 1-2 if (b & 0x20)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "nop" "\n\t" // 1 nop total 7 clocks
+ // Bit 5:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "sbrc %[byte] , 4" "\n\t" // 1-2 if (b & 0x10)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "nop" "\n\t" // 1 nop total 7 clocks
+ // Bit 4:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "sbrc %[byte] , 3" "\n\t" // 1-2 if (b & 0x08)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "nop" "\n\t" // 1 nop total 7 clocks
+ // Bit 3:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "sbrc %[byte] , 2" "\n\t" // 1-2 if (b & 0x04)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "subi %A[count], 1" "\n\t" // 1 Replacing sbiw pt 1 total 7 clocks
+ // Bit 2, 1 clock over:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "sbrc %[byte] , 1" "\n\t" // 1-2 if (b & 0x02)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "sbc %B[count], r1" "\n\t" // 2 Replacing sbiw pt 2 - total 7 clocks clocks
+ // Bit 1, 1 clock over:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "sbrc %[byte] , 0" "\n\t" // 1-2 if (b & 0x01)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ total 8 clocks
+ // Bit 0, 1 ckicj over:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "sbrc %[byte] , 7" "\n\t" // 1-2 if (b & 0x80)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "brne _head5" "\n" // 2 while(i) (Z flag set above) total 8 clocks.
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [n1] "+r" (n1),
+ [n2] "+r" (n2),
+ [count] "+d" (i) /* Relax requirements - it only needs to be an upper register, because we can't use SBIW, because we need to split the subtraction between two bits to meet timing constraints) */
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+
+
+ // 6.4ish MHz(ish) AVRxt
+ #elif (F_CPU >= 5600000UL) && (F_CPU <= 7400000UL)
+
+ volatile uint8_t n1, n2 = 0; // First, next bits out
+
+ // We need to be able to write to the port register in one clock
+ // to meet timing constraints here.
+
+ // 8 instruction clocks per bit: HHxxxLLL H:2 x:3 L3
+ // OUT instructions: ^ ^ ^ (T=0,2,5)
+ // 333 ns zero bit - definitely legal.
+ // 833 ns highs - legal.
+ // 500 ns lows - legal
+ // 8 clock per bit target met with NO DEVIANT BITS!
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ n1 = lo;
+ if (b & 0x80) n1 = hi;
+
+ // Dirty trick: RJMPs proceeding to the next instruction are used
+ // to delay two clock cycles in one instruction word (rather than
+ // using two NOPs). This was necessary in order to squeeze the
+ // loop down to exactly 64 words -- the maximum possible for a
+ // relative branch.
+
+ asm volatile(
+ "_head6dot4:" "\n\t" // Clk Pseudocode
+ // Bit 7:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "sbrc %[byte] , 6" "\n\t" // 1-2 if (b & 0x40)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop total 8 clocks
+ // Bit 6:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "sbrc %[byte] , 5" "\n\t" // 1-2 if (b & 0x20)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop total 8 clocks
+ // Bit 5:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "sbrc %[byte] , 4" "\n\t" // 1-2 if (b & 0x10)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop total 8 clocks
+ // Bit 4:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "sbrc %[byte] , 3" "\n\t" // 1-2 if (b & 0x08)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop total 8 clocks
+ // Bit 3:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "sbrc %[byte] , 2" "\n\t" // 1-2 if (b & 0x04)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop total 8 clocks
+ // Bit 2:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "sbrc %[byte] , 1" "\n\t" // 1-2 if (b & 0x02)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet) total 8 clocks
+ // Bit 1:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "sbrc %[byte] , 0" "\n\t" // 1-2 if (b & 0x01)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ total 8 clocks
+ // Bit 0:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "sbrc %[byte] , 7" "\n\t" // 1-2 if (b & 0x80)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "brne _head6dot4" "\n" // 2 while(i) (Z flag set above)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [n1] "+r" (n1),
+ [n2] "+r" (n2),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+
+
+ // 8 MHz(ish) AVRxt ---------------------------------------------------------
+ #elif (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
+
+ volatile uint8_t n1, n2 = 0; // First, next bits out
+
+ // We need to be able to write to the port register in one clock
+ // to meet timing constraints here.
+
+ // 10 instruction clocks per bit: HHxxxxxLLL
+ // OUT instructions: ^ ^ ^ (T=0,2,7)
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ n1 = lo;
+ if (b & 0x80) n1 = hi;
+
+ // Dirty trick: RJMPs proceeding to the next instruction are used
+ // to delay two clock cycles in one instruction word (rather than
+ // using two NOPs). This was necessary in order to squeeze the
+ // loop down to exactly 64 words -- the maximum possible for a
+ // relative branch.
+
+ asm volatile(
+ "_head8:" "\n\t" // Clk Pseudocode
+ // Bit 7:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "sbrc %[byte] , 6" "\n\t" // 1-2 if (b & 0x40)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop
+ // Bit 6:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "sbrc %[byte] , 5" "\n\t" // 1-2 if (b & 0x20)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop
+ // Bit 5:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "sbrc %[byte] , 4" "\n\t" // 1-2 if (b & 0x10)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop
+ // Bit 4:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "sbrc %[byte] , 3" "\n\t" // 1-2 if (b & 0x08)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop
+ // Bit 3:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "sbrc %[byte] , 2" "\n\t" // 1-2 if (b & 0x04)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop
+ // Bit 2:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "sbrc %[byte] , 1" "\n\t" // 1-2 if (b & 0x02)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "rjmp .+0" "\n\t" // 2 nop nop
+ // Bit 1:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
+ "st %a[port], %[n1]" "\n\t" // 1 PORT = n1
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "sbrc %[byte] , 0" "\n\t" // 1-2 if (b & 0x01)
+ "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet)
+ // Bit 0:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi
+ "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
+ "st %a[port], %[n2]" "\n\t" // 1 PORT = n2
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++
+ "sbrc %[byte] , 7" "\n\t" // 1-2 if (b & 0x80)
+ "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo
+ "brne _head8" "\n" // 2 while(i) (Z flag set above)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [n1] "+r" (n1),
+ [n2] "+r" (n2),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+ #elif (F_CPU >= 9500000UL) && (F_CPU <= 11100000UL)
+ /*
+ volatile uint8_t n1, n2 = 0; // First, next bits out
+
+ */
+ // 14 instruction clocks per bit: HHHHxxxxLLLLL
+ // ST instructions: ^ ^ ^ (T=0,4,7)
+ volatile uint8_t next;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ if (b & 0x80) {
+ next = hi;
+ }
+
+ // Don't "optimize" the OUT calls into the bitTime subroutine;
+ // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
+ asm volatile(
+ "_head10:" "\n\t" // (T = 0)
+ "st %a[port], %[hi]" "\n\t" // (T = 1)
+ "rcall _bitTime10" "\n\t" // Bit 7 (T = 14)
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime10" "\n\t" // Bit 6
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime10" "\n\t" // Bit 5
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime10" "\n\t" // Bit 4
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime10" "\n\t" // Bit 3
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime10" "\n\t" // Bit 2
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime10" "\n\t" // Bit 1
+ // Bit 0:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "nop" "\n\t" // 1 nop (T = 2)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 4)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
+ "nop" "\n\t" // 1 nop (T = 6)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
+ "sbrc %[byte] , 7" "\n\t" // 1-2 if (b & 0x80) (T = 8)
+ "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 10)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 12)
+ "brne _head10" "\n\t" // 2 if (i != 0) -> (next byte) (T = 14)
+ "rjmp _done10" "\n\t"
+ "_bitTime10:" "\n\t" // nop nop nop (T = 4)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
+ "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6)
+ "lsl %[byte]" "\n\t" // 1 b <<= 1 (T = 7)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 0x80) (T = 8)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 10)
+ "ret" "\n\t" // 4 return to above where we called from
+ "_done10:" "\n"
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+
+
+// 12 MHz(ish) AVRxt --------------------------------------------------------
+#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
+
+ // In the 12 MHz case, an optimized 800 KHz datastream (no dead time
+ // between bytes) requires a PORT-specific loop similar to the 8 MHz
+ // code (but a little more relaxed in this case).
+
+ // 15 instruction clocks per bit: HHHHxxxxxxLLLLL H:4 x:6 L5
+ // OUT instructions: ^ ^ ^ (T=0,4,10)
+
+ volatile uint8_t next;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ if (b & 0x80) {
+ next = hi;
+ }
+
+ // Don't "optimize" the OUT calls into the bitTime subroutine;
+ // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
+ asm volatile(
+ "_head12:" "\n\t" // (T = 0)
+ "st %a[port], %[hi]" "\n\t" // (T = 1)
+ "rcall _bitTime12" "\n\t" // Bit 7 (T = 15)
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime12" "\n\t" // Bit 6
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime12" "\n\t" // Bit 5
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime12" "\n\t" // Bit 4
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime12" "\n\t" // Bit 3
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime12" "\n\t" // Bit 2
+ "st %a[port], %[hi]" "\n\t"
+ "rcall _bitTime12" "\n\t" // Bit 1
+ // Bit 0:
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "nop" "\n\t" // 1 nop (T = 2)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 4)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 6)
+ "sbrc %[byte] , 7" "\n\t" // 1-2 if (b & 0x80) (T = 7)
+ "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 8)
+ "rjmp .+0" "\n\t" // 1 nop nop (T = 10)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 13)
+ "brne _head12" "\n\t" // 2 if (i != 0) -> (next byte)
+ "rjmp _done12" "\n\t"
+ "_bitTime12:" "\n\t" // nop nop nop (T = 4)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
+ "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6)
+ "lsl %[byte]" "\n\t" // 1 b <<= 1 (T = 7)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 0x80) (T = 8)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9)
+ "nop" "\n\t" // 1 (T = 10)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11)
+ "ret" "\n\t" // 4 return to above where we called from
+ "_done12:" "\n"
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+
+// 16 MHz(ish) AVRxt ------------------------------------------------------
+#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
+
+ // WS2811 and WS2812 have different hi/lo duty cycles; this is
+ // similar but NOT an exact copy of the prior 400-on-8 code.
+
+ // 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL H:5 x:8 L7
+ // ST instructions: ^ ^ ^ (T=0,5,13)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+
+ asm volatile(
+ "_head16:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "nop" "\n\t" // 1 nop (T = 2)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 5)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 6)
+ "nop" "\n\t" // 1 nop (T = 7)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8)
+ "breq _nextbyte16" "\n\t" // 1-2 if (bit == 0) (from dec above)
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
+ "nop" "\n\t" // 1 nop (T = 13)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 14)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
+ "rjmp _head16" "\n\t" // 2 -> _head16 (next bit out) (T=20)
+ "_nextbyte16:" "\n\t" // (T = 10)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 14)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
+ "brne _head16" "\n" // 2 if (i != 0) -> _head16 (bit 0 of next byte.) (T=20)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+// 20 MHz(ish) AVRxt ------------------------------------------------------
+#elif (F_CPU >= 19000000UL) && (F_CPU <= 22000000L)
+
+
+ // 25 inst. clocks per bit: HHHHHHHxxxxxxxLLLLLLLLLLL H:7 x:7 L11
+ // ST instructions: ^ ^ ^ (T=0,7,14)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+
+ asm volatile(
+ "_head20:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 3)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 4)
+ "nop" "\n\t" // 1 nop (T = 5)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 7)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 8)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 9)
+ "breq _nextbyte20" "\n\t" // 1-2 if (bit == 0) (from dec above) -> _nextbyte20
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 11)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 13)
+ "nop" "\n\t" // 1 nop (T = 14)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 15)
+ "rcall _onlydelay20" "\n\t" // 2+4+2 = 7 (T = 23)
+ "rjmp _head20" "\n\t" // 2 -> _head20 (next bit out T = 25)
+ "_onlydelay20:" "\n\t" // 2 rcall (T = n+2)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = n+4)
+ "ret" "\n\t" // 4 4x nop (T = n+8)
+ "_nextbyte20:" "\n\t" // (T = 11)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 12)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 14)
+ "nop" "\n\t" // 1 nop (T = 15)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 16)
+ "nop" "\n\t" // 1 nop (T = 17)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 19)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 21)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 23)
+ "brne _head20" "\n" // 2 if (i != 0) -> _head20 (next byte)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+// 24 (22~26) MHz AVRxt ------------------------------------------------------
+#elif (F_CPU >= 22000000UL) && (F_CPU <= 26000000L)
+
+
+ // 30 inst. clocks per bit: HHHHHHHHxxxxxxxxLLLLLLLLLLLLLL H:8 x:8 L14
+ // ST instructions: ^ ^ ^ (T=0,8,16)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+
+
+ asm volatile(
+ "_head24:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 3)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 4)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 8)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 9)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 10)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
+ "breq _nextbyte24" "\n\t" // 1-2 if (bit == 0) (from dec above) -> _nextbyte24
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 16)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 17)
+ "rcall _seconddelay24" "\n\t" // 2+4+5=11 (T = 28)
+ "rjmp _head24" "\n\t" // 2 -> _head24 (next bit out)
+ "_seconddelay24:" "\n\t" //
+ "rjmp .+0" "\n\t" // 2
+ "rjmp .+0" "\n\t" // 2
+ "_thirddelay24:" "\n\t"
+ "nop" "\n\t" // 1
+ "ret" "\n\t" // 4
+ "_nextbyte24:" "\n\t" // last bit of a byte (T = 15)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 16)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 17)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 19)
+ "rcall _thirddelay24" "\n\t" // 2+4+1=7 (T = 26)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 28)
+ "brne _head24" "\n" // 2 if (i != 0) -> _head24 (next byte) (T = 30)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+
+
+
+// 28 (26~30) MHz AVRxt ------------------------------------------------------
+#elif (F_CPU >= 26000000UL) && (F_CPU <= 30000000L)
+
+
+ // 35 inst. clocks per bit: HHHHHHHHHxxxxxxxxxxxLLLLLLLLLLLLLLL - H:8 x:9 L15
+ // ST instructions: ^ ^ ^ (T=0,9,20)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+
+ asm volatile(
+ "_head28:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 3)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 4)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
+ "rjmp .+0" "\n\t" // 2 nop nop (T = 8)
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 9)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 10)
+ "rcall _firstdelay28" "\n\t" // 2+4 = 7 (T = 17)
+ "breq _nextbyte28" "\n\t" // 1-2 if (bit == 0) (from dec above) -> _nextbyte28
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 19)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 20)
+ "rcall _seconddelay28" "\n\t" // 2+4+1+6=11 (T = 31)
+ "rjmp _head28" "\n\t" // 2 -> _head28 (next bit out)
+ "_seconddelay28:" "\n\t" //
+ "rcall _thirddelay28" "\n\t" // 2+4=6 saves 2 instruction words vs two rjmp .+0
+ "_firstdelay28:" "\n\t" // first delay
+ "nop" "\n\t" // 1 nop
+ "_thirddelay28:" "\n\t" // third delay
+ "ret" "\n\t" // 4
+ "_nextbyte28:" "\n\t" // last bit of a byte (T = 21)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 22)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 23)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 25)
+ "rcall _thirddelay28" "\n\t" // 2+4 = 6 (T = 31)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 33)
+ "brne _head28" "\n" // 2 if (i != 0) -> _head28 (next byte)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+
+// 32 (30~34) MHz AVRxt ------------------------------------------------------
+#elif (F_CPU > 30000000UL) && (F_CPU <= 34000000L)
+
+
+ // 40 inst. clocks per bit: HHHHHHHHHHHHxxxxxxxxxxxxxLLLLLLLLLLLLLLL
+ // ST instructions: ^ ^ ^ (T=0,10,23)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+
+ asm volatile(
+ "_head32:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 3)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 4)
+ "rcall _zerothdelay32" "\n\t" // 2+4=6
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 11)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 12)
+ "rcall _firstdelay32" "\n\t" // 2+4+1+2 = 9 (T = 21)
+ "breq _nextbyte32" "\n\t" // 1-2 if (bit == 0) (from dec above)
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 23)
+ "rcall _seconddelay32" "\n\t" // 2+4+6+3=15 (T = 38)
+ "rjmp _head32" "\n\t" // 2 -> _head32 (next bit out)
+ "_seconddelay32:" "\n\t" // second delay 15 cycles
+ "rcall _zerothdelay32" "\n\t" // 2+4=6
+ "_firstdelay32:" "\n\t" // first delay 9 cycles
+ "nop" "\n\t" // 1 nop
+ "_thirddelay32:" "\n\t" // third delay 8 cycles
+ "rjmp .+0" "\n\t" // 1 nop
+ "_zerothdelay32:" "\n\t" // zeroth delay 6 cycles
+ "ret" "\n\t" // 4
+ "_nextbyte32:" "\n\t" // last bit of a byte (T = 23)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 24)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 26)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 28)
+ "rcall _thirddelay32" "\n\t" // 2+4+2 = 8 (T = 36)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 38)
+ "brne _head32" "\n" // 2 if (i != 0) -> _head32 (next byte)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+// 36 (34~38) MHz AVRxt ------------------------------------------------------
+#elif (F_CPU > 3400000UL) && (F_CPU <= 38000000L)
+
+
+ // 45 inst. clocks per bit: HHHHHHHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLL
+ // ST instructions: ^ ^ ^ (T=0,12,27)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+
+ asm volatile(
+ "_head36:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 3)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 4)
+ "rcall _zerothdelay36" "\n\t" // 2+4+2=8
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 13)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 14)
+ "rcall _firstdelay36" "\n\t" // 2+4+3 = 11 (T = 25)
+ "breq _nextbyte36" "\n\t" // 1-2 if (bit == 0) (from dec above)
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 28)
+ "rcall _seconddelay36" "\n\t" // 2+4+3+2+2=15 (T = 43)
+ "rjmp _head36" "\n\t" // 2 -> _head36 (next bit out)
+ "_seconddelay36:" "\n\t" // second delay 15 cycles
+ "rjmp .+0" "\n\t" // 2
+ "rjmp .+0" "\n\t" // 2
+ "_firstdelay36:" "\n\t" // first delay 11 cycles
+ "nop" "\n\t" // 1 nop
+ "_thirddelay36:" "\n\t" // third delay 10 cycles
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "_zerothdelay36:" "\n\t" // zeroth delay 8 cycles
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "ret" "\n\t" // 4
+ "_nextbyte36:" "\n\t" // last bit of a byte (T = 27)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 28)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 29)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 31)
+ "rcall _thirddelay36" "\n\t" // 2+4 = 10 (T = 41)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 43)
+ "brne _head36" "\n" // 2 if (i != 0) -> _head36 (next byte)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+
+// 40 (38-44) MHz AVRxt ------------------------------------------------------
+#elif (F_CPU > 3800000UL) && (F_CPU <= 44000000L)
+
+
+ // 50 inst. clocks per bit: HHHHHHHHHHHHHHxxxxxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL
+ // ST instructions: ^ ^ ^ (T=0,14,30)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+
+ asm volatile(
+ "_head40:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 3)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 4)
+ "rcall _zerothdelay40" "\n\t" // 2+4+4=10
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 15)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 16)
+ "rcall _firstdelay40" "\n\t" // 2+4+4+2 = 12 (T = 28)
+ "breq _nextbyte40" "\n\t" // 1-2 if (bit == 0) (from dec above)
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 30)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 31)
+ "rcall _seconddelay40" "\n\t" // 2+4+3+2+3=17 (T = 48)
+ "rjmp _head40" "\n\t" // 2 -> _head40 (next bit out)
+ "_seconddelay40:" "\n\t" // second delay 17 cycles
+ "nop" "\n\t" // 1 nop
+ "rjmp .+0" "\n\t" // 2
+ "rjmp .+0" "\n\t" // 2
+ "_firstdelay40:" "\n\t" // first delay 12 cycles
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "_zerothdelay40:" "\n\t" // zeroth delay 10 cycles
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "ret" "\n\t" // 4
+ "_nextbyte40:" "\n\t" // last bit of a byte (T = 30)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 31)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 32)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 34)
+ "rcall _firstdelay40" "\n\t" // 2+4+4+2 = 12 (T = 46)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 48)
+ "brne _head40" "\n" // 2 if (i != 0) -> _head40 (next byte)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+// 48 (44-50) MHz AVRxt ------------------------------------------------------
+#elif (F_CPU > 4400000UL) && (F_CPU <= 50000000L)
+
+
+ // 60 inst. clocks per bit: HHHHHHHHHHHHHHHxxxxxxxxxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
+ // ST instructions: ^ ^ ^ (T=0,16,35)
+
+ volatile uint8_t next, bit;
+
+ hi = *port | pinMask;
+ lo = *port & ~pinMask;
+ next = lo;
+ bit = 8;
+ asm volatile(
+ "_head48:" "\n\t" // Clk Pseudocode (T = 0)
+ "st %a[port], %[hi]" "\n\t" // 1 PORT = hi (T = 1)
+ "sbrc %[byte], 7" "\n\t" // 1-2 if (b & 128)
+ "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 3)
+ "dec %[bit]" "\n\t" // 1 bit-- (T = 4)
+ "rcall _zerothdelay48" "\n\t" // 2+4=13
+ "st %a[port], %[next]" "\n\t" // 1 PORT = next (T = 17)
+ "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 18)
+ "rcall _firstdelay48" "\n\t" // 2+4+3 = 15 (T = 33)
+ "breq _nextbyte48" "\n\t" // 1-2 if (bit == 0) (from dec above)
+ "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 35)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 36)
+ "rcall _seconddelay48" "\n\t" // 2+4+3+2+3=22 (T = 58)
+ "rjmp _head48" "\n\t" // 2 -> _head48 (next bit out)
+ "_seconddelay48:" "\n\t" // second delay 22 cycles
+ "rjmp .+0" "\n\t" // 2
+ "rjmp .+0" "\n\t" // 2
+ "nop" "\n\t" // 1 nop
+ "_thirddelay48:" "\n\t" // third delay 17 cycles
+ "rjmp .+0" "\n\t" // 2
+ "_firstdelay48:" "\n\t" // first delay 15 cycles
+ "rjmp .+0" "\n\t" // 2 nop nop
+ "_zerothdelay48:" "\n\t" // zeroth delay 13 cycles
+ "nop" "\n\t" // 1 nop
+ "rcall _emptydelay48" "\n\t" // 2+4
+ "ret" "\n\t" // 4
+ "_emptydelay48:" "\n\t" // immediately returns: 2+4 = 6 cycles, for 2 words!
+ "ret" "\n\t" // 4
+ "_nextbyte48:" "\n\t" // last bit of a byte (T = 35)
+ "st %a[port], %[lo]" "\n\t" // 1 PORT = lo (T = 36)
+ "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 37)
+ "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 39)
+ "rcall _thirddelay48" "\n\t" // 2+4 = 17 (T = 56)
+ "sbiw %[count], 1" "\n\t" // 2 i-- (T = 58)
+ "brne _head48" "\n" // 2 if (i != 0) -> _head48 (next byte)
+ : [ptr] "+e" (ptr),
+ [byte] "+r" (b),
+ [bit] "+d" (bit),
+ [next] "+r" (next),
+ [count] "+w" (i)
+ : [port] "e" (port),
+ [hi] "r" (hi),
+ [lo] "r" (lo));
+
+ #else
+ #error "CPU SPEED NOT SUPPORTED"
+ #endif
+
+
+
+ interrupts();
+ #if (!defined(MILLIS_USE_TIMERNONE) && !defined(MILLIS_USE_TIMERRTC) && !defined(MILLIS_USE_TIMERRTC_XTAL) && !defined(MILLIS_USE_TIMERRTC_XOSC))
+ endTime = micros();
+ // Save EOD time for latch on next call
+ #pragma message("micros() present. This library assumes the canonical 50 us latch delay; some pixels will wait as long as 250us. In these cases, you must be sure to not call show more often. See documentation.")
+ #else
+ #pragma message("micros() is not available because millis is disabled from the tools subemnu. It is your responsibility to ensure a sufficient time has passed between calls to show(). See documentation.")
+ #endif
+}
+
+// Set the output pin number
+void tinyNeoPixel::setPin(uint8_t p) {
+ pin = p;
+ port = portOutputRegister(digitalPinToPort(p));
+ pinMask = digitalPinToBitMask(p);
+}
+
+// Set pixel color from separate R,G,B components:
+void tinyNeoPixel::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
+ if (n < numLEDs) {
+ if (brightness) { // See notes in setBrightness()
+ r = (r * brightness) >> 8;
+ g = (g * brightness) >> 8;
+ b = (b * brightness) >> 8;
+ }
+ uint8_t *p;
+ if (wOffset == rOffset) { // Is an RGB-type strip
+ p = &pixels[n * 3]; // 3 bytes per pixel
+ } else { // Is a WRGB-type strip
+ p = &pixels[n * 4]; // 4 bytes per pixel
+ p[wOffset] = 0; // But only R,G,B passed -- set W to 0
+ }
+ p[rOffset] = r; // R,G,B always stored
+ p[gOffset] = g;
+ p[bOffset] = b;
+ }
+}
+
+void tinyNeoPixel::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+ if (n < numLEDs) {
+ if (brightness) { // See notes in setBrightness()
+ r = (r * brightness) >> 8;
+ g = (g * brightness) >> 8;
+ b = (b * brightness) >> 8;
+ w = (w * brightness) >> 8;
+ }
+ uint8_t *p;
+ if (wOffset == rOffset) { // Is an RGB-type strip
+ p = &pixels[n * 3]; // 3 bytes per pixel (ignore W)
+ } else { // Is a WRGB-type strip
+ p = &pixels[n * 4]; // 4 bytes per pixel
+ p[wOffset] = w; // Store W
+ }
+ p[rOffset] = r; // Store R,G,B
+ p[gOffset] = g;
+ p[bOffset] = b;
+ }
+}
+
+// Set pixel color from 'packed' 32-bit RGB color:
+void tinyNeoPixel::setPixelColor(uint16_t n, uint32_t c) {
+ if (n < numLEDs) {
+ uint8_t *p,
+ r = (uint8_t)(c >> 16),
+ g = (uint8_t)(c >> 8),
+ b = (uint8_t)c;
+ if (brightness) { // See notes in setBrightness()
+ r = (r * brightness) >> 8;
+ g = (g * brightness) >> 8;
+ b = (b * brightness) >> 8;
+ }
+ if (wOffset == rOffset) {
+ p = &pixels[n * 3];
+ } else {
+ p = &pixels[n * 4];
+ uint8_t w = (uint8_t)(c >> 24);
+ p[wOffset] = brightness ? ((w * brightness) >> 8) : w;
+ }
+ p[rOffset] = r;
+ p[gOffset] = g;
+ p[bOffset] = b;
+ }
+}
+
+/*!
+ @brief Fill all or part of the NeoPixel strip with a color.
+ @param c 32-bit color value. Most significant byte is white (for
+ RGBW pixels) or ignored (for RGB pixels), next is red,
+ then green, and least significant byte is blue. If all
+ arguments are unspecified, this will be 0 (off).
+ @param first Index of first pixel to fill, starting from 0. Must be
+ in-bounds, no clipping is performed. 0 if unspecified.
+ @param count Number of pixels to fill, as a positive value. Passing
+ 0 or leaving unspecified will fill to end of strip.
+*/
+void tinyNeoPixel::fill(uint32_t c, uint16_t first, uint16_t count) {
+ uint16_t i, end;
+
+ if (first >= numLEDs) {
+ return; // If first LED is past end of strip, nothing to do
+ }
+
+ // Calculate the index ONE AFTER the last pixel to fill
+ if (count == 0) {
+ // Fill to end of strip
+ end = numLEDs;
+ } else {
+ // Ensure that the loop won't go past the last pixel
+ end = first + count;
+ if (end > numLEDs) end = numLEDs;
+ }
+
+ for (i = first; i < end; i++) {
+ this->setPixelColor(i, c);
+ }
+}
+
+
+/*!
+ @brief Convert hue, saturation and value into a packed 32-bit RGB color
+ that can be passed to setPixelColor() or other RGB-compatible
+ functions.
+ @param hue An unsigned 16-bit value, 0 to 65535, representing one full
+ loop of the color wheel, which allows 16-bit hues to "roll
+ over" while still doing the expected thing (and allowing
+ more precision than the wheel() function that was common to
+ prior NeoPixel examples).
+ @param sat Saturation, 8-bit value, 0 (min or pure grayscale) to 255
+ (max or pure hue). Default of 255 if unspecified.
+ @param val Value (brightness), 8-bit value, 0 (min / black / off) to
+ 255 (max or full brightness). Default of 255 if unspecified.
+ @return Packed 32-bit RGB with the most significant byte set to 0 -- the
+ white element of WRGB pixels is NOT utilized. Result is linearly
+ but not perceptually correct, so you may want to pass the result
+ through the gamma32() function (or your own gamma-correction
+ operation) else colors may appear washed out. This is not done
+ automatically by this function because coders may desire a more
+ refined gamma-correction function than the simplified
+ one-size-fits-all operation of gamma32(). Diffusing the LEDs also
+ really seems to help when using low-saturation colors.
+*/
+uint32_t tinyNeoPixel::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
+
+ uint8_t r, g, b;
+
+ // Remap 0-65535 to 0-1529. Pure red is CENTERED on the 64K rollover;
+ // 0 is not the start of pure red, but the midpoint...a few values above
+ // zero and a few below 65536 all yield pure red (similarly, 32768 is the
+ // midpoint, not start, of pure cyan). The 8-bit RGB hexcone (256 values
+ // each for red, green, blue) really only allows for 1530 distinct hues
+ // (not 1536, more on that below), but the full unsigned 16-bit type was
+ // chosen for hue so that one's code can easily handle a contiguous color
+ // wheel by allowing hue to roll over in either direction.
+ hue = (hue * 1530L + 32768) / 65536;
+ // Because red is centered on the rollover point (the +32768 above,
+ // essentially a fixed-point +0.5), the above actually yields 0 to 1530,
+ // where 0 and 1530 would yield the same thing. Rather than apply a
+ // costly modulo operator, 1530 is handled as a special case below.
+
+ // So you'd think that the color "hexcone" (the thing that ramps from
+ // pure red, to pure yellow, to pure green and so forth back to red,
+ // yielding six slices), and with each color component having 256
+ // possible values (0-255), might have 1536 possible items (6*256),
+ // but in reality there's 1530. This is because the last element in
+ // each 256-element slice is equal to the first element of the next
+ // slice, and keeping those in there this would create small
+ // discontinuities in the color wheel. So the last element of each
+ // slice is dropped...we regard only elements 0-254, with item 255
+ // being picked up as element 0 of the next slice. Like this:
+ // Red to not-quite-pure-yellow is: 255, 0, 0 to 255, 254, 0
+ // Pure yellow to not-quite-pure-green is: 255, 255, 0 to 1, 255, 0
+ // Pure green to not-quite-pure-cyan is: 0, 255, 0 to 0, 255, 254
+ // and so forth. Hence, 1530 distinct hues (0 to 1529), and hence why
+ // the constants below are not the multiples of 256 you might expect.
+
+ // Convert hue to R,G,B (nested ifs faster than divide+mod+switch):
+ if (hue < 510) { // Red to Green-1
+ b = 0;
+ if (hue < 255) { // Red to Yellow-1
+ r = 255;
+ g = hue; // g = 0 to 254
+ } else { // Yellow to Green-1
+ r = 510 - hue; // r = 255 to 1
+ g = 255;
+ }
+ } else if (hue < 1020) { // Green to Blue-1
+ r = 0;
+ if (hue < 765) { // Green to Cyan-1
+ g = 255;
+ b = hue - 510; // b = 0 to 254
+ } else { // Cyan to Blue-1
+ g = 1020 - hue; // g = 255 to 1
+ b = 255;
+ }
+ } else if (hue < 1530) { // Blue to Red-1
+ g = 0;
+ if (hue < 1275) { // Blue to Magenta-1
+ r = hue - 1020; // r = 0 to 254
+ b = 255;
+ } else { // Magenta to Red-1
+ r = 255;
+ b = 1530 - hue; // b = 255 to 1
+ }
+ } else { // Last 0.5 Red (quicker than % operator)
+ r = 255;
+ g = b = 0;
+ }
+
+ // Apply saturation and value to R,G,B, pack into 32-bit result:
+ uint32_t v1 = 1 + val; // 1 to 256; allows >>8 instead of /255
+ uint16_t s1 = 1 + sat; // 1 to 256; same reason
+ uint8_t s2 = 255 - sat; // 255 to 0
+ return ((((((r * s1) >> 8) + s2) * v1) & 0xff00) << 8) |
+ (((((g * s1) >> 8) + s2) * v1) & 0xff00) |
+ (((((b * s1) >> 8) + s2) * v1) >> 8);
+}
+
+
+// Query color from previously-set pixel (returns packed 32-bit RGB value)
+uint32_t tinyNeoPixel::getPixelColor(uint16_t n) const {
+ if (n >= numLEDs) {
+ return 0; // Out of bounds, return no color.
+ }
+
+ uint8_t *p;
+
+ if (wOffset == rOffset) { // Is RGB-type device
+ p = &pixels[n * 3];
+ if (brightness) {
+ // Stored color was decimated by setBrightness(). Returned value
+ // attempts to scale back to an approximation of the original 24-bit
+ // value used when setting the pixel color, but there will always be
+ // some error -- those bits are simply gone. Issue is most
+ // pronounced at low brightness levels.
+ return (((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
+ (((uint32_t)(p[gOffset] << 8) / brightness) << 8) |
+ ((uint32_t)(p[bOffset] << 8) / brightness);
+ } else {
+ // No brightness adjustment has been made -- return 'raw' color
+ return ((uint32_t)p[rOffset] << 16) |
+ ((uint32_t)p[gOffset] << 8) |
+ (uint32_t)p[bOffset];
+ }
+ } else { // Is RGBW-type device
+ p = &pixels[n * 4];
+ if (brightness) { // Return scaled color
+ return (((uint32_t)(p[wOffset] << 8) / brightness) << 24) |
+ (((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
+ (((uint32_t)(p[gOffset] << 8) / brightness) << 8) |
+ ((uint32_t)(p[bOffset] << 8) / brightness);
+ } else { // Return raw color
+ return ((uint32_t)p[wOffset] << 24) |
+ ((uint32_t)p[rOffset] << 16) |
+ ((uint32_t)p[gOffset] << 8) |
+ (uint32_t)p[bOffset];
+ }
+ }
+}
+
+// Returns pointer to pixels[] array. Pixel data is stored in device-
+// native format and is not translated here. Application will need to be
+// aware of specific pixel data format and handle colors appropriately.
+uint8_t *tinyNeoPixel::getPixels(void) const {
+ return pixels;
+}
+
+uint16_t tinyNeoPixel::numPixels(void) const {
+ return numLEDs;
+}
+
+// Adjust output brightness; 0=darkest (off), 255=brightest. This does
+// NOT immediately affect what's currently displayed on the LEDs. The
+// next call to show() will refresh the LEDs at this level. However,
+// this process is potentially "lossy," especially when increasing
+// brightness. The tight timing in the WS2811/WS2812 code means there
+// aren't enough free cycles to perform this scaling on the fly as data
+// is issued. So we make a pass through the existing color data in RAM
+// and scale it (subsequent graphics commands also work at this
+// brightness level). If there's a significant step up in brightness,
+// the limited number of steps (quantization) in the old data will be
+// quite visible in the re-scaled version. For a non-destructive
+// change, you'll need to re-render the full strip data.
+void tinyNeoPixel::setBrightness(uint8_t b) {
+ // Stored brightness value is different than what's passed.
+ // This simplifies the actual scaling math later, allowing a fast
+ // 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t,
+ // adding 1 here may (intentionally) roll over...so 0 = max brightness
+ // (color values are interpreted literally; no scaling), 1 = min
+ // brightness (off), 255 = just below max brightness.
+ uint8_t newBrightness = b + 1;
+ if (newBrightness != brightness) { // Compare against prior value
+ // Brightness has changed -- re-scale existing data in RAM
+ uint8_t c,
+ *ptr = pixels,
+ oldBrightness = brightness - 1; // De-wrap old brightness value
+ uint16_t scale;
+ if (oldBrightness == 0) {
+ scale = 0; // Avoid 0
+ } else if (b == 255) {
+ scale = 65535 / oldBrightness;
+ } else {
+ scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
+ }
+ for (uint16_t i = 0; i < numBytes; i++) {
+ c = *ptr;
+ *ptr++ = (c * scale) >> 8;
+ }
+ brightness = newBrightness;
+ }
+}
+
+// Return the brightness value
+uint8_t tinyNeoPixel::getBrightness(void) const {
+ return brightness - 1;
+}
+
+void tinyNeoPixel::clear() {
+ memset(pixels, 0, numBytes);
+}
+
+// A 32-bit variant of gamma8() that applies the same function
+// to all components of a packed RGB or WRGB value.
+uint32_t tinyNeoPixel::gamma32(uint32_t x) {
+ uint8_t *y = (uint8_t *)&x;
+ // All four bytes of a 32-bit value are filtered even if RGB (not WRGB),
+ // to avoid a bunch of shifting and masking that would be necessary for
+ // properly handling different endianisms (and each byte is a fairly
+ // trivial operation, so it might not even be wasting cycles vs a check
+ // and branch for the RGB case). In theory this might cause trouble *if*
+ // someone's storing information in the unused most significant byte
+ // of an RGB value, but this seems exceedingly rare and if it's
+ // encountered in reality they can mask values going in or coming out.
+ for (uint8_t i = 0; i<4; i++) y[i] = gamma8(y[i]);
+ return x; // Packed 32-bit return
+}
+// *INDENT-ON*
diff --git a/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/tinyNeoPixel_Static.h b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/tinyNeoPixel_Static.h
new file mode 100644
index 0000000..aa7b7fb
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/arduino_libraries/tinyNeoPixel_static/tinyNeoPixel_Static.h
@@ -0,0 +1,334 @@
+/*--------------------------------------------------------------------
+ This file is part of the tinyNeoPixel library, derived from
+ Adafruit_NeoPixel.
+
+ NeoPixel 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 3 of
+ the License, or (at your option) any later version.
+
+ NeoPixel 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 NeoPixel. If not, see
+ .
+ --------------------------------------------------------------------*/
+// *INDENT-OFF* astyle hates this file
+// *PAD-OFF* and destroys the lookup tables!
+
+#ifndef TINYNEOPIXEL_H
+#define TINYNEOPIXEL_H
+
+#include
+
+#if (__AVR_ARCH__ < 100)
+ #error "This version of the library only supports AVRxt parts (tinyAVR 0/1/2-series, megaAVR 0-series and the AVR DA/DB/DD parts. For tinyNeoPixel, for classic AVR, get from ATTinyCore package"
+#endif
+
+// The order of primary colors in the NeoPixel data stream can vary
+// among device types, manufacturers and even different revisions of
+// the same item. The third parameter to the Adafruit_NeoPixel
+// constructor encodes the per-pixel byte offsets of the red, green
+// and blue primaries (plus white, if present) in the data stream --
+// the following #defines provide an easier-to-use named version for
+// each permutation. e.g. NEO_GRB indicates a NeoPixel-compatible
+// device expecting three bytes per pixel, with the first byte
+// containing the green value, second containing red and third
+// containing blue. The in-memory representation of a chain of
+// NeoPixels is the same as the data-stream order; no re-ordering of
+// bytes is required when issuing data to the chain.
+
+// Bits 5,4 of this value are the offset (0-3) from the first byte of
+// a pixel to the location of the red color byte. Bits 3,2 are the
+// green offset and 1,0 are the blue offset. If it is an RGBW-type
+// device (supporting a white primary in addition to R,G,B), bits 7,6
+// are the offset to the white byte...otherwise, bits 7,6 are set to
+// the same value as 5,4 (red) to indicate an RGB (not RGBW) device.
+// i.e. binary representation:
+// 0bWWRRGGBB for RGBW devices
+// 0bRRRRGGBB for RGB
+
+// RGB NeoPixel permutations; white and red offsets are always same
+// Offset: W R G B
+#define NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2))
+#define NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1))
+#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2))
+#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1))
+#define NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0))
+#define NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0))
+
+// RGBW NeoPixel permutations; all 4 offsets are distinct
+// Offset: W R G B
+#define NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
+#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
+#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
+#define NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
+#define NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
+#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))
+
+#define NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
+#define NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
+#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
+#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
+#define NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
+#define NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))
+
+#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
+#define NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
+#define NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
+#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
+#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
+#define NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))
+
+#define NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
+#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
+#define NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
+#define NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
+#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
+#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))
+
+#define NEO_KHZ800 0x0000 ///< 800 KHz data transmission
+
+// 400 kHz neopixels are virtually absent from the market today
+// They are not supported.
+
+// These two tables are declared outside the Adafruit_NeoPixel class
+// because some boards may require oldschool compilers that don't
+// handle the C++11 constexpr keyword.
+
+/* A pre-calculated 8-bit sine look-up table stored in flash for use
+with the sine8() function. This is apparently of use in some animation
+algorithms. If __AVR_ARCH__==103, then all of the flash is memory
+mapped, and we can simply declare it const, access it like a
+normal variable, and it won't be copied to RAM.
+
+AVRxt devices with too much flash for all of it to be mapped
+which includes the AVR64Dx and AVR128Dx parts. DxCore defines a
+.section for the area of PROGMEM that is mapped by default, and
+a PROGMEM_MAPPED macro. A variable declared const PROGMEM_MAPPED can
+be accessed normally, but will be stored in the flash and not copied to RAM.
+
+Finally, if neither of those are an option - it gets declared with PROGMEM
+
+
+ Copy & paste this snippet into a Python REPL to regenerate:
+import math
+for x in range(256):
+ print("{:3},".format(int((math.sin(x/128.0*math.pi)+1.0)*127.5+0.5))),
+ if x&15 == 15: print
+*/
+#if (__AVR_ARCH__==103)
+ // All out flash is mapped - yay!
+ static const uint8_t _NeoPixelSineTable[256] = {
+#elif defined(PROGMEM_MAPPED)
+ // Some of it is - but we can put stuff there - yay!
+ static const uint8_t PROGMEM_MAPPED _NeoPixelSineTable[256] = {
+#else
+ // Back to progmem...
+ static const uint8_t PROGMEM _NeoPixelSineTable[256] = {
+#endif
+ 128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,
+ 176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,
+ 218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244,
+ 245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
+ 255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,
+ 245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,
+ 218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,
+ 176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,
+ 128,124,121,118,115,112,109,106,103,100, 97, 93, 90, 88, 85, 82,
+ 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
+ 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
+ 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9,
+ 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
+ 37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
+ 79, 82, 85, 88, 90, 93, 97,100,103,106,109,112,115,118,121,124};
+
+/* Similar to above, but for an 8-bit gamma-correction table.
+ Copy & paste this snippet into a Python REPL to regenerate:
+import math
+gamma=2.6
+for x in range(256):
+ print("{:3},".format(int(math.pow((x)/255.0,gamma)*255.0+0.5))),
+ if x&15 == 15: print
+*/
+#if (__AVR_ARCH__==103)
+ // All our flash is mapped - yay!
+ static const uint8_t _NeoPixelGammaTable[256] = {
+#elif defined(PROGMEM_MAPPED)
+ // Some of it is - but we can put stuff there - yay!
+ static const uint8_t PROGMEM_MAPPED _NeoPixelGammaTable[256] = {
+#else
+ // Back to progmem...
+ static const uint8_t PROGMEM _NeoPixelGammaTable[256] = {
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
+ 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7,
+ 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12,
+ 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
+ 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29,
+ 30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75,
+ 76, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96,
+ 97, 99,100,102,103,105,106,108,109,111,112,114,115,117,119,120,
+ 122,124,125,127,129,130,132,134,136,137,139,141,143,145,146,148,
+ 150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,
+ 182,184,186,188,191,193,195,197,199,202,204,206,209,211,213,215,
+ 218,220,223,225,227,230,232,235,237,240,242,245,247,250,252,255};
+
+
+typedef uint8_t neoPixelType;
+
+class tinyNeoPixel {
+
+ public:
+
+ // Constructor: number of LEDs, pin number, LED type
+ tinyNeoPixel(uint16_t n, uint8_t p, neoPixelType t, uint8_t *pxl);
+ ~tinyNeoPixel();
+
+ void
+ show(void),
+ #if (PROGMEM_SIZE > 4096UL)
+ show(uint16_t leds),
+ #endif
+ setPin(uint8_t p),
+ setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
+ setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w),
+ setPixelColor(uint16_t n, uint32_t c),
+ fill(uint32_t c = 0, uint16_t first = 0, uint16_t count = 0),
+ setBrightness(uint8_t b),
+ clear(),
+ updateLatch(uint16_t latchtime = 50);
+ uint8_t
+ *getPixels(void) const,
+ getBrightness(void) const;
+ uint16_t
+ numPixels(void) const;
+ uint32_t
+ getPixelColor(uint16_t n) const;
+ uint8_t getPin(void) { return pin; }
+ void begin(void) {return;}
+ /*!
+ @brief An 8-bit integer sine wave function, not directly compatible
+ with standard trigonometric units like radians or degrees.
+ @param x Input angle, 0-255; 256 would loop back to zero, completing
+ the circle (equivalent to 360 degrees or 2 pi radians).
+ One can therefore use an unsigned 8-bit variable and simply
+ add or subtract, allowing it to overflow/underflow and it
+ still does the expected contiguous thing.
+ @return Sine result, 0 to 255, or -128 to +127 if type-converted to
+ a signed int8_t, but you'll most likely want unsigned as this
+ output is often used for pixel brightness in animation effects.
+ */
+ static uint8_t sine8(uint8_t x) { // 0-255 in, 0-255 out
+ #if (__AVR_ARCH__ == 103 || defined(PROGMEM_MAPPED))
+ return _NeoPixelSineTable[x];
+ #else // We had to put it in PROGMEM, and that's how we get it out
+ return pgm_read_byte(&_NeoPixelSineTable[x]); // 0-255 in, 0-255 out
+ #endif
+ }
+
+ /*!
+ @brief An 8-bit gamma-correction function for basic pixel brightness
+ adjustment. Makes color transitions appear more perceptially
+ correct.
+ @param x Input brightness, 0 (minimum or off/black) to 255 (maximum).
+ @return Gamma-adjusted brightness, can then be passed to one of the
+ setPixelColor() functions. This uses a fixed gamma correction
+ exponent of 2.6, which seems reasonably okay for average
+ NeoPixels in average tasks. If you need finer control you'll
+ need to provide your own gamma-correction function instead.
+ */
+
+ static uint8_t gamma8(uint8_t x) {
+ #if (__AVR_ARCH__ == 103 || defined(PROGMEM_MAPPED))
+ return _NeoPixelGammaTable[x];
+ #else
+ return pgm_read_byte(&_NeoPixelGammaTable[x]);
+ #endif
+ }
+ /*!
+ @brief Convert separate red, green and blue values into a single
+ "packed" 32-bit RGB color.
+ @param r Red brightness, 0 to 255.
+ @param g Green brightness, 0 to 255.
+ @param b Blue brightness, 0 to 255.
+ @return 32-bit packed RGB value, which can then be assigned to a
+ variable for later use or passed to the setPixelColor()
+ function. Packed RGB format is predictable, regardless of
+ LED strand color order.
+ */
+ static uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
+ return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
+ }
+ /*!
+ @brief Convert separate red, green, blue and white values into a
+ single "packed" 32-bit WRGB color.
+ @param r Red brightness, 0 to 255.
+ @param g Green brightness, 0 to 255.
+ @param b Blue brightness, 0 to 255.
+ @param w White brightness, 0 to 255.
+ @return 32-bit packed WRGB value, which can then be assigned to a
+ variable for later use or passed to the setPixelColor()
+ function. Packed WRGB format is predictable, regardless of
+ LED strand color order.
+ */
+ static uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+ return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
+ }
+ static uint32_t ColorHSV(uint16_t hue, uint8_t sat = 255, uint8_t val = 255);
+ /*!
+ @brief A gamma-correction function for 32-bit packed RGB or WRGB
+ colors. Makes color transitions appear more perceptially
+ correct.
+ @param x 32-bit packed RGB or WRGB color.
+ @return Gamma-adjusted packed color, can then be passed in one of the
+ setPixelColor() functions. Like gamma8(), this uses a fixed
+ gamma correction exponent of 2.6, which seems reasonably okay
+ for average NeoPixels in average tasks. If you need finer
+ control you'll need to provide your own gamma-correction
+ function instead.
+ */
+ static uint32_t gamma32(uint32_t x);
+
+ #if (!defined(MILLIS_USE_TIMERNONE) && !defined(MILLIS_USE_TIMERRTC) && !defined(MILLIS_USE_TIMERRTC_XTAL) && !defined(MILLIS_USE_TIMERRTC_XOSC))
+ inline bool canShow(void) { return (micros() - endTime) >= (uint32_t) latchTime; }
+ #else
+ inline bool canShow(void) {return 1;} // we don't have micros here;
+ #endif
+
+
+ protected:
+
+ uint16_t
+ numLEDs, // Number of RGB LEDs in strip
+ numBytes, // Size of 'pixels' buffer below (3 or 4 bytes/pixel)
+ latchTime; // Latch waiting period in us varies from 6 (contrary
+ // to datasheet) for original 2812's, all the way to 250 us.
+ // 50us is what the originals claim. Clones copied that, and some made it even longer.
+ int8_t
+ pin; // Output pin number (-1 if not yet set)
+ uint8_t
+ brightness,
+ *pixels, // Holds LED color values (3 or 4 bytes each)
+ rOffset, // Index of red byte within each 3- or 4-byte pixel
+ gOffset, // Index of green byte
+ bOffset, // Index of blue byte
+ wOffset; // Index of white byte (same as rOffset if no white)
+ uint32_t
+ endTime; // Latch timing reference
+ volatile uint8_t
+ *port; // Output PORT register
+ uint8_t
+ pinMask; // Output PORT bitmask
+
+};
+
+#endif // TINYNEOPIXEL_H
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/Arduino.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/Arduino.h
new file mode 100644
index 0000000..b38692c
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/Arduino.h
@@ -0,0 +1,1171 @@
+/* Arduino.h - Main include file for the Arduino SDK
+ * Copyright (c) 2005-2013 Arduino Team. All right reserved.
+ * And presumably from then until 2018 when this was forked
+ * for megaTinyCore. Copyright 2018-2022 Spence Konde
+ * Part of megaTinyCore, which adds Arduino support for the
+ * ATtiny 0/1/2-series microcontrollers from Microchip.
+ * megaTinyCore is free software (LGPL 2.1)
+ * See LICENSE.txt for full legal boilerplate if you must */
+
+/*************************************************************
+ * This file contains the stuff I think people are most likely
+ * to need to refer to. The minutia has all been pushed into
+ * core_devices.h if it's independent of pins_arduino.h or into
+ * pinswap.h if it relates to PORTMUX, which is a great volume
+ * of stuff nobody should have to read.
+ *
+ * That means functions and macros that may be used by user code
+ * (except for some part info macros, which are described in
+ * Ref_Defines.md in the documentation.
+ * I also try to put detailed comments in where appropriate.
+ *************************************************************/
+
+#ifndef Arduino_h
+#define Arduino_h
+#include "dirty_tricks.h"
+#include "api/ArduinoAPI.h"
+#include "UART_constants.h"
+
+#define CLOCK_TUNE_START (USER_SIGNATURES_SIZE - 12)
+
+#include "core_devices.h"
+/* Gives names to all the timer pins - relies on core_devices.h being included first.*/
+/* These names look like:
+ * PIN_TCD0_WOC_DEFAULT
+ * PIN_TCA0_WO5_ALT3
+ * and so on.
+ * They are #defines. Pins that don't exist are #defined as NOT_A_PIN.
+ * TCA and TCD only currently */
+#include
+#include
+
+#ifdef __cplusplus
+ extern "C"{
+#endif
+
+/* we call badArg() when we know at compile time that one or more arguments passed to
+ * the function is nonsensical or doomed to generate useless output. For example,
+ * analogWrite() on a constant pin that will never support PWM, or digitalWrite() on
+ * a pin number that is neither a pin nor NOT_A_PIN (which silently does nothing for
+ * compatibility).
+ *
+ * badCall() on the other hand is called if we know that regardless of what arguments
+ * are passed, that function is nonsensical with current settings, for example, millis()
+ * when millis timekeeping has been disabled.
+ * Closely related in check_constant_pin, which calls badArg to stop compilation if
+ * the pin number it was passed isn't a foldably constant value known at compile time,
+ * which is used by the fast digital I/O functions and other things that require than
+ * you pass them a *constant* pin.
+ */
+
+#if !defined(LTODISABLED)
+ void badArg(const char*) __attribute__((error("")));
+ void badCall(const char*) __attribute__((error("")));
+ // The fast digital I/O functions only work when the pin is known at compile time.
+ inline __attribute__((always_inline)) void check_constant_pin(pin_size_t pin)
+ {
+ if(!__builtin_constant_p(pin))
+ badArg("Fast digital pin must be a constant");
+ }
+#else
+ void badArg(const char*);
+ void badCall(const char*);
+ void check_constant_pin(pin_size_t pin);
+ #if defined(ARDUINO_MAIN) // We need to make sure these substitutes for the badArg and badCall functions are generated once and only once.
+ // They must not attempt to actually detect any error if LTO is disabled
+ void badArg(__attribute__((unused))const char* c) {
+ return;
+ }
+ void badCall(__attribute__((unused))const char* c) {
+ return;
+ }
+ void check_constant_pin(__attribute__((unused))pin_size_t pin) {
+ return;
+ }
+ #endif // Intentionally outside of the above #if so that your console gets fucking spammed with this warning.
+ // The linker errors you turned off LTO to better understand will still be at the bottom.
+ #warning "LTO is disabled. digitalWriteFast(), digitalReadFast(), pinModeFast() and openDrainFast() are unavailable, delayMicroseconds() for short delays and delay() with millis timing disabled is less accuratetest. Unsupported forms of 'new' compile without errors (but always return a NULL pointer). Additionally, functions which normally generate a compile error when passed a value that is known to be invalid at compile time will not do so. The same is true of functions which are not valid with the currently selected tools submenu options."
+ #warning "This mode is ONLY for debugging LINK-TIME ERRORS that are reported by the linker as being located at .text+0, and you can't figure out where the bug is from other information it provides. As noted above, while this may make compilation succeed, it will only turn compile-time errors into incorrect runtime behavior, which is much harder to debug. As soon as the bug that forced this to be used is fixed, switch back to the standard platform.txt!"
+ #warning "UART implementation is forcibly downgraded, Flash.h writes are replaced with NOPs, and pin interrupts are downgraded to the old (less efficient) implementation. All uploading is disabled, and behavior of exported binaries may vary from normal behavior arbitrarily."
+#endif
+
+/* ADC-related stuff */
+/* With 2.3.0, we do the same thing as ATTinyCore and DxCore to specify
+ that something is a channel number: set the high bit 1, since it is
+ incredibly unlikely that a part with more than 127 digital pins will
+ ever be supported by this core */
+
+#define ADC_CH(ch) (0x80 | (ch))
+
+#if MEGATINYCORE_SERIES < 2
+ /* ADC constants for 0/1-series */
+ #define _ADC_ENABLE_VAL 0x10
+ #define _ADC_ENABLE_CTRL 0x20
+ #define _ADC_STANDBY_VAL 0X40
+ #define _ADC_STANDBY_CTRL 0x80
+ #define LOW_LAT_ON badArg("This option is on 2-series tiny and AVR Ex-series only")
+ #define LOW_LAT_OFF badArg("This option is on 2-series tiny and AVR Ex-series only")
+ #define ADC_LOWLAT_ON badArg("This option is on 2-series tiny and AVR Ex-series only")
+ #define ADC_LOWLAT_OFF badArg("This option is on 2-series tiny and AVR Ex-series only")
+ #define PGA_KEEP_ON badArg("This option is on 2-series tiny and AVR Ex-series only")
+ #define PGA_AUTO_OFF badArg("This option is on 2-series tiny and AVR Ex-series only")
+ #define PGA_OFF_ONCE badArg("This option is on 2-series tiny and AVR Ex-series only")
+ #define ADC_ENABLE _ADC_ENABLE_CTRL | _ADC_ENABLE_VAL
+ #define ADC_DISABLE _ADC_ENABLE_CTRL
+ #define ADC_STANDBY_ON _ADC_STANDBY_CTRL | _ADC_STANDBY_VAL
+ #define ADC_STANDBY_OFF _ADC_STANDBY_CTRL
+ #define INTERNAL0V55 (VREF_ADC0REFSEL_0V55_gc >> VREF_ADC0REFSEL_gp)
+ #define INTERNAL1V1 (VREF_ADC0REFSEL_1V1_gc >> VREF_ADC0REFSEL_gp)
+ #define INTERNAL2V5 (VREF_ADC0REFSEL_2V5_gc >> VREF_ADC0REFSEL_gp)
+ #define INTERNAL4V3 INTERNAL4V34
+ #define INTERNAL4V34 (VREF_ADC0REFSEL_4V34_gc >> VREF_ADC0REFSEL_gp)
+ #define INTERNAL1V5 (VREF_ADC0REFSEL_1V5_gc >> VREF_ADC0REFSEL_gp)
+
+ #define DEFAULT ADC_REFSEL_VDDREF_gc
+ #define INTERNAL ADC_REFSEL_INTREF_gc
+ #define VDD ADC_REFSEL_VDDREF_gc
+
+ #if (defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny1617__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__))
+ #define EXTERNAL ADC_REFSEL_VREFA_gc
+ #endif
+
+ #define ADC_TEMPERATURE ADC_CH(ADC_MUXPOS_TEMPSENSE_gc)
+ #define ADC_INTREF ADC_CH(ADC_MUXPOS_INTREF_gc)
+ #define ADC_GROUND ADC_CH(ADC_MUXPOS_GND_gc)
+ #ifdef DAC0
+ #define ADC_DAC0 ADC_CH(ADC_MUXPOS_DAC0_gc)
+ #define ADC_DACREF0 ADC_DAC0
+ #endif
+
+ #if defined(ADC1)
+ #define ADC1_CH(ch) (0xC0 | (ch))
+ // All parts with the second adc have both extra dacrefs.
+ #define ADC1_DAC0 ADC1_CH(ADC_MUXPOS_DAC0_gc)
+ #define ADC1_DACREF0 ADC1_DAC0
+ #define ADC1_DAC1 ADC1_CH(ADC_MUXPOS_TEMPSENSE_gc) // see section 30.5.7 MUXPOS register.
+ #define ADC1_DACREF1 ADC1_DAC1
+ #define ADC1_DAC2 ADC1_CH(0x1B) // see section 30.5.7 MUXPOS register.
+ #define ADC1_DACREF2 ADC1_DAC2
+ #endif
+ #define ADC_DEFAULT_SAMPLE_LENGTH 14
+ #define ADC_ACC2 0x81
+ #define ADC_ACC4 0x82
+ #define ADC_ACC8 0x83
+ #define ADC_ACC16 0x84
+ #define ADC_ACC32 0x85
+ #define ADC_ACC64 0x86
+ #define ADC_ACC2S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC4S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC8S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC16S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC32S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC64S badArg("Sign chopping is only supported on Ex-series")
+#else
+ /* ADC constants for 2-series */
+ #define VDD (0) /* ADC_REFSEL_VDD_gc */
+ #define DEFAULT VDD /* Gee, I really wish these were named differently - both names are horrendously generic and could mean lots of different things that should be distinguished. */
+ #define EXTERNAL (2) /* ADC_REFSEL_VREFA_gc */
+ #define INTERNAL1V024 (4) /* ADC_REFSEL_1024MV_gc */
+ #define INTERNAL2V048 (5) /* ADC_REFSEL_2048MV_gc */
+ #define INTERNAL2V5 (6) /* ADC_REFSEL_2500MV_gc */
+ #define INTERNAL4V096 (7) /* ADC_REFSEL_4096MV_gc */
+ #define INTERNAL4V1 INTERNAL4V096 /* Alias */
+
+ #define AC_REF_1V024 (VREF_AC0REFSEL_1V024_gc)
+ #define AC_REF_2V048 (VREF_AC0REFSEL_2V048_gc)
+ #define AC_REF_2V5 (VREF_AC0REFSEL_2V5_gc)
+ #define AC_REF_4V096 (VREF_AC0REFSEL_4V096_gc)
+ #define AC_REF_VDD (VREF_AC0REFSEL_AVDD_gc)
+ #define AC_REF_4V1 AC_REF_4V096/* Alias */
+
+ #define ADC_TEMPERATURE ADC_CH(ADC_MUXPOS_TEMPSENSE_gc)
+ #define ADC_GROUND ADC_CH(ADC_MUXPOS_GND_gc)
+ #define ADC_DACREF0 ADC_CH(ADC_MUXPOS_DACREF0_gc)
+ #define ADC_DAC0 ADC_DACREF0 /* for compatibility, since on tinyAVR 0/1-seies, the DAC0 voltage is also AC0 DACREF if used */
+ #define ADC_VDDDIV10 ADC_CH(ADC_MUXPOS_VDDDIV10_gc)
+
+ /* >= 1us - can't use clockcycles per microsecond from timers.h because
+ this needs to always round up */
+ #if !(F_CPU >= 32000000)
+ #define TIMEBASE_1US (((F_CPU + 999999UL)/1000000UL) << ADC_TIMEBASE_gp)
+ #else
+ #define TIMEBASE_1US (31 << ADC_TIMEBASE_gp)
+ #endif
+
+ #define ADC_DEFAULT_SAMPLE_LENGTH 15
+ #define ADC_ACC2 0x81
+ #define ADC_ACC4 0x82
+ #define ADC_ACC8 0x83
+ #define ADC_ACC16 0x84
+ #define ADC_ACC32 0x85
+ #define ADC_ACC64 0x86
+ #define ADC_ACC128 0x87
+ #define ADC_ACC256 0x88
+ #define ADC_ACC512 0x89
+ #define ADC_ACC1024 0x8A
+ #define ADC_ACC2S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC4S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC8S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC16S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC32S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC64S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC128S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC256S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC512S badArg("Sign chopping is only supported on Ex-series")
+ #define ADC_ACC1024S badArg("Sign chopping is only supported on Ex-series")
+
+ #define _PGA_CFG_MASK 0x03
+ #define _ADC_LOWLAT_CTRL 0x08
+ #define _ADC_LOWLAT_VAL 0x04
+ #define _ADC_ENABLE_VAL 0x10
+ #define _ADC_ENABLE_CTRL 0x20
+ #define _ADC_STANDBY_VAL 0X40
+ #define _ADC_STANDBY_CTRL 0x80
+ #define PGA_OFF_ONCE 0x01
+ #define PGA_KEEP_ON 0x02
+ #define PGA_AUTO_OFF 0x03
+ #define LOW_LAT_ON _ADC_LOWLAT_CTRL | _ADC_LOWLAT_VAL// deprecated
+ #define LOW_LAT_OFF _ADC_LOWLAT_CTRL// deprecated
+ #define ADC_LOWLAT_ON _ADC_LOWLAT_CTRL | _ADC_LOWLAT_VAL
+ #define ADC_LOWLAT_OFF _ADC_LOWLAT_CTRL
+ #define ADC_ENABLE _ADC_ENABLE_CTRL | _ADC_ENABLE_VAL
+ #define ADC_DISABLE _ADC_ENABLE_CTRL
+ #define ADC_STANDBY_ON _ADC_STANDBY_CTRL | _ADC_STANDBY_VAL
+ #define ADC_STANDBY_OFF _ADC_STANDBY_CTRL
+#endif
+
+/* Errors in analogReadEnh and analogReadDiff are large negative numbers,
+ * since it's a signed long returned, and a raw maximally accumulated
+ * differential reading could be a huge negative number. Largest negative
+ * possible is -2 147 483 648; It would be hard to tell the difference between
+ * that and -2147483647, or -2147483646 and remember which is which,
+ * so they start at -2100000000.
+ * Errors for normal analogRead are small negative numbers because
+ * analogRead should never return a negative. Neither should analogReadEnh
+ * but I decided to have only 2 sets of ADC errors, not three. */
+
+#define ADC_ERROR_BAD_PIN_OR_CHANNEL (-32001)
+#define ADC_ERROR_BUSY (-32002)
+#define ADC_ERROR_DISABLED (-32007)
+#define ADC_ENH_ERROR_BAD_PIN_OR_CHANNEL (-2100000001)
+// positive channel is not (0x80 | valid_channel) nor a digital pin number
+// referring to a pin with analog input.
+#define ADC_ENH_ERROR_BUSY (-2100000002)
+// The ADC is currently performing another conversion in the background (either
+// in free-running mode or a long-running burst conversion; taking a burst
+// accumulated reading and then calling a specified function when the result
+// was finally ready may be supported in a future version.
+#define ADC_ENH_ERROR_RES_TOO_LOW (-2100000003)
+// analogReadEnh() must not be called with a resolution lower than 8-bits.
+// you can right-shift as well as the library can, without wasting flash for everyone who doesn't need to.
+#define ADC_ENH_ERROR_RES_TOO_HIGH (-2100000004)
+// Only resonlutions that can be generated through accumulator oversample
+// + decimation are supported, maximum is 13, 15, or 17 bits. This will
+// also be returned if a larger raw accumulated result is requested.
+#define ADC_DIFF_ERROR_BAD_NEG_PIN (-2100000005)
+// Analog pin given as negative pin is not a valid negative mux pin
+#define ADC_ENH_ERROR_NOT_DIFF_ADC (-2100000006)
+// analogReadDiff() called from a part without a differential ADC;
+// Never actually returned, because we give compile error here
+#define ADC_ENH_ERROR_DISABLED (-2100000007)
+// The ADC is not currently enabled. This error is disabled currently - if analogReadEnh encounters a disabled ADC, it will enable it, take the reading, and disable it again.
+#define ADC_ERROR_INVALID_CLOCK (-32255)
+// Returned by analogClockSpeed if the value in the register is currently unknown, or if an invalid frequency is requested.
+
+
+// only returned by analogCheckError()
+#define ADC_IMPOSSIBLE_VALUE (-127)
+
+
+#if (!defined(TCB_CLKSEL2_bm))
+ // This means it's a tinyAVR 0/1-series, or a megaAVR 0-series.
+ // Their TCB_CLKSEL enums use different names for the clock settings, for reasons unclear.
+ // To align with the future, we use the Dx-series names for these.
+ #define TCB_CLKSEL_DIV2_gc TCB_CLKSEL_CLKDIV2_gc
+ #define TCB_CLKSEL_DIV1_gc TCB_CLKSEL_CLKDIV1_gc
+#endif
+
+#define VCC_5V0 2
+#define VCC_3V3 1
+#define VCC_1V8 0
+
+#define interrupts() sei()
+#define noInterrupts() cli()
+
+
+// NON-STANDARD API
+
+
+void init_ADC0(void); /* Called by init() after clock is set */
+#if defined(ADC1)
+ void init_ADC1(void); /* Never called automatically, but must be called manuaklkly in order to use the ADC1 functions. */
+#endif
+void init_clock(void);/* called by init() first */
+void init_millis(); /* called by init() last */
+void init_timers(); /* called by init() */
+void init_TCA0(); /* called by init_timers() */
+void init_TCD0(); /* called by init_timers() */
+
+// callbacks normally empty and optimized away.
+void onPreMain();
+void onBeforeInit();
+uint8_t onAfterInit();
+void initVariant();
+
+
+// Peripheral takeover
+// These will remove things controlled by
+// these timers from analogWrite()/turnOffPWM()
+// 0x40 - TCD0, 0x10 - TCA0
+void takeOverTCA0();
+void takeOverTCD0();
+
+
+
+
+/* inlining of a call to delayMicroseconds() would throw it off */
+void _delayMicroseconds(unsigned int us) __attribute__((noinline));
+
+
+/*******************************************************
+ * Extended API - Enhanced DxCore features *
+ * These are functions users might call from the *
+ * sketch, or in some cases, override. *
+ * 1. Timer + millis() control. *
+ * 2. initialization routines to override *
+ * 3. Advanced Analog functionality *
+ * 4. Advanced Digital functionality *
+ ******************************************************/
+// stop, restart and set millis intended for switching to RTC for millis timekeeping while sleeping.
+void stop_millis(); // stop the timer being used for millis, and disable the interrupt.
+void restart_millis(); // After having stopped millis either for sleep or to use timer for something else and optionally have set it to correct for passage of time, call this to restart it.
+void set_millis(uint32_t newmillis); // Sets the millisecond timer to the specified number of milliseconds. DO NOT CALL with a number lower than the current millis count if you have any timeouts ongoing.
+ // they may expire instantly.
+// Allows for user to mark a timer "do not touch" for purposes of analogWrite and the like, so you can take over a timer and reconfigure it, and not worry about digitalWrite() flipping a CMPEN bit.
+// On megaTinyCore this also prevents the situation where PWM is remapped, but then when the user is digitalWrite'ing pins that default to having PWM, it would turn off the PWM now coming from another pin
+// This is not an issue because we fully support portmux (can't spare the flash overhead on the tinies, people already complain that the core uses too much flash)
+void takeOverTCA0(); // Can be used to tell core not to use TCA0 for any API calls - user has taken it over.
+void takeOverTCA1(); // Can be used to tell core not to use TCA1 for any API calls - user has taken it over.
+void takeOverTCD0(); // Can be used to tell core not to use TCD0 for any API calls - user has taken it over.
+void resumeTCA0(); // Restores core-mediated functionality that uses TCA0 and restores default TCA0 configuration.
+void resumeTCA1(); // Restores core-mediated functionality that uses TCA1 and restores default TCA1 configuration.
+// bool digitalPinHasPWM(uint8_t p); // Macro. Returns true if the pin can currently output PWM using analogWrite(), regardless of which timer is used and considering current PORTMUX setting
+uint8_t digitalPinToTimerNow(uint8_t p); // Returns the timer that is associated with the pin now (considering PORTMUX)
+
+// These are in here so that - should it be necessary - library functions or user code could override these.
+void init_clock() __attribute__((weak)); // this is called first, to initialize the system clock.
+void init_ADC0() __attribute__((weak)); // this is called to initialize ADC0
+// init_DAC0() // no _init_DAC0() - all that the core does is call DACReference().
+void init_TCA0() __attribute__((weak)); // called by init_timers() - without this, pins that give PWM from TCA0 will not function.
+void init_TCA1() __attribute__((weak)); // called by init_timers() - without this, pins that give PWM from TCA1 will not function, nor will the TCBs unless the clock source is changed.
+void init_TCBs() __attribute__((weak)); // called by init_timers()
+void init_TCD0() __attribute__((weak)); // called by init_timers()
+void init_millis() __attribute__((weak)); // called by init() after everything else and just before enabling interrupts and calling setup() - sets up and enables millis timekeeping.
+
+void onClockFailure() __attribute__((weak)); // called by the clock failure detection ISR. Default action is a blink code with 4 blinks.
+void onClockTimeout() __attribute__((weak)); // called if we try to switch to external clock, but it doesn't work. Default action is a blink code with 3 blinks.
+
+#ifndef CORE_ATTACH_OLD
+// The old attachInterrupt did not require any calls to be made to enable a port.
+// It would just grab every port, and take over every port's pin interrupt ISR, so nobody could define one themselves.
+// which wouldn't be so bad... except that attachInterrupt interrupts are slow as hell
+ void attachPortAEnable();
+ void attachPortBEnable();
+ void attachPortCEnable();
+ void attachPortDEnable();
+ void attachPortEEnable();
+ void attachPortFEnable();
+ void attachPortGEnable();
+#endif
+
+// ANALOG EXTENDED FUNCTIONS
+// Covered in documentation.
+int32_t analogReadEnh( uint8_t pin, /* no neg */ uint8_t res, uint8_t gain);
+int32_t analogReadDiff( uint8_t pos, uint8_t neg, uint8_t res, uint8_t gain);
+int16_t analogClockSpeed( int16_t frequency, uint8_t options);
+bool analogSampleDuration( uint8_t dur);
+void ADCPowerOptions( uint8_t options); // fewer options on 0/1=seroes
+#if defined(ADC1)
+ int32_t analogReadEnh1( uint8_t pin, /* no neg */ uint8_t res, uint8_t gain);
+ int32_t analogReadDiff1( uint8_t pos, uint8_t neg, uint8_t res, uint8_t gain); /* This just errors because these parts don't have a differential ADC */
+ int16_t analogClockSpeed1( int16_t frequency, uint8_t options);
+ bool analogSampleDuration1(uint8_t dur);
+ int16_t analogRead1( uint8_t pin);
+ void analogReference1( uint8_t mode);
+ void ADCPowerOptions1( uint8_t options); // Fewer optiopms
+#endif
+void DACReference( uint8_t mode);
+
+int32_t analogReadEnh(uint8_t pin, uint8_t res, uint8_t gain);
+int32_t analogReadDiff(uint8_t pos, uint8_t neg, uint8_t res, uint8_t gain);
+int16_t analogClockSpeed(int16_t frequency, uint8_t options);
+bool analogReadResolution(uint8_t res);
+bool analogSampleDuration(uint8_t dur);
+void DACReference(uint8_t mode);
+
+uint8_t getAnalogReference();
+uint8_t getDACReference();
+int8_t getAnalogReadResolution();
+
+//
+// DIGITAL I/O EXTENDED FUNCTIONS
+// Covered in documentation.
+void openDrain(uint8_t pinNumber, uint8_t val);
+#if !defined(LTODISABLED)
+ int8_t digitalReadFast(uint8_t pinNumber );
+ void digitalWriteFast(uint8_t pinNumber, uint8_t val);
+ void pinModeFast(uint8_t pinNumber, uint8_t mode);
+ void openDrainFast(uint8_t pinNumber, uint8_t val);
+#elif defined(FAKE_FAST_IO)
+ // Should be enabled if, and only if, you are debugging something that you can't debug with LTO enabled, AND
+ // your code makes use of the fast functions. Note that this drastically alters behavior of code that calls them, taking, in some cases, two orders of magnitude longer
+ #warning "FAKE_FAST_IO code should **never** be expected to work correctly running on hardware. It is just here to provide a way to get past missing definition errors when you are forced to disable LTO for debugging."
+ #define digitalRead(uint8_t pinNumber );
+ #define digitalWrite(uint8_t pinNumber, uint8_t val);
+ #define pinMode(uint8_t pinNumber, uint8_t mode);
+ #define openDrain(uint8_t pinNumber, uint8_t val);
+ #endif
+void turnOffPWM(uint8_t pinNumber );
+
+// Not a function, still important
+#define digitalPinHasPWMNow(p) (digitalPinToTimerNow(p) != NOT_ON_TIMER)
+
+uint8_t PWMoutputTopin(uint8_t timer, uint8_t channel);
+// Realized we're not going to be able to make generic code without this.
+
+/* Even when millis is off, we should still have access to the clock cycle counting macros.
+ * That's the only way we can get time estimates there!
+ * 3/19/23: These are supposed to be macros, not inline functions
+ * Users have reported problems resulting from their being functions, even inline ones
+ */
+#define clockCyclesPerMicrosecond() ((uint16_t)(F_CPU / 1000000UL))
+#define clockCyclesToMicroseconds(__a__) ((uint32_t)((__a__) / clockCyclesPerMicrosecond()))
+#define microsecondsToClockCycles(__a__) ((uint32_t)((__a__) * clockCyclesPerMicrosecond()))
+
+// Currently DxCore has no cases where the millis timer isn't derived from system clock, but that will change
+/* This becomes important when we support other timers for timekeeping. The Type D timer can be faster, requiring:
+ * These talk about the timebase from which millis is derived, not the actual timer counting frequency.
+ * That is, it's used to calculqte the values that are we multipliy by the prescaler to get the timekeeping stuff.
+ * These can be different from the above only when the millis timer isn't running from CLK_PER.
+ For example, if we run it from a TCD clocked from internal HF but we are running on a crystal.
+ That's a strange way to use the TCD, but
+ * megaTinyCore has these, and we will have wsomething analogous.
+
+uint16_t millisClockCyclesPerMicrosecond();
+uint32_t millisClockCyclesToMicroseconds(uint32_t cycles);
+uint32_t microsecondsToMillisClockCycles(uint32_t microseconds);
+
+ * the time and sleep library will require some things like this.
+ */
+
+
+// Copies of above for internal use, and for the really exotic use cases that want this instead of system clocks (basically never in user-land)
+
+/* Even when millis is off, we should still have access to the clock cycle counting macros.
+ * That's the only way we can get time estimates there!
+ * 3/19/23: These are supposed to be macros, not inline functions
+ * Users have reported problems resulting from their being functions, even inline ones
+ */
+#ifdef MILLIS_USE_TIMERD0
+ #if (F_CPU == 20000000UL || F_CPU == 10000000UL ||F_CPU == 5000000UL)
+ #define millisClockCyclesPerMicrosecond() ((uint16_t)(20)) // this always runs off the 20MHz oscillator
+ #else
+ #define millisClockCyclesPerMicrosecond() ((uint16_t)(16))
+ #endif
+#else
+ #define millisClockCyclesPerMicrosecond() ((uint16_t)((F_CPU / 1000000UL)))
+#endif
+#define millisClockCyclesToMicroseconds(__a__) ((uint32_t)(__a__ / millisClockCyclesPerMicrosecond()))
+#define microsecondsToMillisClockCycles(__a__) ((uint32_t)(__a__ * millisClockCyclesPerMicrosecond()))
+
+/* Timers and Timer-like-things
+ * These are used for two things: Identifying the timer on a pin in
+ * digitalPinToTimer(), and for the MILLIS_TIMER define that users can test to
+ * verify which timer is being used for millis.
+ *
+ * Prior to 1.3.x TCAs were all 0x1_, TCBs 0x2_. But in order to make the
+ * take-over tracking work efficiently I needed a dedicated bit for each TCA.
+ * so that we can just do (__PeripheralControl | TIMERA0) to test if user has
+ * taken over the timer. Hence, all the "big" timers (those which have a
+ * takeOverTCxn() function and which PORTMUX moves en masse instead of one at
+ * a time) have their own bit within these macros.
+ * Note also that the digital_pin_to_timer table doesn't list these anymore.\
+ * There are two functions within the core that need to know this:
+ * AnalogWrite, and turnOffPWM. These each carry their own implementation of
+ * logic to identify the timer and channel; the only other cases in which these
+ * pins need to be identified are within user code, where the pin mapping can
+ * be chosen freely (subject to user code needing access to other pins), so
+ * it does not present the complexity of the core library which must work with
+ * the pins in ANY of 7, 2, or 5 mappings (for TCA0, TCA1 and TCD0 respectively)
+ *
+ * Prior to this change, only the arbitrarily chosen core default timer pin-
+ * mapping was supported, so this was a dramatic leap forward in capabilitt.
+ *
+ * The DAC is listed here because analogWrite() uses it almost exactly like
+ * a PWM timer.
+ * RTC can be used as a millis timekeeping source (well, not currently on
+ * DxCore, but it can on megaTinyCore, and might one day be possible on DxCore
+ * though I'm not sure I want to implement it that way).
+ *****************************************************************************/
+/* More may be implemented here in the future */
+
+#define NOT_ON_TIMER (0x00)
+#define TIMERA0 (0x10) // A "simple" type A timer mapping doesn't get constants for the WO channels.
+#define TIMERA1 (0x08) // Formerly 0x11 - giving it a dedicated bit makes the takeover tracking easy and efficient instead of being a morass of tests and bitmath.
+#define TIMERB0 (0x20) // TCB0
+#define TIMERB1 (0x21) // TCB1
+#define TIMERB2 (0x22) // TCB2
+#define TIMERB3 (0x23) // TCB3
+#define TIMERB4 (0x24) // TCB4
+#define TIMERD0 (0x40) // If any of these bits match it's potentially on TCD0
+#define DACOUT (0x80) /// If the high bit is set, it;s either the DAC oone of the new timers.
+#define TIMERE0 (0x90) // Full dettails not known, the below constants are guesses
+#define TIMERF0 (0xC0) // as abpve
+#define TIMERE1 (0xA0)
+#define TIMERF1 (0xD0)
+/* The above are all used in the digitalPinToTimer() macro and appear in the timer table, in addition to being how we identify millis timer.
+ * For the millis timer, there's nothing weird here.
+ * But the timer table constants contain more information than that for these. When user code interprets the timer table entries it is critical to do it right:
+ * 1. If 0x40 is set, TCD0 can output here. bits 4 and 5 contain information on what channel, and bits 0-2 specify what the PORTMUX must be set to.
+ * 2. If 0x20 us set, there is a TCB can output PWM there.
+ * 2a. If 0x20 is set, check 0x10 - if that's set, it's the alt pin mapping. This is currently not returned by the table, and I assess it to be unlikely to be of use
+ * 4. If 0x10 is set, it's a TCA0 pin. This is never used in the timer table, but digitalPinToTimerNow() can return it.
+ * 5. If 0x08 is set, it's a TCA1 pin. This is never used in the timer table, but digitalPinToTimerNow() can return it.
+ * Ergo, use bitwise ands
+ */
+
+#define TIMERRTC (0x90) // RTC with internal osc
+#define TIMERRTC_XTAL (0x91) // RTC with crystal
+#define TIMERRTC_CLK (0x92) // RTC with ext clock
+
+/* Not used in table */
+#define TIMERA0_MUX0 (0x10) // Mapping0 (PORTA 0-5)
+#define TIMERA0_MUX1 (0x11) // Mapping1 (PORTB 0-5)
+#define TIMERA0_MUX2 (0x12) // Mapping2 (PORTC 0-5)
+#define TIMERA0_MUX3 (0x13) // Mapping3 (PORTD 0-5)
+#define TIMERA0_MUX4 (0x14) // Mapping4 (PORTE 0-5)
+#define TIMERA0_MUX5 (0x15) // Mapping5 (PORTF 0-5)
+#define TIMERA0_MUX6 (0x16) // Mapping6 (PORTG 0-5)
+#define TIMERA0_MUX7 (0x17) // Mapping7 (PORTA 0-5)
+#define TIMERA1_MUX0 (0x08) // Mapping0 (PORTB 0-5) - 48+ pin only.
+#define TIMERA1_MUX1 (0x09) // Mapping1 (PORTC 4-6) - only three channels available. 48+ pin only.
+#define TIMERA1_MUX2 (0x0A) // Mapping2 (PORTE 4-6) - only three channels available. DB-series only due to errata. 64-pin parts only
+#define TIMERA1_MUX3 (0x0B) // Mapping3 (PORTG 0-5) - DB-series only due to errata. 64-pin parts only.
+#define TIMERA1_MUX4 (0x0C) // Mapping4 (PORTA 4-6) - only three channels available. New on EA-series.
+#define TIMERA1_MUX5 (0x0D) // Mapping5 (PORTD 4-6) - only three channels available. New on EA-series.
+
+/* Not used in table or at all, yet */
+#define TIMERB0_ALT (0x30) // TCB0 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB1_ALT (0x31) // TCB1 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB2_ALT (0x32) // TCB2 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB3_ALT (0x33) // TCB3 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB4_ALT (0x34) // TCB4 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB0_ALT (0x30) // TCB0 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB1_ALT (0x31) // TCB1 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB2_ALT (0x32) // TCB2 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB3_ALT (0x33) // TCB3 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+#define TIMERB4_ALT (0x34) // TCB4 with alternate pin mapping - DANGER: NOT YET USED BY CORE.
+
+
+// 0b01MC 0mmm - the 3 lowest bits refer to the PORTMUX.
+// bit C specifies whether it's channel A (0) or B (1). If M is 1 it is WOC outputting chan A or WOB outputting D.
+// WOD outputting A or WOC outputting B is not supported by the core. WOB outputting A or WOA outputting B is not supported by the hardware.
+// Hence, PORTMUX.TCDROUTEA == (timer table entry) & (0x07)
+// and any table entry > 0x40 but less than 0x80 could be a TCD
+/*
+#define TIMERD0_0WOA (0x40) // PORTA
+#define TIMERD0_0WOB (0x50)
+#define TIMERD0_0WOC (0x60)
+#define TIMERD0_0WOD (0x70)
+#define TIMERD0_1WOA (0x41) // PORTB
+#define TIMERD0_1WOB (0x51)
+#define TIMERD0_1WOC (0x61)
+#define TIMERD0_1WOD (0x71)
+#define TIMERD0_2WOA (0x42) // PORTF
+#define TIMERD0_2WOB (0x52)
+#define TIMERD0_2WOC (0x62)
+#define TIMERD0_2WOD (0x72)
+#define TIMERD0_3WOA (0x43) // PORTG
+#define TIMERD0_3WOB (0x53)
+#define TIMERD0_3WOC (0x63)
+#define TIMERD0_3WOD (0x73)
+#define TIMERD0_4WOA (0x44) // this is PA4, duplicates mux 0.
+#define TIMERD0_4WOB (0x54) // this is PA5, duplicates mux 0.
+#define TIMERD0_4WOC (0x64) // second half is PORTD
+#define TIMERD0_4WOD (0x74)
+
+// For future use
+// If timer D ever gets all 8 options, we'd need these
+
+#define TIMERD0_5WOA (0x45) // hypothetical TCD0 WOA ALT5
+#define TIMERD0_5WOB (0x55) // hypothetical TCD0 WOB ALT5
+#define TIMERD0_5WOC (0x65) // hypothetical TCD0 WOC ALT5
+#define TIMERD0_5WOD (0x75) // hypothetical TCD0 WOD ALT5
+#define TIMERD0_6WOA (0x46) // hypothetical TCD0 WOA ALT6
+#define TIMERD0_6WOB (0x56) // hypothetical TCD0 WOB ALT6
+#define TIMERD0_6WOC (0x66) // hypothetical TCD0 WOC ALT6
+#define TIMERD0_6WOD (0x76) // hypothetical TCD0 WOD ALT6
+#define TIMERD0_7WOA (0x47) // hypothetical TCD0 WOA ALT7
+#define TIMERD0_7WOB (0x57) // hypothetical TCD0 WOB ALT7
+#define TIMERD0_7WOC (0x67) // hypothetical TCD0 WOC ALT7
+#define TIMERD0_7WOD (0x77) // hypothetical TCD0 WOD ALT7
+
+// Uhoh, EB has a new kind of timer, a TCE which looks a lot like a TCA-PWM-Powerhouse timer, only better.
+// We predict that PORTMUX.TCEROUTEA will not give individual pin control, but that it will be much like TCA.
+// and we will thus be able to quickly detect if the port it's poimted at is ours.
+
+#define TIMERE0_MUX0 (0x90) // HypotheticalTCE/WEX mux
+#define TIMERE0_MUX1 (0x91) // HypotheticalTCE/WEX mux
+#define TIMERE0_MUX2 (0x92) // HypotheticalTCE/WEX mux
+#define TIMERE0_MUX3 (0x93) // HypotheticalTCE/WEX mux
+#define TIMERE0_MUX4 (0x94) // HypotheticalTCE/WEX mux
+#define TIMERE0_MUX5 (0x95) // HypotheticalTCE/WEX mux
+#define TIMERE0_MUX6 (0x96) // HypotheticalTCE/WEX mux
+#define TIMERE0_MUX7 (0x97) // HypotheticalTCE/WEX mux
+
+// They might make a chip with 2 of them!
+#define TIMERE1_MUX0 (0xA0) // HypotheticalTCE/WEX mux
+#define TIMERE1_MUX1 (0xA1) // HypotheticalTCE/WEX mux
+#define TIMERE1_MUX2 (0xA2) // HypotheticalTCE/WEX mux
+#define TIMERE1_MUX3 (0xA3) // HypotheticalTCE/WEX mux
+#define TIMERE1_MUX4 (0xA4) // HypotheticalTCE/WEX mux
+#define TIMERE1_MUX5 (0xA5) // HypotheticalTCE/WEX mux
+#define TIMERE1_MUX6 (0xA6) // HypotheticalTCE/WEX mux
+#define TIMERE1_MUX7 (0xA7) // HypotheticalTCE/WEX mux
+
+
+// They might make a chip with 3 of them!
+#define TIMERE2_MUX0 (0xB0) // HypotheticalTCE/WEX mux
+#define TIMERE2_MUX1 (0xB1) // HypotheticalTCE/WEX mux
+#define TIMERE2_MUX2 (0xB2) // HypotheticalTCE/WEX mux
+#define TIMERE2_MUX3 (0xB3) // HypotheticalTCE/WEX mux
+#define TIMERE2_MUX4 (0xB4) // HypotheticalTCE/WEX mux
+#define TIMERE2_MUX5 (0xB5) // HypotheticalTCE/WEX mux
+#define TIMERE2_MUX6 (0xB6) // HypotheticalTCE/WEX mux
+#define TIMERE2_MUX7 (0xB7) // HypotheticalTCE/WEX mux
+
+// Plus this wacky TCF thing.
+// Premering on low pincount parts, it's hard to say what the full lineup of pin options will be likek
+// I predict... 3 bits for the mux position, and that a larger chip might have 2....
+
+#define TIMERF0_MUX0A (0xC0) // Hypothetical TCF MUX
+#define TIMERF0_MUX0B (0xC8) // Hypothetical TCF MUX
+#define TIMERF0_MUX1A (0xC1) // Hypothetical TCF MUX
+#define TIMERF0_MUX1B (0xC9) // Hypothetical TCF MUX
+#define TIMERF0_MUX2A (0xC2) // Hypothetical TCF MUX
+#define TIMERF0_MUX2B (0xCA) // Hypothetical TCF MUX
+#define TIMERF0_MUX3A (0xC3) // Hypothetical TCF MUX
+#define TIMERF0_MUX3B (0xCB) // Hypothetical TCF MUX
+#define TIMERF0_MUX4A (0xC4) // Hypothetical TCF MUX
+#define TIMERF0_MUX4B (0xCC) // Hypothetical TCF MUX
+#define TIMERF0_MUX5A (0xC5) // Hypothetical TCF MUX
+#define TIMERF0_MUX5B (0xCD) // Hypothetical TCF MUX
+#define TIMERF0_MUX6A (0xC6) // Hypothetical TCF MUX
+#define TIMERF0_MUX6B (0xCE) // Hypothetical TCF MUX
+#define TIMERF0_MUX7A (0xC7) // Hypothetical TCF MUX
+#define TIMERF0_MUX7B (0xCF) // Hypothetical TCF MUX
+
+// What if a chip has two of them? No problem!
+#define TIMERF1_MUX0A (0xD0) // Hypothetical TCF MUX
+#define TIMERF1_MUX0B (0xD8) // Hypothetical TCF MUX
+#define TIMERF1_MUX1A (0xD1) // Hypothetical TCF MUX
+#define TIMERF1_MUX1B (0xD9) // Hypothetical TCF MUX
+#define TIMERF1_MUX2A (0xD2) // Hypothetical TCF MUX
+#define TIMERF1_MUX2B (0xDA) // Hypothetical TCF MUX
+#define TIMERF1_MUX3A (0xD3) // Hypothetical TCF MUX
+#define TIMERF1_MUX3B (0xDB) // Hypothetical TCF MUX
+#define TIMERF1_MUX4A (0xD4) // Hypothetical TCF MUX
+#define TIMERF1_MUX4B (0xDC) // Hypothetical TCF MUX
+#define TIMERF1_MUX5A (0xD5) // Hypothetical TCF MUX
+#define TIMERF1_MUX5B (0xDD) // Hypothetical TCF MUX
+#define TIMERF1_MUX6A (0xD6) // Hypothetical TCF MUX
+#define TIMERF1_MUX6B (0xDE) // Hypothetical TCF MUX
+#define TIMERF1_MUX7A (0xD7) // Hypothetical TCF MUX
+#define TIMERF1_MUX7B (0xDF) // Hypothetical TCF MUX
+*/
+
+
+__attribute__ ((noinline)) void _delayMicroseconds(unsigned int us);
+
+
+// Get the bit location within the hardware port of the given virtual pin.
+// This comes from the arrays in the pins_arduino.c file for the active
+// board configuration.
+// These perform slightly better as macros compared to inline functions
+
+extern const uint8_t digital_pin_to_port[];
+extern const uint8_t digital_pin_to_bit_mask[];
+extern const uint8_t digital_pin_to_bit_position[];
+extern const uint8_t digital_pin_to_timer[];
+
+
+
+/*
+Supplied by Variant file:
+#define digitalPinToAnalogInput(p) // Given digital pin (p), returns the analog channel number, or NOT_A_PIN if the pin does not suipport analog input.
+#define analogChannelToDigitalPin(p) // Inverse of above. Given analog chanbel number (p) in raw form not ADC_CH() form, returns the digital pin number corresponding to it.
+#define analogInputToDigitalPin(p) // Similar to previous. Given analog input number (p) with the high bit set, returns the digital pin number corresponding to it)
+#define digitalOrAnalogPinToDigital(p) // Given either an analog input number (with high bit set) or a digital pin number (without it set), returns the digital pin number.
+Yes, these are poorky named and do not use analog input, analog pin, and analog channel consistently. Unfortunately the names of some of these were set in stone by virtue of their being preexisting macros used in code in the wild.
+See Ref_Analog.md for more information of the representations of "analog pins". I blame Arduino for the original sin of "analog pins" as a concept in the first place.
+*/
+
+#include "pins_arduino.h"
+#define digitalPinToPort(pin) (((pin) < NUM_TOTAL_PINS ) ? digital_pin_to_port[pin] : NOT_A_PIN)
+#define digitalPinToBitPosition(pin) (((pin) < NUM_TOTAL_PINS ) ? digital_pin_to_bit_position[pin] : NOT_A_PIN)
+#define digitalPinToBitMask(pin) (((pin) < NUM_TOTAL_PINS ) ? digital_pin_to_bit_mask[pin] : NOT_A_PIN)
+#define analogPinToBitPosition(pin) ((digitalPinToAnalogInput(pin) != NOT_A_PIN) ? digital_pin_to_bit_position[pin] : NOT_A_PIN)
+#define analogPinToBitMask(pin) ((digitalPinToAnalogInput(pin) != NOT_A_PIN) ? digital_pin_to_bit_mask[pin] : NOT_A_PIN)
+#define digitalPinToTimer(pin) (((pin) < NUM_TOTAL_PINS ) ? digital_pin_to_timer[pin] : NOT_ON_TIMER)
+#define portToPortStruct(port) (((port) < NUM_TOTAL_PORTS) ? (((PORT_t *) &PORTA) + (port)) : NULL)
+#define digitalPinToPortStruct(pin) (((pin) < NUM_TOTAL_PINS ) ? (((PORT_t *) &PORTA) + digitalPinToPort( pin)) : NULL)
+#define getPINnCTRLregister(port, bit_pos) ((((port) != NULL) && (bit_pos < 8)) ? (((volatile uint8_t *) &(port->PIN0CTRL)) + bit_pos) : NULL)
+#define digitalPinToInterrupt(P) (P)
+// Remember to test for NOT_A_PORT before using thiese.
+#define portOutputRegister(P) ((volatile uint8_t *)(&portToPortStruct(P)->OUT))
+#define portInputRegister(P) ((volatile uint8_t *)(&portToPortStruct(P)->IN ))
+#define portModeRegister(P) ((volatile uint8_t *)(&portToPortStruct(P)->DIR))
+#if defined(PORTA_EVGENCTRL) //Ex-series only - this all may belong in the Event library anyway, but since the conditional is never met, this code is never used.
+ #define portEventRegister(p) ((volatile uint8_t *)(&portToPortStruct(P)->EVGENCTRL))
+ uint8_t _setRTCEventChan(uint8_t val, uint8_t chan);
+ uint8_t _setEventPin(uint8_t pin, uint8_t number); // preliminary thought - pass a pin number, it looks up port, and from there the event control register and sets it.
+ //Number being 0 or 1 or 255 to pick the lowest numbered one not set. Returns event channel number TBD if that should be the EVSYS values or 0 or 1. If "Pick unused ome" is requested but both already assigned, will return 255
+ uint8_t _getPortEventConfig(uint8_t port); // just shorthand for looking up the port and returning it's EVGENCTRL value
+ uint8_t _setRTCEventChan(uint8_t vail, uint8_t chan); // number is 0, 1 or 255 like above, div is log(2) of the divisor (ie, for 2^5, his would be 5).
+ uint8_t _getRTCEventConfig(); //simply returns the RTC channel configuration. Will likely return 255 if called on non Ex
+ uint8_t _RTCPrescaleToVal(uint16_t prescale)
+#endif
+ /* The Variant file must do one of the following */
+/* 1. Use the same pin order as this core's default pin mapping (recommended)
+ * 2. Number each pin (port * 8) + bit_position, and define HYPERRATIONAL_PIN_NUMBERS (also recommended)
+ * 3. Number each pin (port * 8) + bit_position + 1, with PA0 wrapping around to the highest number and define RATIONALPLUS_PIN_NUMBERS
+ * 4. Define SPECIAL_PIN_NUMBERS, and use any pin numbering. (recommended if you must use a layout that departs significantly from the above)
+ */
+
+#if defined(HYPERRATIONAL_PIN_NUMBERS) /* Pins numbered starting from PA0, and PB6 and PB7 (14, 15) skipped on 20-pin */
+ #define _digitalPinToCanon(pin) (((pin) < NUM_TOTAL_PINS) ? (pin) : NOT_A_PIN)
+#elif defined(RATIONALPLUS_PIN_NUMBERS) /* Pins numbered starting from PA1 = 0, so pin + 1 = canonical pin number */
+ #define _digitalPinToCanon(pin) (((pin) < NUM_TOTAL_PINS) ? (((pin) == NUM_TOTAL_PINS - 1) ? 0 :((pin) + 1 )) : NOT_A_PIN)
+#elif defined(SPECIAL_PIN_NUMBERS)
+ #define _digitalPinToCanon(pin) (((pin) < NUM_TOTAL_PINS) ? ((digital_pin_to_port[pin] << 3) + digital_pin_to_bit_position[pin] ) : NOT_A_PIN)
+#else
+ #if _AVR_PINCOUNT == 8
+ #define _digitalPinToCanon(pin) (((pin) < NUM_TOTAL_PINS) ? digital_pin_to_bit_position[pin] : NOT_A_PIN)
+ #elif _AVR_PINCOUNT == 14
+ #define _digitalPinToCanon(pin) (((pin) < NUM_TOTAL_PINS) ? (((pin) < PIN_PA1) ? ((((pin) > PIN_PA7 && (pin) < PIN_PC0) ? 15 - (pin) : (pin) + 4)) : (((pin) == 11) ? 0 : (pin) - 7)) : NOT_A_PIN)
+ #elif _AVR_PINCOUNT == 20
+ #define _digitalPinToCanon(pin) (((pin) < NUM_TOTAL_PINS) ? (((pin) < PIN_PA1) ? ((((pin) > PIN_PA7 && (pin) < PIN_PC0) ? 17 - (pin) : (pin) + 4)) : (((pin) == 17) ? 0 : (pin) - 13)) : NOT_A_PIN)
+ #else /* 24 pins */
+ #define _digitalPinToCanon(pin) (((pin) < NUM_TOTAL_PINS) ? (((pin) < PIN_PA1) ? ((((pin) > PIN_PA7 && (pin) < PIN_PC0) ? 19 - (pin) : (pin) + 4)) : (((pin) == 21) ? 0 : (pin) - 17)) : NOT_A_PIN)
+ #endif
+#endif
+#ifdef __cplusplus
+} // extern "C"
+#endif
+/********************************************************************************
+ * CORE AND HARDWARE FEATURE SUPPORT *
+ * CORE_HAS_ERRORFUNS is defined and 1 if there is a badArg() and badCall() function supplied by the core
+ * CORE_HAS_FASTIO is 1 when digitalReadFast and digitalWriteFast are supplied, and 2 when openDrainFast and pinModeFast are as well.
+ * CORE_HAS_OPENDRAIN
+ * CORE_HAS_PINCONFIG is 1 if pinConfig is supplied. The allows full configuration of any pin. It is 2 if it accepts commas instead of bitwise or between configuration parameters (NYI)
+ * CORE_HAS_FASTPINMODE is 1 if pinModeFast is supplied
+ * CORE_HAS_ANALOG_ENH is 0 if no analogReadEnh is supplied, 1 if it is, and 2 if it is supplied and both core and hardware support a PGA.
+ * CORE_HAS_ANALOG_DIFF is 0 if no analogReadDiff is supplied, 1 if it's DX-like (Vin < VREF), and 2 if it's a proper
+ * differential ADC, supported in both hardware and software. The value -1 is also valid and indicates it's a classic AVR with a * differential ADC, see the documentation for the core.
+ * CORE_HAS_TIMER_TAKEOVER is 1 if takeOverTCxn functions are provided to tell the core not to automatically use all
+ * type A and D timers.
+ * CORE_HAS_TIMER_RESUME is 1 if resumeTCAn functions are provided to hand control back to the core and reinitialize them.
+ * CORE_DETECTS_TCD_PORTMUX is 1 if the TCD portmux works correctly on the hardware and is used by the core, 0 if it would be if
+ * the hardware worked, and not defined at all if the hardware doesn't have such a feature even in theory
+ * CORE_SUPPORT_LONG_TONES is 1 if the core supports the three argument tone for unreasonably long tones.
+ ********************************************************************************/
+#define CORE_HAS_ERRORFUNS (1) /* megaTinyCore implements badArg and badCall */
+#define CORE_HAS_FASTIO (2)
+#define CORE_HAS_OPENDRAIN (1)
+#define CORE_HAS_PINCONFIG (1)
+#define CORE_HAS_FASTPINMODE (1)
+
+#define CORE_HAS_TIMER_TAKEOVER (1)
+#define CORE_HAS_TIMER_RESUME (0)
+#if (MEGATINYCORE_SERIES == 2)
+ #define CORE_HAS_ANALOG_ENH (2)
+ #define CORE_HAS_ANALOG_DIFF (2)
+#else
+ #define CORE_HAS_ANALOG_ENH (1)
+ #define CORE_HAS_ANALOG_DIFF (0)
+#endif
+
+#ifndef CORE_SUPPORT_LONG_TONES
+ #if (PROGMEM_SIZE > 8192)
+ #define CORE_SUPPORT_LONG_TONES 1
+ #endif
+#endif
+
+/* Hardware capabilities (ADC)
+ * ADC_DIFFERENTIAL is 1 for a half-way differential ADC like DX-serie has, 2 for a real one like EA-series will *
+ * ADC_MAX_OVERSAMPLED_RESOLUTION is the maximum resolution attainable by oversampling and decimation *
+ * ADC_NATIVE_RESOLUTION is the higher of the two native ADC resolutions. Either 10 or 12 *
+ * ADC_NATIVE_RESOLUTION_LOW is the lower of the two native ADC resolutions. Either 8 or 10. Can't be deduced from *
+ * above. All permutations where the "native resolution" is higher are extant somewhere *
+ * ADC_MAXIMUM_ACCUMULATE is the maximum number of sameples that can be accumulated by the burst accumulation mode *
+ * ADC_MAXIMUM_SAMPDUR is the maximum sample duration value. Refer to the core documentation or datasheet for detail*
+ * ADC_RESULT_SIZE is the size (in bits) of the registers that hold the ADC result. V2.0 ADC has 32, others have 16 *
+ * ADC_MAXIMUM_GAIN is defined if there is a way to amplify the input to the ADC. If you have to use onchip opamps *
+ * and the chip has them, it's -1, otherwise it is the maximum multiplier
+ * ADC_REFERENCE_SET is 1 if the references are the weird ones that tinyAVR 0 and 1 use, and 2 if they are 1.024, *
+ * 2.048, 4.096 and 2.5V like civilized parts */
+
+#if MEGATINYCORE_SERIES != 2
+ #define ADC_DIFFERENTIAL (0)
+ #define ADC_MAX_OVERSAMPLED_RESOLUTION (13)
+ #define ADC_NATIVE_RESOLUTION (10)
+ #define ADC_NATIVE_RESOLUTION_LOW (8)
+ #define ADC_MAXIMUM_ACCUMULATE (64)
+ #define ADC_MAXIMUM_SAMPDUR (0x1F)
+ #define ADC_RESULT_SIZE (16)
+ #define ADC_REFERENCE_SET (1)
+#else
+ #define ADC_DIFFERENTIAL (2)
+ #define ADC_MAX_OVERSAMPLED_RESOLUTION (17)
+ #define ADC_NATIVE_RESOLUTION (12)
+ #define ADC_NATIVE_RESOLUTION_LOW (8)
+ #define ADC_MAXIMUM_ACCUMULATE (1024)
+ #define ADC_MAXIMUM_SAMPDUR (0xFF)
+ #define ADC_RESULT_SIZE (32)
+ #define ADC_REFERENCE_SET (2)
+ #define ADC_MAXIMUM_GAIN (16)
+#endif
+
+/* Oh and DB and later can use inlvl to adjust trigger points. But not the tinAVRs */
+#define PORT_HAS_INLVL 0
+
+#ifdef __cplusplus
+ #include "UART.h"
+ int32_t analogReadEnh( uint8_t pin, uint8_t res = ADC_NATIVE_RESOLUTION, uint8_t gain = 0);
+ int32_t analogReadDiff(uint8_t pos, uint8_t neg, uint8_t res = ADC_NATIVE_RESOLUTION, uint8_t gain = 0);
+ int16_t analogClockSpeed(int16_t frequency = 0, uint8_t options = 0);
+ #if defined(ADC1)
+ int32_t analogReadEnh1(uint8_t pin, uint8_t res = ADC_NATIVE_RESOLUTION, uint8_t gain = 0);
+ int32_t analogReadDiff1(uint8_t pos, uint8_t neg, uint8_t res = ADC_NATIVE_RESOLUTION, uint8_t gain = 0);
+ int16_t analogClockSpeed1(int16_t frequency = 0, uint8_t options = 0);
+ #endif
+#endif
+#if !defined(NUM_I2C_PINS)
+ #define NUM_I2C_PINS (2) // per I2C port in use - this number is nonsensical without qualification is is only for compatibility.
+#endif
+#if !defined(NUM_SPI_PINS)
+ #define NUM_SPI_PINS (3) // per SPI port in use - this number is nonsensical without qualification is is only for compatibility.
+#endif
+#if !defined(NUM_TOTAL_FREE_PINS)
+ #define NUM_TOTAL_FREE_PINS (PINS_COUNT - NUM_INTERNALLY_USED_PINS)
+#endif
+#if !defined(NUM_TOTAL_PINS)
+ #define NUM_TOTAL_PINS (NUM_DIGITAL_PINS) /* Used the same way as NUM_DIGITAL_PINS. so it doesn't mean what it's named - I didn't make the convention*/
+#endif
+
+inline __attribute__((always_inline)) void check_valid_digital_pin(pin_size_t pin) {
+ if (__builtin_constant_p(pin)) {
+ if (pin >= NUM_TOTAL_PINS && pin != NOT_A_PIN) {
+ // Exception made for NOT_A_PIN - code exists which relies on being able to pass this and have nothing happen.
+ // While IMO very poor coding practice, these checks aren't here to prevent lazy programmers from intentionally
+ // taking shortcuts we disapprove of, but to call out things that are virtually guaranteed to be a bug.
+ // Passing -1/255/NOT_A_PIN to the digital I/O functions is most likely intentional.
+ badArg("Digital pin is constant, but not a valid pin");
+ }
+ #if (CLOCK_SOURCE == 2)
+ #if defined(MEGATINYCORE)
+ if (pin == PIN_PA3) {
+ badArg("Constant digital pin PIN_PA3 is used for the external osc, and is not available for other uses.");
+ }
+ #else
+ if (pin == PIN_PA0) {
+ badArg("Constant digital pin PIN_PA0 is used for the external osc, and is not available for other uses.");
+ }
+ #endif
+ #elif CLOCK_SOURCE == 1
+ if (pin < 2) {
+ badArg("Pin PA0 and PA1 cannot be used for digital I/O because those are used for external crystal clock.");
+ }
+ #elif defined(XTAL_PINS_HARDWIRED)
+ if (pin < 2) {
+ badArg("On the selected board, PA0 and PA1 are hardwired to the crystal. They may not be used for other purposes.");
+ }
+ #endif
+ }
+}
+/*******************************************************************
+ * PIN CONFIGURE Set any or all pin settings, easily invert, etc *
+ *******************************************************************
+// These are used as the second argument to pinConfigure(pin, configuration)
+// You can bitwise OR as many of these as you want, or just do one. Very
+// flexible function; not the world's fastest though. Directives are handled
+// in the order they show up on this list, by pin function:
+// PIN_DIR Direction
+// PIN_OUT Output value
+// PIN_ISC Enable and interrupt mode. If interrupts are turned on w/out the ISR, it will trigger dirty reset.
+// PIN_PULLUP Pullups
+// PIN_INLVL Input levels (MVIO parts only - everything else is schmitt trigger only, except on I2C pins acting as I2C with SMBus levels enabled. )
+// PIN_INVERT Invert pin
+//
+// Systematically named constants can be made by combining those names with the postfixes here
+// except for PIN_ISC which is not a non-binary option. Valid values are listed below.
+// _SET, _CLR, and _TGL can be used as a postfix on all binary options.
+// _TOGGLE and _TGL are interchangeable as well.
+// Additional names are defined where they might be easier to remember.
+// It's not an accident that the PORT options have PIN_(name of register in PORTx)
+// as an alias.
+// Microchip can add one more binary option >.> */
+
+
+/* External definitions */
+/* Actual implementation is in wiring_extra.c (or .cpp, if I find that I'm not able tomake it work with .c)
+ * Because of the incrutable rules of C++ scoping, you can define an inline function or a template function in a header....
+ * and not in the body of a separate file, while the opposite is true for ANY OTHER KIND OF FUNCTION. */
+
+void __pinconfigure(const uint8_t digital_pin, uint16_t pin_config);
+void _pinconfigure(uint8_t pin, uint16_t pin_config);
+void pinConfigure(uint8_t digital_pin, uint16_t pin_config);
+
+#ifdef __cplusplus
+typedef enum : uint16_t
+{
+ // OUTPUT
+ PIN_DIR_SET = 0x0001,
+ PIN_DIRSET = 0x0001,
+ PIN_DIR_OUTPUT = 0x0001,
+ PIN_DIR_OUT = 0x0001,
+ // INPUT
+ PIN_DIR_CLR = 0x0002,
+ PIN_DIRCLR = 0x0002,
+ PIN_DIR_INPUT = 0x0002,
+ PIN_DIR_IN = 0x0002,
+ // TOGGLE INPUT/OUTPUT
+ PIN_DIR_TGL = 0x0003,
+ PIN_DIRTGL = 0x0003,
+ PIN_DIR_TOGGLE = 0x0003,
+ // HIGH
+ PIN_OUT_SET = 0x0004,
+ PIN_OUTSET = 0x0004,
+ PIN_OUT_HIGH = 0x0004,
+ // LOW
+ PIN_OUT_CLR = 0x0008,
+ PIN_OUTCLR = 0x0008,
+ PIN_OUT_LOW = 0x0008,
+// CHANGE/TOGGLE
+ PIN_OUT_TGL = 0x000C,
+ PIN_OUTTGL = 0x000C,
+ PIN_OUT_TOGGLE = 0x000C,
+//Interrupt disabled but input buffer enabled
+ PIN_ISC_ENABLE = 0x0080,
+ PIN_INPUT_ENABLE = 0x0080,
+ // Interrupt on change
+ PIN_ISC_CHANGE = 0x0090,
+ PIN_INT_CHANGE = 0x0090,
+// Interrupt on rising edge
+ PIN_ISC_RISE = 0x00A0,
+ PIN_INT_RISE = 0x00A0,
+// Interrupt on falling edge
+ PIN_ISC_FALL = 0x00B0,
+ PIN_INT_FALL = 0x00B0,
+// Interrupt and input buffer disabled
+ PIN_ISC_DISABLE = 0x00C0,
+ PIN_INPUT_DISABLE = 0x00C0,
+// Interrupt enabled with sense on low level
+ PIN_ISC_LEVEL = 0x00D0,
+ PIN_INT_LEVEL = 0x00D0,
+// PULLUP ON
+ PIN_PULLUP_ON = 0x0100,
+ PIN_PULLUP = 0x0100,
+ PIN_PULLUP_SET = 0x0100,
+// PULLUP OFF
+ PIN_PULLUP_OFF = 0x0200,
+ PIN_PULLUP_CLR = 0x0200,
+// PULLUP TOGGLE
+ PIN_PULLUP_TGL = 0x0300,
+ PIN_PULLUP_TOGGLE = 0x0300,
+ PIN_NOPULLUP = 0x0200,
+// Pin Input Level Control
+ PIN_INLVL_TTL = 0x1000,
+ PIN_INLVL_ON = 0x1000,
+ PIN_INLVL_SET = 0x1000,
+ PIN_INLVL_SCHMITT = 0x2000,
+ PIN_INLVL_OFF = 0x2000,
+ PIN_INLVL_CLR = 0x2000, // alias
+// PIN INVERT ON
+ PIN_INVERT_ON = 0x4000,
+ PIN_INVERT_SET = 0x4000,
+// PIN INVERT OFF
+ PIN_INVERT_OFF = 0x8000,
+ PIN_INVERT_CLR = 0x8000,
+// PIN_INVERT_TOGGLE
+ PIN_INVERT_TGL = 0xC000,
+ PIN_INVERT_TOGGLE = 0xC000
+} pin_configure_t;
+
+/**
+ * @brief Helper functions to catch the last argument in the pincfg recursion loop
+ *
+ * @param mode Mode parameter
+ * @return pin_configure_t
+ */
+
+
+inline pin_configure_t _pincfg(const pin_configure_t mode) {
+ return mode;
+}
+
+/**
+ * @brief Helper functions to catch the nth in the pincfg recursion loop
+ *
+ * @param digital_pin Arduino pin
+ * @param mode First "mode" parameter
+ * @param modes Nth "mode" parameter
+ * @return uint16_t pin configuration or'ed together
+ */
+template
+uint16_t _pincfg(const pin_configure_t mode, const MODES&... modes) {
+ return mode | _pincfg(modes...);
+}
+
+
+
+//void pinConfigure(const uint8_t pinNumber, const uint16_t mode, const MODES&... modes);
+
+/**
+ * @brief Variadic template function for configuring a pin
+ *
+ * @param digital_pin Arduino pin number
+ * @param mode First "mode" parameter
+ * @param modes Nth "mode" parameter
+ */
+template
+void pinConfigure(const uint8_t digital_pin, const pin_configure_t mode, const MODES&... modes) {
+ // Or-ing together the arguments using recursion
+ uint16_t pin_config = _pincfg(mode, modes...);
+ _pinconfigure(digital_pin, pin_config);
+}
+#endif // end
+
+
+#ifdef PIN_WIRE_SCL_PINSWAP_1
+ #define SDA_NOW ((uint8_t) (PORTMUX.CTRLB & PORTMUX_TWI0_bm ? PIN_WIRE_SDA_PINSWAP_1 : PIN_WIRE_SDA))
+ #define SCL_NOW ((uint8_t) (PORTMUX.CTRLB & PORTMUX_TWI0_bm ? PIN_WIRE_SCL_PINSWAP_1 : PIN_WIRE_SCL))
+ static const uint8_t SDA_ALT __attribute__ ((deprecated("Use SDA_ALT1 to match the conventions used in DxCore"))) = PIN_WIRE_SDA_PINSWAP_1; /* deprecated */
+ static const uint8_t SCL_ALT __attribute__ ((deprecated("Use SCL_ALT1 to match the conventions used in DxCore"))) = PIN_WIRE_SCL_PINSWAP_1; /* deprecated */
+ static const uint8_t SDA_ALT1 = PIN_WIRE_SCL_PINSWAP_1;
+ static const uint8_t SCL_ALT1 = PIN_WIRE_SCL_PINSWAP_1;
+#endif
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+
+#ifdef PIN_SPI_SCK_PINSWAP_1
+ #define SS_NOW ((uint8_t) (PORTMUX.CTRLB & PORTMUX_SPI0_bm ? PIN_SPI_SS_PINSWAP_1 : PIN_SPI_SS))
+ #define MOSI_NOW ((uint8_t) (PORTMUX.CTRLB & PORTMUX_SPI0_bm ? PIN_SPI_MOSI_PINSWAP_1 : PIN_SPI_MOSI))
+ #define MISO_NOW ((uint8_t) (PORTMUX.CTRLB & PORTMUX_SPI0_bm ? PIN_SPI_MISO_PINSWAP_1 : PIN_SPI_MISO))
+ #define SCK_NOW ((uint8_t) (PORTMUX.CTRLB & PORTMUX_SPI0_bm ? PIN_SPI_SCK_PINSWAP_1 : PIN_SPI_SCK))
+ static const uint8_t SS_ALT __attribute__ ((deprecated("Use SS_ALT1 to match the conventions used in DxCore" ))) = PIN_SPI_SS_PINSWAP_1; /* deprecated */
+ static const uint8_t MOSI_ALT __attribute__ ((deprecated("Use MOSI_ALT1 to match the conventions used in DxCore"))) = PIN_SPI_MOSI_PINSWAP_1; /* deprecated */
+ static const uint8_t MISO_ALT __attribute__ ((deprecated("Use MISO_ALT1 to match the conventions used in DxCore"))) = PIN_SPI_MISO_PINSWAP_1; /* deprecated */
+ static const uint8_t SCK_ALT __attribute__ ((deprecated("Use SCK_ALT1 to match the conventions used in DxCore" ))) = PIN_SPI_SCK_PINSWAP_1; /* deprecated */
+ static const uint8_t SS_ALT1 = PIN_SPI_SS_PINSWAP_1;
+ static const uint8_t MOSI_ALT1 = PIN_SPI_MOSI_PINSWAP_1;
+ static const uint8_t MISO_ALT1 = PIN_SPI_MISO_PINSWAP_1;
+ static const uint8_t SCK_ALT1 = PIN_SPI_SCK_PINSWAP_1;
+#endif
+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;
+
+
+
+// A little bit of trickery - this allows Serial to be defined as something other than USART0
+// Use case is for boards where the main serial port is not USART0 to be used without the user
+// having to find/replace Serial with Serial2 or whatever on their existing code if that's where
+// the monitor is. It requires that the board be defined by a variant file
+#ifndef Serial
+ #define Serial Serial0 // Error here? Check for missing ; previous line in sketch.
+#endif
+
+/* Moved from pins_arduino.h to reduce code duplication - also made better decisions */
+// 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.
+
+// First, we allow a define to be passed (lkely from boards.txt - though it could
+// come from pins_arduino, I suppose) to force a certain port here. The plan is
+// that I will pass defines from board definitions specifying this for the Curiosity
+// Nano boards, in order to improve the user experience there - though this may be
+// obliviated by the Serial/Serial0 thing just above, which has the advantage of
+// transparently adapting user code as well.
+
+#if !defined(SERIAL_PORT_MONITOR)
+ #if defined(SERIAL_PORT_BOOT)
+ #define SERIAL_PORT_MONITOR SERIAL_PORT_BOOT
+ #else
+ #define SERIAL_PORT_MONITOR Serial
+ #endif
+#endif
+
+// Following example in the Arduino Mega, where despite having 4 serial ports, they
+// use Serial for both SERIAL_PORT_MONITOR and SERIAL_PORT_HARDWARE, I will not
+// try to spread around the ports we use for these defines - if we're
+// going to declare some other port to be the "main" serial port, with the monitor
+// on it and all, we should be consistent about that, right? *shrug*
+#if !defined(SERIAL_PORT_HARDWARE)
+ #define SERIAL_PORT_HARDWARE SERIAL_PORT_MONITOR
+#endif
+
+// If we have USART2 (ie, we are not a DD-series) we will declare that to be
+// SERIAL_PORT_HARDWARE_OPEN, so that on a DB-series, libraries are less likely to
+// squabble over the more powerful USART1 - USART1 being more powerful because it
+// is on PORTC, the MVIO port.
+/*
+#if !defined(SERIAL_PORT_MONITOR)
+ #if defined(USART2) && (SERIAL_PORT_MONITOR != Serial2) && (!defined(SERIAL_PORT_BOOT) || SERIAL_PORT_BOOT != Serial2)
+ #define SERIAL_PORT_HARDWARE_OPEN Serial2
+ #else
+ #if (SERIAL_PORT_MONITOR != Serial0 ) && (!defined(SERIAL_PORT_BOOT) || SERIAL_PORT_BOOT != Serial0)
+ #define SERIAL_PORT_HARDWARE_OPEN Serial0
+ #else
+ #define SERIAL_PORT_HARDWARE_OPEN Serial1
+ #endif
+ #endif
+#endif
+#if !defined(SERIAL_PORT_MVIO) && defined(MVIO) // defined on DD snd DB.
+// DD-series parts with 20-or-fewer pins will not have a PC0 for the TX line of
+// Serial1. that makes it difficult to , so it can't be their MVIO serial port (without involving the event
+// system, of course) - but they can get a serial port on MVIO pins with USART0
+// and an alternate mapping. So for those parts only, Serial is their MVIO port.
+// For everyone else it's Serial1, and for non-DD parts, that is the only serial port connected to the mvio pins.
+// Note that if MVIO is disabled, we cannot detect that.
+ #if defined(DD_14_PINS) || defined(DD_20_PINS)
+ #define SERIAL_PORT_MVIO Serial0
+ #define SERIAL_PORT_MVIO_MUX 0x04 // TX PC1 RX PC2
+ #else
+ #define SERIAL_PORT_MVIO Serial1
+ #endif
+#endif
+*/
+
+// Spence Konde: This is a bit silly - but it does have some utility. I am of the
+// opinion that anything that needs to use a serial port or other peripheral of
+// which a chip may have several, and it needs to be sure to pick the "right" one
+// (that is, most of the time), it should be accepting an argument somewhere to set which serial port rather than assuming.
+
+
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/ExtraWiring.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/ExtraWiring.cpp
new file mode 100644
index 0000000..302ce24
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/ExtraWiring.cpp
@@ -0,0 +1 @@
+/*placeholder*/
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/HardwareSerial.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/HardwareSerial.h
new file mode 100644
index 0000000..046fa18
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/HardwareSerial.h
@@ -0,0 +1,473 @@
+// Many cores use HardwareSerial.h and HardwareSerial. However, the core from which this was derived names them differently.
+// This only rarely a problem - but it causes problems when libraries want to #include HardwareSerial.h and expect it to provide a class of that name, instead of UartClass. Soon after this workaround, it was realized that there was an extra layer in the class hierarchy forcing multiple virtual functions and explained why serial was a space hog
+
+/* UART.h - Hardware serial library, main header.
+ * This library is free software released under LGPL 2.1.
+ * See License.md for more information.
+ * This file is part of DxCore and/or megaTinyCore
+ *
+ * Copyright (c) 2006 Nicholas Zambetti, Modified by
+ * 11/23/2006 David A. Mellis, 9/20/2010 Mark Sproul,
+ * 8/24/2012 Alarus, 12/3/2013 Matthijs Kooijman
+ * Others (unknown) 2013-2017, 2017-2022 Spence Konde
+ * and 2021-2022 MX682X
+ *
+ * Modified 28 September 2010 by Mark Sproul
+ * Modified 14 August 2012 by Alarus
+ * Modified 3 December 2013 by Matthijs Kooijman
+ * Modified by SOMEONE around 2016-2017; hardware serial didn't port itself to the megaAVR 0-series.
+ * Modified 2017-2021 by Spence Konde for megaTinyCore and DxCore.
+ * Modified late 2021 by Spence Konde and MX682X for DxCore
+ * 12/26/21: Correct bug introduced in my ASM macros. -Spence
+ * 12/30/21: Clean up tests for conditional compilation
+ tests for defined(USE_ASM_*) removed UART.h tests that test both defined and the value of
+ USE_ASM_* macros. We check if they're defined and define them if they're not defined already
+ so whenever UART.h has been loaded, those three macros are defined as either 1, or wharever
+ value the user overode them with, likely 0. Also high byte of UART address always 0x08, so replace
+ 2-clock ldd with 1 clock ldi. - Spence
+ * 03/12/23: Correct bug in TxD1' and XCK1'
+*/
+
+#pragma once
+#include "core_devices.h"
+#include
+#include "api/Stream.h"
+#include "pins_arduino.h"
+#include "UART_constants.h"
+#include "UART_check_pins.h"
+
+// No UART_swap.h on megaTinyCore - there isn't enough to put in separate file.
+
+/* Define constants and variables for buffering incoming serial data. We're
+ * using a ring buffer, 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.
+ * NOTE: a "power of 2" buffer size is **REQUIRED** - the compiler
+ * was missing optimizations, and there's no particular reason to have
+ * a weird sized buffer, and several reasons not to.
+ *
+ * More than 256b buffers imposes a considerable performance penalty,
+ * - one large enough to obliviate the entire purpose, because of the
+ * need to make the access to the current index atomic. This atomic
+ * block is costly - it's a macro for cli and sei
+ * implemented in inline assembly, which sounds fast. But the optimizer
+ * can reorder instructions *and isn't smart enough not to here* without the
+ * ": memory" clobber to create a memory barrier. This ensures that it
+ * is atomic, but significantly hurts performance. (theoretical worst case
+ * is 94 clocks, real-world is usually far less, but I'll only say "less"
+ * The functions in question have considerable register pressure). But,
+ * it unquestionably would impact USART performance at high speeds.
+ *
+ * * The USE_ASM_* options can be disabled by defining them as 0 either in variant pins_arduino.h
+ * The buffer sizes can be overridden in by defining SERIAL_TX_BUFFER either in variant file (
+ * as defines in pins_arduino.h) or boards.txt as (By passing them as extra flags).
+ * Note that buffer sizes must be powers of 2 only no matter how you override it.
+ * The alternative is doing division to get the modulo every time instead of a single clock bitwise and, which further lowers the
+ * maximum RX speed (which, without the ASM implementation, is already lower than what the receiver is capable of).
+ * The defaults below are only used if the relevant macro isn't already defined.
+ * Since the USE_ASM_* = 1 option is apparently working, we do not recommend disabling it, as it will waste flash and hurt performance.
+ *
+ * Flash versus RAM table
+ * | | modern tinyAVR series parts | Other modern parts |
+ * | Flash | 0-series | 1-series | 2-series | mega | All Dx | EA | EB |
+ * |-------|----------|----------|----------|------|--------|------|------|
+ * | 2048 | 128 | 128 | - | - | - | - | - |
+ * | 4096 | 256 | 256 | 512 | - | - | - | - |
+ * | 8192 | 512 | 512 | 1024 | 1024 | - | 1024 | 1024 |
+ * | 16384 | 1024 | 2048 | 2048 | 2048 | 2048 | 2048 | 2048 |
+ * | 32768 | - | 2048 | 3072 | 4096 | 4096 | 4096 | 3072 |
+ * | 49152 | - | - | - | 6120 | - | - | - |
+ * | 65536 | - | - | - | - | 8192 | 6120 | - |
+ * | 128k | - | - | - | - | 16384 | - | - |
+ * This ratio is remarkably consistent. No AVR part was ever made with less than 8:1 flash:ram,
+ * nor more than 16:1, since the earliest recognizable AVRs. I am only aware of one exception. Was it some bizarro part
+ * from the dark ages? Nope - it's the surprisingly popular ATmega2560!
+ * The ATmega2560/2561 has only 8k RAM, a 32:1 flash to ram ratio. (to be fair, you are allowed to use external RAM
+ * on those, which was a very rare feature indeed, and that is by far the most widespread part with such a feature - though if you're using the
+ * XMEM interface, you've burned 19 GPIO lines right there.... The ATmega2560 is kind of the "I have a job too big for an AVR.
+ * But I don't know how to program anything else!" part. That is not a compliment.
+ *
+ * | RAM | TX | RX | Amount of RAM implied | Total ram used |
+ * |-------|----|----|-----------------------|----------------|
+ * | < 512 | 16 | 16 | 256b (0/1 w/2k or 4k) | 32b, all 1 port|
+ * | <1024 | 16 | 32 | 512b | 48b or 96b |
+ * | <2048 | 32 | 64 | 1024b | 96b or 192b |
+ * | More | 64 | 64 | 2048b or 3072b | 128b or 256b |
+ *
+ * (the two numbers in final column are given because 0/1-serieas has 1 port, but tiny2 has 2, though if you only use one, you only
+ * get one set of buffers)
+ */
+
+/* Buffer Sizing */
+
+// The buffer sizes can be overridden in by defining SERIAL_TX_BUFFER either in variant file (as defines in pins_arduino.h) or boards.txt (By passing them as extra flags).
+// note that buffer sizes must be powers of 2 only.
+
+#if !defined(SERIAL_TX_BUFFER_SIZE)
+ #if (INTERNAL_SRAM_SIZE < 1024) // 128/256b/512b RAM
+ #define SERIAL_TX_BUFFER_SIZE 16
+ #elif (INTERNAL_SRAM_SIZE < 2048) // 1k RAM
+ #define SERIAL_TX_BUFFER_SIZE 32
+ #else
+ #define SERIAL_TX_BUFFER_SIZE 64 // 2k/3k RAM
+ #endif
+#endif
+#if !defined(SERIAL_RX_BUFFER_SIZE) // could be overridden by boards.txt
+ #if (INTERNAL_SRAM_SIZE < 512) // 128/256b RAM
+ #define SERIAL_RX_BUFFER_SIZE 16
+ // current tx buffer position = SerialClass + txtail + 37
+ #elif (INTERNAL_SRAM_SIZE < 1024) // 512b RAM
+ #define SERIAL_RX_BUFFER_SIZE 32
+ // current tx buffer position = SerialClass + txtail + 53
+ #else
+ #define SERIAL_RX_BUFFER_SIZE 64 // 1k+ RAM
+ // current tx buffer position = SerialClass + txtail + 85
+ // rx buffer position always = SerialClass + rxhead + 21
+ #endif
+#endif
+/* Use INTERNAL_SRAM_SIZE instead of RAMEND - RAMSTART, which is vulnerable to
+ * a fencepost error. */
+#if (SERIAL_TX_BUFFER_SIZE > 256)
+ typedef uint16_t tx_buffer_index_t;
+#else
+ typedef uint8_t tx_buffer_index_t;
+#endif
+// I am not convinced > 256b is safe for the RX buffer....
+#if (SERIAL_RX_BUFFER_SIZE > 256)
+ typedef uint16_t rx_buffer_index_t;
+#else
+ typedef uint8_t rx_buffer_index_t;
+#endif
+// As noted above, forcing the sizes to be a power of two saves a small
+// amount of flash, and there's no compelling reason to NOT have them be
+// a power of two. If this is a problem, since you're already modifying
+// core, change the lines in UART.cpp where it does & (SERIAL_xX_BUFFERLSIZE-1)
+// and replace them with % SERIAL_xX_BUFFER_SIZE; where xX is TX or RX.
+// There are two of each, and the old ending of the line is even commented
+// out at the end of the line.
+#if (SERIAL_TX_BUFFER_SIZE & (SERIAL_TX_BUFFER_SIZE - 1))
+ #error "ERROR: TX buffer size must be a power of two."
+#endif
+#if (SERIAL_RX_BUFFER_SIZE & (SERIAL_RX_BUFFER_SIZE - 1))
+ #error "ERROR: RX buffer size must be a power of two."
+#endif
+
+/* Buffer sizing done */
+
+
+#if !defined(LTODISABLED)
+#if !defined(USE_ASM_TXC)
+ #define USE_ASM_TXC 2 // A bit slower than 1 in exchange for halfduplex.
+//#define USE_ASM_TXC 1 // This *appears* to work? It's the easy one. saves 6b for 1 USART and 44b for each additional one
+#endif
+
+#if !defined(USE_ASM_RXC)
+ #define USE_ASM_RXC 1 // This now works. Saves only 4b for 1 usart but 98 for each additional one
+#endif
+
+#if !defined(USE_ASM_DRE)
+ #define USE_ASM_DRE 1 // This is the hard one...Depends on BOTH buffers, and has that other method of calling it. saves 34b for 1 USART and 68b for each additional one
+#endif
+#else
+ #warning "LTO has been disabled! ASM TXC/RXC/DRE not available. USART falling back to the old, flash-inefficient implementation with fewer features."
+ #if defined(USE_ASM_TXC)
+ #undef USE_ASM_TXC
+ #endif
+
+ #if defined(USE_ASM_RXC)
+ #undef USE_ASM_RXC
+ #endif
+
+ #if defined(USE_ASM_DRE)
+ #undef USE_ASM_DRE
+ #endif
+#endif
+
+
+// savings:
+// 44 total for 0/1,
+// 301 for 2-series, which may be nearly 9% of the total flash!
+// The USE_ASM_* options can be disabled by defining them as 0 (in the same way that buffer sizes can be overridden)
+// The buffer sizes can be overridden in by defining SERIAL_TX_BUFFER either in variant file (as defines in pins_arduino.h) or boards.txt (By passing them as extra flags).
+// note that buffer sizes must be powers of 2 only.
+
+#if USE_ASM_RXC == 1 && !(SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16)
+ #error "Assembly RX Complete (RXC) ISR is only supported when RX buffer size are 256, 128, 64, 32 or 16 bytes"
+#endif
+
+#if USE_ASM_DRE == 1 && !((SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
+ (SERIAL_TX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
+ #error "Assembly Data Register Empty (DRE) ISR is only supported when both TX and RX buffer sizes are 256, 128, 64, 32 or 16 bytes"
+#endif
+
+
+/* Macros to help the rare few who want sync or MSPI mode */
+#define syncBegin(port, baud, config, syncopts) ({\
+ if ((config & 0xC0) == 0x40) \
+ {pinConfigure(port.getPin(2), syncopts); \
+ port.begin(baud >> 3, config); \
+ }})
+
+#define mspiBegin(port, baud, config, invert) ({ \
+ if ((config & 0xC0) == 0xC0) { \
+ pinConfigure(port.getPin(2), invert); \
+ port.begin(baud >> 3, config); \
+ }})
+
+
+
+// tinyAVR 0/1-series has 2 bits devoted to RS485, supporting normal (00), RS485 with XDIR driven to control
+// an external line driver (01), and some other mysterious mode (10) the function of which is unclear. There is
+// evidence that this poorly documented feature is also present in other hardware, and was only removed on paper.
+#if !defined(USART_RS485_bm)
+ #if defined(USART_RS485_0_bm)
+ #define USART_RS485_bm USART_RS485_0_bm
+ #else
+ #define USART_RS485_bm 0x01
+ #endif
+#endif
+#if defined(__AVR_ATtinyxy2__) // 8-pin parts use a different set of pin mappings.
+const uint8_t _usart_pins[][4] = {{PIN_PA6, PIN_PA7, PIN_PA3, PIN_PA0},{PIN_PA1, PIN_PA2, NOT_A_PIN, NOT_A_PIN}};
+#elif !defined(__AVR_ATtinyx26__) && !defined(__AVR_ATtinyx27__) // Everything that's not a 2-series with >= 20 pins has the standard mappings.
+const uint8_t _usart_pins[][4] = {{PIN_PB2, PIN_PB3, PIN_PB1, PIN_PB0},{PIN_PA1, PIN_PA2, PIN_PA3, PIN_PA4}};
+#elif defined(__AVR_ATtinyx26__) || defined(__AVR_ATtinyx27__) // 2-series with 20 or 24 pins have the alt pins for USART1.
+const uint8_t _usart_pins[][4] = {
+ {PIN_PB2, PIN_PB3, PIN_PB1, PIN_PB0},
+ {PIN_PA1, PIN_PA2, PIN_PA3, PIN_PA4},
+ {PIN_PC2, PIN_PC1, PIN_PC1, PIN_PC3}
+};
+#else
+ #error "This can't happen - it doesn't have 8, 14, 20 or 24 pins, or it has 14 pins but no serial port - defines aren't being picked up correctly."
+#endif
+/*
+#if defined(__AVR_ATtinyxy2__)
+const uint8_t _usart_pins[][7] = {{PIN_PA6, PIN_PA7, PIN_PA0, PIN_PA3},{PIN_PA1, PIN_PA2, NOT_A_PIN, NOT_A_PIN}};
+#elif !defined(__AVR_ATtinyx26__) && !defined(__AVR_ATtinyx27__) && defined(MEGATINYCORE_SERIES)
+const uint8_t _usart_pins[][7] = {{4, 8, 2, 1, 0x22, 0x23, 0x20},{2, 4, 8, 16, 0x01, 0x02, 0x04}};
+#elif defined(__AVR_ATtinyx26__) || defined(__AVR_ATtinyx27__)
+const uint8_t _usart_pins[][7] = {
+ {4, 8, 2, 1, 0x22, 0x23, 0x20},
+ {2, 4, 8, 16, 0x01, 0x02, 0x04},
+ {1, 2, 4, 8, 0x40, 0x41, 0x43}
+};
+*/
+#define SERIAL_PIN_SETS 2
+// WHAT THE HELL IS WRONG WITH THIS?!
+// When this definition is used, row 0 is {PIN_PB3,PIN_PB2,PIN_PB1,PIN_PB0 in this file and row 2 is 0, 0, 0, 0! WTF}
+// TX, RX, XCK, XDIR
+/*
+const uint8_t _usart_pins[][4] = {
+ #if defined(HWSERIAL0_MUX)
+ #if (defined(PIN_HWSERIAL0_TX) && defined(PIN_HWSERIAL0_RX) && defined(PIN_HWSERIAL0_XCK) && defined(PIN_HWSERIAL0_XIR) && PIN_HWSERIAL0_TX != NOT_A_PIN && PIN_HWSERIAL0_RX != NOT_A_PIN)
+ {PIN_HWSERIAL0_TX, PIN_HWSERIAL0_RX, PIN_HWSERIAL0_XCK, PIN_HWSERIAL0_XDIR},
+ #else
+ {NOT_A_PIN, NOT_A_PIN, NOT_A_PIN, NOT_A_PIN},
+ #endif
+ #endif
+ #if defined(HWSERIAL0_MUX_PINSWAP_1)
+ #if (defined(PIN_HWSERIAL0_TX_PINSWAP_1) && defined(PIN_HWSERIAL0_RX_PINSWAP_1) && defined(PIN_HWSERIAL0_XCK_PINSWAP_1) && defined(PIN_HWSERIAL0_XIR_PINSWAP_1) && PIN_HWSERIAL0_TX_PINSWAP_1 != NOT_A_PIN && PIN_HWSERIAL0_RX_PINSWAP_1 != NOT_A_PIN)
+ {PIN_HWSERIAL0_TX_PINSWAP_1, PIN_HWSERIAL0_RX_PINSWAP_1, PIN_HWSERIAL0_XCK_PINSWAP_1, PIN_HWSERIAL0_XDIR_PINSWAP_1},
+ #else
+ {NOT_A_PIN, NOT_A_PIN, NOT_A_PIN, NOT_A_PIN},
+ #endif
+ #endif
+ #if defined(USART1) // On 0/1-series, with only one USART, we don't even need the third row.
+ #if defined(HWSERIAL1_MUX_PINSWAP_1)
+ #if (defined(PIN_HWSERIAL1_TX_PINSWAP_1) && defined(PIN_HWSERIAL1_RX_PINSWAP_1) && defined(PIN_HWSERIAL1_XCK_PINSWAP_1) && defined(PIN_HWSERIAL1_XIR_PINSWAP_1) && PIN_HWSERIAL1_TX_PINSWAP_1 != NOT_A_PIN && PIN_HWSERIAL1_RX_PINSWAP_1 != NOT_A_PIN)
+ {PIN_HWSERIAL1_TX_PINSWAP_1, PIN_HWSERIAL1_RX_PINSWAP_1, PIN_HWSERIAL1_XCK_PINSWAP_1, PIN_HWSERIAL1_XDIR_PINSWAP_1},
+ #else
+ {NOT_A_PIN, NOT_A_PIN, NOT_A_PIN, NOT_A_PIN},
+ #endif
+ #endif
+ #endif
+};
+*/
+
+
+
+/* DANGER DANGER DANGER */
+/* CHANGING THE MEMBER VARIABLES BETWEEN HERE AND THE OTHER SCARY COMMENT WILL COMPLETELY BREAK SERIAL
+ * WHEN USE_ASM_DRE and/or USE_ASM_RXC is used! */
+/* DANGER DANGER DANGER */
+class HardwareSerial : public Stream {
+ protected:
+ volatile USART_t *const _hwserial_module;
+ const uint8_t _module_number;
+ uint8_t _pin_set;
+
+ volatile uint8_t _state; /* 0bvV__fphw */
+ // Of course this has to be volatile! We started writing it in 2.6.x from ISRs in opaque asm.
+ // Bit E ("There's an echo in here") is used if halfduplex mode is enabled, and when RXC reads the buffer,
+ // it also reads state, and if this bit is set, clears the bit and exits the ISR. The opposite of a parity
+ // error, which sets it's bit and exits the isr except that it doesn't care if it's already set) .
+ // v = Overflow has happened at hardware level. Interrupts were disabled for too long.
+ // V = ring buffer overflow has occurred.
+ // _ = reserved
+ // f = One or more framing errors have occurred.
+ // p = One or more parity errors has occurred.
+ // h = half duplex with open drain - disable RX while TX.
+ // w = written (like old _written)
+
+ volatile rx_buffer_index_t _rx_buffer_head;
+ volatile rx_buffer_index_t _rx_buffer_tail;
+ volatile tx_buffer_index_t _tx_buffer_head;
+ volatile tx_buffer_index_t _tx_buffer_tail;
+
+ // Don't put any members after these buffers, since only the first
+ // 32 bytes of this struct can be accessed quickly using the ldd
+ // instruction.
+ volatile uint8_t _rx_buffer[SERIAL_RX_BUFFER_SIZE];
+ volatile uint8_t _tx_buffer[SERIAL_TX_BUFFER_SIZE];
+/* DANGER DANGER DANGER */
+/* ANY CHANGES BETWEEN OTHER SCARY COMMENT AND THIS ONE WILL BREAK SERIAL IF THEY CHANGE RAM USED BY CLASS! */
+/* DANGER DANGER DANGER */
+
+ public:
+ inline HardwareSerial(volatile USART_t *hwserial_module, uint8_t module_number, uint8_t default_pinset);
+ bool pins(uint8_t tx, uint8_t rx);
+ bool swap(uint8_t mux_level = 1);
+ void begin(uint32_t baud) {begin(baud, SERIAL_8N1);}
+ void begin(uint32_t baud, uint16_t options);
+ void end();
+ // printHex!
+ void printHex(const uint8_t b);
+ void printHex(const int8_t b) {printHex((uint8_t ) b); }
+ void printHex(const char b) {printHex((uint8_t ) b); }
+ void printHex(const uint16_t w, bool s = 0);
+ void printHex(const int16_t w, bool s = 0) {printHex((uint16_t)w, s); }
+ void printHex(const uint32_t l, bool s = 0);
+ void printHex(const int32_t l, bool s = 0) {printHex((uint32_t)l, s); }
+ void printHexln(const int8_t b) {printHex((uint8_t ) b); println();}
+ void printHexln(const char b) {printHex((uint8_t ) b); println();}
+ void printHexln(const uint8_t b) {printHex( b); println();}
+ void printHexln(const uint16_t w, bool s = 0) {printHex( w, s); println();}
+ void printHexln(const uint32_t l, bool s = 0) {printHex( l, s); println();}
+ void printHexln(const int16_t w, bool s = 0) {printHex((uint16_t)w, s); println();}
+ void printHexln(const int32_t l, bool s = 0) {printHex((uint32_t)l, s); println();}
+ // The pointer-versions for mass printing uint8_t and uint16_t arrays.
+ uint8_t * printHex( uint8_t* p, uint8_t len, char sep = 0 );
+ uint16_t * printHex( uint16_t* p, uint8_t len, char sep = 0, bool s = 0);
+ volatile uint8_t * printHex(volatile uint8_t* p, uint8_t len, char sep = 0 );
+ volatile uint16_t * printHex(volatile uint16_t* p, uint8_t len, char sep = 0, bool s = 0);
+ uint8_t * printHexln( uint8_t* p, uint8_t len, char sep = 0 ) {
+ uint8_t* ret;
+ ret=printHex(p, len, sep);
+ println(); return ret;
+ }
+ uint16_t * printHexln( uint16_t* p, uint8_t len, char sep = 0, bool s = 0) {
+ uint16_t* ret; ret=printHex(p, len, sep, s); println(); return ret;
+ }
+ volatile uint8_t * printHexln(volatile uint8_t* p, uint8_t len, char sep = 0 ) {
+ volatile uint8_t* ret;
+ ret=printHex(p, len, sep);
+ println();
+ return ret;
+ }
+ volatile uint16_t * printHexln(volatile uint16_t* p, uint8_t len, char sep = 0, bool s = 0) {
+ volatile uint16_t* ret;
+ ret=printHex(p, len, sep, s);
+ println();
+ return ret;
+ }
+
+ virtual int availableForWrite(void);
+ virtual int available(void);
+ virtual int peek(void);
+ virtual int read(void);
+ virtual void flush(void);
+ virtual size_t write(uint8_t ch);
+ inline size_t write(unsigned long n) {return write((uint8_t)n);}
+ inline size_t write(long n) {return write((uint8_t)n);}
+ inline size_t write(unsigned int n) {return write((uint8_t)n);}
+ inline size_t write(int n) {return write((uint8_t)n);}
+ using Print::write; // pull in write(str) and write(buf, size) from Print
+ explicit operator bool() {
+ return true;
+ }
+ uint8_t autoBaudWFB();
+ void simpleSync();
+
+ uint8_t autobaudWFB_and_wait(uint8_t n);
+ uint8_t waitForSync();
+ uint8_t autobaudWFB_and_request(uint8_t n = 2);
+ uint8_t getStatus() {
+ uint8_t ret = _statuscheck(_hwserial_module->CTRLB, _hwserial_module->STATUS, _state);
+ if ((ret & 0x30) == 0x30) {
+ _hwserial_module->STATUS = USART_ISFIF_bm;
+ #if defined(ERRATA_ISFIF)
+ uint8_t ctrlb _hwserial_module->CTRLB;
+ uint8_t rxoff = ctrlb & (~USART_RXEN_bm);
+ _hwserial_module->CTRLB = rxoff;
+ _hwserial_module->CTRLB = ctrlb;
+ #endif
+ }
+ _state &= 0x03; // Clear the errors we just reported.
+ return ret;
+ }
+
+ uint8_t getPin(uint8_t pin); //wrapper around static _getPin
+
+ // Interrupt handlers - Not intended to be called externally
+ #if !(USE_ASM_RXC == 1 && \
+ (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16))
+ static void _rx_complete_irq(HardwareSerial& uartClass);
+ #endif
+ #if !(USE_ASM_DRE == 1 && \
+ (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
+ (SERIAL_TX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
+ static void _tx_data_empty_irq(HardwareSerial& uartClass);
+ #endif
+
+ private:
+ void _poll_tx_data_empty(void);
+ static void _set_pins(uint8_t port_num, uint8_t mux_setting, uint8_t enmask);
+ static uint8_t _pins_to_swap(uint8_t port_num, uint8_t tx_pin, uint8_t rx_pin);
+
+
+ /* _statuscheck() - the static side to getStatus(). Static methods have no concept of which instance they are called from. This gives the optimizer more handholds
+ * As you probably know, the optimizer's hands are pretty tightly bound when working with a normal class method, but it has a much freer hand in static methods.
+ * Return value is:
+ * 0HRaaFPHW
+ * H = Hardware RX buffer overflowed because interrupts were disabled for too long while trying to receive data.
+ * R = Ring buffer suffered an overflow. When you check Serial.available, use a while loop to read in characters until nothing is left in the ring buffer.
+ * aa = Autobaud state:
+ * 00 = Disabled
+ * 01 = SERIAL_AUTOBAUD_ENABLED
+ * 10 = SERIAL_AUTOBAUD_SYNC
+ * 11 = SERIAL_AUTOBAUD_BADSYNC - This is Bad News, bro. Baaaaaad news. You tried to do autobaud, but got something that wasn't a sync, and some parts have an errata
+ * that results in the receiver disabling itself until you clear this, turn off RXEN, and turn it back on. This ugly kludge is implemented by getStatus, which calls
+ * this function. Currently only DD parts have this erratum, but I won't trust that until I've seen more recent errata that don't list it (my prediction is anything
+ * with the SFDEN bug has the ISFIF one too, which would be most or all modern AVRs)
+ * F = SERIAL_FRAME_ERROR - A framing error has occurred since you last called this, indicating mismatched baud settings. See Serial Reference.
+ * P = SERIAL_PARITY_ERROR - A parity error has occurred since you last called this, and the bad character did not make it to the application.
+ * When using parity mode, but mismatched baud settings, you will get a mixture of gibberish + framing error set, and
+ * parity errors.
+ * H = SERIAL_HALF_DUPLEX_ENABLED - indicates that half duplex mode is enabled.
+ *
+ * Test for these errors like st = Serial.getStatus(); if (st & SERIAL_FRAME_ERROR) { ... }
+ * For the autobaud ones with 2 bits: if (st & SERIAL_AUTOBAUD_BADSYNC) { // If it wasn't fixed by the core, you'd have to take action. But it is}
+ */
+ static uint8_t _statuscheck(uint8_t ctrlb, uint8_t status, uint8_t state) {
+ uint8_t ret = state;
+ // We have now: |HW OVF| RING OVF|_____|_______|FrameError|ParityError|HalfDuplex|Written|
+ // now we fill high nybble
+ if ((ctrlb & 0x06) == 0x04) {
+ // Autobaud
+ if (status & USART_BDF_bm) {
+ ret |= SERIAL_AUTOBAUD_SYNC;
+ } else if (status & USART_ISFIF_bm) {
+ ret |= SERIAL_AUTOBAUD_BADSYNC;
+ } else {
+ ret |= SERIAL_AUTOBAUD_ENABLED;
+ }
+ }
+ return ret;
+ }
+ };
+
+#if defined(USART0)
+ extern HardwareSerial Serial0;
+#endif
+#if defined(USART1)
+ extern HardwareSerial Serial1;
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/Tone.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/Tone.cpp
new file mode 100644
index 0000000..64c0513
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/Tone.cpp
@@ -0,0 +1,333 @@
+/* Tone.cpp
+
+ A Tone Generator Library
+
+ Written by Brett Hagman
+
+ 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
+
+ -------- ----------- -------- --------
+ 0001 B Hagman 09/08/02 Initial coding
+ 0002 B Hagman 09/08/18 Multiple pins
+ 0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
+ 0004 B Hagman 09/09/26 Fixed problems with ATmega8
+ 0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
+ 09/11/25 Changed pin toggle method to XOR
+ 09/11/25 Fixed timer0 from being excluded
+ 0006 D Mellis 09/12/29 Replaced objects with functions
+ 0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
+ 0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
+ 0009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62)
+ 0010 jipp 15/04/13 added additional define check #2923
+ 0011 E Roy 13/02/18 ported to ATmega4809
+ 1.3.3 S Konde 3/30/21 Fixed bug where output could be left high.
+ Fixed bug that would cause anomalies on PORTB through use of
+ a NULL pointer, which points rght at the low IO space. Just return
+ if the pin isn't a valid pin.
+ Fix anomalous silent pointless interrupts for duration of a
+ frequency = 0 "tone" Now I just drive pin low and turn off timer.
+ You asked for 0 Hz? That's 0 Hz alright!
+ In all cases, we ave to avoid leaving it high because
+ that can damage speakers, so I am told..
+ Just return and turn off tone if it's the current tone pin
+ bit_mask was declared volatile; but it shouldn't.
+ _pin was not decared volatile when it should be.
+ Fix bug where high-pitch tones old overflow when calculating
+ duration (the intermediate 2 * frequency was an unsigned int,
+ even though next operation multipolied it by an unsigned long
+ - simply reoved the 2* altogether and divide by 500 at end instead
+ of 1000.
+ Long tones (where frequency * duration > 2.145 billion resulted in an
+ intermediate overflowing before the divide by 1000. removing the
+ 2* doubled this limit. But high frequencies and long durations (where
+ frequency * duration would overflow a unsigned long) still break it.
+ I added a way to distribute the division before the multiplication
+ if the duration was long enough to start worrying about. But I decided
+ not to enable by on all parts - it is SUPPORT_LONG_TONES - if defined
+ and 1, when duration is over 2^16, we split that line into
+ (frequency/5) * (duration/100) This version was developed for DxCore
+ 1.3.3 and megaTinyCore 2.3.0. The former always uses the bulkier
+ implementation, while the latter does only on parts with 16k+ flash.
+1.3.6 S Konde 4/17/21 Fixed bug that would break compilation of all sketches if TCB0
+ was used for millis on parts without a TCB1. Now, we intentionally break
+ the compilation only if the user code actually calls tone() or noTone()
+ This version was developed for DxCore 1.3.6 and megaTinyCore 2.3.2
+1.3.7 S Konde 7/21/21 reorganized code, improved comments. caught a couple of corner
+ cases which could cause odd behavior in obscure cases. Added a check
+ for ENABLE_TCB_PWM which will turn the restoration of PWM mode on and
+ off - will make it easier to move this to DxCore without breakage.
+ I think the cleanup more or less exactly got enough flash back that
+ the coverage of corner cases cost.
+2.4.0 S Konde Spotted amd fixed a few improperly handled corner cases, and a lot of
+ reorganization of questionable value.
+2.4.3 S Konde 11/14/21 - Removed debug code which had not been disabled and would
+ print garbage to the serial port.
+
+ **********************************************************************************************************/
+/************************************************************************************************************
+ S. Konde 7/21/21:
+I have to wonder a few things here:
+ 1. We have option for available tone pins, though very little of whatever else
+ would have been needed to support it is present. I guess on DxCore, that *could*
+ be increased, but a great deal of plumbing for it would also be needed - multiple pins, multiple timers...
+ Generally "a damned big deal" to implement, with a large number of design decisions.
+ What is strange is that I can find no sign of Arduino having supported more than one simultaneous tone pin, which
+ is the only case where this #define makes sense. Unless there were in the past arduinos withonly certain pinsthat could play tone or something
+ have.
+ 2. In light of the fact that tone does not let you output multiple tones on multiple pins at once, one could
+ argue that noTone() should shut off the tone and ignore the argument. But the official API says ignore
+ noTone(wrong_pin)
+My tentative ruling is that:
+ A. Any polyphonic tone functionality belongs in a library, tone should never have AVAILABLE_TONE_PINS =/= 1
+ One approach would be to conditionally compile the ISRs for timers based on a #define
+ that would have to be used before the library is #included; that file could check for ARDUINO_MAIN, and define
+ the ISRs if and only if it is (otherwise it would cause multiple definition error if included by sketch and other library).
+ Another approach would have the functions to control the tone output driven by each timer each in a separate file, or have
+ multiple instances of a TCB tone class, each instantiated in it's own file. The stock core has done this with the
+ HardwareSerial class since the dawn of time. Thus also not creating ISRs for timers we're not 'tone()ing' with.
+ The separate files would also provide an efficient means of keeping the variables that track the state of each
+ timer's tone separate..
+ I suspect that one could do worse than using this file, with liberal addition of the static keyword, as a basis
+ for those timer-specific tone() libraries. Personally, I don't feel like I have a good idea of what features
+ would be desirable for a tone library of that sort. I'm not an audio guy, and I have never connected a buzzer to
+ an MCU. I test these libraries with the 'scope (hell, I wouldn't be able to tell a 1kHz tone from a hole in the
+ ground without looking at it). In that hypothetical library, one design decision would have to be how to deal with
+ the most important part, that being turning the noisy thing off - basically, whether to implement multiTone() and
+ noMultiTone(pin), or to have things like `toneTimerTCB0.tone()/toneTimerTCB0.noTone()`. I am inclined
+ to think the second approach is a more sound one. If anytone wants to write such a librarty, I'm happy to advise
+ B. For the default noTone() that does not involve a library, pin should he required. Arguanbly there should be two
+ versions of it, with and without a pin argument, where the latter would shut down tone wherever it is.
+ ************************************************************************************************************/
+
+#include
+#include
+#include "Arduino.h"
+#include "pins_arduino.h"
+
+#define AVAILABLE_TONE_PINS 1
+
+#if defined(MILLIS_USE_TIMERB0)
+ #if defined(TCB1)
+ #define USE_TIMERB1
+ #else
+ #define TONE_UNAVAILABLE
+ #endif
+#else
+ #define USE_TIMERB0
+#endif
+
+#ifndef TONE_UNAVAILABLE
+ static volatile TCB_t* _timer =
+ #if defined(USE_TIMERB0)
+ &TCB0;
+ #endif
+ #if defined(USE_TIMERB1)
+ &TCB1;
+ #endif
+
+ volatile uint8_t _pin = NOT_A_PIN;
+ // timerx_toggle_count:
+ // > 0 - duration specified
+ // = 0 - stopped
+ // < 0 - infinitely (until stop() method called, or new tone() called)
+
+ volatile long timer_toggle_count;
+ volatile uint8_t *timer_outtgl_reg;
+ static uint8_t timer_bit_mask;
+ uint8_t timer_cycle_per_tgl;
+ uint8_t timer_cycle_per_tgl_count;
+
+ // helper functions
+ static void disableTimer();
+#endif
+
+
+// frequency (in hertz) and duration (in milliseconds).
+#ifndef TONE_UNAVAILABLE
+ void tone(uint8_t pin, unsigned int frequency, unsigned long duration) {
+ // Believe it or not, we don't need to turn off interrupts!
+ if (frequency == 0) {
+ noTone(pin);
+ /* turn it off (frequency 0, right? Note that this won't do anything
+ * unless that was the pin outputting tone. If it wasn't nothing
+ * will change. But there's no way of outputting a "0 Hz frequency"
+ * and a 1 Hz frequency makes even less sense. (they did ask for 0)
+ * But outputting a 1 Hz frequency on nothing (bitmask was cleared)
+ * achieves nothing except generate do-nothing interrupts regularly.
+ * When it is clear that provided arguments are sufficiently wrong
+ * that you can't do anything useful with them, at least don't
+ * do useless things instead. */
+ return;
+ }
+ // Get pin related info
+ uint8_t bit_mask = digitalPinToBitMask(pin);
+ if (bit_mask == NOT_A_PIN) return;
+ /* Same logic as above holds here except what it did was actively
+ * disruptive. When library code takes user supplied pins and looks
+ * up bitmasks and position, always check that one of them isn;t
+ * NOT_A_PIN - before you get the PORT struct. Because the port
+ * struct function cannot have it's result used safely. For bad
+ * pins, yes it returns a null pointer, 0x0000. But not only is
+ * that a valid register, it's an SFR (VPORTA.DIR)! So we don't
+ * want to end up writing to that. The convention of NULL pointers
+ * being invalid to work with is NOT safe to assume on embedded
+ * systems. */
+
+ // Serial.println(frequency);
+ long toggle_count;
+ // Calculate the toggle count
+ if (duration > 0) { // Duration defined
+ #if defined(SUPPORT_LONG_TONES) && SUPPORT_LONG_TONES == 1
+ if (duration > 65536) {
+ toggle_count = (frequency / 5) * (duration / 100);
+ } else {
+ toggle_count = (frequency * duration) / 500;
+ }
+ #else
+ toggle_count = (frequency * duration) / 500;
+ #endif
+ } else {
+ // Duration not specified -> infinite
+ // Represented internally by toggle_count = -1
+ toggle_count = -1;
+ }
+ // Calculate compare value
+ int8_t divisionfactor = 0; // no prescale, toggles at twice the frequency
+
+ // Timer settings -- will be type B timer or bust....
+ uint32_t compare_val = ((F_CPU / frequency) >> 1);
+ // We're are however disabling the timer. There may be one final interrupt at the moment we do so
+ // but that's not a problem
+ if (compare_val < 0x10000) { /* previously this tested for divisionfactor == 1,
+ * but that relied on us having already gone through the while loop to
+ * adjust it, which we haven't done yet, but we want to do this *after* the
+ * timeconsuming division operation, but *before* we actually change any
+ * other settings, because this is the point at which we stop the timer -
+ * hence it needs to be the first to be set if we want to leave interrupts on*/
+ _timer->CTRLA = TCB_CLKSEL_DIV1_gc;
+ } else {
+ _timer->CTRLA = TCB_CLKSEL_DIV2_gc;
+ divisionfactor--;
+ }
+ while ((compare_val > 0x10000) && (divisionfactor < 6)) {
+ // If the "else" branch above was followed, this is always true initially.
+ compare_val = compare_val >> 1;
+ divisionfactor++;
+ }
+ if (--compare_val > 0xFFFF) {
+ // if still too high, divisionfactor reached 6 (each phase lasts 64 overflows), meaning the
+ // user is using tone() to generate something that is not, by any stretch of the word, a
+ // "tone", and they should be generating it through other means.
+ compare_val = 0xFFFF; // do the best we can
+ }
+ // Serial.println(compare_val);
+ // Serial.println(divisionfactor);
+ // Anyway - so we know that the new pin is valid....
+ if (_pin != pin) { // ...let's see if we're using it already.
+ if (_pin != NOT_A_PIN) { // If not - were we using one before?
+ // If we were, we're gonna be in a world of hurt if we don't
+ // turn it off before we actually start reconfiguring stuff
+ // *(timer_outtgl_reg - 5) = timer_bit_mask; // pinMode(_pin, INPUT); (write dirclr for old pin)
+ // Apparently maybe it is intended for the pin to be left as an output?
+ // It does need to be LOW though, otherwise it can damage some speakers!
+ *(timer_outtgl_reg - 1) = timer_bit_mask; // digitalWrite(_pin, LOW); (write outclr for old pin)
+ }
+ // whether or not we _were_ using a pin, we are now, so configure the new one as an output...
+ PORT_t *port = digitalPinToPortStruct(pin); // Since not known at compile time, use PORTs not VPORTS.
+ timer_bit_mask = bit_mask; // We no longer need old pin's bit_mask
+ timer_outtgl_reg = (volatile uint8_t *) &(port->OUTTGL); // or toggle register.
+ *(timer_outtgl_reg - 1) = bit_mask; // digitalWrite(pin, LOW);
+ *(timer_outtgl_reg - 6) = bit_mask; // pinMode(pin, OUTPUT);
+ }
+ // Save the results of our calculations
+ timer_toggle_count = toggle_count;
+ timer_cycle_per_tgl = 1 << divisionfactor; // 1, 2, 4, 8, 16, 32, or 64 - toggle pin once per this many cycles...
+ timer_cycle_per_tgl_count = timer_cycle_per_tgl; // running count of remaining toggle cycles.
+ _timer->CCMP = compare_val; // ...and each cycle is this many timer ticks long
+ _timer->CTRLB = TCB_CNTMODE_INT_gc; // Set mode to Periodic Interrupt mode.
+ _timer->CNT = 0; // Not strictly necessary, but ensures there's no glitch.
+ _pin = pin; // Record new pin number.
+ _timer->INTCTRL = TCB_CAPTEI_bm; // Enable the interrupt (flag is already cleared)
+ _timer->CTRLA |= TCB_ENABLE_bm; // Everything is ready - Enable timer!
+ }
+#else
+ void tone(__attribute__ ((unused)) uint8_t pin, __attribute__ ((unused)) unsigned int frequency, __attribute__ ((unused)) unsigned long duration) {
+ badCall("TCB0 used for millis, no other TCBs on this part; tone requires exclusive use of a type B timer, use a differemt millis timer or a tinyAVR with a second TCB (any 2-series, or 1-series with 16k+ flash)");
+ }
+#endif
+
+// pin which currently is being used for a tone
+#ifndef TONE_UNAVAILABLE
+ void noTone(uint8_t pin) {
+ if (pin == _pin) {
+ uint8_t old_SREG = SREG; // Save SREG
+ cli(); // Interrupts off
+ timer_toggle_count = 0; // clear this one
+ _pin = NOT_A_PIN;
+ disableTimer(); // End with pin LOW, otherwise can damage some speakers.
+ SREG = old_SREG;
+ }
+ }
+#else
+ void noTone(__attribute__ ((unused)) uint8_t pin) {
+ badCall("TCB0 used for millis, no other TCBs on this part; tone requires exclusive use of a type B timer, use a differemt millis timer or a tinyAVR with a second TCB (any 2-series, or 1-series with 16k+ flash)");
+ }
+#endif
+
+#ifndef TONE_UNAVAILABLE
+ // helper function for ending tone.
+ /* Works for all timers -- the timer being disabled will go back to the
+ configuration it had on startup */
+ static void disableTimer() {
+ _timer->CTRLA = 0; // disable timer
+ _timer->INTCTRL = 0; // disable the timer interrupts, otherwise if something else configures it and assumes that it's in the reset configuration
+ // and so doesn't write INTCTRL (because it doesn't use interrupts), the tone ISR could be called inappropriately.
+ _timer->INTFLAGS = 0xFF; // Make sure the flags are cleared (flags can be set without their interrupt being enabled, these will fire as soon as it is)
+ _pin = NOT_A_PIN; // and clear _pin.
+ #if defined(ENABLE_TCB_PWM) && ENABLE_TCB_PWM == 1
+ // RESTORE PWM FUNCTIONALITY, for use with cores that use the TCBs for PWM.
+ // This section adds 12 words of flash and as many clock cycles, and could probably be done less expensively if the compiler was smarter about
+ // using ldd/std when it offered a speed/flash advantage. But it isn't, so it doesn't. =
+ _timer->CTRLB = (TCB_CNTMODE_PWM8_gc); // 8 bit PWM mode, but do not enable output yet, will do in analogWrite()
+ _timer->CCMPL = PWM_TIMER_PERIOD; // Assign 8-bit period, probably 254.
+ _timer->CCMPH = PWM_TIMER_COMPARE; // We need to set low byte in order for high byte to be written (see silicon errata).
+ _timer->CTRLA = (TCB_CLKSEL_CLKTCA_gc) | (TCB_ENABLE_bm); // Use TCA clock (250kHz) and enable
+ #endif
+ *(timer_outtgl_reg - 1) = timer_bit_mask; // Write OUTCLR, so we are sure to end with pin LOW.
+ }
+#endif
+#if !defined(TONE_UNAVAILABLE)
+ #if defined(USE_TIMERB0)
+ ISR(TCB0_INT_vect)
+ #elif defined(USE_TIMERB1)
+ ISR(TCB1_INT_vect)
+ #endif
+ {
+ if (!(--timer_cycle_per_tgl_count)) { // Are we ready to toggle? pre-decrement, then see if we're at 0 yet.
+ timer_cycle_per_tgl_count = timer_cycle_per_tgl; // reset countdown
+ *timer_outtgl_reg = timer_bit_mask; // toggle the pin
+ if (timer_toggle_count > 0) { // if duration was specified, decrement toggle count.
+ timer_toggle_count--;
+ } else if (timer_toggle_count == 0) { // If toggle count = 0 we are done.
+ disableTimer();
+ } // otherwise timer_toggle_count wasn't supplied, go on until noTone() called
+ }
+ _timer->INTFLAGS = TCB_CAPT_bm; // Clear flag
+ }
+#else
+ void disableTimer() {
+ badCall("TCB0 used for millis, no other TCBs on this part; tone requires exclusive use of a type B timer, use a differemt millis timer or a tinyAVR with a second TCB (any 2-series, or 1-series with 16k+ flash)");
+ }
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART.cpp
new file mode 100644
index 0000000..bb6cd8f
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART.cpp
@@ -0,0 +1,888 @@
+/* UART.cpp - Hardware serial library, main file.
+ * This library is free software released under LGPL 2.1.
+ * See License.md for more information.
+ * This file is part of megaTinyCore.
+ *
+ * Copyright (c) 2006 Nicholas Zambetti, Modified by
+ * 11/23/2006 David A. Mellis, 9/20/2010 Mark Sproul,
+ * 8/24/2012 Alarus, 12/3/2013 Matthijs Kooijman
+ * Others (unknown) 2013-2017, 2017-2021 Spence Konde
+ * and 2021 MX682X
+ *
+ * See UART.h for more of a record of changes.
+ */
+
+#include
+#include
+#include
+#include
+#include
+//#include
+#include "Arduino.h"
+#include "UART.h"
+#include "UART_private.h"
+
+// this next line disables the entire UART.cpp if there's no hardware serial
+#if defined(USART0) || defined(USART1) || defined(USART2) || defined(USART3) || defined(USART4) || defined(USART5)
+
+ #if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) || defined(HAVE_HWSERIAL4) || defined(HAVE_HWSERIAL5)
+ // macro to guard critical sections when needed for large TX buffer sizes
+ #if (SERIAL_TX_BUFFER_SIZE > 256)
+ #define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ #else
+ #define TX_BUFFER_ATOMIC
+ #endif
+
+ /*## ### ####
+ # # # #
+ # ### ####
+ # # # #
+ ### #### # */
+ /* There ain't no such thing as a free lunch. Every new feature makes these worse.
+ USE_ASM_TXC 2 takes an additional 2 words/2 clocks vs 1
+ USE_ASM_RXC 2 takes an additional 5 words/5 clocks vs 1
+ RXC takes another 3 words/4 clocks if SDF errata compensation is needed.
+ Both USE_ASM_RXC and USE_ASM_TXC must be mode 2 for half duplex to work
+
+ Transmit Complete for Half Duplex
+ This is a more efficient and scalable version of the TXC ISR, the original implementation is below:
+
+
+
+ #if defined(USART1)
+ ISR(USART1_TXC_vect) {
+ uint8_t ctrla;
+ while (USART1.STATUS & USART_RXCIF_bm) {
+ ctrla = USART1.RXDATAL;
+ }
+ ctrla = USART1.CTRLA;
+ ctrla |= USART_RXCIE_bm; // turn on receive complete
+ ctrla &= ~USART_TXCIE_bm; // turn off transmit complete
+ USART1.CTRLA = ctrla;
+ }
+
+ In the USARTn.cpp, there's something like this that puts the low byte of the address of the USART into r30
+ after saving the register. Then it just jumps to this routine, which loads the (always the same) high byte!
+ and finishes up clearing out the other register we will need and saving the SREG. The logic is very simple,
+ It's just ugly. It gets worse for the other interrupts because we have to work with the class, not just the
+ hardware. Crucially the only thing different betweren the USARTs here isthe addressthey're working with.
+ Much of the benefit comes from being able to get the benefits of functionsin terms of flash use without the
+ penalties that come with using a true CALL instruction in an ISR (50-80 byte prologue + epiloge), and also
+ being aware that the X register can't do displacement when planning what goes in which regiseser... which
+ is not avr-gcc's strong suite, and often ends up displacing from the X with adiw/sbiw spam. savings for one
+ copy of it is small. Savings for several is gets large fast! Performance is better, but not much.
+ Biggest advantage is for 2-series with the dual UARTs, but potentially as little as 4k of flash.
+
+ TXC isr starts from this:
+ ISR(USART1_TXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t" // 1
+ "ldi r30, 0x20" "\n\t" // 1
+ "rjmp do_txc" "\n\t" // 1
+ :::);
+ }
+
+ */
+
+ #if USE_ASM_TXC == 2
+ void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) _do_txc(void) {
+ __asm__ __volatile__(
+ "_do_txc:" "\n\t" // We start out 11-13 clocks after the interrupt
+ "push r24" "\n\t" // r30 and r31 pushed before this.
+ "in r24, 0x3f" "\n\t" // Save SREG
+ "push r24" "\n\t" //
+ "push r25" "\n\t" //
+ "push r28" "\n\t" //
+ "push r29" "\n\t" //
+ "ldd r28, Z + 8" "\n\t" // Load USART into Y pointer, low byte
+ "ldi r29, 0x08" "\n\t" // all USARTs are 0x08n0 where n is an even hex digit.
+ "ldd r25, Y + 5" "\n\t" // Y + 5 = USARTn.CTRLA read CTRLA
+ "_txc_flush_rx:" "\n\t" // start of rx flush loop.
+ "ld r24, Y" "\n\t" // Y + 0 = USARTn.RXDATAL rx data
+ "ldd r24, Y + 4" "\n\t" // Y + 4 = USARTn.STATUS
+ "sbrc r24, 7" "\n\t" // if RXC bit is clear...
+ "rjmp _txc_flush_rx" "\n\t" // .... skip this jump to remove more from the buffer.
+ "andi r25, 0xBF" "\n\t" // clear TXCIE
+ "ori r25, 0x80" "\n\t" // set RXCIE
+ "std Y + 5, r25" "\n\t" // store CTRLA
+// "ldd r24, Z + 12" "\n\t"
+// "ahha, always, true" "\n\t" // wait, if we're in TXC, We are in half duplex mode, duuuuh
+// "sbrs r24, 2" "\n\t" // if we're in half duplex skip...
+// "rjmp .+ 6" "\n\t" // a jump over the next three instructoins. Do do them iff in half duplex only
+// "ori r24, 0x10" "\n\t" // add the "there's an echo in here" bit
+// "std Z + 12, r24" "\n\t" // Store modified state
+ "pop r29" "\n\t"
+ "pop r28" "\n\t"
+ "pop r25" "\n\t"
+ "pop r24" "\n\t" // pop r24 to get old SREG back
+ "out 0x3F, r24" "\n\t" // restore sreg.
+ "pop r24" "\n\t" // pop r24 restore it
+ "pop r31" "\n\t" // and r31
+ "pop r30" "\n\t" // Pop the register the ISR did
+ "reti" "\n" // return from the interrupt.
+ ::
+ );
+ __builtin_unreachable();
+ }
+ #elif USE_ASM_TXC == 1
+ void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) _do_txc(void) {
+ __asm__ __volatile__(
+ "_do_txc:" "\n\t" //
+ "push r31" "\n\t" // push other half of Z register.
+ "push r24" "\n\t" // push r24
+ "in r24, 0x3f" "\n\t" // save sreg to r24
+ "push r24" "\n\t" // and push that. r30 pushed and loaded by ISR already.
+ "ldi r31, 0x08" "\n\t" // all USARTs are 0x08n0 where n is an even hex digit.
+ "_txc_flush_rx:" "\n\t" // start of rx flush loop.
+ "ld r24, Z" "\n\t" // Z + 0 = USARTn.RXDATAL rx data
+ "ldd r24, Z + 4" "\n\t" // Z + 4 = USARTn.STATUS
+ "sbrc r24, 7" "\n\t" // if RXC bit is set...
+ "rjmp _txc_flush_rx" "\n\t" // .... skip this jump to remove more from the buffer.
+ "ldd r24, Z + 5" "\n\t" // Z + 5 = USARTn.CTRLA read CTRLA
+ "andi r24, 0xBF" "\n\t" // clear TXCIE
+ "ori r24, 0x80" "\n\t" // set RXCIE
+ "std Z + 5, r24" "\n\t" // store CTRLA
+ "pop r24" "\n\t" // pop r24, xcontaining old sreg.
+ "out 0x3f, r24" "\n\t" // restore it
+ "pop r24" "\n\t" // pop r24 to get it's old value back
+ "pop r31" "\n\t" // and r31
+ "pop r30" "\n\t" // Pop the register the ISR pushed
+ "reti" "\n" // return from the interrupt.
+ ::);
+ __builtin_unreachable();
+ }
+ #endif
+ /*
+ We are starting from this:
+ ISR(USART0_RXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ :::);
+ __asm__ __volatile__(
+ "rjmp do_rxc" "\n\t"
+ ::"z"(&Serialn));
+ __builtin_unreachable();
+ }
+
+ */
+
+ #if ((USE_ASM_RXC == 1) && (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) )
+ void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) _do_rxc(void) {
+ __asm__ __volatile__(
+ "_do_rxc:" "\n\t" // We start out 11-13 clocks after the interrupt
+ "push r18" "\n\t" // r30 and r31 pushed before this.
+ "in r18, 0x3f" "\n\t" // Save SREG
+ "push r18" "\n\t" //
+ "push r19" "\n\t" // Ugh we needed another register....
+ "push r24" "\n\t" //
+ "push r25" "\n\t" //
+ "push r28" "\n\t" //
+ "push r29" "\n\t" //
+ "ldd r28, Z + 8" "\n\t" // Load USART into Y pointer
+ // "ldd r29, Z + 9" "\n\t" // We interact with the USART only this once
+ "ldi r29, 0x08" "\n\t" // High byte always 0x08 for USART peripheral: Save-a-clock. 11 clocks to here
+ #if defined(ERRATA_USART_WAKE) // This bug appears to be near-universal, 4 clocks to workaround.
+ "ldd r18, Y + 6" "\n\t"
+ "andi r18, 0xEF" "\n\t"
+ "std Y + 6, r18" "\n\t" // turn off SFD interrupt before reading RXDATA so we don't corrupt the next character.
+ #endif
+ "ldd r24, Y + 1" "\n\t" // Y + 1 = USARTn.RXDATAH - load high byte first - 16 clocks from here to next
+ "ld r25, Y" "\n\t" // Y + 0 = USARTn.RXDATAL - then low byte of RXdata
+ "andi r24, 0x46" "\n\t" // extract framing, parity bits.
+ "lsl r24" "\n\t" // leftshift them one place
+ "ldd r19, Z + 12" "\n\t" // load _state
+ "or r19, r24" "\n\t" // bitwise or with errors extracted from _state
+ "sbrc r24, 2" "\n\t" // if there's a parity error, then do nothing more (note the leftshift).
+ "rjmp _end_rxc" "\n\t" // Copies the behavior of stock implementation - framing errors are ok, apparently...
+ //#if USE_ASM_TXC == 2 && USE_ASM_RXC == 2
+ //"sbic 0x1F, 0" "\n\t"
+ //"sbi 0x01, 2" "\n\t"
+ //"sbrs r19, 4" "\n\t" // Is there an echo in here?
+ //"rjmp storechar" "\n\t" // if not skip these next isns "\n\t"
+ //"sbic 0x1F, 0" "\n\t"
+ //"sbi 0x02, 4" "\n\t"
+ //"andi r19, 0xEF" "\n\t" // clear t
+ //"rjmp _end_rxc" "\n\t"
+ // "storechar:"
+ //#endif
+ "ldd r28, Z + 13" "\n\t" // load current head index
+ "ldi r24, 1" "\n\t" // Clear r24 and initialize it with 1
+ "add r24, r28" "\n\t" // add current head index to it
+ #if SERIAL_RX_BUFFER_SIZE == 256
+ // No additional action needed, head wraps naturally.
+ #elif SERIAL_RX_BUFFER_SIZE == 128
+ "andi r24, 0x7F" "\n\t" // Wrap the head around
+ #elif SERIAL_RX_BUFFER_SIZE == 64
+ "andi r24, 0x3F" "\n\t" // Wrap the head around
+ #elif SERIAL_RX_BUFFER_SIZE == 32
+ "andi r24, 0x1F" "\n\t" // Wrap the head around
+ #elif SERIAL_RX_BUFFER_SIZE == 16
+ "andi r24, 0x0F" "\n\t" // Wrap the head around
+ #endif
+ "ldd r18, Z + 14" "\n\t" // load tail index This to _end_rxc is 11 clocks unless the buffer was full, in which case it's 8.
+ "cp r18, r24" "\n\t" // See if head is at tail. If so, buffer full. The incoming data is discarded,
+ "breq _buff_full_rxc" "\n\t" // because there is noplace to put it, and we just restore state and leave.
+ "add r28, r30" "\n\t" // r28 has what would be the next index in it.
+ "mov r29, r31" "\n\t" // and this is the high byte of serial instance
+ "ldi r18, 0" "\n\t" // need a known zero to carry.
+ "adc r29, r18" "\n\t" // carry - Y is now pointing 17 bytes before head
+ "std Y + 17, r25" "\n\t" // store the new char in buffer
+ "std Z + 13, r24" "\n\t" // write that new head index.
+ "_end_rxc:" "\n\t"
+ "std Z + 12, r19" "\n\t" // record new state including new errors
+ // Epilogue: 9 pops + 1 out + 1 reti +1 std = 24 clocks
+ "pop r29" "\n\t" // Y Pointer was used for head and usart.
+ "pop r28" "\n\t" //
+ "pop r25" "\n\t" // r25 held the received character
+ "pop r24" "\n\t" // r24 held rxdatah, then the new head.
+ "pop r19" "\n\t" // restore r19 which held the value that State will have after this.
+ "pop r18" "\n\t" // Restore saved SREG
+ "out 0x3f, r18" "\n\t" // and write back
+ "pop r18" "\n\t" // used as tail offset, and then as known zero.
+ "pop r31" "\n\t" // end with Z which the isr pushed to make room for
+ "pop r30" "\n\t" // pointer to serial instance
+ "reti" "\n\t" // return
+ "_buff_full_rxc:" "\n\t" // potential improvement: move _buff_full_rxc to after the reti, and then rjmp back, saving 2 clocks for the common case
+ "ori r19, 0x40" "\n\t" // record that there was a ring buffer overflow. 1 clk
+ "rjmp _end_rxc" "\n\t" // and now jump back to end. That way we don't need to jump over this in the middle of the common case.
+ ::); // total: 77 or 79 clocks, just barely squeaks by for cyclic RX of up to RX_BUFFER_SIZE characters.
+ __builtin_unreachable();
+
+ }
+ #elif defined(USE_ASM_RXC) && USE_ASM_RXC == 1
+ #warning "USE_ASM_RXC is defined and this has more than one serial port, but the buffer size is not supported, falling back to the classical RXC."
+ #else
+ #if defined(PERMIT_USART_WAKE)
+ #error "USART Wake is not supported by the non-ASM RXC interrupt handler"
+ #endif
+ void HardwareSerial::_rx_complete_irq(HardwareSerial& HardwareSerial) {
+ // if (bit_is_clear(*_rxdatah, USART_PERR_bp)) {
+ uint8_t rxDataH = HardwareSerial._hwserial_module->RXDATAH;
+ uint8_t c = HardwareSerial._hwserial_module->RXDATAL; // no need to read the data twice. read it, then decide what to do
+ rx_buffer_index_t rxHead = HardwareSerial._rx_buffer_head;
+
+ if (!(rxDataH & USART_PERR_bm)) {
+ // No Parity error, read byte and store it in the buffer if there is room
+ // unsigned char c = HardwareSerial._hwserial_module->RXDATAL;
+ #if SERIAL_RX_BUFFER_SIZE > 256
+ rx_buffer_index_t i = (uint16_t)(rxHead + 1) % SERIAL_RX_BUFFER_SIZE;
+ #else
+ rx_buffer_index_t i = (uint8_t)(rxHead + 1) % SERIAL_RX_BUFFER_SIZE;
+ #endif
+
+ // 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 != HardwareSerial._rx_buffer_tail) {
+ HardwareSerial._rx_buffer[rxHead] = c;
+ HardwareSerial._rx_buffer_head = i;
+ }
+ }
+ }
+ #endif
+ /*
+ DRE starts just like RXC
+ ISR(USART0_DRE_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ push r30
+ push r31 "\n\t"
+ :::);
+ __asm__ __volatile__(
+ "rjmp do_dre" "\n\t"
+ ::"z"(&Serialn));
+ __builtin_unreachable();
+
+ */
+
+ #if USE_ASM_DRE == 1 && (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
+ (SERIAL_TX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16)
+ void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) _do_dre(void) {
+ __asm__ __volatile__(
+ "_do_dre:" "\n\t"
+ "push r18" "\n\t"
+ "in r18, 0x3F" "\n\t"
+ "push r18" "\n\t"
+ "push r24" "\n\t"
+ "push r25" "\n\t"
+ "push r26" "\n\t"
+ "push r27" "\n\t"
+ "set" "\n\t" // SEt the T flag - we use this to determine how we got here and hence whether to rjmp to end of poll or reti
+ "_poll_dre:" "\n\t"
+ "push r28" "\n\t"
+ "push r29" "\n\t"
+ "ldi r18, 0" "\n\t"
+ "ldd r28, Z + 8" "\n\t" // usart in Y
+ // "ldd r29, Z + 9" "\n\t" // usart in Y
+ "ldi r29, 0x08" "\n\t" // High byte always 0x08 for USART peripheral: Save-a-clock.
+ "ldd r25, Z + 16" "\n\t" // tx tail in r25
+ "movw r26, r30" "\n\t" // copy of serial in X
+ "add r26, r25" "\n\t" // SerialN + txtail
+ "adc r27, r18" "\n\t" // X = &Serial + txtail
+ #if SERIAL_RX_BUFFER_SIZE == 256 // RX buffer determines offset from start of class to TX buffer
+ "subi r26, 0xEF" "\n\t" // There's no addi/adci, so we instead subtract (65536-(offset we want to add))
+ "sbci r27, 0xFE" "\n\t" // +273
+ "ld r24, X" "\n\t" // grab the character
+ #elif SERIAL_RX_BUFFER_SIZE == 128
+ "subi r26, 0x6F" "\n\t" //
+ "sbci r27, 0xFF" "\n\t" // +145
+ "ld r24, X" "\n\t" // grab the character
+ #elif SERIAL_RX_BUFFER_SIZE == 64
+ "subi r26, 0xAF" "\n\t" //
+ "sbci r27, 0xFF" "\n\t" // +81
+ "ld r24, X" "\n\t" // grab the character
+ #elif SERIAL_RX_BUFFER_SIZE == 32
+ "adiw r26, 0x31" "\n\t" // +49
+ "ld r24, X" "\n\t" // grab the character
+ #elif SERIAL_RX_BUFFER_SIZE == 16
+ "adiw r26, 0x21" "\n\t" // +33
+ "ld r24, X" "\n\t" // grab the character
+ #endif
+ "ldi r18, 0x40" "\n\t"
+ "std Y + 4, r18" "\n\t" // Y + 4 = USART.STATUS - clear TXC
+ "std Y + 2, r24" "\n\t" // Y + 2 = USART.TXDATAL - write char
+ "subi r25, 0xFF" "\n\t" // txtail +1
+ #if SERIAL_TX_BUFFER_SIZE == 256
+ // // No action needed to wrap the tail around -
+ #elif SERIAL_TX_BUFFER_SIZE == 128
+ "andi r25, 0x7F" "\n\t" // Wrap the tail around
+ #elif SERIAL_TX_BUFFER_SIZE == 64
+ "andi r25, 0x3F" "\n\t" // Wrap the tail around
+ #elif SERIAL_TX_BUFFER_SIZE == 32
+ "andi r25, 0x1F" "\n\t" // Wrap the tail around
+ #elif SERIAL_TX_BUFFER_SIZE == 16
+ "andi r25, 0x0F" "\n\t" // Wrap the tail around
+ #endif
+ "ldd r24, Y + 5" "\n\t" // Y + 5 = USART.CTRLA - get CTRLA into r24
+ "ldd r18, Z + 15" "\n\t" // txhead into r18
+ "cpse r18, r25" "\n\t" // if they're the same
+ "rjmp _done_dre_irq" "\n\t"
+ "andi r24, 0xDF" "\n\t" // DREIE off
+ "std Y + 5, r24" "\n\t" // write new ctrla
+ "_done_dre_irq:" "\n\t" // Beginning of the end of DRE
+ "std Z + 16, r25" "\n\t" // store new tail
+ "pop r29" "\n\t" // pop Y
+ "pop r28" "\n\t" // finish popping Y
+ #if PROGMEM_SIZE > 8192
+ "brts .+4" "\n\t" // hop over the next insn if T bit set, means entered through do_dre, rather than poll_dre
+ "jmp _poll_dre_done" "\n\t" // >8k parts must us jmp, otherwise it will give PCREL error.
+ #else
+ "brts .+2" "\n\t" // hop over the next insn if T bit set, means entered through do_dre, rather than poll_dre
+ "rjmp _poll_dre_done" "\n\t" // 8k parts can use RJMP
+ #endif
+ "pop r27" "\n\t" // and continue with popping registers. 21 clocks left
+ "pop r26" "\n\t"
+ "pop r25" "\n\t"
+ "pop r24" "\n\t"
+ "pop r18" "\n\t" // pop SREG value from stack
+ "out 0x3f, r18" "\n\t" // restore SREG
+ "pop r18" "\n\t" // pop old r18
+ "pop r31" "\n\t" // pop the Z that the isr pushed.
+ "pop r30" "\n\t"
+ "reti" "\n" // and RETI!
+ ::);
+ __builtin_unreachable();
+ }
+ #elif USE_ASM_DRE == 1
+ #warning "USE_ASM_DRE == 1, but the buffer sizes are not supported, falling back to the classical DRE."
+ #else
+ void HardwareSerial::_tx_data_empty_irq(HardwareSerial& HardwareSerial) {
+ USART_t* usartModule = (USART_t*)HardwareSerial._hwserial_module; // reduces size a little bit
+ tx_buffer_index_t txTail = HardwareSerial._tx_buffer_tail;
+
+ // Check if tx buffer already empty. when called by _poll_tx_data_empty()
+ // if (HardwareSerial._tx_buffer_head == txTail) {
+ // Buffer empty, so disable "data register empty" interrupt
+ // usartModule->CTRLA &= (~USART_DREIE_bm);
+ // return;
+ //} // moved to poll function to make ISR smaller and faster
+
+ // There must be more data in the output
+ // buffer. Send the next byte
+ uint8_t c = HardwareSerial._tx_buffer[txTail];
+
+ // clear the TXCIF flag -- "can be cleared by writing a one to its bit
+ // location". This makes sure flush() won't return until the bytes
+ // actually got written. It is critical to do this BEFORE we write the next byte
+ usartModule->STATUS = USART_TXCIF_bm;
+ usartModule->TXDATAL = c;
+
+ txTail = (txTail + 1) & (SERIAL_TX_BUFFER_SIZE - 1); //% SERIAL_TX_BUFFER_SIZE;
+ uint8_t ctrla = usartModule->CTRLA;
+ if (HardwareSerial._tx_buffer_head == txTail) {
+ // Buffer empty, so disable "data register empty" interrupt
+ ctrla &= ~(USART_DREIE_bm);
+ usartModule->CTRLA = ctrla;
+ }
+ HardwareSerial._tx_buffer_tail = txTail;
+ }
+ #endif
+
+ // To invoke data empty "interrupt" via a call, use this method
+ void HardwareSerial::_poll_tx_data_empty(void) {
+ if ((!(SREG & CPU_I_bm)) || CPUINT.STATUS) {
+ // We're here because we're waiting for space in the buffer *or* we're in flush
+ // and waiting for the last byte to leave, yet we're either in an ISR, or
+ // interrupts are disabled so the ISR can't fire on it's own.
+ //
+ // Interrupts are disabled either globally or for data register empty,
+ // or we are in another ISR. (It doesn't matter *which* ISR we are in
+ // whether it's another level 0, the priority one, or heaven help us
+ // the NMI, if the user code says to print something or flush the buffer
+ // we might as well do it. It is entirely plausible that an NMI might
+ // attempt to print out some sort of record of what happened.
+ //
+ // so we'll have to poll the "data register empty" flag ourselves.
+ // If it is set, pretend an interrupt has happened and call the handler
+ // to free up space for us.
+ // -Spence 10/23/20
+ // Invoke interrupt handler only if conditions data register is empty
+ if ((*_hwserial_module).STATUS & USART_DREIF_bm) {
+ if (_tx_buffer_head == _tx_buffer_tail) {
+ // Buffer empty, so disable "data register empty" interrupt
+ (*_hwserial_module).CTRLA &= (~USART_DREIE_bm);
+
+ return;
+ }
+ #if !(USE_ASM_DRE == 1 && (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
+ (SERIAL_TX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
+ _tx_data_empty_irq(*this);
+ #else // We're using ASM DRE
+ #ifdef USART1
+ void * thisSerial = this;
+ #endif
+ __asm__ __volatile__(
+ "clt" "\n\t" // Clear the T flag to signal to the ISR that we got there from here. This is safe per the ABI - The T-flag can be treated like R0
+ #if PROGMEM_SIZE > 8192
+ "jmp _poll_dre" "\n\t"
+ #else
+ "rjmp _poll_dre" "\n\t"
+ #endif
+ "_poll_dre_done:" "\n"
+ #ifdef USART1
+ ::"z"((uint16_t)thisSerial)
+ #else
+ ::"z"(&Serial0)
+ #endif
+ : "r18","r19","r24","r25","r26","r27"); // these got saved and restored in the ISR context, but here we don't need top and in many cases no action is needed.
+ // the Y pointer was already handled, because as a call-saved register, it would always need to be saved and restored, so we save 4 words of flash by doing that after
+ // jumps into the middle of the ISR, and before it jumps back here.
+ #endif
+ }
+ }
+ // In case interrupts are enabled, the interrupt routine will be invoked by itself
+ // Note that this currently does not handle cases where the DRE interruopt becomes
+ // disabled, yet you are actually attempting to send. I don't think it can happen.
+ }
+
+ /*### # # #### # ### ### # # #### ##### # # ### #### ###
+ # # # # # # # # # ## ## # # # # # # # # #
+ #### # # #### # # # # # # ### # ##### # # # # ###
+ # # # # # # # # # # # # # # # # # # #
+ # ### #### #### ### ### # # #### # # # ### #### ##*/
+
+ // Invoke this function before 'begin' to define the pins used
+ bool HardwareSerial::pins(uint8_t tx, uint8_t rx) {
+ uint8_t ret_val = _pins_to_swap(_module_number, tx, rx); // return 127 when correct swap number wasn't found
+ return swap(ret_val);
+ }
+
+ uint8_t HardwareSerial::_pins_to_swap(uint8_t port_num, uint8_t tx_pin, uint8_t rx_pin) {
+ if (tx_pin == NOT_A_PIN && rx_pin == NOT_A_PIN) {
+ return 128; // get MUX_NONE
+ } else {
+ const uint8_t * muxtab_ptr = _usart_pins[port_num];
+ if (*muxtab_ptr == tx_pin && (*(muxtab_ptr + 1) == rx_pin)) {
+ return 0;
+ }
+ #if !defined(__AVR_ATtinyx24__)
+ if ((*(muxtab_ptr + 4)) == tx_pin && (*(muxtab_ptr + 5) == rx_pin))
+ #else
+ if (port_num && (*(muxtab_ptr + 4)) == tx_pin && (*(muxtab_ptr + 5) == rx_pin))
+ #endif
+ {
+ return 1;
+ }
+ return NOT_A_MUX; // At this point, we have checked all group codes for this peripheral. It ain't there. Return NOT_A_MUX.
+ }
+ }
+
+ uint8_t HardwareSerial::getPin(uint8_t pin) {
+ if (pin >3) return NOT_A_PIN;
+ return (_usart_pins[_module_number + _pin_set][pin]);
+ }
+
+ bool HardwareSerial::swap(uint8_t newmux) {
+ #if !(MEGATINYCORE_SERIES == 2 && defined(__ATtinyxy4__))
+ // it's either a 0/1-series: They have options of 0 and 1.
+ // Or it's a 2-series with 20 or 24 pins. Both USARTS have option of 0 & 1.
+ if (newmux < 2) {
+ _pin_set = newmux;
+ return true;
+ }
+ #else
+ // means it is a 14-pin 2-series, whose second USART doesn't have an alternate location.
+ if (_module_number + newmux < 2) {
+ _pin_set = newmux;
+ return true;
+ }
+ #endif
+ #if MEGATINYCORE_SERIES == 2
+ else if (newmux == MUX_NONE) { // 128 codes for MUX_NONE
+ _pin_set = 3;
+ return true;
+ }
+ #endif
+ else {
+ _pin_set = 0;
+ }
+ return false;
+ }
+
+ void HardwareSerial::begin(unsigned long baud, uint16_t options) {
+ // Make sure no transmissions are ongoing and USART is disabled in case begin() is called by accident
+ // without first calling end()
+ if (_state & 1) {
+ this->end();
+ }
+
+ uint8_t ctrlc = (uint8_t) options;
+ if (ctrlc == 0) { // see if they passed anything in low byte or SERIAL_CONFIG_VALID.
+ ctrlc = (uint8_t)SERIAL_8N1; // low byte of 0 could mean they want SERIAL_5N1. Or that they thought they'd
+ }
+ ctrlc &= ~0x04; // Now unset that 0x04 bit if it's set, because none of the values with it set are supported. We use that to smuggle in a "this constant was specified" for 5N1
+ uint8_t ctrla = (uint8_t) (options >> 8);// CTRLA will get the remains of the options high byte.
+ uint16_t baud_setting = 0; // at this point it should be able to reuse those 2 registers that it received options in!
+ uint8_t ctrlb = (~ctrla & 0xC0); // Top two bits (TXEN RXEN), inverted so they match he sense in the registers.
+ if (baud > F_CPU / 16) { // if this baud is too fast for non-U2X
+ ctrlb |= USART_RXMODE0_bm; // set the U2X bit in what will become CTRLB
+ baud >>= 1; // And lower the baud rate by haldf
+ }
+ baud_setting = (((4 * F_CPU) / baud)); // And now the registers that baud was passed in are done.
+ if (baud_setting < 64) // so set to the maximum baud rate setting.
+ baud_setting= 64; // set the U2X bit in what will become CTRLB
+ //} else if (baud < (F_CPU / 16800)) { // Baud rate is too low
+ // baud_setting = 65535; // minimum baud rate.'
+ // Baud setting done now we do the other options not in CTRLC;
+ if (ctrla & 0x04) { // is ODME option set?
+ ctrlb |= USART_ODME_bm; // set the bit in what will become CTRLB
+ }
+ // Baud setting done now we do the other options.
+ // that aren't in CTRLC;
+ ctrla &= 0x2B; // Only LBME and RS485 (both of them); will get written to CTRLA, but we leave the event bit.
+ if (ctrlb & USART_RXEN_bm) { // if RX is to be enabled
+ ctrla |= USART_RXCIE_bm; // we will want to enable the ISR.
+ }
+ uint8_t setpinmask = ctrlb & 0xC8; // ODME in bit 3, TX and RX enabled in bit 6, 7
+ if ((ctrla & USART_LBME_bm) && (setpinmask == 0xC8)) { // if it's open-drain and loopback, need to set state bit 2.
+ _state |= 2; // since that changes some behavior (RXC disabled while sending) // Now we should be able to ST _state.
+ setpinmask |= 0x10; // this tells _set_pins not to disturb the configuration on the RX pin.
+ }
+ if (ctrla & USART_RS485_bm) { // RS485 mode recorded here too... because we need to set
+ setpinmask |= 0x01; // set pin output if we need to do that. Datasheet isn't clear
+ }
+ uint8_t oldSREG = SREG;
+ cli();
+ volatile USART_t* MyUSART = _hwserial_module;
+ (*MyUSART).CTRLB = 0; // gotta disable first - some things are enable-locked.
+ (*MyUSART).CTRLC = ctrlc; // No reason not to set first.
+ (*MyUSART).BAUD = baud_setting; // Wish I could have set it long ago
+ if (ctrla & 0x20) { // Now we have to do a bit of work
+ setpinmask &= 0x7F; // Remove the RX pin in this case because we get the input from elsewhere.
+ (*MyUSART).EVCTRL = 1; // enable event input - not clear from datasheet what's needed to
+ (*MyUSART).TXPLCTRL = 0xFF; // Disable pulse length encoding.
+ } else {
+ (*MyUSART).EVCTRL = 0; // This needs to be turned off when not in use.
+ } // finally strip out the SERIAL_EVENT_RX bit which is in the DREIE
+ (*MyUSART).CTRLA = ctrla & 0xDF; // position, which we never set in begin.
+ (*MyUSART).CTRLB = ctrlb; // Set the all important CTRLB...
+ _set_pins(_module_number, _pin_set, setpinmask); // set up the pin(s)
+ SREG = oldSREG; // re-enable interrupts, and we're done.
+ }
+
+ void HardwareSerial::_set_pins(uint8_t mod_nbr, uint8_t mux_set, uint8_t enmask) {
+ // Set the mux register
+ #if defined(PORTMUX_USARTROUTEA)
+ uint8_t muxregval = PORTMUX.USARTROUTEA;
+ muxregval &= ~(mod_nbr ? 0x0C : 0x03);
+ PORTMUX.USARTROUTEA = (muxregval) | (mux_set << (mod_nbr ? 2 : 0)); // shift muxset left if needed.
+
+ #else
+ if (mux_set) {
+ PORTMUX.CTRLB |= 0x01; // for 0/1-series this can only be zero or 1
+ } else {
+ PORTMUX.CTRLB &= 0xFE;
+ }
+ #endif
+ #if MEGATINYCORE_SERIES == 2
+ if (mux_set == 3) { // not connected to pins...
+ return; // so we are done!
+ }
+ #endif
+ const uint8_t* muxrow = &(_usart_pins[mod_nbr + mux_set][0]);
+ if ((enmask & 0x40 && !(enmask & 0x08))) {
+ pinMode(muxrow[0], OUTPUT); // If and only if TX is enabled and open drain isn't should the TX interrupt be used. .
+ } else if (enmask & 0x50) { // if it is enabled but is in open drain mode, or is disabled, but loopback is enabled
+ // TX should be INPUT_PULLUP.
+ pinMode(muxrow[0], INPUT_PULLUP);
+ }
+ if (enmask & 0x80 && !(enmask & 0x10)) {
+ // Likewise if RX is enabled, unless loopback mode is too (in which case we caught it above, it should be pulled up
+ pinMode(muxrow[1], INPUT_PULLUP);
+ }
+ if (enmask & 0x01) { // finally if RS485 mode is enabled, we make XDIR output, otherwise it can't drive the pin.
+ pinMode(muxrow[3], OUTPUT); // make XDIR output.
+ }
+ /*
+ uint8_t muxrow = mod_nbr + mux_set;
+ if ((enmask & 0x40 && !(enmask & 0x08))) {
+ pinMode(_usart_pins[muxrow][0], OUTPUT); // If any only if TX is enabled and open drain isn't should the TX pin be output.
+ } else if (enmask & 0x50) { // if it is enabled but is in open drain mode, or is disabled, but loopback is enabled
+ // TX should be INPUT_PULLUP.
+ pinMode(_usart_pins[muxrow][0], INPUT_PULLUP);
+ }
+ if (enmask & 0x80 && !(enmask & 0x10)) {
+ // Likewise if RX is enabled, unless loopback mode is too (in which case we caught it above, it should be pulled up
+ pinMode(_usart_pins[muxrow][1], INPUT_PULLUP);
+ }
+ if (enmask & 0x01) { // finally if RS485 mode is enabled, we make XDIR output, otherwise it can't drive the pin.
+ pinMode(_usart_pins[muxrow][3], OUTPUT); // make XDIR output.
+ }
+ // And it is up to the user to configure the XCK pin as required for their application if they are using that.
+ */
+ /*
+ uint8_t muxrow = mod_nbr + mux_set;
+ if (enmask & 0x40) { // tx enabled
+ pinMode(_usart_pins[muxrow][0], (enmask & 0x08) ? INPUT_PULLUP : OUTPUT);
+ }
+ if (enmask & 0x80) {
+ if (!(enmask & 0x10)) {
+
+ pinMode(_usart_pins[muxrow][1], INPUT_PULLUP);
+ } else if (!(enmask & 0x40)) { // Loopback mode set, TX disabled, and RX enabled. Wacky configuration, but I guess that means TX should be INPUT_PULLUP.
+ pinMode(_usart_pins[muxrow][0], INPUT_PULLUP);
+ }
+ }
+ if (enmask & 0x01) { // RS485 enabled
+ pinMode(_usart_pins[muxrow][3], OUTPUT); // make XDIR output.
+ }
+ */
+ }
+
+ void HardwareSerial::end() {
+ // wait for transmission of outgoing data
+ flush();
+ // Disable receiver and transmitter as well as the RX complete and the data register empty interrupts.
+ // TXCIE only used in half duplex - we can just turn the damned thing off yo!
+ volatile USART_t * temp = _hwserial_module; /* compiler does a slightly better job with this. */
+ temp -> CTRLB = 0; //~(USART_RXEN_bm | USART_TXEN_bm);
+ temp -> CTRLA = 0; //~(USART_RXCIE_bm | USART_DREIE_bm | USART_TXCIE_bm);
+ temp -> STATUS = USART_TXCIF_bm | USART_RXCIF_bm; // want to make sure no chance of that firing in error now that the USART is off. TXCIE only used in half duplex
+ // clear any received data
+ _rx_buffer_head = _rx_buffer_tail;
+
+ // Note: Does not change output pins
+ // though the datasheetsays turning the TX module off sets it to input.
+ _state = 0;
+ }
+
+ int HardwareSerial::available(void) {
+ return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) & (SERIAL_RX_BUFFER_SIZE - 1); //% SERIAL_RX_BUFFER_SIZE;
+ }
+
+ int HardwareSerial::peek(void) {
+ if (_rx_buffer_head == _rx_buffer_tail) {
+ return -1;
+ } else {
+ return _rx_buffer[_rx_buffer_tail];
+ }
+ }
+
+ int HardwareSerial::read(void) {
+ // if the head isn't ahead of the tail, we don't have any characters
+ if (_rx_buffer_head == _rx_buffer_tail) {
+ return -1;
+ } else {
+ unsigned char c = _rx_buffer[_rx_buffer_tail];
+ _rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) & (SERIAL_RX_BUFFER_SIZE - 1); // % SERIAL_RX_BUFFER_SIZE;
+ return c;
+ }
+ }
+
+ int HardwareSerial::availableForWrite(void) {
+ tx_buffer_index_t head;
+ tx_buffer_index_t tail;
+
+ TX_BUFFER_ATOMIC {
+ head = _tx_buffer_head;
+ tail = _tx_buffer_tail;
+ }
+ if (head >= tail) {
+ return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
+ }
+ return tail - head - 1;
+ }
+
+ void HardwareSerial::flush() {
+ // If we have never written a byte, no need to flush. This special
+ // case is needed since there is no way to force the TXCIF (transmit
+ // complete) bit to 1 during initialization
+ if (!(_state & 1)) {
+ return;
+ }
+
+ // Check if we are inside an ISR already (e.g. connected to a different peripheral then UART), in which case the UART ISRs will not be called.
+ // Spence 10/23/20: Changed _poll_tx_data_empty() to instead call the ISR directly in this case too
+ // Why elevate the interrupt if we're going to go into a busywait loop checking if the interrupt is disabled and if so, check for the bit and
+ // manually call the ISR if the bit is set... *anyway*? Plus, in write(), this mode will be enabled upon a write of a single character from an ISR
+ // and will stay that way until the buffer is empty, which would mean that the fairly long and slow UART TX ISR would have priority over a
+ // potentially very fast interrupt that the user may have set to priority level 1. Just because a whizz-bang feature is there doesn't mean
+ // it's appropriate to use for applications where it has only very small benefits, and significant risk of surprising the user and causing
+ // breakage of code that would otherwise work. Finally, the previous implementation didn't check if it was called from the current lvl1 ISR
+ // and in that case flush(), and write() with full buffer would just straight up hang...
+
+ // Spin until the data-register-empty-interrupt is disabled and TX complete interrupt flag is raised
+ while (((*_hwserial_module).CTRLA & USART_DREIE_bm) || (!((*_hwserial_module).STATUS & USART_TXCIF_bm))) {
+
+ // If interrupts are globally disabled or the and DR empty interrupt is disabled,
+ // poll the "data register empty" interrupt flag to prevent deadlock
+
+ _poll_tx_data_empty();
+ }
+ // When we get here, nothing is queued anymore (DREIE is disabled) and
+ // the hardware finished transmission (TXCIF is set).
+ }
+
+
+ size_t HardwareSerial::write(uint8_t c) {
+ _state |= 1; // Record that we have written to serial since it was begun.
+ // If the buffer and the data register is empty, just write the byte
+ // to the data register and be done. This shortcut helps
+ // significantly improve the effective data rate at high (>
+ // 500kbit/s) bit rates, where interrupt overhead becomes a slowdown.
+ if ((_tx_buffer_head == _tx_buffer_tail) && ((*_hwserial_module).STATUS & USART_DREIF_bm)) {
+ if (_state & 2) { // in half duplex mode, we turn off RXC interrupt
+ uint8_t ctrla = (*_hwserial_module).CTRLA;
+ ctrla &= ~USART_RXCIE_bm;
+ ctrla |= USART_TXCIE_bm;
+ (*_hwserial_module).STATUS = USART_TXCIF_bm;
+ (*_hwserial_module).CTRLA = ctrla;
+ } else {
+ (*_hwserial_module).STATUS = USART_TXCIF_bm;
+ }
+ // MUST clear TXCIF **before** writing new char, otherwise ill-timed interrupt can cause it to erase the flag after the new charchter has been sent!
+ (*_hwserial_module).TXDATAL = c;
+
+ /* I cannot figure out *HOW* the DRE could be enabled at this point (buffer empty and DRE flag up)
+ * When the buffer was emptied, it would have turned off the DREI after it loaded the last byte.
+ * Thus, the only possible way this could happen is if an interrupt also tried to write to serial,
+ * *immediately* after we checked that the buffer was empty, before we made it not empty. And
+ * in that case, without this line it would lose one of the characters... with that line, it could
+ * stop servicing DRE until another serial write, AND lose a character. That's not better! -Spence 4/2021
+ * So this is to stop a race condition in which people are doing something that every guide everywhere says not to do
+ * (writing serial from within an ISR).
+ * I maintain that users SHOULD NOT WRITE TO SERIAL FROM AN ISR, and certainly not while the non-interrupt code is also writing!
+ * Original comments:
+ * // Make sure data register empty interrupt is disabled to avoid
+ * // that the interrupt handler is called in this situation
+ * (*_hwserial_module).CTRLA &= (~USART_DREIE_bm);
+ */
+ return 1;
+ }
+ tx_buffer_index_t i = (_tx_buffer_head + 1) & (SERIAL_TX_BUFFER_SIZE - 1); // % SERIAL_TX_BUFFER_SIZE;
+
+ // If the output buffer is full, there's nothing we can do other than to
+ // wait for the interrupt handler to empty it a bit (or emulate interrupts)
+ while (i == _tx_buffer_tail) {
+ _poll_tx_data_empty();
+ }
+ _tx_buffer[_tx_buffer_head] = c;
+ _tx_buffer_head = i;
+ if (_state & 2) { // in half duplex mode, we turn off RXC interrupt
+ uint8_t ctrla = (*_hwserial_module).CTRLA;
+ ctrla &= ~USART_RXCIE_bm;
+ ctrla |= USART_TXCIE_bm | USART_DREIE_bm;
+ (*_hwserial_module).STATUS = USART_TXCIF_bm;
+ (*_hwserial_module).CTRLA = ctrla;
+ } else {
+ // Enable "data register empty interrupt"
+
+ (*_hwserial_module).CTRLA |= USART_DREIE_bm;
+ }
+ return 1;
+ }
+
+ void HardwareSerial::printHex(const uint8_t b) {
+ char x = (b >> 4) | '0';
+ if (x > '9')
+ x += 7;
+ write(x);
+ x = (b & 0x0F) | '0';
+ if (x > '9')
+ x += 7;
+ write(x);
+ }
+
+ void HardwareSerial::printHex(const uint16_t w, bool swaporder) {
+ uint8_t *ptr = (uint8_t *) &w;
+ if (swaporder) {
+ printHex(*(ptr++));
+ printHex(*(ptr));
+ } else {
+ printHex(*(ptr + 1));
+ printHex(*(ptr));
+ }
+ }
+
+ void HardwareSerial::printHex(const uint32_t l, bool swaporder) {
+ uint8_t *ptr = (uint8_t *) &l;
+ if (swaporder) {
+ printHex(*(ptr++));
+ printHex(*(ptr++));
+ printHex(*(ptr++));
+ printHex(*(ptr));
+ } else {
+ ptr+=3;
+ printHex(*(ptr--));
+ printHex(*(ptr--));
+ printHex(*(ptr--));
+ printHex(*(ptr));
+ }
+ }
+
+ uint8_t * HardwareSerial::printHex(uint8_t* p, uint8_t len, char sep) {
+ for (byte i = 0; i < len; i++) {
+ if (sep && i) write(sep);
+ printHex(*p++);
+ }
+ println();
+ return p;
+ }
+
+ uint16_t * HardwareSerial::printHex(uint16_t* p, uint8_t len, char sep, bool swaporder) {
+ for (byte i = 0; i < len; i++) {
+ if (sep && i) write(sep);
+ printHex(*p++, swaporder);
+ }
+ println();
+ return p;
+ }
+ volatile uint8_t * HardwareSerial::printHex(volatile uint8_t* p, uint8_t len, char sep) {
+ for (byte i = 0; i < len; i++) {
+ if (sep && i) write(sep);
+ uint8_t t = *p++;
+ printHex(t);
+ }
+ return p;
+ }
+ volatile uint16_t * HardwareSerial::printHex(volatile uint16_t* p, uint8_t len, char sep, bool swaporder) {
+ for (byte i = 0; i < len; i++) {
+ if (sep && i) write(sep);
+ uint16_t t = *p++;
+ printHex(t, swaporder);
+ }
+ return p;
+ }
+ #endif
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART.h
new file mode 100644
index 0000000..3fac342
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART.h
@@ -0,0 +1,7 @@
+// We are returning to the conventional name and there is no longer a bloat inducing class layer between
+
+#ifndef HWSERIALNAME_HACK_H
+ #define HWSERIALNAME_HACK_H
+ #include
+ #define UartClass HardwareSerial
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART0.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART0.cpp
new file mode 100644
index 0000000..7befd6c
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART0.cpp
@@ -0,0 +1,131 @@
+/* UART0.cpp - Hardware serial library for USART0
+ * This library is free software released under LGPL 2.1.
+ * See License.md for more information.
+ * This file is part of megaTinyCore.
+ *
+ * Copyright (c) 2006 Nicholas Zambetti, Modified by
+ * 11/23/2006 David A. Mellis, 9/20/2010 Mark Sproul,
+ * 8/24/2012 Alarus, 12/3/2013 Matthijs Kooijman
+ * unknown others 2013-2020, 2020-2022 Spence Konde
+ */
+
+/* Each HardwareSerial is defined in its own file, sine the linker pulls
+ * in the entire file when any element inside is used. --gc-sections can
+ * additionally cause unused symbols to be dropped, but ISRs have the
+ * "used" attribute so are never dropped and they keep the
+ * HardwareSerial instance in as well. Putting each instance in its own
+ * file prevents the linker from pulling in any unused instances in the
+ * first place.
+ * There are now two versions of each ISR. All versions are stubs to call
+ * the real code (so it is not duplicated). The ASM versions are more
+ * efficient than calling normally can ever be because they completely
+ * ignore the ABI rules for the transition from duplicated to shared
+ * code and call it the most effcieient way possiblem so the almost all of
+ * the flash overhead is in the shared section. They'll stop working if
+ * anything changes, and it's not entirely clear whether the trick of
+ * dropping out of assembly while naked to grab the address is legal,
+ * though there's no reason it shouldn't be.
+ * The assembly implementations over in UART.cpp depends on the structure
+ * of the SerialClass. Any changes to the class member variables will
+ * require changes to the asm to match.
+ * This was done for 1.5.12 to correct a serious defect. amd fix a
+ * to make things work better with millis off, and free up 4 bytes of sram.
+ */
+#include "Arduino.h"
+#include "UART.h"
+#include "UART_private.h"
+
+#if defined(USART0)
+ #if defined(USE_ASM_TXC) && USE_ASM_TXC == 1 //&& defined(USART1) // No benefit to this if it's just one USART
+ // Note the difference between this and the other ISRs - here we don't care at all about the serial object, we just have to work with the USART
+ ISR(USART0_TXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t" // push the low byte of Z - we start out 5-6 clocks behind the ball, these three instructions take 4-5 -> 9 or 11 by th time we reach _do_txc
+ "ldi r30, 0x00" "\n\t" // and put the low bit of this USART there - 0x20 * n
+#if PROGMEM_SIZE > 8192
+ "jmp _do_txc" "\n\t"
+#else
+ "rjmp _do_txc" "\n\t"
+#endif // _do_txc pushes the other necessary registers and loads 0x08 into the high byte.
+ // The reason this is possible here and not elsewhere is because TXC only needs the USART, while the others need the HardwareSerial instance.
+ :::);
+ }
+#elif defined(USE_ASM_TXC) && USE_ASM_TXC == 2
+ ISR(USART0_TXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ :::);
+ __asm__ __volatile__(
+#if PROGMEM_SIZE > 8192
+ "jmp _do_txc" "\n\t"
+#else
+ "rjmp _do_txc" "\n\t"
+#endif
+ ::"z"(&Serial0));
+ __builtin_unreachable();
+ }
+
+ #else
+ ISR(USART0_TXC_vect) {
+ // only enabled in half duplex mode - we disable RX interrupt while sending.
+ // When we are done sending, we re-enable the RX interrupt and disable this one.
+ // Note that we do NOT clear TXC flag, which the flush() method relies on.
+ uint8_t ctrla;
+ while (USART0.STATUS & USART_RXCIF_bm) {
+ ctrla = USART0.RXDATAL; // We sent these, so dump them, using local var as trashcan.
+ }
+ ctrla = USART0.CTRLA; // Get current CTRLA
+ ctrla |= USART_RXCIE_bm; // turn on receive complete
+ ctrla &= ~USART_TXCIE_bm; // turn off transmit complete
+ USART0.CTRLA = ctrla; // Write it back to CTRLA.
+ }
+ #endif
+
+ #if !(defined(USE_ASM_RXC) && (USE_ASM_RXC == 1 || USE_ASM_RXC == 2) && (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) /* && defined(USART1)*/)
+ ISR(USART0_RXC_vect) {
+ HardwareSerial::_rx_complete_irq(Serial);
+ }
+ #else
+ ISR(USART0_RXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t" //we start out 5-6 clocks behind the ball, then do 2 push + 2 ldi + 2-3 for jump = 11 or 13 clocks to _do_rxc (and dre is the same)
+ "push r31" "\n\t"
+ "cbi 0x1F, 0" "\n\t"
+ :::);
+ __asm__ __volatile__(
+#if PROGMEM_SIZE > 8192
+ "jmp _do_rxc" "\n\t"
+#else
+ "rjmp _do_rxc" "\n\t"
+#endif
+ ::"z"(&Serial0));
+ __builtin_unreachable();
+ }
+ #endif
+ #if !(defined(USE_ASM_DRE) && USE_ASM_DRE == 1 && \
+ (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
+ (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
+ ISR(USART0_DRE_vect) {
+ HardwareSerial::_tx_data_empty_irq(Serial);
+ }
+ #else
+ ISR(USART0_DRE_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ "cbi 0x1F, 0" "\n\t"
+ :::);
+ __asm__ __volatile__(
+#if PROGMEM_SIZE > 8192
+ "jmp _do_dre" "\n\t"
+#else
+ "rjmp _do_dre" "\n\t"
+#endif
+ ::"z"(&Serial0));
+ __builtin_unreachable();
+ }
+ #endif
+
+ HardwareSerial Serial0(&USART0, 0, HWSERIAL0_MUX_DEFAULT); //Elsewhere we define an alias of Serial for this :-)
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART1.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART1.cpp
new file mode 100644
index 0000000..dd2d3c0
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART1.cpp
@@ -0,0 +1,103 @@
+/* UART1.cpp - Hardware serial library for USART1
+ * This library is free software released under LGPL 2.1.
+ * See License.md for more information.
+ * This file is part of megaTinyCore.
+ *
+ * Copyright (c) 2006 Nicholas Zambetti, Modified by
+ * 11/23/2006 David A. Mellis, 9/20/2010 Mark Sproul,
+ * 8/24/2012 Alarus, 12/3/2013 Matthijs Kooijman
+ * Others (unknown) 2013-2017, 2017-2021 Spence Konde
+ */
+
+#include "Arduino.h"
+#include "UART.h"
+#include "UART_private.h"
+
+#if defined(USART1)
+ #if USE_ASM_TXC == 1
+ ISR(USART1_TXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t" // push the low byte of Z
+ "ldi r30, 0x20" "\n\t" // and put the low bit of this USART there - 0x20 * n
+#if PROGMEM_SIZE > 8192
+ "jmp _do_txc" "\n\t"
+#else
+ "rjmp _do_txc" "\n\t"
+#endif // _do_txc pushes the other necessary registers and loads 0x08 into the high byte.
+ :::);
+ }
+ #elif USE_ASM_TXC == 2
+ ISR(USART1_TXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ :::);
+ __asm__ __volatile__(
+#if PROGMEM_SIZE > 8192
+ "jmp _do_txc" "\n\t"
+#else
+ "rjmp _do_txc" "\n\t"
+#endif
+ ::"z"(&Serial1));
+ __builtin_unreachable();
+ }
+
+ #else
+ ISR(USART1_TXC_vect) {
+ uint8_t ctrla;
+ while (USART1.STATUS & USART_RXCIF_bm) {
+ ctrla = USART1.RXDATAL;
+ }
+ ctrla = USART1.CTRLA;
+ ctrla |= USART_RXCIE_bm; // turn on receive complete
+ ctrla &= ~USART_TXCIE_bm; // turn off transmit complete
+ USART1.CTRLA = ctrla;
+ }
+ #endif
+
+ #if !(defined(USE_ASM_RXC) && (USE_ASM_RXC == 1 || USE_ASM_RXC == 2) && (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) /* && defined(USART1)*/)
+ ISR(USART1_RXC_vect) {
+ HardwareSerial::_rx_complete_irq(Serial1);
+ }
+ #else
+ ISR(USART1_RXC_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ "sbi 0x1F, 0" "\n\t"
+ :::);
+ __asm__ __volatile__(
+#if PROGMEM_SIZE > 8192
+ "jmp _do_rxc" "\n\t"
+#else
+ "rjmp _do_rxc" "\n\t"
+#endif
+ ::"z"(&Serial1));
+ __builtin_unreachable();
+ }
+ #endif
+ #if !(defined(USE_ASM_DRE) && USE_ASM_DRE == 1 && \
+ (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_RX_BUFFER_SIZE == 128 || SERIAL_RX_BUFFER_SIZE == 64 || SERIAL_RX_BUFFER_SIZE == 32 || SERIAL_RX_BUFFER_SIZE == 16) && \
+ (SERIAL_RX_BUFFER_SIZE == 256 || SERIAL_TX_BUFFER_SIZE == 128 || SERIAL_TX_BUFFER_SIZE == 64 || SERIAL_TX_BUFFER_SIZE == 32 || SERIAL_TX_BUFFER_SIZE == 16))
+ ISR(USART1_DRE_vect) {
+ HardwareSerial::_tx_data_empty_irq(Serial1);
+ }
+ #else
+ ISR(USART1_DRE_vect, ISR_NAKED) {
+ __asm__ __volatile__(
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ "sbi 0x1F, 0" "\n\t"
+ :::);
+ __asm__ __volatile__(
+#if PROGMEM_SIZE > 8192
+ "jmp _do_dre" "\n\t"
+#else
+ "rjmp _do_dre" "\n\t"
+#endif
+ ::"z"(&Serial1));
+ __builtin_unreachable();
+ }
+ #endif
+ HardwareSerial Serial1(&USART1, 1, HWSERIAL1_MUX_DEFAULT);
+#endif // HWSERIAL1
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_check_pins.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_check_pins.h
new file mode 100644
index 0000000..b95bc58
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_check_pins.h
@@ -0,0 +1,114 @@
+/* UART_check_pins.h - Validate pins_arduino from the variant.
+ *
+ * Written by Spence Konde in late 2021.
+ *
+ * This file is part of DxCore, which is free software (LGPL 2.1) based on the work
+ * of countless members of the Arduino community.
+ * See License.md for more information
+ *
+ * This is a mixture of stuff that was formerly spread out, and novel code to generate a _usart_pins variable to
+ * hold required pin identifiers, mux values, and so on, as well as moving things that we bloody well know
+ * out of variants. It's not like the DRE vector for hardware serial 1 is ever going to be something other than
+ * USART1_DRE_vect or something, so why do we act like it could be?
+ */
+
+#pragma once
+
+/* Recreate all those old defines so they aren't spread over all the variants when they don't vary!
+ * The core does NOT use these, but other code might, so we should make sure they're here.
+ * We also pick the default as the default if it's not defined.
+ */
+
+#if defined(USART0) && !defined(HWSERIAL0_MUX_DEFAULT)
+ #define HWSERIAL0_MUX_DEFAULT (0)
+#endif
+
+#if defined(USART1) && !defined(HWSERIAL1_MUX_DEFAULT)
+ #define HWSERIAL1_MUX_DEFAULT (0)
+#endif
+
+#if defined(USART1)
+ #define NUM_HWSERIAL_PORTS 2
+#elif defined(USART0)
+ #define NUM_HWSERIAL_PORTS 1
+#else
+ #error "No USARTs present. All supported parts have at least 1 - something is wrong!"
+#endif
+
+#if defined(USART0)
+ #define HAVE_HWSERIAL0 1
+ #define HWSERIAL0_DRE_VECTOR USART0_DRE_vect
+ #define HWSERIAL0_DRE_VECTOR_NUM USART0_DRE_vect_num
+ #define HWSERIAL0_RXC_VECTOR USART0_RXC_vect
+ #define HWSERIAL0 &USART0
+#endif
+#if defined(USART1)
+ #define HAVE_HWSERIAL1 1
+ #define HWSERIAL1_DRE_VECTOR USART1_DRE_vect
+ #define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num
+ #define HWSERIAL1_RXC_VECTOR USART1_RXC_vect
+ #define HWSERIAL1 &USART1
+#endif
+
+
+#include "Arduino.h"
+/* Make sure the variant doesn't define non-existent pins as belonging to serial ports. */
+#if defined(PIN_HWSERIAL0_TX) && (PIN_HWSERIAL0_TX >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_TX != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_TX is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL0_RX) && (PIN_HWSERIAL0_RX >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_RX != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_RX is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL0_XCK) && (PIN_HWSERIAL0_XCK >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_XCK != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_XCK is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL0_XDIR) && (PIN_HWSERIAL0_XDIR >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_XDIR != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_XDIR is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL0_TX_PINSWAP_1) && (PIN_HWSERIAL0_TX_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_TX_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_TX_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL0_RX_PINSWAP_1) && (PIN_HWSERIAL0_RX_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_RX_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_RX_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL0_XCK_PINSWAP_1) && (PIN_HWSERIAL0_XCK_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_XCK_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_XCK_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL0_XDIR_PINSWAP_1) && (PIN_HWSERIAL0_XDIR_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL0_XDIR_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL0_XDIR_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_TX) && (PIN_HWSERIAL1_TX >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_TX != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_TX is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_RX) && (PIN_HWSERIAL1_RX >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_RX != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_RX is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_XCK) && (PIN_HWSERIAL1_XCK >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_XCK != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_XCK is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_XDIR) && (PIN_HWSERIAL1_XDIR >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_XDIR != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_XDIR is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_TX_PINSWAP_1) && (PIN_HWSERIAL1_TX_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_TX_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_TX_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_RX_PINSWAP_1) && (PIN_HWSERIAL1_RX_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_RX_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_RX_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_XCK_PINSWAP_1) && (PIN_HWSERIAL1_XCK_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_XCK_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_XCK_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if defined(PIN_HWSERIAL1_XDIR_PINSWAP_1) && (PIN_HWSERIAL1_XDIR_PINSWAP_1 >= NUM_TOTAL_PINS) && (PIN_HWSERIAL1_XDIR_PINSWAP_1 != NOT_A_PIN)
+ #error "Variant file is not self-consistent - PIN_HWSERIAL1_XDIR_PINSWAP_1 is defined as a pin which does not exist, but not NOT_A_PIN"
+#endif
+#if (defined(USART1) && !((PIN_HWSERIAL1_TX != NOT_A_PIN && PIN_HWSERIAL1_RX != NOT_A_PIN)))
+ // if USART1 is defined, and default pins aren't NOT_A_PIN they should be the same as USART0's alternates
+ #if (((PIN_HWSERIAL1_TX != PIN_HWSERIAL0_TX_PINSWAP_1) || (PIN_HWSERIAL1_RX != PIN_HWSERIAL0_RX_PINSWAP_1)) || \
+ ((PIN_HWSERIAL1_XCK != PIN_HWSERIAL0_XCK_PINSWAP_1) && (PIN_HWSERIAL1_XCK != NOT_A_PIN)) || \
+ ((PIN_HWSERIAL1_XDIR != PIN_HWSERIAL0_XDIR_PINSWAP_1) && (PIN_HWSERIAL1_XDIR != NOT_A_PIN)))
+ #error "The variant file is incorrect. On all supported parts, the default USART1 pinset is identical to the alternate USART0 one."
+ #endif
+#elif (defined(USART1) && ((PIN_HWSERIAL1_TX == NOT_A_PIN || PIN_HWSERIAL1_RX == NOT_A_PIN)))
+ // if USART1 is defined and the pins are NOT_A_PIN, then the variant is wrong, because there are no parts like that.
+ #error "The variant file is incorrect. On all supported parts w/USART1, the default TX and RX exist, variant says they're NOT_A_PIN"
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_constants.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_constants.h
new file mode 100644
index 0000000..8014c39
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_constants.h
@@ -0,0 +1,290 @@
+/* UART_constants.h - Hardware serial library constants.
+ * (C) Spence Konde 2021
+ * This library is free software released under LGPL 2.1.
+ * See License.md for more information.
+ * This file is part of DxCore and megaTinyCore
+ *
+ * These are values that get passed to the second argument of Serial.begin in
+ * DxCore 1.4.0+ and megaTinyCore 2.5.0+.
+ */
+/*"What the bloody hell are all these static casts for?!"
+ * Well, the io headers define them as enumerated types. From C++20 onwards mixing enums is deprecated. These static casts do not effect behavior for everyone else
+ * but makethe user experience significantly better for C++20 people.
+ * Note that C++ 20 is not supported by this core . This was done in response to a PR and has zero impact om everyone else. Changes to make life easier for users
+ * of unsupported versions of the standards that do not meet both of thoe criteria will not be addressed.
+ */
+
+#ifndef UART_CONSTANTS_H
+ #define UART_CONSTANTS_H
+
+ #define SERIAL_PARITY_EVEN (static_cast(USART_PMODE_EVEN_gc))
+ #define SERIAL_PARITY_ODD (static_cast(USART_PMODE_ODD_gc))
+ #define SERIAL_PARITY_NONE (static_cast(USART_PMODE_DISABLED_gc))
+ #define SERIAL_PARITY_MASK (static_cast(USART_PMODE_gm))
+
+ #define SERIAL_STOP_BIT_1 (static_cast(USART_SBMODE_1BIT_gc))
+ #define SERIAL_STOP_BIT_2 (static_cast(USART_SBMODE_2BIT_gc))
+ #define SERIAL_STOP_BIT_MASK (static_cast(USART_SBMODE_gm))
+
+ #define SERIAL_DATA_5 (static_cast(USART_CHSIZE_5BIT_gc | 0x04))
+ // Special case - we strip out bit 2 in order to detect use of high-byte modifiers without specifying low byte, which is presumably user error.
+ // and default 8N1 instead of the hardware default of 5N1.
+ #define SERIAL_DATA_6 (static_cast(USART_CHSIZE_6BIT_gc))
+ #define SERIAL_DATA_7 (static_cast(USART_CHSIZE_7BIT_gc))
+ #define SERIAL_DATA_8 (static_cast(USART_CHSIZE_8BIT_gc))
+ #define SERIAL_DATA_INVALID1 (static_cast(badArg("This is a 'reserved' value and does not identify a character size"), 0x04))
+ #define SERIAL_DATA_INVALID2 (static_cast(badArg("This is a 'reserved' value and does not identify a character size"), 0x05))
+ #define SERIAL_DATA_9L (static_cast(badArg("9-bit serial not supported"),0x06))
+ #define SERIAL_DATA_9H (static_cast(badArg("9-bit serial not supported"),0x07))
+ #define SERIAL_DATA_MASK (static_cast(USART_CHSIZE_gm))
+/* 9-bit is a can of worms. Aggressive ones with sharp teeth,
+ * hungry for soft fle-- oh, hm, it seems to be a typo, it says "flash"...
+ *
+ * It would be a nightmare to support overhead of everything is
+ * greatly increased because you have to switch from 8-bit to
+ * 16-bit types.
+ * Nothing uses 9-bit serial! Including our implementation.
+ *
+ * A future update may mask off 0x04 from this bitfield before writing it
+ * so that SERIAL_DATA_5 could be #defined as 0x04. That way, before masking it, we
+ * could test if it was 0, and get rid of the SERIAL_CONFIG_VALID below.
+ */
+
+ #define SERIAL_MODE_ASYNC (static_cast(USART_CMODE_ASYNCHRONOUS_gc))
+ #define SERIAL_MODE_MSPI (static_cast(USART_CMODE_MSPI_gc))
+ #define SERIAL_MODE_IRCOM (static_cast(USART_CMODE_IRCOM_gc))
+ #define SERIAL_MODE_SYNC (static_cast(USART_CMODE_SYNCHRONOUS_gc))
+/* MSPI doesn't use the Parity, have start or stop bits and is always 8 bit characters.
+ * Sync and IRCOM modes are like ASync - but only */
+
+// Used only in MSPI mode.
+ #define SERIAL_MSPI_LSB (static_cast(USART_UDORD_bm))
+ #define SERIAL_MSPI_MSB (static_cast(0))
+ #define SERIAL_MSPI_PHASE (static_cast(USART_UCPHA_bm))
+/* You can combine them yourself with | - but you need 5 things:
+ * A SERIAL_MODE
+ * A SERIAL_STOP_BIT option (can be omitted for 1 SB)
+ * A SERIAL_PARITY option (can be omitted for none)
+ * A SERIAL_DATA option specifying the size of a character (Cannot be omitted, default is 5bit!)
+*/
+
+ #define SERIAL_5N1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_5)
+ #define SERIAL_6N1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_6)
+ #define SERIAL_7N1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_7)
+ #define SERIAL_8N1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_8)
+ #define SERIAL_5N2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_5)
+ #define SERIAL_6N2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_6)
+ #define SERIAL_7N2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_7)
+ #define SERIAL_8N2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_8)
+ #define SERIAL_5E1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_5)
+ #define SERIAL_6E1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_6)
+ #define SERIAL_7E1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_7)
+ #define SERIAL_8E1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_8)
+ #define SERIAL_5E2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_5)
+ #define SERIAL_6E2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_6)
+ #define SERIAL_7E2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_7)
+ #define SERIAL_8E2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_8)
+ #define SERIAL_5O1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_5)
+ #define SERIAL_6O1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_6)
+ #define SERIAL_7O1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_7)
+ #define SERIAL_8O1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_8)
+ #define SERIAL_5O2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_5)
+ #define SERIAL_6O2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_6)
+ #define SERIAL_7O2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_7)
+ #define SERIAL_8O2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_8)
+
+ #define SERIAL_MSPI_MSB_FIRST (SERIAL_MODE_MSPI | SERIAL_MSPI_MSB)
+ #define SERIAL_MSPI_LSB_FIRST (SERIAL_MODE_MSPI | SERIAL_MSPI_LSB)
+ #define SERIAL_MSPI_MSB_FIRST_PHASE (SERIAL_MODE_MSPI | SERIAL_MSPI_PHASE | SERIAL_MSPI_MSB)
+ #define SERIAL_MSPI_LSB_FIRST_PHASE (SERIAL_MODE_MSPI | SERIAL_MSPI_PHASE | SERIAL_MSPI_LSB)
+
+/* helper options for syncBegin() and mspiBegin() */
+ #define MSPIBEGIN_INVERT (PIN_DIR_SET | PIN_INVERT_SET)
+ #define MSPIBEGIN_NORMAL (PIN_DIR_SET | PIN_INVERT_CLR)
+ #define SYNCBEGIN_INVERT_MASTER (PIN_DIR_SET | PIN_INVERT_SET)
+ #define SYNCBEGIN_NORMAL_MASTER (PIN_DIR_SET | PIN_INVERT_CLR)
+ #define SYNCBEGIN_INVERT_SLAVE (PIN_DIR_CLR | PIN_INVERT_SET)
+ #define SYNCBEGIN_NORMAL_SLAVE (PIN_DIR_CLR | PIN_INVERT_CLR)
+/* helper defines to get pins currently selected by number */
+ #define PIN_SERIAL_TX (0)
+ #define PIN_SERIAL_RX (1)
+ #define PIN_SERIAL_XCK (2)
+ #define PIN_SERIAL_XDIR (3)
+
+/* Modifier Definitions - these can be OR'ed with the other definition to turn on features like one-wire half duplex and more */
+#if !defined(USART_RS485_0_bm)
+ #define USART_RS485_0_bm USART_RS4850_bm
+ #if defined(USART_RS4851_bm)
+ #define USART_RS485_1_bm USART_RS4851_bm
+ #endif
+#elif !defined(USART_RS4850_bm)
+ #define USART_RS4850_bm USART_RS485_0_bm
+ #if defined(USART_RS485_1_bm)
+ #define USART_RS4851_bm USART_RS485_1_bm
+ #endif
+#endif
+#define SERIAL_RS485 (((uint16_t) USART_RS485_0_bm) << 8)// 0x0100
+#if defined(USART_RS485_1_bm)
+ #define SERIAL_RS485_OTHER (((uint16_t) USART_RS485_1_bm) << 9)// 0x0200 tinyAVR 0/1
+#endif
+
+#define SERIAL_OPENDRAIN ((uint16_t) 0x0400)// 0x0400
+#define SERIAL_LOOPBACK (((uint16_t) USART_LBME_bm) << 8)// 0x0800
+#define SERIAL_TX_ONLY (((uint16_t) USART_RXEN_bm) << 8)// 0x8000 The TXEN/RXEN bits are swapped - we invert the meaning of this bit.
+#define SERIAL_RX_ONLY (((uint16_t) USART_TXEN_bm) << 8)// 0x4000 so if not specified, you get a serial port with both pins. Do not specify both. That will not enable anything.
+#define SERIAL_EVENT_RX ((uint16_t) 0x2000)// 0x2000
+//#define SERIAL_MODE_SYNC Defined Above // 0x0040 - works much like a modifier to enable synchronous mode.
+// See the Serial reference for more information as additional steps are required
+ #define SERIAL_HALF_DUPLEX (SERIAL_LOOPBACK | SERIAL_OPENDRAIN)
+ //
+
+#define SERIAL_AUTOBAUD (0x80000000) // OR with baud rate for topology 3 in Ref. Serial
+#define SERIAL_REQUIRE_AUTOBAUD (0xFFFFFFFF) // Specify autobaud... plus an obscenely fast baud rate. The other device must send a sync frame. Good for slaves in topology 2, or in topology 1
+#define SERIAL_MAKE_AUTOBAUD(intial_baud) ((__asm__ __volatile__ ("ori %D0, 0x80" "\n\t" : "+d" (uint32_t)(initial_baud))), initial_baud) // Like ORing the baud rate, only faster, if it works;
+
+#define SERIAL_AUTOBAUD_DISABLED 0x00
+
+/* Cumulative generally negative statii */
+#define SERIAL_WRITTEN 0x01 // Indicates that one or more character has been written to this serial port since begin called, used internally
+#define SERIAL_HALF_DUPLEX_ENABLED 0x02 // Indicates we are in half duplex mode. Used internally to control when interrupts are switched
+#define SERIAL_PARITY_ERROR 0x04 // Indicates that since getStatus() was last called there has been one or more parity error. Parity error characters are not retained.
+#define SERIAL_FRAME_ERROR 0x08 // Indicates that since getStatus() was last called there has been one or more framing error, this usually indicates a baud mismatch
+#define SERIAL_AUTOBAUD_ENABLED 0x10 // Autobaud enabled.
+#define SERIAL_AUTOBAUD_SYNC 0x20 // Indicates that a fresh baud rate has been set.
+/* Some parts are afflicted by an errata that requires the receiver to be bounced to restore functioning after ICSIF is set and then cleared. the core does this automatically. */
+#define SERIAL_AUTOBAUD_BADSYNC 0x30 // Indicates that an unsuccessful sync attempt was made. On parts known to be impacted by the errata, (AVR32DD20/14 - and maybe others)
+ // RXEN must be turned off and back on after clearing this. That is done when checkStatus() is called and finds ISFIF set.
+#define SERIAL_OVERFLOW_RING 0x40 // Indicates that the *RING BUFFER* lost data due to overflow - you are not calling read() as fast as data is coming in.
+#define SERIAL_OVERFLOW_HARDWARE 0x80 // Indicates that the *HARDWARE* buffer overflowed because interrupts were disabled for too long while receiving data.
+
+
+/* CTRLA is interrupt flags, plus 3 options relevant to RS485
+ *
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | USARTn.CTRLA
+ * |---|---|---|---|---|---|---|---|
+ * |RXC|TXC|DRE|RXS| - |ABE| - | - | Interrupt Enable bits
+ * | - - - - |LBM| - | RS485 | RS485 stuff
+ *
+ * LBME - Loopback Mode Enable turns off RX and ties that channel to TX
+ * RS485 - RS485 mode tells it to drive XDIR pin HIGH while transmitting in
+ * order to control an external RS485 line driver. 1 bit of guard time on
+ * either side.
+ *
+ * RS485 field is strange - on 0/1-series, bit 1 was used was described as
+ * an transmit enable field for the UART, so an external device would use
+ * that to tell the device when it was allowed to drive the pin. But that
+ * has not been described in recent datasheets and the bit is marked as
+ * reserved, and only 1 RS485 mode was supported.
+ * Just as well - I've never tried it and am unsure of what it was supposed
+ * to do, but I suspect you that could debate how something like that "should"
+ * work in all the corner cases for weeks. It brings up all a great many
+ * issues, was probably a nightmare for designers, and considering the amount
+ * of errata on those parts, it probably didn't work very well.
+ */
+
+/* CTRLB configures a few major aspects of configuration:
+ *
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | USARTn.CTRLB
+ * |-------|---|---|---|-------|---|
+ * | TX RX | - |SFD|ODM|RX MODE|MPCM
+ * |ENABLE | - | Configuration | |
+ *
+ * TXEN - enables transmit functionality. When it transitions from enable to
+ * disabled, the pin is forcibly set to an input.
+ * RXEN - enables receive functionality
+ * SFDEN - enables Start of Frame detection to wake from sleep.
+ * ODME - enables Open Drain Mode. Tx pin must be INPUT instead of OUTPUT!
+ * MPCM - Multi Processor Communication Mode. A weird Atmel-only feature that
+ * turns a UART into a multidrop bus. I doubt it is in widespread use anywhere.
+ * Looks like the bastard son of UART and I2C that never got enough love or
+ * uptake to prosper. Likely dates to when Phillips was on the warpath
+ * regarding I2C intellectual property. (Maybe they were afraid that they would
+ * be forced to remove the TWI module?) Anyway, the core doesn't support it
+ * and it looks like a really ugly kludge.
+ * RXMODE - Controls the baud rate for both sending and receiving. 4 modes:
+ * Normal
+ * U2X - double-speed USART - much less important now with the fractional
+ * baud rate generator, but does the same thing. Serial.begin() chooses this
+ * if it needs to in order to generate the required baud rate only.
+ * GENAUTO - generic auto-baud mode
+ * LINAUTO - LIN constrained auto-baud mode
+ * Autobaud mode requires a "break" to be sent followed by a sync (0x55).
+ * LIN mode has more constraints in accordance with that stadatd, while
+ * generic mode has clearly just disabled the checks and added a WFB or
+ * "wait for break" option so you can use autobaud without having to
+ * guess what baud it's using.
+ *
+ * These parts have no trouble keeping a clock accurate enough for serial
+ * and since you need to have control over the software on the the device
+ * that it's talking so you can make it send the break/sync, and you are
+ * also programming this device, wherever it is viable, you know the baud
+ * rate that both ends are set to and don't need it. It's great if you need
+ * to meet the LIN specifications, of course, but that's not a typical or
+ * advisable Arduino use case...
+ * Based on persistent requests from users, who want it badly enough to try
+ * hacking something together to make use of it anyway, a future version
+ * will incorporate generic autobaud mode, even though it's pretty silly.
+ */
+
+/* Everything contigured by the SERIAL_xPs constants goes right into CTRLC:
+ *
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | USARTn.CTRLC
+ * |---|---|---|---|---|---|---|---|
+ * | MODE | PARITY| SB| CHAR SIZE |
+ *
+ *
+ * Plus there's there's the IRCOM - it is able to take an event input, and
+ * you can turn off the pulse coding that nobody's going to use in Arduino-land
+ * IRDA has been dead for years - we don't support using that, but we want event input.
+ *
+ * Additionally there are reasons to want to control to some bits from CTRLA + CTRLB too...
+ *
+ * It's also not clear yet how it actually behaves when disabled, namely:
+ * Can the event input be used in all modes, or must it be in IRCOM mode?
+ * Do we have to do something that applies the 115200 baud maximum to get it?
+ *
+ * We want a way to request that only TX, or only RX be enabled, but default should be both.
+ * And we want to control Open Drain, RS485 and LoopBack options independently of each other
+ *
+ * In summary:
+ *
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * |---|---|---|---|---|---|---|---|
+ * | x x x | |LBM| |485| CTRLA
+ * |TXRX EN| |ODM| x __ | | CTRLB
+ * | |IREI EVCTRL
+ * Bits used actively for basic UART are marked with an x.
+ *
+ * That means 6 bits will be needed. Plus, we sometimes use use one of
+ * them internally, and the tinyAVR parts have that funky backwards
+ * RS485 option
+ * All the ones CTRLA default 0, and so we can AND with 0x09 (or 0x0B on tinyAVR) and OR with other CTRLA settings.
+ * And we want the two inverted CTRLB ones in their final locations so we can AND with 0xC0 and XOR the settings
+ * we're going to write to CTRLB. The other CTRLB one and the internal need to be done individually, so it doesn't matter
+ * that needs to set other options too.
+ */
+
+
+ /* These are not usable on these parts. badCall() gets pulled in if you use them. */
+
+ #define SERIAL_PARITY_MARK (badArg("'Mark' as parity is not supported, use an extra stop bit"),0)
+ #define SERIAL_PARITY_SPACE (badArg("'Space' as parity is not supported on AVR"),0)
+ #define SERIAL_STOP_BIT_1_5 (badArg("1.5 stop bits is not a supported setting on AVR"),0)
+ #define SERIAL_5M1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_5)
+ #define SERIAL_6M1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_6)
+ #define SERIAL_7M1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_7)
+ #define SERIAL_8M1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_8)
+ #define SERIAL_5M2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_5)
+ #define SERIAL_6M2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_6)
+ #define SERIAL_7M2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_7)
+ #define SERIAL_8M2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_8)
+ #define SERIAL_5S1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 |SERIAL_PARITY_SPACE | SERIAL_DATA_5)
+ #define SERIAL_6S1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 |SERIAL_PARITY_SPACE | SERIAL_DATA_6)
+ #define SERIAL_7S1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 |SERIAL_PARITY_SPACE | SERIAL_DATA_7)
+ #define SERIAL_8S1 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_1 |SERIAL_PARITY_SPACE | SERIAL_DATA_8)
+ #define SERIAL_5S2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 |SERIAL_PARITY_SPACE | SERIAL_DATA_5)
+ #define SERIAL_6S2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 |SERIAL_PARITY_SPACE | SERIAL_DATA_6)
+ #define SERIAL_7S2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 |SERIAL_PARITY_SPACE | SERIAL_DATA_7)
+ #define SERIAL_8S2 (SERIAL_MODE_ASYNC | SERIAL_STOP_BIT_2 |SERIAL_PARITY_SPACE | SERIAL_DATA_8)
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_private.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_private.h
new file mode 100644
index 0000000..a53dd55
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/UART_private.h
@@ -0,0 +1,22 @@
+/* UART_private.h - Constructor for HardwareSerial
+ * This library is free software released under LGPL 2.1.
+ * See License.md for more information.
+ * This file is part of megaTinyCore
+ *
+ * Totally rewritten 2021-22 by Spence Konde and MX682X.
+ * The original version was written in 2006 by Nicholas
+ * Zambetti, and modified 11/23/2006 by David A. Mellis,
+ * 9/20/2010 by Mark Sproul, 8/24/2012 by Alarus, and
+ * other members of the Arduino community who did not sign.
+ */
+
+#include "wiring_private.h"
+
+#if defined(USART0) || defined(USART1)
+/* Significant changes in UART.cpp, UART.h, and UART_swap.h required to support more UARTs */
+
+HardwareSerial::HardwareSerial(volatile USART_t *hwserial_module, uint8_t module_number, uint8_t mux_default) :
+ _hwserial_module(hwserial_module), _module_number(module_number), _pin_set(mux_default) {
+}
+
+#endif // whole file
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts.c
new file mode 100644
index 0000000..6f5713f
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts.c
@@ -0,0 +1,535 @@
+/* Completely rewritten 2021 Spence Konde;
+ * This is part of DxCore/megaTinyCore. Open source softeare (LGPL 2.1) see License.md for more info.
+ *
+ * attachInterrupt() that uses less flash and doesn't assimilate every interrupt vector...
+ *
+ * The ultimate goal was not achieved, but we can manually force the effect I wanted.
+ * Someone with deeper knowledge of how C/C++ decides that it will include the ISR from a file
+ * but it does give *a way* to write code that can use an attachInterrupt library and manually define pin interrupts.
+ * thisis important because attachInterrupt interrupts are miserably slow. Even in assembly, it's like 42 clocks to
+ * get to the loop, 7+ per pass through it, and a little over 40 more on the way out!
+ * Using lower numbered pins within a port minimizes how crappy this is. A port with 1 interrupt on bit 7 will take
+ * almost 42 clocks longer to be reached as it checks lower bits than one with it's one interrupt on bit 0
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include "wiring_private.h"
+
+#if !defined(CORE_ATTACH_OLD)
+/* Well, I couldn't get it to autodetect awhere you're putting constant pins on interrupts, but there are tiny
+ * that you can call when using manual enabling;. Referencing them causes it to grab the associated vector, though it does have to be called to actually enable it - that's how we
+ * avoid wasting resourceses - each one not used also drops an array of 8 pointers to ISRs.
+ *
+ * attachPortAEnable() attachPortBEnable() attachPortCEnable() attachPortDEnable()
+ * attachPortEEnable() attachPortFEnable() attachPortGEnable()
+ *
+ * So you get the option wehether to enable it for each port. Each port also doesn't get it's own bloated ISR composed almost entirely of pushes and pops for calling a function
+ * it was done by doing rather evil things here but it does appear to work!
+ */
+ /*Only create arrays for ports that exist) */
+ #if !defined(CORE_ATTACH_ALL)
+ extern voidFuncPtr * intFunc_A;
+ #ifdef PORTB_PINS
+ extern voidFuncPtr * intFunc_B;
+ #endif
+ #ifdef PORTC_PINS
+ extern voidFuncPtr * intFunc_C;
+ #endif
+ #else
+ voidFuncPtr intFunc_A[8];
+ #ifdef PORTB_PINS
+ voidFuncPtr intFunc_B[PORTB_PINS];
+ #endif
+ #ifdef PORTC_PINS
+ voidFuncPtr intFunc_C[PORTC_PINS];
+ #endif
+ volatile voidFuncPtr * intFunc[] = {
+ intFunc_A,
+ #ifdef PORTB_PINS
+ intFunc_B,
+ #endif
+ #ifdef PORTC_PINS
+ intFunc_C
+ #endif
+ };
+ #endif
+ #if !defined(CORE_ATTACH_ALL)
+ #if defined(PORTC_PINS)
+ volatile voidFuncPtr * intFunc[] = {NULL, NULL, NULL};
+ #elif defined(PORTB_PINS)
+ volatile voidFuncPtr * intFunc[] = {NULL, NULL};
+ #else
+ volatile voidFuncPtr * intFunc[] = {NULL};
+ #endif
+ #endif
+
+ volatile uint8_t* portbase = (volatile uint8_t*)((uint16_t)0x400);
+ /* On modern AVRs, the PORT registers start at 0x400
+ * At 32 bytes per port, with plenty of room to spare, up to 8 ports will fit before we are forced into 0x500.
+ * And the rest of this implementation falls over if there's an 8th port because it relies on VPORTs
+ * of which there are only 7 ports worth of registers available. So this implementation is guaranteed not to work on a
+ * future part with 8 ports anyway. We will cross that bridge once Microchip has announced intent to build it.
+ */
+
+ void attachInterrupt(uint8_t pin, void (*userFunc)(void), uint8_t mode) {
+ uint8_t bitpos = digitalPinToBitPosition(pin);
+ if (bitpos == NOT_A_PIN) {
+ return;
+ }
+ uint8_t port = digitalPinToPort(pin);
+ switch (mode) {
+ case CHANGE:
+ mode = PORT_ISC_BOTHEDGES_gc;
+ break;
+ case FALLING:
+ mode = PORT_ISC_FALLING_gc;
+ break;
+ case RISING:
+ mode = PORT_ISC_RISING_gc;
+ break;
+ case LOW:
+ mode = PORT_ISC_LEVEL_gc;
+ break;
+ default:
+ return;
+ }
+ if (intFunc[port] != NULL && userFunc != NULL) {
+ // if it is null the port is not enabled for attachInterrupt, and obviously a null user function is invalid too.
+ intFunc[port][bitpos] = userFunc;
+ uint8_t portoffset = ((port << 5) & 0xE0) + 0x10 + bitpos;
+ uint8_t oldSREG = SREG;
+ cli();
+ // We now have the port, the mode, the bitpos and the pointer
+ uint8_t settings = *(portbase + portoffset) & 0xF8;
+ *(portbase + portoffset) = settings | mode;
+ SREG = oldSREG;
+ }
+ }
+#if !defined(CORE_ATTACH_EARLYCLEAR) // late clear.
+ void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) isrBody() {
+ asm volatile (
+ "AttachedISR:" "\n\t" // as the scene opens, we have r16 on the stack already, portnumber x 2 in the r16
+ "push r0" "\n\t" // so we start with a normal prologue
+ "in r0, 0x3f" "\n\t" // The SREG
+ "push r0" "\n\t" // on the stack
+ #if PROGMEM_SIZE > 0x10000
+ "in r0, 0x3b" "\n\t" // RAMPZ
+ "push r0" "\n\t" // on the stack.
+ #endif
+ "push r1" "\n\t" // We don't need r1 but the C code we call
+ "eor r1, r1" "\n\t" // is going to want this to be zero....
+ "push r15" "\n\t" // push r15 (we use it - it's call-saved)
+ "push r17" "\n\t" // and now we push all call used registers
+ "push r18" "\n\t" // except r16 which was pused over in WInterrupts_Px
+ "push r19" "\n\t"
+ "push r20" "\n\t"
+ "push r21" "\n\t"
+ "push r22" "\n\t"
+ "push r23" "\n\t"
+ "push r24" "\n\t"
+ "push r25" "\n\t"
+ "push r26" "\n\t"
+ "push r27" "\n\t"
+ "push r28" "\n\t" // Not call used, but we use it.
+ "push r29" "\n\t" // same thing.
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ ::);
+ asm volatile ( // This gets us the address of intFunc in Y pointer reg.
+ "add r26, r16" "\n\t" // get the address of the functions for this port (r 16 is 2x the port number)
+ "adc r27, r1" "\n\t" // by adding that offset to the address we had the compiler generate the ldi's for
+ "ld r28, X+" "\n\t" // load the pointer to this port's function array...
+ "ld r29, X" "\n\t" // ... to the Y pointer reg.
+ "add r16, r16" "\n\t" // double r16, so it is 4x port number - that's the address of the start of the VPORT
+ "subi r16, 253" "\n\t" // Now this is the address of the VPORTx.INTFLAGS
+ "mov r26, r16" "\n\t" // r16 to x reg low byte ASM always lists the destination operand first.
+ "ldi r27, 0" "\n\t" // clear x high byte
+ "ld r15, X" "\n\t" // Load flags to r15"
+ "sbiw r26, 0" "\n\t" // subtract 0 from it - this serves as a single-word way to test if it's 0, because it will still set the Zero flag. It's no faster than cpi r26, 0, cpc r27, r1 but takes less flash.
+ "breq AIntEnd" "\n\t" // port not enabled, null pointer, just clear flags end hit the exit ramp.
+ "mov r17, r15" "\n\t" // copy the flags to r17
+ "AIntLoop:" "\n\t"
+ "lsr r17" "\n\t" // shift it right one place, now the LSB is in carry.
+ "brcs .+6" "\n\t" // means we have something to do this time.
+ "breq AIntEnd" "\n\t" // This means carry wasn't set and r17 is 0. - we're done.
+ "adiw r28, 2" "\n\t" // otherwise it's not a the int we care about, increment Y by 2, so it will point to the next element.
+ "rjmp AIntLoop" "\n\t" // restart the loop in that case.
+ "ld r30, Y+" "\n\t" // load the function pointer;
+ "ld r31, Y+" "\n\t" // load the function pointer;
+ "sbiw r30, 0" "\n\t" // zero-check it.
+ "breq AIntLoop" "\n\t" // restart loop if it is, don't call the null pointer
+ "icall" "\n\t" // call their function, which is allowed to shit on any upper registers other than 28, 29, 16, and 17.
+ "rjmp AIntLoop" "\n\t" // Restart loop after.
+ "AIntEnd:" "\n\t" // sooner or later r17 will be 0 and we'll branch here.
+ "mov r26, r16" "\n\t" // We previously stashed the VPORT address in r16, so copy that to low byte of X pointer <>
+ "ldi r27, 0" "\n\t" // high byte is 0, cause we're targeting the VPORT, address < 0x20
+ "st X, r15" "\n\t" // store to clear the flags.... that we recorded at the start of the interrupt. (LATECLEAR)
+ "pop r31" "\n\t" // clean up a million registers
+ "pop r30" "\n\t"
+ "pop r29" "\n\t"
+ "pop r28" "\n\t"
+ "pop r27" "\n\t"
+ "pop r26" "\n\t"
+ "pop r25" "\n\t"
+ "pop r24" "\n\t"
+ "pop r23" "\n\t"
+ "pop r22" "\n\t"
+ "pop r21" "\n\t"
+ "pop r20" "\n\t"
+ "pop r19" "\n\t"
+ "pop r18" "\n\t"
+ "pop r17" "\n\t" // skip 16 again - it's way down at the end, because it was pushed earlier
+ "pop r15" "\n\t"
+ "pop r1" "\n\t"
+ #if PROGMEM_SIZE > 0x10000
+ "pop r0" "\n\t"
+ "out 0x3b, r0" "\n\t"
+ #endif
+ "pop r0" "\n\t"
+ "out 0x3f, r0" "\n\t" // between these is where there had been stuff added to the stack that we flushed.
+ "pop r0" "\n\t"
+ "pop r16" "\n\t" // this was the reg we pushed back in the port-specific file.
+ "reti" "\n" // now we should have the pointer to the return address fopr the ISR on top of the stack, so reti're
+ :: "x" ((uint16_t)(&intFunc))
+ );
+ __builtin_unreachable();
+ }
+#else // EARLYCLEAR
+ void __attribute__((naked)) __attribute__((used)) __attribute__((noreturn)) isrBody() {
+ asm volatile (
+ "AttachedISR:" "\n\t" // as the scene opens, we have r16 on the stack already, portnumber x 2 in the r16
+ "push r0" "\n\t" // so we start with a normal prologue
+ "in r0, 0x3f" "\n\t" // The SREG
+ "push r0" "\n\t" // on the stack
+ "in r0, 0x3b" "\n\t" // RAMPZ
+ "push r0" "\n\t" // on the stack.
+ "push r1" "\n\t" // We don't need r1 but the C code we call
+ "eor r1, r1" "\n\t" // is going to want this to be zero....
+ // "push r15" "\n\t" // We don't use r15 with EARLYCLEAR.
+ // "push r17" "\n\t" // Eyyyyy lookit dat, we don't need r17 for EARLYCLEAR either. So that's two fewer call-saved registers that we need to save and restore.
+ "push r18" "\n\t" // and now we push all call used registers
+ "push r19" "\n\t" // except r16 which was pushed over in WInterrupts_Px
+ "push r20" "\n\t"
+ "push r21" "\n\t"
+ "push r22" "\n\t"
+ "push r23" "\n\t"
+ "push r24" "\n\t"
+ "push r25" "\n\t"
+ "push r26" "\n\t"
+ "push r27" "\n\t"
+ "push r28" "\n\t" // Not call used, but we use it.
+ "push r29" "\n\t" // And we need it's call-saved-ness ourselves to maintain state through the
+ "push r30" "\n\t"
+ "push r31" "\n\t"
+ ::);
+ asm volatile ( // This gets us the address of intFunc in Y pointer reg.
+ "add r26, r16" "\n\t" // get the address of the functions for this port (r 16 is 2x the port number)
+ "adc r27, r1" "\n\t" // by adding that offset to the address we had the compiler generate the ldi's for;
+ "ld r28, X+" "\n\t" // That was the address of the start of array of pointers to arrays of pointers
+ "ld r29, X" "\n\t" // Now we loaded Y with the start of our port's array of function pointers
+ "add r16, r16" "\n\t" // double r16, so it is 4x port number - that's the address of the start of the VPORT
+ "subi r16, 253" "\n\t" // Add 3; now this is the address of the VPORTx.INTFLAGS
+ "mov r26, r16" "\n\t" // r16 holds the INTFLAGs address, copy it to X reg low byte.
+ "ldi r27, 0" "\n\t" // clear x high byte
+ "ld r16, X" "\n\t" // Load flags to r16"
+ "st X, r16" "\n\t" // EARLYCLEAR
+ "sbiw r26, 0" "\n\t" // this will set flag if it's zero.
+ "breq AIntEnd" "\n\t" // port not enabled, null pointer, just clear flags end hit the exit ramp.
+ "AIntLoop:" "\n\t"
+ "lsr r16" "\n\t" // shift it right one place, now the LSB is in carry.
+ "brcs .+6" "\n\t" // means we have something to do this time.
+ "breq AIntEnd" "\n\t" // This means carry wasn't set and r17 is 0. - we're done.
+ "adiw r28, 2" "\n\t" // otherwise it's not the int we care about, increment Y by 2, so it will point to the next element.
+ "rjmp AIntLoop" "\n\t" // restart the loop in that case.
+ "ld r30, Y+" "\n\t" // load the function pointer simultaneously advancing the Y pointer so next iteration it will
+ "ld r31, Y+" "\n\t" // be pointing to the next function pointer.
+ "sbiw r30, 0" "\n\t" // zero-check the pointer before we call it.
+ "breq AIntLoop" "\n\t" // restart loop if pointer is null. There is no interrupt handler yet interrupt is enabled and fired; Don't call the null pointer
+ "icall" "\n\t" // call their function, which is allowed to shit on any upper registers other than 28, 29, 16, and 17.
+ "rjmp AIntLoop" "\n\t" // Restart loop after.
+ "AIntEnd:" "\n\t" // sooner or later r17 will be 0 and we'll branch here.
+ // with EARLYCLEAR variant, we don't need to do anything other than cleaning up working registers - flags already cleared.
+ "pop r31" "\n\t" // clean up a million registers
+ "pop r30" "\n\t"
+ "pop r29" "\n\t"
+ "pop r28" "\n\t"
+ "pop r27" "\n\t"
+ "pop r26" "\n\t"
+ "pop r25" "\n\t"
+ "pop r24" "\n\t"
+ "pop r23" "\n\t"
+ "pop r22" "\n\t"
+ "pop r21" "\n\t"
+ "pop r20" "\n\t"
+ "pop r19" "\n\t" // skip 16 again - it's way down at the end, because it was pushed earlier
+ "pop r18" "\n\t"
+ //"pop r17" "\n\t" // Early clear doesn't need the extra registers.
+ //"pop r15" "\n\t" // Early clear doesn't need the extra registers.
+ "pop r1" "\n\t"
+ "pop r0" "\n\t"
+ "out 0x3b, r0" "\n\t"
+ "pop r0" "\n\t"
+ "out 0x3f, r0" "\n\t" // between these is where there had been stuff added to the stack that we flushed.
+ "pop r0" "\n\t"
+ "pop r16" "\n\t" // this was the reg we pushed back in the port-specific file.
+ "reti" "\n" // now we should have the pointer to the return address fopr the ISR on top of the stack, so reti're
+ :: "x" ((uint16_t)(&intFunc))
+ );
+ __builtin_unreachable();
+ }
+#endif
+
+ void detachInterrupt(uint8_t pin) {
+ /* Get bit position and check pin validity */
+ uint8_t bitpos = digitalPinToBitPosition(pin);
+ if (bitpos == NOT_A_PIN) {
+ return;
+ }
+ uint8_t port = digitalPinToPort(pin);
+ uint8_t p = (port << 5) + bitpos;
+ *(((volatile uint8_t*) &PORTA_PIN0CTRL) + p) &= 0xF8; // int off....
+ *((volatile uint8_t*) ((uint16_t)((port << 4) + 3))) = (1 << bitpos);// flag clear
+ intFunc[port][bitpos] = 0; // clear pointer
+ }
+/* If not enabling attach on all ports always, instead the identical ISR definitions are in the WInterruptsA/B/C/D/E/F/G.c files.
+ * Okay, so what the f-- is going on here?
+ * To avoid each interrupt vector having it's own lengthy prologue and epilog separaely, which is needed in order for a function call to be made in an ISR
+ * All we do is push an upper register onto the stack so can load a value twice the PORT number there, and jump to actual function that does the work here.
+ *
+ * The isrBody() has two consecutive blocks of inline assembly, First, do what is basically a standard prologue, for something that calls a function (thus there is only one prologue, instead of one per port).
+ * We finish the prologue but we need to push the Y pointer and r15 (call saved) for this routine. Then we slip out out of that assembly block just to grab the pointer to IntFunc array, which we need in a pointer reg;
+ * The second block of inline ASM specifies that the pointer to the array of pointers to arrays of pointers to interrupt functions be passed in the X pointer register
+ *
+ * Assembly is split up only so we can grab that address through that in a constraint.
+ * We couldn't have done that any sooner, we had nowhere to put it. To that we add the pre-doubled port number - pointers are 2 bytes so we need that
+ * doubling.
+ *
+ * We can then load the pointer to this port's int functions to the call-saved Y register.
+ * Sutract 0 from that pointer to check that it's not 0. A null pointer is of no use. Assuming that there's a pointer, we continue.
+ * Next we need the INTFLAGs. We will get them from the VPORT, not the PORT. This is much easier. We double r16 for address of VPORT and add 3 with subi to
+ * get INTFLAGs, copy to r26, and load the 0 high byte to r27, read the flags into r15.
+ *
+ * Copy flags to r17 and then start the loop. We will check the intflags one at a time. We rightshift once, and check if carry is set, indicating we pushed a 1 out, if so we jump over
+ * three instructions handling the case if we it was a 0: We check then check first for the carry bit. If not, then we check if the zero flag is set, If THAT is then what's left of flags
+ * is and we've handled them all, and we jump to end. and if it's not, we increment the Y pointer by 2 and return to start of the loop
+ *
+ * For each of the ones that we do have a flag for, we load that pointer into Z with postincrement, subtract 0 from it and look at zero flag to make sure it's not null.
+ * assuming it's not, we fire icall to call the user function. Either way we then repeat the loop until out of flags.
+ * which at latest will happen when we're also at end of the ports intfunc array....
+ * Then, with the initial flags still in 15 and the the VPORT address in r16 copy that once more to a pointer register, 0 the high byte, and store the flags value we read to clear it.
+ * then it's just a matter of making sure we pop everything we pushed onto the stack in the reverse order, including r16 followed by the reti to exit the interrupt..
+*/
+
+ #if defined(CORE_ATTACH_ALL)
+ ISR(PORTA_PORT_vect, ISR_NAKED) {
+ asm volatile(
+ "push r16" "\n\t"
+ "ldi r16, 0" "\n\t"
+ #if PROGMEM_SIZE > 8192
+ "jmp AttachedISR" "\n\t"
+ #else
+ "rjmp AttachedISR" "\n\t"
+ #endif
+ ::);
+ __builtin_unreachable();
+ }
+ #ifdef PORTB_PINS
+ ISR(PORTB_PORT_vect, ISR_NAKED) {
+ asm volatile(
+ "push r16" "\n\t"
+ "ldi r16, 2" "\n\t"
+ #if PROGMEM_SIZE > 8192
+ "jmp AttachedISR" "\n\t"
+ #else
+ "rjmp AttachedISR" "\n\t"
+ #endif
+ ::);
+ __builtin_unreachable();
+ }
+ #endif
+ #ifdef PORTC_PINS
+ ISR(PORTC_PORT_vect, ISR_NAKED) {
+ asm volatile(
+ "push r16" "\n\t"
+ "ldi r16, 4" "\n\t"
+ #if PROGMEM_SIZE > 8192
+ "jmp AttachedISR" "\n\t"
+ #else
+ "rjmp AttachedISR" "\n\t"
+ #endif
+ ::);
+ __builtin_unreachable();
+ }
+ #endif
+ #endif
+#else /* This is the old implementation, and it's copyright boilerplate. */
+
+ /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ //<---- FFS! That was in the original!
+
+ /*
+ Part of the Wiring project - http://wiring.uniandes.edu.co
+
+ Copyright (c) 2004-05 Hernando Barragan
+
+ 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
+
+ Modified 24 November 2006 by David A. Mellis
+ Modified 1 August 2010 by Mark Sproul
+ (Spence: and presumably someone who didn't sign to adapt it to modernAVRs,
+ since nothing that this implementation would work with had been released until
+ 2016)
+ */
+
+
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #include "wiring_private.h"
+
+ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
+
+ void attachInterrupt(uint8_t pin, void (*userFunc)(void), uint8_t mode) {
+
+ /* Get bit position and check pin validity */
+ uint8_t bit_pos = digitalPinToBitPosition(pin);
+ if (bit_pos == NOT_A_PIN) return;
+
+ /* Get interrupt number from pin */
+ uint8_t interruptNum = (digitalPinToPort(pin) * 8) + bit_pos;
+
+ /* Check interrupt number and apply function pointer to correct array index */
+ if (interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+ intFunc[interruptNum] = userFunc;
+
+ // Configure the interrupt mode (trigger on low input, any change, rising
+ // edge, or falling edge)
+
+ switch (mode) {
+ case CHANGE:
+ mode = PORT_ISC_BOTHEDGES_gc;
+ break;
+ case FALLING:
+ mode = PORT_ISC_FALLING_gc;
+ break;
+ case RISING:
+ mode = PORT_ISC_RISING_gc;
+ break;
+ case LOW:
+ mode = PORT_ISC_LEVEL_gc;
+ break;
+ default:
+ return;
+ }
+
+ // Enable the interrupt.
+
+ /* Get pointer to correct pin control register */
+ PORT_t *port = digitalPinToPortStruct(pin);
+ volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(port, bit_pos);
+
+ /* Clear any previous setting */
+ *pin_ctrl_reg &= ~(PORT_ISC_gm);
+
+ /* Apply ISC setting */
+ *pin_ctrl_reg |= mode;
+ }
+ }
+
+ void detachInterrupt(uint8_t pin) {
+ /* Get bit position and check pin validity */
+ uint8_t bit_pos = digitalPinToBitPosition(pin);
+ if (bit_pos == NOT_A_PIN) return;
+
+ /* Get interrupt number from pin */
+ uint8_t interruptNum = (digitalPinToPort(pin) * 8) + bit_pos;
+
+ if (interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+ // Disable the interrupt.
+
+ /* Get pointer to correct pin control register */
+ PORT_t *port = digitalPinToPortStruct(pin);
+ volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(port, bit_pos);
+
+ /* Clear ISC setting */
+ *pin_ctrl_reg &= ~(PORT_ISC_gm);
+
+ intFunc[interruptNum] = 0;
+ }
+ }
+
+ static void port_interrupt_handler(uint8_t port) {
+
+ PORT_t *portStruct = portToPortStruct(port);
+ /* Copy flags */
+ uint8_t int_flags = portStruct->INTFLAGS;
+
+ uint8_t bit_pos = PIN0_bp, bit_mask = PIN0_bm;
+
+ /* Iterate through flags */
+ while(bit_pos <= PIN7_bp) {
+
+ /* Check if flag raised */
+ if (int_flags & bit_mask) {
+
+ /* Get interrupt */
+ uint8_t interrupt_num = port*8 + bit_pos;
+
+ /* Check if function defined */
+ if (intFunc[interrupt_num] != 0) {
+
+ /* Call function */
+ intFunc[interrupt_num]();
+ }
+ }
+ bit_pos++;
+ bit_mask = (bit_mask << 1);
+ }
+
+ /* Clear flags that have been handled */
+ portStruct->INTFLAGS = int_flags;
+ }
+
+ #define IMPLEMENT_ISR(vect, port) \
+ ISR(vect) { \
+ port_interrupt_handler(port);\
+ } \
+
+
+ IMPLEMENT_ISR(PORTA_PORT_vect, PA)
+ #if defined(PORTB_PORT_vect)
+ IMPLEMENT_ISR(PORTB_PORT_vect, PB)
+ #endif
+ #if defined(PORTC_PORT_vect)
+ IMPLEMENT_ISR(PORTC_PORT_vect, PC)
+ #endif
+ #if defined(PORTD_PORT_vect)
+ IMPLEMENT_ISR(PORTD_PORT_vect, PD)
+ #endif
+ #if defined(PORTE_PORT_vect)
+ IMPLEMENT_ISR(PORTE_PORT_vect, PE)
+ #endif
+ #if defined(PORTF_PORT_vect)
+ IMPLEMENT_ISR(PORTF_PORT_vect, PF)
+ #endif
+ // Nope, there was never attachInterrupt for PORTG and nobody complained for 2 years. Not going to change that -Speence 3/5/22
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PA.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PA.c
new file mode 100644
index 0000000..cb95748
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PA.c
@@ -0,0 +1,34 @@
+#if !defined(CORE_ATTACH_OLD) && !defined(CORE_ATTACH_ALL)
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include "wiring_private.h"
+
+ #ifdef PORTA
+ extern voidFuncPtr * intFunc[];
+ voidFuncPtr intFunc_A[8];
+ void attachPortAEnable() {
+ intFunc[0] = intFunc_A;
+ }
+ /* It is the act of referencing attachPortAEnable() in this file that the compiler to also include the ISR.
+ * (ISRs can't be assigned at runtime - the only way things like attachInterruprt look like they can is
+ * by having the ISR call a function pointer (ie, icall). After saving every call used plus SREG and RAMPZ.
+ * Beyond being slow, these lengthy prologues and epilogs slow take up flash. This can be like 80+ bytes
+ * per vector... That's ugly, particularly on small flash parts. See the discussion in WInterrupts.c about
+ * what this actually does.
+ */
+ ISR(PORTA_PORT_vect, ISR_NAKED) {
+ asm volatile(
+ "push r16" "\n\t"
+ "ldi r16, 0" "\n\t"
+#if PROGMEM_SIZE > 8192
+ "jmp AttachedISR" "\n\t"
+#else
+ "rjmp AttachedISR" "\n\t"
+#endif
+ ::);
+ }
+ #endif
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PB.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PB.c
new file mode 100644
index 0000000..041b898
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PB.c
@@ -0,0 +1,26 @@
+#if !defined(CORE_ATTACH_OLD) && !defined(CORE_ATTACH_ALL)
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include "wiring_private.h"
+ #if defined(PORTB_PINS)
+ extern voidFuncPtr * intFunc[];
+ voidFuncPtr intFunc_B[PORTB_PINS];
+ void attachPortBEnable() {
+ intFunc[1] = intFunc_B;
+ }
+ ISR(PORTB_PORT_vect, ISR_NAKED) {
+ asm volatile(
+ "push r16" "\n\t"
+ "ldi r16, 2" "\n\t"
+#if PROGMEM_SIZE > 8192
+ "jmp AttachedISR" "\n\t"
+#else
+ "rjmp AttachedISR" "\n\t"
+#endif
+ ::);
+ }
+ #endif
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PC.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PC.c
new file mode 100644
index 0000000..3c62356
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WInterrupts_PC.c
@@ -0,0 +1,26 @@
+#if !defined(CORE_ATTACH_OLD) && !defined(CORE_ATTACH_ALL)
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include "wiring_private.h"
+ #if defined(PORTC_PINS)
+ extern voidFuncPtr * intFunc[];
+ voidFuncPtr intFunc_C[PORTC_PINS];
+ void attachPortCEnable() {
+ intFunc[2] = intFunc_C;
+ }
+ ISR(PORTC_PORT_vect, ISR_NAKED) {
+ asm volatile(
+ "push r16" "\n\t"
+ "ldi r16, 4" "\n\t"
+#if PROGMEM_SIZE > 8192
+ "jmp AttachedISR" "\n\t"
+#else
+ "rjmp AttachedISR" "\n\t"
+#endif
+ ::);
+ }
+ #endif
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/WMath.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WMath.cpp
new file mode 100644
index 0000000..ab39002
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/WMath.cpp
@@ -0,0 +1,47 @@
+/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+ Part of the Wiring project - http://wiring.org.co
+ Copyright (c) 2004-06 Hernando Barragan
+ Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
+
+ 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
+*/
+
+extern "C" {
+#include "stdlib.h"
+}
+
+void randomSeed(unsigned long seed) {
+ if (seed != 0) {
+ srandom(seed);
+ }
+}
+
+long random(long howbig) {
+ if (howbig == 0) {
+ return 0;
+ }
+ return random() % howbig;
+}
+
+long random(long howsmall, long howbig) {
+ if (howsmall >= howbig) {
+ return howsmall;
+ }
+ long diff = howbig - howsmall;
+ return random(diff) + howsmall;
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/abi.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/abi.cpp
new file mode 100644
index 0000000..81d881e
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/abi.cpp
@@ -0,0 +1,34 @@
+/*
+ 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
+
+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();
+ abort();
+}
+
+void __cxa_deleted_virtual(void) {
+ // We might want to write some diagnostics to uart in this case
+ // std::terminate();
+ abort();
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/ArduinoAPI.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/ArduinoAPI.h
new file mode 100644
index 0000000..5e8e3bf
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/ArduinoAPI.h
@@ -0,0 +1,54 @@
+/*
+ Arduino API main include
+ 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
+*/
+
+#ifndef ARDUINO_API_H
+#define ARDUINO_API_H
+
+// version 1.0.0
+#define ARDUINO_API_VERSION 10000
+
+#include "Binary.h"
+
+#ifdef __cplusplus
+ #include "Client.h"
+ #include "HardwareI2C.h"
+ #include "HardwareSerial.h"
+ #include "IPAddress.h"
+ #include "Print.h"
+ #include "Printable.h"
+ #include "PluggableUSB.h"
+ #include "Server.h"
+ #include "String.h"
+ #include "Stream.h"
+ #include "Udp.h"
+ #include "USBAPI.h"
+ #include "WCharacter.h"
+#endif
+
+/* Standard C library includes */
+#include
+#include
+#include
+#include
+#include
+
+// Misc Arduino core functions
+#include "Common.h"
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Binary.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Binary.h
new file mode 100644
index 0000000..aec4c73
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/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/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Client.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Client.h
new file mode 100644
index 0000000..9b79edc
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Client.h
@@ -0,0 +1,44 @@
+/*
+ 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
+*/
+
+#pragma once
+
+#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();
+ };
+};
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Common.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Common.cpp
new file mode 100644
index 0000000..154ff1d
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Common.cpp
@@ -0,0 +1,13 @@
+#include "Common.h"
+
+/* C++ prototypes */
+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;
+}
+
+uint16_t makeWord(uint16_t w) {
+ return w;
+}
+uint16_t makeWord(uint8_t h, uint8_t l) {
+ return (h << 8) | l;
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Common.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Common.h
new file mode 100644
index 0000000..aacd897
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Common.h
@@ -0,0 +1,195 @@
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void yield(void);
+
+#define LOW 0 /* used for digitalWrite(), digitalRead(), openDrain() and attachInterrupt() */
+#define HIGH 1 /* used for digitalWrite(), digitalRead(). There is no option for HIGH level interrupt provided by the hardware */
+#define FLOATING HIGH /* Not in official API - used for openDrain, while making clear what you're doing */
+#define CHANGE 4 /* used for attachInterrupt() */
+#define FALLING 2 /* used for attachInterrupt() */
+#define RISING 3 /* used for attachInterrupt() */
+#define INPUT 0 /* used for pinMode() */
+#define OUTPUT 1 /* used for pinMode() */
+#define INPUT_PULLUP 2 /* used for pinMode() */
+#define LSBFIRST 0 /* used for shiftIn/shiftOut */
+#define MSBFIRST 1 /* used for shiftIn/shiftOut */
+
+
+#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 0x00
+#define DISPLAY 0x01
+
+#define min(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+#define max(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a > _b ? _a : _b; })
+
+#ifndef constrain
+#define constrain(x,low,high) ({ \
+ __typeof__ (x) _x = (x); \
+ __typeof__ (low) _l = (low); \
+ __typeof__ (high) _h = (high); \
+ _x < _l ? _l : _x > _h ? _h :_x ;})
+#endif
+
+#ifndef radians
+#define radians(deg) ((deg)*DEG_TO_RAD)
+#endif
+
+#ifndef degrees
+#define degrees(rad) ((rad)*RAD_TO_DEG)
+#endif
+
+#ifndef sq
+#define sq(x) ({ __typeof__ (x) _x = (x); _x * _x; })
+#endif
+
+
+/* This is sorta silly. But normal round() builtin is bulkier and returns a float while arduino code written for other platforms will expect
+integer types... This also has the same concerns about sideffects as before - except they're less likely to show up when
+starting from a float. Who does meFloat++? Certainly not as many as do constrain(myInt++,minval,maxval);
+*/
+
+#ifndef round
+#define round(x) ({ __typeof__ (x) _x = (x); _x >= 0 ? (long)(_x + 0.5) : (long)(_x - 0.5 );})
+#endif
+
+/* In the end, it is probably better to do this manually rather than using round(). Why?
+
+* If you know the value you're starting with is positive, you can skip the first test and just add 0.5 and cast to integer type - saves space.
+* You can use the minimum size datatypes (wthis casts things to 4-byte values. Maybe the thing your rounding is, say -50.0 to 50.0 you can cast to a single byte for more compact code
+* You can choose which of the rounding strategies you wish to use. Because there are not less than TEN DIFFERENT STRATEGIES TO ROUND NUMBERS
+* Any of these approaches will result in smaller code:
+* For example, rounding a number you know ought to fit a 16 bit unsigned datatype easily, you might do:
+* uint16_t roundedval = (uint16_t) (floatval + 0.5)
+*
+* Even better, avoid using floats in the first place. Why are you using them? sometimes you really don't have much of a choice, other times
+* you very definitely do. This is particularly true with ADC readings, for example say you're using to 4.096 Volt reference, and you
+* want to measure and print out a voltage.
+uint32_t reading = analogReadEnh(adc_pin, 12); //where adc_pin is just the pin number being read
+float temp = reading;
+Serial.print(temp/1000); // 4.096v reference, and 12 bit accuracy (ie, 0-4095). So each LSB is 1 mv so dividing by 1000 gets volts.
+Serial.println('V'); //print out the units too
+3.2k on a 1626/
+Or you could do:
+uint32_t reading = analogReadEnh(adc_pin, 12); // same analog reading
+Serial.print(reading/1000) //volts
+Serial.print('.'); //decimal point
+Serial.print(reading%1000) //millivolts
+Serial.println('V'); //print out the units too
+// This would print the same thing, only without any floating point derived error... weighing in at 2k of flash.
+
+// And just doing this saves another 100 bytes:
+uint32_t reading = analogReadEnh(1, 12); //where adc_pin is just the pin number being read
+Serial.print((uint16_t)reading);
+Serial.println("mV");
+
+
+* Yeah the last one is kind of a copoout, but not only is it flash-efficient, it also runs *much* faster, because division,
+* be it floating point or otherwise, is sloowwwwwwww on AVR. But the fact that there are better ways to round than round()
+* was not an excuse for it being broken like that.
+*/
+
+
+
+typedef void (*voidFuncPtr)(void);
+
+// interrupts() / noInterrupts() must be defined by the core
+
+// a bunch of really silly hand-holding macros!
+#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))
+#ifndef bit
+#define bit(b) (1UL << (b))
+#endif
+
+#if defined(DISCOURAGE_NONSTANDARD_TYPES) && DISCOURAGE_NONSTANDARD_TYPES
+typedef bool boolean __attribute__ ((deprecated("a 'boolean' is called a 'bool' in standard C - suggest using standard type name")));
+typedef uint8_t byte __attribute__ ((deprecated("a 'byte' is an 'unsigned char' (may be more than 8 bits on non-AVR) or 'uint8_t' (always 8 bits) in standard C - suggest using one of these standard types.")));
+typedef uint16_t word __attribute__ ((deprecated("a 'word' is an 'unsigned int' (may be more than 16 bits on non-AVR) or 'uint15_t' (always 16 bits) in standard C - suggest using one of these standard types.")));
+#else
+typedef bool boolean;
+typedef uint8_t byte;
+typedef uint16_t word;
+#endif
+void init(void);
+void initVariant(void);
+
+int atexit(void (*func)()) __attribute__((weak));
+int main() __attribute__((weak));
+
+#ifdef EXTENDED_PIN_MODE
+// Platforms who want to declare more than 256 pins need to define EXTENDED_PIN_MODE globally
+typedef uint32_t pin_size_t;
+#else
+typedef uint8_t pin_size_t;
+#endif
+
+void pinMode( pin_size_t pinNumber, uint8_t mode);
+void digitalWrite( pin_size_t pinNumber, uint8_t val);
+int8_t digitalRead( pin_size_t pinNumber);
+void analogWrite( pin_size_t pinNumber, int value);
+int analogRead( pin_size_t pinNumber);
+void analogReference( uint8_t mode);
+bool analogReadResolution( uint8_t res);
+
+unsigned long millis(void);
+unsigned long micros(void);
+
+void delay(unsigned long);
+void delayMicroseconds(unsigned int us);
+unsigned long pulseIn(pin_size_t pin, uint8_t state, unsigned long timeout);
+unsigned long pulseInLong(pin_size_t pin, uint8_t state, unsigned long timeout);
+
+void shiftOut(pin_size_t dataPin, pin_size_t clockPin, uint8_t bitOrder, uint8_t val);
+uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, uint8_t bitOrder);
+
+void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, uint8_t mode);
+void detachInterrupt(pin_size_t interruptNumber);
+
+void setup(void);
+void loop(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#ifdef __cplusplus
+ /* C++ prototypes */
+ uint16_t makeWord(uint16_t w);
+ uint16_t makeWord(byte h, byte l);
+
+ #define word(...) makeWord(__VA_ARGS__)
+
+ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
+ unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
+
+ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
+ void noTone(uint8_t _pin);
+
+ // WMath prototypes
+ long random(long);
+ long random(long, long);
+ void randomSeed(unsigned long);
+ long map(long, long, long, long, long);
+
+#endif // __cplusplus
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/HardwareI2C.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/HardwareI2C.h
new file mode 100644
index 0000000..16a395e
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/HardwareI2C.h
@@ -0,0 +1,45 @@
+/*
+ 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
+*/
+/* THIS FILE IS NOT USED BY ANY PART OF megaTinyCore
+ * Wire subclasses Stream directly, saving a large amount of flash
+ * The overhead was additive, and made the Wire.h unusable 2/4k parts.
+ */
+
+#pragma once
+
+#include
+#include "Stream.h"
+
+class HardwareI2C : public Stream {
+ public:
+ virtual void begin() = 0;
+ virtual void begin(uint8_t address) = 0;
+ virtual void end() = 0;
+
+ virtual void setClock(uint32_t freq) = 0;
+
+ virtual void beginTransmission(uint8_t address) = 0;
+ virtual uint8_t endTransmission(bool stopBit) = 0;
+ virtual uint8_t endTransmission(void) = 0;
+
+ virtual uint8_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
+ virtual uint8_t requestFrom(uint8_t address, size_t len) = 0;
+
+ virtual void onReceive(void(*)(int)) = 0;
+ virtual void onRequest(void(*)(void)) = 0;
+};
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/HardwareSerial.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/HardwareSerial.h
new file mode 100644
index 0000000..dd822d6
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/HardwareSerial.h
@@ -0,0 +1,54 @@
+/*
+ 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
+
+ Modified Spence Konde 2021 - constants removed.
+ Modified Spence Konde 2022 - commemt out the entire class. .
+*/
+
+//#prama never
+/*
+
+#pragma once
+
+#include
+#include "Stream.h"
+
+// XXX: Those constants should be defined as const int / enums?
+// XXX: shall we use namespaces too?
+// Spence: Screw that noise!
+// We do not have flash to waste, this code will be run with parts that have only 4k of flash
+// so using an integer to hold settings, and then REARRANGING THE BITS AT RUNTIME,
+// when they are ALL LOCATED NEXT TO EACH OTHER ON THE SAME BYTE is madness!
+// See UART_constants.h
+
+class HardwareSerial : public Stream {
+ public:
+ virtual void begin(unsigned long) = 0;
+ virtual void begin(unsigned long baudrate, uint16_t config) = 0;
+ virtual void end() = 0;
+ 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;
+};
+
+// XXX: Are we keeping the serialEvent API?
+// Spence: Apparently not.
+*/
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/IPAddress.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/IPAddress.cpp
new file mode 100644
index 0000000..ace636b
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/IPAddress.cpp
@@ -0,0 +1,101 @@
+/*
+ IPAddress.cpp - Base class that provides IPAddress
+ 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
+*/
+
+#include "IPAddress.h"
+#include "Print.h"
+
+IPAddress::IPAddress() {
+ _address.dword = 0;
+}
+
+IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
+ _address.bytes[0] = first_octet;
+ _address.bytes[1] = second_octet;
+ _address.bytes[2] = third_octet;
+ _address.bytes[3] = fourth_octet;
+}
+
+IPAddress::IPAddress(uint32_t address) {
+ _address.dword = address;
+}
+
+IPAddress::IPAddress(const uint8_t *address) {
+ memcpy(_address.bytes, address, sizeof(_address.bytes));
+}
+
+bool IPAddress::fromString(const char *address) {
+ // TODO: add support for "a", "a.b", "a.b.c" formats
+
+ uint16_t acc = 0; // Accumulator
+ uint8_t dots = 0;
+
+ while (*address) {
+ char c = *address++;
+ if (c >= '0' && c <= '9') {
+ acc = acc * 10 + (c - '0');
+ if (acc > 255) {
+ // Value out of [0..255] range
+ return false;
+ }
+ } else if (c == '.') {
+ if (dots == 3) {
+ // Too much dots (there must be 3 dots)
+ return false;
+ }
+ _address.bytes[dots++] = acc;
+ acc = 0;
+ } else {
+ // Invalid char
+ return false;
+ }
+ }
+
+ if (dots != 3) {
+ // Too few dots (there must be 3 dots)
+ return false;
+ }
+ _address.bytes[3] = acc;
+ return true;
+}
+
+IPAddress &IPAddress::operator = (const uint8_t *address) {
+ memcpy(_address.bytes, address, sizeof(_address.bytes));
+ return *this;
+}
+
+IPAddress &IPAddress::operator = (uint32_t address) {
+ _address.dword = address;
+ return *this;
+}
+
+bool IPAddress::operator==(const uint8_t *addr) const {
+ return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
+}
+
+size_t IPAddress::printTo(Print &p) const {
+ size_t n = 0;
+ for (int i = 0; i < 3; i++) {
+ n += p.print(_address.bytes[i], DEC);
+ n += p.print('.');
+ }
+ n += p.print(_address.bytes[3], DEC);
+ return n;
+}
+
+const IPAddress INADDR_NONE(0, 0, 0, 0);
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/IPAddress.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/IPAddress.h
new file mode 100644
index 0000000..2d1cb5e
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/IPAddress.h
@@ -0,0 +1,87 @@
+/*
+ IPAddress.h - Base class that provides IPAddress
+ 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
+*/
+
+#pragma once
+
+#include
+#include "Printable.h"
+#include "String.h"
+
+// A class to make it easier to handle and pass around IP addresses
+
+class IPAddress : public Printable {
+private:
+ union {
+ uint8_t bytes[4]; // IPv4 address
+ uint32_t dword;
+ } _address;
+
+ // Access the raw byte array containing the address. Because this returns a pointer
+ // to the internal structure rather than a copy of the address this function should only
+ // be used when you know that the usage of the returned uint8_t* will be transient and not
+ // stored.
+ uint8_t *raw_address() {
+ return _address.bytes;
+ };
+
+ public:
+ // Constructors
+ IPAddress();
+ IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
+ IPAddress(uint32_t address);
+ IPAddress(const uint8_t *address);
+
+ bool fromString(const char *address);
+ bool fromString(const String &address) {
+ return fromString(address.c_str());
+ }
+
+ // Overloaded cast operator to allow IPAddress objects to be used where a pointer
+ // to a four-byte uint8_t array is expected
+ operator uint32_t() const {
+ return _address.dword;
+ };
+ bool operator==(const IPAddress &addr) const {
+ return _address.dword == addr._address.dword;
+ };
+ bool operator==(const uint8_t *addr) const;
+
+ // Overloaded index operator to allow getting and setting individual octets of the address
+ uint8_t operator[](int index) const {
+ return _address.bytes[index];
+ };
+ uint8_t &operator[](int index) {
+ return _address.bytes[index];
+ };
+
+ // Overloaded copy operators to allow initialisation of IPAddress objects from other types
+ IPAddress &operator = (const uint8_t *address);
+ IPAddress &operator = (uint32_t address);
+
+ virtual size_t printTo(Print &p) const;
+
+ friend class EthernetClass;
+ friend class UDP;
+ friend class Client;
+ friend class Server;
+ friend class DhcpClass;
+ friend class DNSClient;
+};
+
+extern const IPAddress INADDR_NONE;
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/PluggableUSB.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/PluggableUSB.cpp
new file mode 100644
index 0000000..08cfe0d
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/PluggableUSB.cpp
@@ -0,0 +1,95 @@
+/*
+ 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 "PluggableUSB.h"
+
+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) > totalEP) {
+ 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++) {
+ *(unsigned int *)(epBuffer(lastEp)) = node->endpointType[i];
+ lastEp++;
+ }
+ return true;
+ // restart USB layer???
+}
+
+PluggableUSB_ &PluggableUSB() {
+ static PluggableUSB_ obj;
+ return obj;
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/PluggableUSB.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/PluggableUSB.h
new file mode 100644
index 0000000..056aed8
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/PluggableUSB.h
@@ -0,0 +1,78 @@
+/*
+ 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
+#include
+
+// core need to define
+void *epBuffer(unsigned int n); // -> returns a pointer to the Nth element of the EP buffer structure
+
+class PluggableUSBModule {
+ public:
+ PluggableUSBModule(uint8_t numEps, uint8_t numIfs, unsigned int *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 unsigned int *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;
+ uint8_t totalEP;
+};
+
+// 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
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Print.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Print.cpp
new file mode 100644
index 0000000..272ee87
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Print.cpp
@@ -0,0 +1,285 @@
+/*
+ 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 "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) {
+ #if defined(__AVR__)
+ PGM_P p = reinterpret_cast(ifsh);
+ size_t n = 0;
+ while (1) {
+ unsigned char c = pgm_read_byte(p++);
+ if (c == 0) {
+ break;
+ }
+ if (write(c)) {
+ n++;
+ } else {
+ break;
+ }
+ }
+ return n;
+ #else
+ return print(reinterpret_cast(ifsh));
+ #endif
+}
+
+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;
+}
+
+// Custom implementation of printf borrowed from the teensy core files
+static int16_t printf_putchar(char c, FILE *fp) {
+ ((class Print *)(fdev_get_udata(fp)))->write((uint8_t)c);
+ return 0;
+}
+
+int16_t Print::printf(const char *format, ...) {
+ FILE f;
+ va_list ap;
+
+ fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE);
+ fdev_set_udata(&f, this);
+ va_start(ap, format);
+ return vfprintf(&f, format, ap);
+}
+
+int16_t Print::printf(const __FlashStringHelper *format, ...) {
+ FILE f;
+ va_list ap;
+
+ fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE);
+ fdev_set_udata(&f, this);
+ va_start(ap, format);
+ return vfprintf_P(&f, (const char *)format, ap);
+}
+
+// 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 < digits; ++i) {
+ rounding /= 10.0;
+ }
+
+ number += rounding;
+
+ // Extract the integer part of the number and print it
+ unsigned long int_part = (unsigned long)number;
+ double remainder = number - (double)int_part;
+ n += print(int_part);
+
+ // Print the decimal point, but only if there are digits beyond
+ if (digits > 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/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Print.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Print.h
new file mode 100644
index 0000000..606a162
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Print.h
@@ -0,0 +1,96 @@
+/*
+ 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
+*/
+
+#pragma once
+
+#include
+#include // for size_t
+
+#include "String.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);
+ }
+
+ // default to zero, meaning "a single write may block"
+ // should be overridden by subclasses with buffering
+ virtual int availableForWrite() { return 0; }
+
+ 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);
+
+ int16_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+ int16_t printf(const __FlashStringHelper *format, ...);
+
+ virtual void flush() { /* Empty implementation for backward compatibility */ }
+};
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Printable.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Printable.h
new file mode 100644
index 0000000..9f6e4b8
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Printable.h
@@ -0,0 +1,34 @@
+/*
+ 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
+*/
+
+#pragma once
+
+#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;
+};
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/RingBuffer.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/RingBuffer.cpp
new file mode 100644
index 0000000..6c7203b
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/RingBuffer.cpp
@@ -0,0 +1,106 @@
+/*
+ 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
+#include
+#include
+
+RingBuffer::RingBuffer(rb_index_type size) : size(size) {
+ _aucBuffer = (uint8_t *)malloc(size);
+ memset(_aucBuffer, 0, size) ;
+ clear();
+}
+
+void RingBuffer::store_char(uint8_t c) {
+ rb_index_type 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) {
+ if (_iHead < size) {
+ _aucBuffer[_iHead] = c ;
+ } else {
+ additionalBuffer[_iHead - size] = c;
+ }
+ _iHead = i ;
+ }
+}
+
+void RingBuffer::clear() {
+ _iHead = 0;
+ _iTail = 0;
+}
+
+int RingBuffer::read_char() {
+ if (_iTail == _iHead) {
+ return -1;
+ }
+
+ uint8_t value;
+ if (_iTail < size) {
+ value = _aucBuffer[_iTail];
+ } else {
+ value = additionalBuffer[_iTail - size];
+ }
+ _iTail = nextIndex(_iTail);
+
+ return value;
+}
+
+int RingBuffer::available() {
+ int delta = _iHead - _iTail;
+
+ if (delta < 0) {
+ return size + additionalSize + delta;
+ } else {
+ return delta;
+ }
+}
+
+int RingBuffer::availableForStore() {
+ int delta = _iHead - _iTail;
+ if (delta >= 0) {
+ return size + additionalSize - 1 - delta;
+ } else {
+ return -delta - 1;
+ }
+}
+
+
+int RingBuffer::peek() {
+ if (_iTail == _iHead) {
+ return -1;
+ }
+
+ if (_iTail < size) {
+ return _aucBuffer[_iTail];
+ } else {
+ return additionalBuffer[_iTail - size];
+ }
+}
+
+rb_index_type RingBuffer::nextIndex(rb_index_type index) {
+ return (rb_index_type)(index + 1) % (size + additionalSize);
+}
+
+bool RingBuffer::isFull() {
+ return (nextIndex(_iHead) == _iTail);
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/RingBuffer.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/RingBuffer.h
new file mode 100644
index 0000000..92723b9
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/RingBuffer.h
@@ -0,0 +1,62 @@
+/*
+ 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 RINGBUFFER_HAS_ADDITIONAL_STORAGE_API
+
+#ifdef RINGBUFFER_FORCE_SMALL_SIZE
+ typedef uint8_t rb_index_type;
+#else
+ typedef unsigned int rb_index_type;
+#endif
+
+class RingBuffer {
+ public:
+ RingBuffer(rb_index_type size = 64) ;
+ void store_char(uint8_t c) ;
+ void clear();
+ int read_char();
+ int available();
+ int availableForStore();
+ int peek();
+ bool isFull();
+ void addStorage(uint8_t *_buffer, rb_index_type _size) {
+ additionalSize = _size;
+ additionalBuffer = _buffer;
+ };
+
+ private:
+ rb_index_type nextIndex(rb_index_type index);
+ uint8_t *additionalBuffer;
+ int additionalSize = 0;
+ rb_index_type size;
+ uint8_t *_aucBuffer;
+ volatile rb_index_type _iHead ;
+ volatile rb_index_type _iTail ;
+};
+
+#endif /* _RING_BUFFER_ */
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Server.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Server.h
new file mode 100644
index 0000000..0e970df
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Server.h
@@ -0,0 +1,27 @@
+/*
+ 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
+*/
+
+#pragma once
+
+#include "Print.h"
+
+class Server : public Print {
+ public:
+ virtual void begin() = 0;
+};
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Stream.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Stream.cpp
new file mode 100644
index 0000000..e757055
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Stream.cpp
@@ -0,0 +1,358 @@
+/*
+ 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 "util/delay.h"
+
+#include "Common.h"
+#include "Stream.h"
+
+
+#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
+/*
+__attribute__ ((inline)) void wait_250_clocks() {
+ for (uint8_t i = 0; i < 245; i++) {
+ NOP();
+ }
+}
+*/
+
+int Stream::timedRead() {
+ #if !defined(MILLIS_USE_TIMERNONE)
+ int c;
+ unsigned long startMillis = millis(); //formerly, this was a member variable! Eating 4 bytes of ram for no bloody reason.
+ do {
+ c = read();
+ if (c >= 0) {
+ return c;
+ }
+ } while (millis() - startMillis < _timeout);
+ return -1; // -1 indicates timeout
+ #else
+ int c;
+ for (uint32_t i = 0; i < _timeout; i++) {
+ c = read();
+ if (c >= 0) {
+ return c;
+ }
+ _delay_us(980); //not 1000, b/c compensation for the rest
+ }
+ return -1; // -1 indicates timeout
+ #endif
+}
+
+// private method to peek stream with timeout
+int Stream::timedPeek() {
+ #if !defined(MILLIS_USE_TIMERNONE)
+ int c;
+ unsigned long startMillis = millis();
+ do {
+ c = peek();
+ if (c >= 0) {
+ return c;
+ }
+ } while (millis() - startMillis < _timeout);
+ return -1; // -1 indicates timeout
+ #else
+ int c;
+ for (uint32_t i = 0; i < _timeout; i++) {
+ c = read();
+ if (c >= 0) {
+ return c;
+ }
+ _delay_us(980); //not 1000, b/c compensation for the rest
+ }
+ return -1; // -1 indicates timeout
+ #endif
+}
+
+// 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 ' ': // fall-through
+ 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/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Stream.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Stream.h
new file mode 100644
index 0000000..038baf7
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Stream.h
@@ -0,0 +1,149 @@
+/*
+ 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
+*/
+
+#pragma once
+
+#include
+#include "Print.h"
+
+// compatibility 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; // Formerly used for timer measurement. Unnecessary. Removed and assembly dependent on the class structure adjusted.
+ 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
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/String.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/String.cpp
new file mode 100644
index 0000000..3b68948
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/String.cpp
@@ -0,0 +1,815 @@
+/*
+ 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 "String.h"
+#include "itoa.h"
+#include "deprecated-avr-comp/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/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/String.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/String.h
new file mode 100644
index 0000000..f3247cc
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/String.h
@@ -0,0 +1,290 @@
+/*
+ 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
+*/
+
+#pragma once
+
+#ifdef __cplusplus
+
+#include
+#include
+#include
+#if defined(__AVR__)
+ #include "avr/pgmspace.h"
+#else
+ #include "deprecated-avr-comp/avr/pgmspace.h"
+#endif
+
+// 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 unsuccessful.
+ 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 access
+ 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 ©(const char *cstr, unsigned int length);
+ String ©(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
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/USBAPI.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/USBAPI.h
new file mode 100644
index 0000000..d363968
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/USBAPI.h
@@ -0,0 +1,57 @@
+/*
+ USBAPI.h
+ Copyright (c) 2005-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 __USBAPI__
+#define __USBAPI__
+
+#include
+
+
+// Low level API
+
+typedef struct __attribute__((packed))
+{
+ 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;
+
+
+int USB_SendControl(uint8_t flags, const void* d, int len);
+int USB_RecvControl(void* d, int len);
+int USB_RecvControlLong(void* d, int len);
+
+uint8_t USB_Available(uint8_t ep);
+uint8_t USB_SendSpace(uint8_t ep);
+int USB_Send(uint8_t ep, const void* data, int len); // blocking
+int USB_Recv(uint8_t ep, void* data, int len); // non-blocking
+int USB_Recv(uint8_t ep); // non-blocking
+void USB_Flush(uint8_t ep);
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Udp.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Udp.h
new file mode 100644
index 0000000..97b45e6
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/Udp.h
@@ -0,0 +1,87 @@
+/*
+ * Udp.cpp: Library to send/receive UDP packets.
+ *
+ * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
+ * 1) UDP does not guarantee the order in which assembled UDP packets are received. This
+ * might not happen often in practice, but in larger network topologies, a UDP
+ * packet can be received out of sequence.
+ * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
+ * aware of it. Again, this may not be a concern in practice on small local networks.
+ * For more information, see http://www.cafeaulait.org/course/week12/35.html
+ *
+ * MIT License:
+ * Copyright (c) 2008 Bjoern Hartmann
+ * 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.
+ *
+ * bjoern@cs.stanford.edu 12/30/2008
+ */
+
+#pragma once
+
+#include "Stream.h"
+#include "IPAddress.h"
+
+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 void stop() = 0; // Finish with the UDP socket
+
+ // Sending UDP packets
+
+ // Start building up a packet to send to the remote host specific in ip and port
+ // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
+ virtual int beginPacket(IPAddress ip, uint16_t port) = 0;
+ // Start building up a packet to send to the remote host specific in host and port
+ // Returns 1 if successful, 0 if there was a problem resolving the hostname or port
+ virtual int beginPacket(const char *host, uint16_t port) = 0;
+ // Finish off this packet and send it
+ // Returns 1 if the packet was sent successfully, 0 if there was an error
+ virtual int endPacket() = 0;
+ // Write a single byte into the packet
+ virtual size_t write(uint8_t) = 0;
+ // Write size bytes from buffer into the packet
+ virtual size_t write(const uint8_t *buffer, size_t size) = 0;
+
+ // Start processing the next available incoming packet
+ // Returns the size of the packet in bytes, or 0 if no packets are available
+ virtual int parsePacket() = 0;
+ // Number of bytes remaining in the current packet
+ virtual int available() = 0;
+ // Read a single byte from the current packet
+ virtual int read() = 0;
+ // Read up to len bytes from the current packet and place them into buffer
+ // Returns the number of bytes read, or 0 if none are available
+ virtual int read(unsigned char *buffer, size_t len) = 0;
+ // Read up to len characters from the current packet and place them into buffer
+ // Returns the number of characters read, or 0 if none are available
+ virtual int read(char *buffer, size_t len) = 0;
+ // Return the next byte from the current packet without moving on to the next byte
+ virtual int peek() = 0;
+ virtual void flush() = 0; // Finish reading the current packet
+
+ // Return the IP address of the host who sent the current incoming packet
+ virtual IPAddress remoteIP() = 0;
+ // Return the port of the host who sent the current incoming packet
+ virtual uint16_t remotePort() = 0;
+ protected:
+ uint8_t *rawIPAddress(IPAddress &addr) {
+ return addr.raw_address();
+ };
+};
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/WCharacter.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/WCharacter.h
new file mode 100644
index 0000000..83be224
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/WCharacter.h
@@ -0,0 +1,152 @@
+/*
+ WCharacter.h - Character utility functions for Wiring & Arduino
+ Copyright (c) 2010 Hernando Barragan. 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
+
+// WCharacter.h prototypes
+inline bool isAlphaNumeric(int c) __attribute__((always_inline));
+inline bool isAlpha(int c) __attribute__((always_inline));
+inline bool isAscii(int c) __attribute__((always_inline));
+inline bool isWhitespace(int c) __attribute__((always_inline));
+inline bool isControl(int c) __attribute__((always_inline));
+inline bool isDigit(int c) __attribute__((always_inline));
+inline bool isGraph(int c) __attribute__((always_inline));
+inline bool isLowerCase(int c) __attribute__((always_inline));
+inline bool isPrintable(int c) __attribute__((always_inline));
+inline bool isPunct(int c) __attribute__((always_inline));
+inline bool isSpace(int c) __attribute__((always_inline));
+inline bool isUpperCase(int c) __attribute__((always_inline));
+inline bool 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));
+
+
+// Checks for an alphanumeric character.
+// It is equivalent to (isalpha(c) || isdigit(c)).
+inline bool isAlphaNumeric(int c) {
+ return (isalnum(c) == 0 ? false : true);
+}
+
+
+// Checks for an alphabetic character.
+// It is equivalent to (isupper(c) || islower(c)).
+inline bool 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 bool isAscii(int c) {
+ return (isascii(c) == 0 ? false : true);
+}
+
+
+// Checks for a blank character, that is, a space or a tab.
+inline bool isWhitespace(int c) {
+ return (isblank(c) == 0 ? false : true);
+}
+
+
+// Checks for a control character.
+inline bool isControl(int c) {
+ return (iscntrl(c) == 0 ? false : true);
+}
+
+
+// Checks for a digit (0 through 9).
+inline bool isDigit(int c) {
+ return (isdigit(c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character except space.
+inline bool isGraph(int c) {
+ return (isgraph(c) == 0 ? false : true);
+}
+
+
+// Checks for a lower-case character.
+inline bool isLowerCase(int c) {
+ return (islower(c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character including space.
+inline bool isPrintable(int c) {
+ return (isprint(c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character which is not a space
+// or an alphanumeric character.
+inline bool 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 bool isSpace(int c) {
+ return (isspace(c) == 0 ? false : true);
+}
+
+
+// Checks for an uppercase letter.
+inline bool 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 bool 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);
+}
+
+
+// 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);
+}
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/dtostrf.c.impl b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/dtostrf.c.impl
new file mode 100644
index 0000000..7f96b11
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/dtostrf.c.impl
@@ -0,0 +1,36 @@
+/*
+ dtostrf - Emulation for dtostrf function from avr-libc
+ Copyright (c) 2016 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
+*/
+
+// This is a default implementation for dtostrf function.
+// This file should be used if the standard lib doesn't provide an
+// implementation of dtostrf.
+
+// Create a file called "dtostrf.c" with the following include:
+// #include "api/deprecated-avr-comp/avr/dtostrf.c.impl"
+
+#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/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/dtostrf.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/dtostrf.h
new file mode 100644
index 0000000..2d287ca
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/dtostrf.h
@@ -0,0 +1,34 @@
+/*
+ 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
+
+#if !defined(ARDUINO_ARCH_AVR)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *dtostrf(double val, signed char width, unsigned char prec, char *sout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/interrupt.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/interrupt.h
new file mode 100644
index 0000000..950509d
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/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/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/pgmspace.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/avr/pgmspace.h
new file mode 100644
index 0000000..97040b2
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated-avr-comp/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/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Client.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Client.h
new file mode 100644
index 0000000..8cb5a89
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Client.h
@@ -0,0 +1,23 @@
+/*
+ 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
+*/
+
+// including Client.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../Client.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/IPAddress.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/IPAddress.h
new file mode 100644
index 0000000..3c4b915
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/IPAddress.h
@@ -0,0 +1,23 @@
+/*
+ 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
+*/
+
+// including IPAddress.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../IPAddress.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Print.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Print.h
new file mode 100644
index 0000000..6f67353
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Print.h
@@ -0,0 +1,23 @@
+/*
+ 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
+*/
+
+// including Print.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../Print.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Printable.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Printable.h
new file mode 100644
index 0000000..be87545
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Printable.h
@@ -0,0 +1,23 @@
+/*
+ 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
+*/
+
+// including Printable.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../Printable.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Server.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Server.h
new file mode 100644
index 0000000..cbf0da7
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Server.h
@@ -0,0 +1,23 @@
+/*
+ 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
+*/
+
+// including Server.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../Server.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Stream.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Stream.h
new file mode 100644
index 0000000..fb96a33
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Stream.h
@@ -0,0 +1,23 @@
+/*
+ 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
+*/
+
+// including Stream.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../Stream.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Udp.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Udp.h
new file mode 100644
index 0000000..46317c7
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/Udp.h
@@ -0,0 +1,23 @@
+/*
+ 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
+*/
+
+// including Udp.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../Udp.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/WString.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/WString.h
new file mode 100644
index 0000000..d64b0e4
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/deprecated/WString.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 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
+*/
+
+// including WString.h is deprecated, for all future projects use Arduino.h instead
+
+// This include is added for compatibility, it will be remove on the next
+// major release of the API
+#include "../String.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/itoa.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/itoa.h
new file mode 100644
index 0000000..595c058
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/api/itoa.h
@@ -0,0 +1,36 @@
+/*
+ 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
+*/
+
+#pragma once
+
+// Standard C functions required in Arduino API
+// If these functions are not provided by the standard library, the
+// core should supply an implementation of them.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *itoa(int value, char *string, int radix);
+extern char *ltoa(long value, char *string, int radix);
+extern char *utoa(unsigned value, char *string, int radix);
+extern char *ultoa(unsigned long value, char *string, int radix);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/asm/wiring_pulse.S b/fw/HackSpaceCon_AS7/Arduino/megatinycore/asm/wiring_pulse.S
new file mode 100644
index 0000000..ffdbf11
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/asm/wiring_pulse.S
@@ -0,0 +1,189 @@
+/*
+ wiring_pulse.s - pulseInASM() function in different flavours
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2014 Martino Facchin, 2020 Spence Konde
+
+ 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
+*/
+
+/*
+ * The following routine was generated by avr-gcc 4.8.3 with the following parameters
+ * -gstabs -Wa,-ahlmsd=output.lst -dp -fverbose-asm -O2
+ * on the original C function
+ *
+ * unsigned long pulseInSimpl(volatile uint8_t *port, uint8_t bit, uint8_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;
+ * }
+ *
+ * some compiler outputs were removed but the rest of the code is untouched
+ *
+ * Spence feb 2020: not untouched anymore! The first two loops ran in 11 cycles instead
+ * of 16, so if no pulse was detected, the timeout would be reached when
+ * 11/16ths of the requested timeout had elapsed. This was fixed by the addition
+ * of 2 rjmps to the next line (a 2 cycle nop that uses only 1 word) and 1 nop
+ * to each of these loops before they decrement maxloops.
+ * Additionally, removed duplication of return sequence to save 12b flash
+ * which is conveniently exactly how much the other fix cost.
+ */
+
+#include
+
+.section .text
+
+.global countPulseASM
+
+countPulseASM:
+
+.LM0:
+.LFBB1:
+ push r12 ; ; 130 pushqi1/1 [length = 1]
+ push r13 ; ; 131 pushqi1/1 [length = 1]
+ push r14 ; ; 132 pushqi1/1 [length = 1]
+ push r15 ; ; 133 pushqi1/1 [length = 1]
+ push r16 ; ; 134 pushqi1/1 [length = 1]
+ push r17 ; ; 135 pushqi1/1 [length = 1]
+/* prologue: function */
+/* frame size = 0 */
+/* stack size = 6 */
+.L__stack_usage = 6
+ mov r30,r24 ; port, port ; 2 *movhi/1 [length = 2]
+ mov r31,r25 ; port, port
+/* unsigned long width = 0;
+*** // wait for any previous pulse to end
+*** while ((*port & bit) == stateMask)
+*/
+.LM1:
+ rjmp .L2 ; ; 181 jump [length = 1]
+.L4:
+/* if (--maxloops == 0) */
+.LM2:
+ rjmp .LM2A ; waste an extra 5 cycles
+.LM2A:
+ rjmp .LM2B ;
+.LM2B:
+ nop ;
+ subi r16,1 ; maxloops, ; 17 addsi3/2 [length = 4]
+ sbc r17, r1 ; maxloops
+ sbc r18, r1 ; maxloops
+ sbc r19, r1 ; maxloops
+ breq .L13 ; , ; 19 branch [length = 1]
+.L2:
+/* if (--maxloops == 0) */
+.LM3:
+ ld r25,Z ; D.1554, *port_7(D) ; 22 movqi_insn/4 [length = 1]
+ and r25,r22 ; D.1554, bit ; 24 andqi3/1 [length = 1]
+ cp r25,r20 ; D.1554, stateMask ; 25 *cmpqi/2 [length = 1]
+ breq .L4 ; , ; 26 branch [length = 1]
+ rjmp .L6 ; ; 184 jump [length = 1]
+.L7:
+/* return 0;
+***
+*** // wait for the pulse to start
+*** while ((*port & bit) != stateMask)
+*** if (--maxloops == 0)
+*/
+.LM4:
+ rjmp .LM4A ; waste an extra 5 cycles
+.LM4A:
+ rjmp .LM4B ;
+.LM4B:
+ nop ;
+ subi r16,1 ; maxloops, ; 31 addsi3/2 [length = 4]
+ sbc r17, r1 ; maxloops
+ sbc r18, r1 ; maxloops
+ sbc r19, r1 ; maxloops
+ breq .L13 ; , ; 33 branch [length = 1]
+.L6:
+/* if (--maxloops == 0) */
+.LM5:
+ ld r25,Z ; D.1554, *port_7(D) ; 41 movqi_insn/4 [length = 1]
+ and r25,r22 ; D.1554, bit ; 43 andqi3/1 [length = 1]
+ cpse r25,r20 ; D.1554, stateMask ; 44 enable_interrupt-3 [length = 1]
+ rjmp .L7 ;
+ mov r12, r1 ; width ; 7 *movsi/2 [length = 4]
+ mov r13, r1 ; width
+ mov r14, r1 ; width
+ mov r15, r1 ; width
+ rjmp .L9 ; ; 186 jump [length = 1]
+.L10:
+/* return 0;
+***
+*** // wait for the pulse to stop
+*** while ((*port & bit) == stateMask) {
+*** if (++width == maxloops)
+*/
+.LM6:
+ ldi r24,-1 ; , ; 50 addsi3/3 [length = 5]
+ sub r12,r24 ; width,
+ sbc r13,r24 ; width,
+ sbc r14,r24 ; width,
+ sbc r15,r24 ; width,
+ cp r16,r12 ; maxloops, width ; 51 *cmpsi/2 [length = 4]
+ cpc r17,r13 ; maxloops, width
+ cpc r18,r14 ; maxloops, width
+ cpc r19,r15 ; maxloops, width
+ breq .L13 ; , ; 52 branch [length = 1]
+.L9:
+/* if (++width == maxloops) */
+.LM7:
+ ld r24,Z ; D.1554, *port_7(D) ; 60 movqi_insn/4 [length = 1]
+ and r24,r22 ; D.1554, bit ; 62 andqi3/1 [length = 1]
+ cp r24,r20 ; D.1554, stateMask ; 63 *cmpqi/2 [length = 1]
+ breq .L10 ; , ; 64 branch [length = 1]
+/* return 0;
+*** }
+*** return width;
+*/
+.LM8:
+ mov r22,r12 ; D.1553, width ; 108 movqi_insn/1 [length = 1]
+ mov r23,r13 ; D.1553, width ; 109 movqi_insn/1 [length = 1]
+ mov r24,r14 ; D.1553, width ; 110 movqi_insn/1 [length = 1]
+ mov r25,r15 ; D.1553, width ; 111 movqi_insn/1 [length = 1]
+ rjmp .LM11 ;
+/* epilogue start */
+.L13:
+.LM10:
+ ldi r22,0 ; D.1553 ; 120 movqi_insn/1 [length = 1]
+ ldi r23,0 ; D.1553 ; 121 movqi_insn/1 [length = 1]
+ ldi r24,0 ; D.1553 ; 122 movqi_insn/1 [length = 1]
+ ldi r25,0 ; D.1553 ; 123 movqi_insn/1 [length = 1]
+/* epilogue start */
+.LM11:
+ pop r17 ; ; 138 popqi [length = 1]
+ pop r16 ; ; 139 popqi [length = 1]
+ pop r15 ; ; 140 popqi [length = 1]
+ pop r14 ; ; 141 popqi [length = 1]
+ pop r13 ; ; 142 popqi [length = 1]
+ pop r12 ; ; 143 popqi [length = 1]
+ ret ; 144 return_from_epilogue [length = 1]
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/core_devices.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/core_devices.h
new file mode 100644
index 0000000..f1a5cfd
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/core_devices.h
@@ -0,0 +1,5094 @@
+/* core_devices - a part of Arduino.h for megaTinyCore 2.3.0 and later and DxCore 1.4.0, but
+ * which takes in much greater importance (and girth) with the toolchain update in 2.6 and 1.6)
+ * This is directly included by Arduino.h and nothing else; it just moves
+ * clutter out of that file. You should not directly include this file ever.
+ *
+ * (C) Spence Konde 2021 - 2023. megaTinyCore and DxCore are free software (LGPL 2.1)
+ * See LICENSE.txt for full legal boilerplate if you must */
+
+#ifndef Core_Devices_h
+#define Core_Devices_h
+#include
+#include
+#define PROGMEM_MAPPED // All modern tinyAVRs have mapped flash.
+//#defines to identify part families
+#if defined(__AVR_ATtiny3227__)
+ #define MEGATINYCORE_MCU 3227
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx27__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 32
+#elif defined(__AVR_ATtiny1627__)
+ #define MEGATINYCORE_MCU 1627
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx27__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny827__)
+ #define MEGATINYCORE_MCU 827
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx27__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny427__)
+ #define MEGATINYCORE_MCU 427
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx27__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny3226__)
+ #define MEGATINYCORE_MCU 3226
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx26__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 32
+#elif defined(__AVR_ATtiny1626__)
+ #define MEGATINYCORE_MCU 1626
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx26__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny826__)
+ #define MEGATINYCORE_MCU 826
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx26__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny426__)
+ #define MEGATINYCORE_MCU 426
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx26__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny3224__)
+ #define MEGATINYCORE_MCU 3224
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx24__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 32
+#elif defined(__AVR_ATtiny1624__)
+ #define MEGATINYCORE_MCU 1624
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx24__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny824__)
+ #define MEGATINYCORE_MCU 824
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx24__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny424__)
+ #define MEGATINYCORE_MCU 424
+ #define MEGATINYCORE_SERIES 2
+ #define __AVR_ATtinyx24__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny3217__)
+ #define MEGATINYCORE_MCU 3217
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx17__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 32
+#elif defined(__AVR_ATtiny1617__)
+ #define MEGATINYCORE_MCU 1617
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx17__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny817__)
+ #define MEGATINYCORE_MCU 817
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx17__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny417__)
+ #define MEGATINYCORE_MCU 417
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx17__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 2
+#elif defined(__AVR_ATtiny3207__)
+ #define MEGATINYCORE_MCU 3207
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx07__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 32
+#elif defined(__AVR_ATtiny1607__)
+ #define MEGATINYCORE_MCU 1607
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx07__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny807__)
+ #define MEGATINYCORE_MCU 807
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx07__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny407__)
+ #define MEGATINYCORE_MCU 407
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx07__
+ #define __AVR_ATtinyxy7__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny3216__)
+ #define MEGATINYCORE_MCU 3216
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx16__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 32
+#elif defined(__AVR_ATtiny1616__)
+ #define MEGATINYCORE_MCU 1616
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx16__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny816__)
+ #define MEGATINYCORE_MCU 816
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx16__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny416__)
+ #define MEGATINYCORE_MCU 416
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx16__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny1606__)
+ #define MEGATINYCORE_MCU 1606
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx06__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny806__)
+ #define MEGATINYCORE_MCU 806
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx06__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny406__)
+ #define MEGATINYCORE_MCU 406
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx06__
+ #define __AVR_ATtinyxy6__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny214__)
+ #define MEGATINYCORE_MCU 214
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx14__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 2
+#elif defined(__AVR_ATtiny1614__)
+ #define MEGATINYCORE_MCU 1614
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx14__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny814__)
+ #define MEGATINYCORE_MCU 814
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx14__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny414__)
+ #define MEGATINYCORE_MCU 414
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx14__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny204__)
+ #define MEGATINYCORE_MCU 204
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx04__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 2
+#elif defined(__AVR_ATtiny804__)
+ #define MEGATINYCORE_MCU 804
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx04__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 8
+#elif defined(__AVR_ATtiny404__)
+ #define MEGATINYCORE_MCU 404
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx04__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny1604__)
+ #define MEGATINYCORE_MCU 1604
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx04__
+ #define __AVR_ATtinyxy4__
+ #define _AVR_FLASH 16
+#elif defined(__AVR_ATtiny212__)
+ #define MEGATINYCORE_MCU 212
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx12__
+ #define __AVR_ATtinyxy2__
+ #define _AVR_FLASH 2
+#elif defined(__AVR_ATtiny412__)
+ #define MEGATINYCORE_MCU 412
+ #define MEGATINYCORE_SERIES 1
+ #define __AVR_ATtinyx12__
+ #define __AVR_ATtinyxy2__
+ #define _AVR_FLASH 4
+#elif defined(__AVR_ATtiny202__)
+ #define MEGATINYCORE_MCU 202
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx02__
+ #define __AVR_ATtinyxy2__
+ #define _AVR_FLASH 2
+#elif defined(__AVR_ATtiny402__)
+ #define MEGATINYCORE_MCU 402
+ #define MEGATINYCORE_SERIES 0
+ #define __AVR_ATtinyx02__
+ #define __AVR_ATtinyxy2__
+ #define _AVR_FLASH 4
+#else
+ #error "Can't-happen: unknown chip somehow being used!"
+#endif
+
+/* Used for AttachInterrupt to reduce RAM use. */
+#ifdef __AVR_ATtinyxy4__
+ #define PORTB_PINS 4
+ #define _AVR_PINCOUNT 14
+#endif
+#ifdef __AVR_ATtinyxy6__
+ #define PORTB_PINS 6
+ #define PORTC_PINS 4
+ #define _AVR_PINCOUNT 20
+#endif
+#ifdef __AVR_ATtinyxy7__
+ #define PORTB_PINS 8
+ #define PORTC_PINS 6
+ #define _AVR_PINCOUNT 24
+#endif
+#ifdef __AVR_ATtinyxy2__
+ #define _AVR_PINCOUNT 8
+#endif
+
+#include "errata.h"
+
+#if MEGATINYCORE_SERIES == 0
+ #define _AVR_FAMILY "T0"
+ #define __AVR_TINY_0__
+#elif MEGATINYCORE_SERIES == 1
+ #define _AVR_FAMILY "T1"
+ #define __AVR_TINY_1__
+#elif MEGATINYCORE_SERIES == 2
+ #define _AVR_FAMILY "T2"
+ #define __AVR_TINY_2__
+#endif
+
+/* FOLLOWING THIS, SHARED WITH DxCoRE DIRECTLY */
+#if defined(AC2)
+ #define _AVR_AC_COUNT (3)
+#elif defined(AC1)
+ #define _AVR_AC_COUNT (2)
+#elif defined(AC0)
+ #define _AVR_AC_COUNT (1)
+#else
+ #define _AVR_AC_COUNT (0)
+ #error "No AC? No supported parts exist without one, something is wrong"
+#endif
+
+#if defined(ADC1)
+ #define _AVR_ADC_COUNT (2)
+#elif defined(ADC0)
+ #define _AVR_ADC_COUNT (1)
+#else
+ #define _AVR_ADC_COUNT (0)
+ #error "No ADC? No supported parts exist without one, something is wrong"
+#endif
+
+/* EVSYS:
+ * Count up the event channels.
+ * There are only 2 possibilities for tinyAVRs with the wacko channels.
+ * Since they're not making more of those, test for those two cases only, otherwise, might as well check every option.
+ */
+#if defined (EVSYS_ASYNCCH3) // tinyAVR 1
+ #define _AVR_EVSYS_COUNT (6)
+ #define _AVR_EVSYS_ASYNC (4)
+ #define _AVR_EVSYS_SYNC (2)
+#elif defined (EVSYS_ASYNCCH1) // tinyAVR 0
+ #define _AVR_EVSYS_COUNT (3)
+ #define _AVR_EVSYS_ASYNC (2)
+ #define _AVR_EVSYS_SYNC (1)
+#elif defined(EVSYS_CHANNEL15)
+ #define _AVR_EVSYS_COUNT (16)
+#elif defined(EVSYS_CHANNEL14)
+ #define _AVR_EVSYS_COUNT (15)
+#elif defined(EVSYS_CHANNEL13)
+ #define _AVR_EVSYS_COUNT (14)
+#elif defined(EVSYS_CHANNEL12)
+ #define _AVR_EVSYS_COUNT (13)
+#elif defined(EVSYS_CHANNEL11)
+ #define _AVR_EVSYS_COUNT (12)
+#elif defined(EVSYS_CHANNEL10)
+ #define _AVR_EVSYS_COUNT (11)
+#elif defined(EVSYS_CHANNEL9)
+ #define _AVR_EVSYS_COUNT (10)
+#elif defined(EVSYS_CHANNEL8)
+ #define _AVR_EVSYS_COUNT (9)
+#elif defined(EVSYS_CHANNEL7)
+ #define _AVR_EVSYS_COUNT (8)
+#elif defined(EVSYS_CHANNEL6)
+ #define _AVR_EVSYS_COUNT (7)
+#elif defined(EVSYS_CHANNEL5)
+ #define _AVR_EVSYS_COUNT (6)
+#elif defined(EVSYS_CHANNEL4)
+ #define _AVR_EVSYS_COUNT (5)
+#elif defined(EVSYS_CHANNEL3)
+ #define _AVR_EVSYS_COUNT (4)
+#elif defined(EVSYS_CHANNEL2)
+ #define _AVR_EVSYS_COUNT (3)
+#elif defined(EVSYS_CHANNEL1)
+ #define _AVR_EVSYS_COUNT (2)
+#elif defined(EVSYS_CHANNEL0)
+ #define _AVR_EVSYS_COUNT (1)
+#else
+ #error "No EVSYS detected? All supported parts have one, something is wrong"
+#endif
+
+/* We should also check what kind of evsys we have, as they are quite different from each other.
+ * Provide a define indicating which revision of EVSYS this is. 1 and 2 differ only in naming of strobe register.
+ * 3 separates the decision of which pin(s) within a port will be used as event input and which of those to use
+ * with the former being configured with PORTx.EVGENCTRL. This allows the number of generators to drop from 8/port to 2/port, and the number of RTC generators to likewise drop to 2 from 16 with 8 available per channel
+ * In exchange for this, we achieve our longtime dream: Equality between all generator channels, because the reduced number of
+ * generators allows them to add both options for all ports and both RTC options to all generator channels
+ * Too bad they released so many parts with the other versions :-/ */
+
+#if defined(PORTA_EVGENCTRL) // Ex-series, with EVGENCTRL registers on RTC and PORT.
+ #define _AVR_EVSYS_VERSION (3)
+#elif defined(EVSYS_STROBE) // mega0 - basically Dx, but different name for strobe.
+ #define _AVR_EVSYS_VERSION (1)
+#elif !defined(EVSYS_ASYNCCH0) // AVR Dx, 2-series
+ #define _AVR_EVSYS_VERSION (2)
+#else // tinyAVR 0/1-series with the two kinds of channels and boneheaded generator layout.
+ #define _AVR_EVSYS_VERSION (0)
+#endif
+
+#if defined(OPAMP)
+ /* OPAMPS:
+ * Allow for future chip with more opamps. There's room for 6 in the struct
+ * which has 64 bytes - 8 per OPAMP, and 16 at the start used for global settings
+ * At time of writing, on the only parts with OPAMPs, only 4 of the global bytes are used
+ * 6 of the 8 bytes for each OPAMP are used, 2 are spares. */
+ #if defined(OPAMP_OP5CTRLA)
+ #define _AVR_OPAMP_COUNT (6)
+ #elif defined(OPAMP_OP4CTRLA)
+ #define _AVR_OPAMP_COUNT (5)
+ #elif defined(OPAMP_OP3CTRLA)
+ #define _AVR_OPAMP_COUNT (4)
+ #elif defined(OPAMP_OP2CTRLA)
+ #define _AVR_OPAMP_COUNT (3)
+ #elif defined(OPAMP_OP1CTRLA)
+ #define _AVR_OPAMP_COUNT (2)
+ #elif defined(OPAMP_OP0CTRLA)
+ #define _AVR_OPAMP_COUNT (1)
+ #else
+ #error "We have an OPAMP peripheral, but no opamps? Something is wrong"
+ #endif
+#else
+ #define _AVR_OPAMP_COUNT (0)
+#endif
+
+
+
+#if defined(CCL_TRUTH6)
+ #define _AVR_LUT_COUNT (8)
+#elif defined(CCL_TRUTH4)
+ #define _AVR_LUT_COUNT (6)
+#elif defined(CCL_TRUTH2)
+ #define _AVR_LUT_COUNT (4)
+#elif defined(CCL_TRUTH0)
+ #define _AVR_LUT_COUNT (2)
+#else
+ #warning "No CCL? No supported parts exist without one, something is wrong"
+#endif
+
+
+#if defined(TCA1)
+ #define _AVR_TCA_COUNT (2)
+#elif defined(TCA0)
+ #define _AVR_TCA_COUNT (1)
+#else
+ #define _AVR_TCA_COUNT (0) // I fear something terrible happened to the TCA on the EB-series... and I think the TCE and that WEX Luther guy he's always with know something about it.
+#endif
+
+#if defined(TCB7)
+ #define _AVR_TCB_COUNT (8)
+#elif defined(TCB6)
+ #define _AVR_TCB_COUNT (7)
+#elif defined(TCB5)
+ #define _AVR_TCB_COUNT (6)
+#elif defined(TCB4)
+ #define _AVR_TCB_COUNT (5)
+#elif defined(TCB3)
+ #define _AVR_TCB_COUNT (4)
+#elif defined(TCB2)
+ #define _AVR_TCB_COUNT (3)
+#elif defined(TCB1)
+ #define _AVR_TCB_COUNT (2)
+#elif defined(TCB0)
+ #define _AVR_TCB_COUNT (1)
+#else
+ #error "No TCBs? No supported parts exist without one, something is wrong"
+#endif
+
+
+#if defined(TCD0)
+ #define _AVR_TCD_COUNT (1) // Only on Dx-series and tinyAVR
+#else
+ #define _AVR_TCD_COUNT (0)
+#endif
+
+#if defined(TCE0)
+ #define _AVR_TCE_COUNT (1) // first appears on the EB-series, 16-bit. Some sort of 8-channeled monster who is always with the one they call WEX. I haven't heard from TCA0 after they showed up and started doing
+#else // PWM on the same pins. I have a bad feeling that TCA0 is either tied up in the basement, or dead in a wooded area. With the TCE's skill at motor control, they could easily have
+ #define _AVR_TCE_COUNT (0) // used power-tools to dismember bury the body.... Anyway, whether these guys are as useful in the silicon as they look on paper will depend a lot on the whether those
+#endif // 8-channels are independent, and whether they need to split like TCA did to handle 8 WO's if so. And, of course on how flexible their clocking options are.
+
+#if defined(TCF0)
+ #define _AVR_TCF_COUNT (1) // Even more enigmatic than the TCE. First appears on the EB-series, this previously unseen timer is said to be 24-bit! Curious how that will work and what clock sources it can use.
+#else // a 24-bit timer clocked from the CPU core, at only 20 MHz would need it's period choked way back, sacrificing all that resolution, in order to get PWM rather than a blinking light.
+ #define _AVR_TCF_COUNT (0) // 2^24 is in the neighborhood of 17 million, so if CLK_PER was it's max, a lot of these frequencies it could generate would be a touch on the slow side. Even if we can get them up to
+#endif // 32 MHz like tiny-2's, we'd need to use only 1-2 bits of that last byte to avoid flicker if you wanted to use for PWM, which Arduino people will.
+
+#if defined(TWI1)
+ #define _AVR_TWI_COUNT (2)
+#elif defined(TWI0)
+ #define _AVR_TWI_COUNT (1)
+#else
+ #error "No TWI? No supported parts exist without one, something is wrong"
+#endif
+
+#if defined(SPI1)
+ #define _AVR_SPI_COUNT (2)
+#elif defined(SPI0)
+ #define _AVR_SPI_COUNT (1)
+#else
+ #error "No SPI? No supported parts exist without one, something is wrong"
+#endif
+
+
+#if defined(USART7)
+ #define _AVR_USART_COUNT (8)
+#elif defined(USART6)
+ #define _AVR_USART_COUNT (7)
+#elif defined(USART5)
+ #define _AVR_USART_COUNT (6)
+#elif defined(USART4)
+ #define _AVR_USART_COUNT (5)
+#elif defined(USART3)
+ #define _AVR_USART_COUNT (4)
+#elif defined(USART2)
+ #define _AVR_USART_COUNT (3)
+#elif defined(USART1)
+ #define _AVR_USART_COUNT (2)
+#elif defined(USART0)
+ #define _AVR_USART_COUNT (1)
+#else
+ #error "No USARTs? No supported parts exist without one, something is wrong"
+#endif
+
+#if defined(ZCD3)
+ #define _AVR_ZCD_COUNT (1) /* Only the DD's have ZCD3, which is their ZCD0 by a different name, since it uses different pins */
+#elif defined(ZCD2)
+ #define _AVR_ZCD_COUNT (3)
+#elif defined(ZCD1)
+ #define _AVR_ZCD_COUNT (2)
+#elif defined(ZCD0)
+ #define _AVR_ZCD_COUNT (1)
+#else
+ #define _AVR_ZCD_COUNT (0) // And only Dx has ZCD's at all.
+#endif
+
+#if defined(DAC2)
+ #define _AVR_DAC_COUNT (3)
+#elif defined(DAC1)
+ #define _AVR_DAC_COUNT (2)
+#elif defined(DAC0)
+ #define _AVR_DAC_COUNT (1) /* Note that thus far, no DAC other than DAC0 has ever been able to output data. DAC1 and DAC2 are just the DACREFs for AC1 and AC2 on tinyAVR 1-series parts.*/
+#else
+ #define _AVR_DAC_COUNT (0)
+#endif
+
+#ifdef DAC0
+ #if defined(DAC_OUTRANGE_gm) // Ex-series - 10-bit, and OUTRANGE, the strange option for selection the range of DATA values that can be output.
+ #define _AVR_DAC_VERSION (2)
+ #elif defined(DAC0_DATAH) // Dx-series - 10-bit
+ #define _AVR_DAC_VERSION (1)
+ #else // tinyAVR 1 - 8-bit
+ #define _AVR_DAC_VERSION (0)
+ #endif
+ #ifndef PIN_DACOUT
+ #if _AVR_DAC_VERSION == 0
+ #define PIN_DACOUT PIN_PA6 // different on tinyAVR!
+ #else
+ #define PIN_DACOUT PIN_PD6
+ #endif
+ #endif
+#endif
+
+
+/* PORT names and the NOT_A_* definitions - used EVERYWHERE! */
+
+#define NOT_A_PIN 255
+#define NOT_A_PORT 255
+#define NOT_AN_INTERRUPT 255
+#define NOT_A_MUX 255
+#define MUX_NONE 128
+
+#if defined(MEGATINYCORE)
+ #define PA 0
+ #if _AVR_PINCOUNT > 8
+ #define PB 1
+ #if _AVR_PINCOUNT > 14
+ #define PC 2
+ #define NUM_TOTAL_PORTS 3
+ #else
+ #define PC NOT_A_PORT
+ #define NUM_TOTAL_PORTS 2
+ #endif
+ #else
+ #define PB NOT_A_PORT
+ #define PC NOT_A_PORT
+ #define NUM_TOTAL_PORTS 1
+ #endif
+ #define PD NOT_A_PORT
+ #define PE NOT_A_PORT
+ #define PF NOT_A_PORT
+ #define PG NOT_A_PORT
+#else
+ #define PA 0
+ #if defined(PORTB)
+ #define PB 1
+ #else
+ #define PB NOT_A_PORT
+ #endif
+ #define PC 2
+ #define PD 3
+ #if defined(PORTE)
+ #define PE 4
+ #else
+ #define PE NOT_A_PORT
+ #endif
+ #define PF 5
+ #if defined(PORTG)
+ #define PG 6
+ #define NUM_TOTAL_PORTS 7
+ #else
+ #define PG NOT_A_PORT
+ #define NUM_TOTAL_PORTS 6
+ #endif
+#endif
+
+
+/* End block shared with DxCore */
+
+
+// Notice NUM_TOTAL_PORTS should always be 1, 2, 3, 6 or 7 - it is the number of the highest port plus 1.
+// The tinyAVRs have either just PORTA, PORTA and PORTB, or ports A, B, and C - 1, 2, or 3 ports.
+// The Dx and Ex parts,however, even on the 14-pin version, have representatives from ports A, C, D, and F.
+// F is the 6th port, so NUM_TOTAL_PORTS is 6, even though at least half of the pins on the represented
+// ports aren't there!
+
+/* In case you need to greatly change the operating frequency of the chip on the fly, and accept that it will trash millis and so on.
+ * That's why it's not documented or in Arduino.h, but this subfile - it's about as blunt an instrument as it gets, and resorting to
+ * methods like this can result in bizarre and unexpected behavior that can be difficult to diagnose if you don't suspect clock issues
+ *
+ * Yes, the nomenclature is strange (I'm referring to the "x"; commonly used for multiplication yet the mathematical operation in question
+ * is division. The symbol for that is not valid in names in C). I didn't start it, but there's no obviously better option, so X it stays.
+ */
+// bits are 0bRRRPPPPE - Reserved x3, prescale x4, prescale enable - nothing we need to preserve!
+
+#define _setPrescale1x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (0))
+#define _setPrescale2x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, ( CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm)) /* 0x01 */
+#define _setPrescale4x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, ( CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm)) /* 0x03 */
+#define _setPrescale8x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, ( CLKCTRL_PDIV_8X_gc | CLKCTRL_PEN_bm)) /* 0x05 */
+#define _setPrescale16x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PDIV_16X_gc | CLKCTRL_PEN_bm)) /* 0x07 */
+#define _setPrescale32x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PDIV_32X_gc | CLKCTRL_PEN_bm)) /* 0x09 */
+#define _setPrescale64x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm)) /* 0x0B */
+#define _setPrescale6x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, ( CLKCTRL_PDIV_6X_gc | CLKCTRL_PEN_bm)) /* 0x11 */
+#define _setPrescale10x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PDIV_10X_gc | CLKCTRL_PEN_bm)) /* 0x13 */
+#define _setPrescale12x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PDIV_12X_gc | CLKCTRL_PEN_bm)) /* 0x15 */
+#define _setPrescale24x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PDIV_24X_gc | CLKCTRL_PEN_bm)) /* 0x17 */
+#define _setPrescale48x() _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PDIV_48X_gc | CLKCTRL_PEN_bm)) /* 0x19 */
+/* DANGER DANGER - NOT MEANT FOR ENDUSER APPLICATIONS. GI - GO */
+#define _getPrescale() (CLKCTRL_MCLKCTRLB)
+#define _setPrescaleValue(val) _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, val)
+/* This is Yucky. These are macros.
+Intended usage scenario:
+uint8_t oldpsc=_getPrescale();
+setPrescaler10x();
+//dostuff
+setPrescalerValue(oldpsc);
+*/
+
+#if MEGATINYCORE_SERIES <= 2
+ #define RTC_CLKSEL_OSC32K_gc RTC_CLKSEL_INT32K_gc
+ #define RTC_CLKSEL_OSC1K_gc RTC_CLKSEL_INT1K_gc
+ #define RTC_CLKSEL_XTAL32K_gc RTC_CLKSEL_TOSC32K_gc
+ #define PORTMUX_LUT0_ALT1_gc PORTMUX_LUT0_ALTERNATE_gc
+ #define PORTMUX_LUT1_ALT1_gc PORTMUX_LUT0_ALTERNATE_gc
+#endif
+
+#if MEGATINYCORE_SERIES == 2
+/* Initial version of the IO headers omits these definitions!
+ * then some versions had them, then the removed them all and stopped
+ * performing the cal at all (which was not as usuful as on 0/1-series)
+ */
+ #if !defined(SIGROW_OSC16ERR3V)
+ #define SIGROW_OSC16ERR3V (SIGROW.reserved_3[badCall("the SIGROW does not contain error information about the main oscillator except on very early versions")]
+ #endif
+ #if !defined(SIGROW_OSC16ERR5V)
+ #define SIGROW_OSC16ERR5V (SIGROW.reserved_3[badCall("the SIGROW does not contain error information about the main oscillator except on very early versions")]
+ #endif
+ #if !defined(SIGROW_OSC20ERR3V)
+ #define SIGROW_OSC20ERR3V (SIGROW.reserved_3[badCall("the SIGROW does not contain error information about the main oscillator except on very early versions")]
+ #endif
+ #if !defined(SIGROW_OSC20ERR5V)
+ #define SIGROW_OSC20ERR5V (SIGROW.reserved_3[badCall("the SIGROW does not contain error information about the main oscillator except on very early versions")]
+ #endif
+#else
+ /* 0/1-series, on the other hand, doesm't have these defined even though they are present */
+ #if !defined(SIGROW_OSCCAL16M0)
+ #define SIGROW_OSCCAL16M0 _SFR_MEM8(0x1118)
+ #endif
+ #if !defined(SIGROW_OSCCAL16M1)
+ #define SIGROW_OSCCAL16M1 _SFR_MEM8(0x1119)
+ #endif
+ #if !defined(SIGROW_OSCCAL20M0)
+ #define SIGROW_OSCCAL20M0 _SFR_MEM8(0x111A)
+ #endif
+ #if !defined(SIGROW_OSCCAL20M1)
+ #define SIGROW_OSCCAL20M1 _SFR_MEM8(0x111B)
+ #endif
+ // Also, the 0/1-series have useless names for the event channels. But we can define the 2-series names for them!
+ // This makes it easier to write portable code without using the event library and incurring that overhead.
+
+ #if defined(EVSYS_SYNCUSER0)
+ #define EVSYS_USERTCA0CNTA EVSYS_SYNCUSER0
+ #endif
+ #if defined(EVSYS_SYNCUSER1)
+ #define EVSYS_USERUSART0IRDA EVSYS_SYNCUSER1
+ #endif
+ #if defined(EVSYS_ASYNCUSER0)
+ #define EVSYS_USERTCB0CAPT EVSYS_ASYNCUSER0
+ #endif
+ #if defined(EVSYS_ASYNCUSER1)
+ #define EVSYS_USERADC0START EVSYS_ASYNCUSER1
+ #endif
+ #if defined(EVSYS_ASYNCUSER2)
+ #define EVSYS_USERCCLLUT0A EVSYS_ASYNCUSER2
+ #endif
+ #if defined(EVSYS_ASYNCUSER3)
+ #define EVSYS_USERCCLLUT1A EVSYS_ASYNCUSER3
+ #endif
+ #if defined(EVSYS_ASYNCUSER4)
+ #define EVSYS_USERCCLLUT0B EVSYS_ASYNCUSER4
+ #endif
+ #if defined(EVSYS_ASYNCUSER5)
+ #define EVSYS_USERCCLLUT1B EVSYS_ASYNCUSER5
+ #endif
+ #if defined(EVSYS_ASYNCUSER6)
+ #define EVSYS_USERTCD0INPUTA EVSYS_ASYNCUSER6
+ #endif
+ #if defined(EVSYS_ASYNCUSER7)
+ #define EVSYS_USERTCD0INPUTB EVSYS_ASYNCUSER7
+ #endif
+ #if defined(EVSYS_ASYNCUSER8)
+ #define EVSYS_USEREVSYSEVOUTA EVSYS_ASYNCUSER8
+ #endif
+ #if defined(EVSYS_ASYNCUSER9)
+ #define EVSYS_USEREVSYSEVOUTB EVSYS_ASYNCUSER9
+ #endif
+ #if defined(EVSYS_ASYNCUSER10)
+ #define EVSYS_USEREVSYSEVOUTC EVSYS_ASYNCUSER10
+ #endif
+ #if defined(EVSYS_ASYNCUSER11)
+ #define EVSYS_USERTCB1CAPT EVSYS_ASYNCUSER11
+ #endif
+ #if defined(EVSYS_ASYNCUSER12)
+ #define EVSYS_USERADC1START EVSYS_ASYNCUSER12
+ #endif
+
+#endif
+
+/* Microchip has shown a tendency to rename registers bitfields and similar between product lines, even when the behavior is identical.
+ * This is a major hindrance to writing highly portable code which I assume is what most people wish to do. It certainly beats having
+ * to run code through find replace making trivial changes, forcing a fork where you would rather not have one.
+ * Since having to adjust code to match the arbitrary and capricious whims of the header generation scheme kinda sucks, we try to catch
+ * all the places they do this and provide a macro for backwards compatibility. For some bizarre reason you may wish to turn this off
+ * maybe in preparation for jumping to another development environment like Microchip Studio that does not use Arduino cores.
+ * Instead of backwards compatibilily, you want the opposite, which some wags have called "Backwards combatibility"
+ * Defining BACKWARD_COMBATIBILITY_MODE turns off all of these definitions that paper over name changes.
+ */
+
+// #define BACKWARD_COMBATIBILITY_MODE
+/* Outside of Backwards COMBATability mode - where our normal measures to paper over microchip's frequent renamings and some of the in-name-only
+differences between part families are disabled (so as to force you to comply strictly with their headers, whereas we try to support every name that
+has once worked for the same thing as meaning that thing */
+#if !defined(BACKWARD_COMBATIBILITY_MODE)
+ // We default to seeking compatibility. for COMBATability you would uncomment that #define, and that turns all these off.
+
+ #if defined(RTC_CLKSEL)
+ /* Man they just *HAD* to change the names of these values that get assigned to the same register and do the same thing didn't they?
+ * Worse still we can't even verify that they are present... just blindly define and pray. Enums can't be seen by macros
+ */
+ // tinyAVR has TOSC32K (tinyOscillator?)
+ #if defined(MEGATINYCORE)
+ #define RTC_CLKSEL_OSC32K_gc RTC_CLKSEL_INT32K_gc
+ #define RTC_CLKSEL_OSC1K_gc RTC_CLKSEL_INT1K_gc
+ #define RTC_CLKSEL_XTAL32K_gc RTC_CLKSEL_TOSC32K_gc
+ #define RTC_CLKSEL_XOSC32K_gc RTC_CLKSEL_TOSC32K_gc
+ #else
+ // Dx has an XOSC32K
+ #define RTC_CLKSEL_INT32K_gc RTC_CLKSEL_OSC32K_gc
+ #define RTC_CLKSEL_INT1K_gc RTC_CLKSEL_OSC1K_gc
+ #define RTC_CLKSEL_TOSC32K_gc RTC_CLKSEL_XOSC32K_gc
+ #define RTC_CLKSEL_XTAL32K_gc RTC_CLKSEL_XOSC32K_gc
+ #endif
+ #endif
+ /* General Purpose Register names, GPR.GPRn, vs GPIORn vs GPIOn
+ * They now appear to have decided they don't like either of the previous conventions, one just a few years old. Now they are grouping
+ * them under a "General Purpose Register". "peripheral". I cannot argue that GPR doesn't make more sense, as there's not really any
+ * I/O occurring here (ofc they were referring to the IN and OUT instructions, which can be used on these), but I certainly wouldn't
+ * have changed a convention like this, at least not when I had just done so a few years prior. */
+
+ // All non-xmega pre-Dx-series modern AVR parts call them GPIORn instead of GPR.GPRn/GPR_GPRn
+ // Some classics called them GPIOn.
+
+ /* In one xMega AVR, they were GPIOn, rather than GPIORn
+ * One? Yup: The ATxmega32d4. Not the 32d3, nor the 32e5, nor anything else. All the xmega's have GPIORs
+ * and their headers list the GPIOn names too. But.... there is only a single header
+ * file with them not marked as "Deprecated": ATxmega32D4
+ * 24 of the 46 xmega parts with headers in the compiler packages (including the 32d3 and 32e5) had the
+ * 4 GPIOR's that we have, and had GPIOn and GPIO_GPIOn present but marked as deprecated.
+ * On those parts, these are at addresses 0x0000-0x003, and 0x0004-0x000F do not appear to be used.
+ * The other 22.... had THE ENTIRE FIRST HALF OF THE LOW I/O SPACE as GPIOR0-GPIORF!
+ * Which ones got all of them and which ones only got 4 seems to have been chosen in typical
+ * Atmel fashion (in other words, randomly). No apparent pattern in time or other parameters.
+ * Either way, that left them with space for only 4 VPORT register sets (like the ones we got)
+ * These had to be configured to point to the desired port.
+ * I'm sure everyone is grateful for the fact that the folks designing the Dx-series have their
+ * heads screwed on properly and realized that 4 GPIOR-- excuse me, GPRs, 4 awkward VPORTs and
+ * 12 unused addresses in the low I/O space was maybe not the best design decision made in the
+ * xmega line. With any parts that would have more than 64 physical pins (56 I/O pins, 7 ports)
+ * far in the future, and no clear need for more than 4 GPRs, this was the obvious choice.
+ * When they do eventually release a modern successor to the 2560, they'll need to decide how
+ * to deal with this, or do what they did on the 2560 itself, which was nothing: They ran out
+ * of low I/O there, and don't even remark on it in the datasheet, that some of the ports are
+ * in low I/O and fast, and others are in extended I/O and slow.
+ *
+ * It's worth thinking about an odd anticoincidence here: On the classic AVRs, address 0x0000
+ * in the dataspace (ie, where a null pointer points) was R0. That's harmless to smash with an
+ * 8-bit value, but if you write a word there, the second write would shit on zero_reg and then
+ * adding 1 and 1 could yield numbers other than 2. 0x0001 + 0x01 could be as high as 65282 if
+ * you've trashed the zero_reg (to add a byte to a word, the compiler uses add on the low bytes
+ * then needs to use adc (add with carry) to get the carry bit into the high byte, so it does
+ * adc %B0, r1
+ * assuming that r1 is 0, as it is required to be. (under the hood, though there are times that
+ * r1 has a special meaning to the hardware, the only times these are manifest is when executing
+ * inline asm; the compiler will never generate the sequences of instructions that do this on
+ * it's own - once you dig enough, you find that somewhere in the dark recesses of avr-libc is
+ * an asm macro that actually executes the instructions that explicitly use r1 (multiplication
+ * is the big one, the high byte of the product always goes in r1. I think the only other is
+ * SPM on some hardware, and again, in those cases either there's no hw support (modern) or it's
+ * asm macros in boot.h). In all cases, if r1 is changed, it must be rezeroed before returning to
+ * c. Otherwise, it'll break everything. Thus, on classic AVRs you could write a null pointer and
+ * probably not see any sign of that if you wrote one byte, if you wrote a 2 byte one, the world
+ * would crash down around you.
+ * On the modern AVRs, address 0x0000 is VPORTA.OUT, so the first thing you'd trash if you wrote
+ * to a null pointer is the PORTA configuration. BUT had they put the GPIOR's first - like xmega
+ * then writing the null pointer would have first trashed a byte or bytes that most applications
+ * don't even use - but which would also naturally be a perfect probe of whether the bizarre bug
+ * you're trying to sort out is caused by following a null pointer somewhere or by something else.
+ * Not that that's a super-common bug. 99 times out of 10 those sorts of "everything is totally
+ * confused" bugs happen when you return from a function that has overflowed the bounds of a
+ * local array. The array, probably the only thing on the stack associated with this call other
+ * than the return address, is going to end up right next to the array. Thus, the first thing you
+ * trash when you overflow the array in that direction (which one that is depends on details - it
+ * could end up between two return addresses, too, so overflowing it one way makes it blow up at
+ * the return from this function, and overflowing the other way it causes it to blow up when the
+ * calling function returns. Either way, it returns to someplace totally different than where it
+ * was called from, and then trundles along the code, executing code that thinks registers have
+ * different data in them than they do and jumping off into some other remote corner of the
+ * program every time they hit a 'ret'. 0xFFFF (empty flash) is treated as 'sbrs r31, 7', 0xFFF7
+ * Usually it will pretty quickly end up at a point where it's either returning to 0 or has run
+ * off the end of the flash, which wraps around. If the sbrs skips 0x0000, it will land on the
+ * next vector, but since we don't use the NMI vector ever (cause it can't do anything useful),
+ * that is just a jump to badisr, which jumps to 0, so unless execution stumbles upon a stable
+ * loop and hangs while misbehaving, it's likely to end up at the reset vector, without a reset.
+ * That starts the chip up in guaranteed-not-to-work mode, which we detect and software-reset
+ * in response to.
+ * Calling a null pointer or a bogus function pointer has the same effect, as does enabling and
+ * triggering an ISR that isn't defined. On classic AVR, these dirty resets would instead reset
+ * into more of a "not-*guaranteed*-not-to-work-but-highly-unlikely-to" mode. Both would often
+ * show the pattern of working -aack-> executes zero or more sections of incorrect code -> "dirty"
+ * reset -> hang or abnormal very tight loop shortly after startup.
+ *
+ * Those three ways of getting a dirty reset are more common (each one is, on it's own, more
+ * common) than instances of null pointers being written to. I don't fault them on the design
+ * and it actually is much easier that VPORTA = *0x0000 than *0x0004, for sure. This does however
+ * demonstrate how the architecture of the ISA controls how readily various flavors of undefined-
+ * -but-unquestionably-broken behavior manifest; the dirty reset may actually work on classic AVR
+ * for your program, as a normal reset, whereas it will never work correctly after a dirty reset
+ * on modern AVR, except that the core traps it. I think it would be nice if this were documented
+ * explicitly, rather than relying on the reader to combine AVR CPU, CPUINT and RSTCTRL chapters
+ * (and less-than-well documented avr-libc behaviors) to conclude that they should always check the
+ * reset cause flags, and if they do that, they must clear them or they won't know which source, if
+ * any caused the reset if one occurs, and that ending up restarting the code without a hardware
+ * reset occurring is a "can't happen" that can happen if your c code is bad enough. From there,
+ * having read the chapters on the other peripherals you are using you'd no doubt have found some
+ * reason your initialization couldn't be done over again exactly the same way without a reset.
+ * Hence in your init code you need to check and clear reset flags if you find them, or software
+ * reset if you find nothing. I think that's asking a lot of the developer, even outside arduino
+ * land.
+ *
+ * Losing the memory mapping of working registers is a Good Thing; they never should have been
+ * made accessible like that. You don't know what's in which registers, and all you're going to
+ * get trying is undefined behavior. If you need to specify registers by number, you should be
+ * writing inline asm, not fucking with the registers from C. The only *capability* they got from
+ * the mess that couldn't be done normally is indirect access via pointer registers, which is
+ * an almos if
+ *
+ */
+
+ #if !defined(GPIOR0)
+ #define GPIOR0 (_SFR_MEM8(0x001C))
+ #define GPIOR1 (_SFR_MEM8(0x001D))
+ #define GPIOR2 (_SFR_MEM8(0x001E))
+ #define GPIOR3 (_SFR_MEM8(0x001F))
+ #endif
+ #if !defined(GPIO0)
+ #define GPIO0 (_SFR_MEM8(0x001C))
+ #define GPIO1 (_SFR_MEM8(0x001D))
+ #define GPIO2 (_SFR_MEM8(0x001E))
+ #define GPIO3 (_SFR_MEM8(0x001F))
+ #endif
+ #if !defined(GPIO_GPIOR0)
+ #define GPIO_GPIO0 (_SFR_MEM8(0x001C))
+ #define GPIO_GPIO1 (_SFR_MEM8(0x001D))
+ #define GPIO_GPIO2 (_SFR_MEM8(0x001E))
+ #define GPIO_GPIO3 (_SFR_MEM8(0x001F))
+ #endif
+ #if !defined(GPR_GPR0)
+ #define GPR_GPR0 (_SFR_MEM8(0x001C))
+ #define GPR_GPR1 (_SFR_MEM8(0x001D))
+ #define GPR_GPR2 (_SFR_MEM8(0x001E))
+ #define GPR_GPR3 (_SFR_MEM8(0x001F))
+ #endif
+ // The naming of this has gotten so confusing. I give up, we all know where the registers are.
+ #if defined (CLKCTRL_SELHF_bm)
+ /* They changed the damned name after selling the part for 6 months!
+ * annoyingly you can't even test if it's using the new version of the headers because it's an enum! */
+ #define CLKCTRL_SELHF_CRYSTAL_gc CLKCTRL_SELHF_XTAL_gc
+ #endif
+ /* And one version later they did it again... */
+ #if !defined(CLKCTRL_FREQSEL_gm) && defined(CLKCTRL_FRQSEL_gm)
+ #define CLKCTRL_FREQSEL_gm (CLKCTRL_FRQSEL_gm) /* Group Mask */
+ #define CLKCTRL_FREQSEL_gp (CLKCTRL_FRQSEL_gp) /* Group Position */
+ // /* Group Codes */
+ #define CLKCTRL_FREQSEL_1M_gc (CLKCTRL_FRQSEL_1M_gc) /* 1 MHz system clock */
+ #define CLKCTRL_FREQSEL_2M_gc (CLKCTRL_FRQSEL_2M_gc) /* 2 MHz system clock */
+ #define CLKCTRL_FREQSEL_3M_gc (CLKCTRL_FRQSEL_3M_gc) /* 3 MHz system clock */
+ #define CLKCTRL_FREQSEL_4M_gc (CLKCTRL_FRQSEL_4M_gc) /* 4 MHz system clock default */
+ #define CLKCTRL_FREQSEL_8M_gc (CLKCTRL_FRQSEL_8M_gc) /* 8 MHz system clock */
+ #define CLKCTRL_FREQSEL_12M_gc (CLKCTRL_FRQSEL_12M_gc) /* 12 MHz system clock */
+ #define CLKCTRL_FREQSEL_16M_gc (CLKCTRL_FRQSEL_16M_gc) /* 16 MHz system clock */
+ #define CLKCTRL_FREQSEL_20M_gc (CLKCTRL_FRQSEL_20M_gc) /* 20 MHz system clock */
+ #define CLKCTRL_FREQSEL_24M_gc (CLKCTRL_FRQSEL_24M_gc) /* 24 MHz system clock */
+ #define CLKCTRL_FREQSEL_28M_gc (CLKCTRL_FRQSEL_28M_gc) /* 28 MHz system clock unofficial - this will just error out if used since it will replace one undefined symbol with another */
+ #define CLKCTRL_FREQSEL_32M_gc (CLKCTRL_FRQSEL_32M_gc) /* 32 MHz system clock unofficial - this will just error out if used since it will replace one undefined symbol with another */
+ #elif defined(CLKCTRL_FRQSEL_gm) && !defined(CLKCTRL_FREQSEL_gm)
+ #define CLKCTRL_FRQSEL_gm (CLKCTRL_FREQSEL_gm) /* Group Mask */
+ #define CLKCTRL_FRQSEL_gp (CLKCTRL_FREQSEL_gp) /* Group Position */
+ // /* Group Codes */
+ #define CLKCTRL_FRQSEL_1M_gc (CLKCTRL_FREQSEL_1M_gc) /* 1 MHz system clock */
+ #define CLKCTRL_FRQSEL_2M_gc (CLKCTRL_FREQSEL_2M_gc) /* 2 MHz system clock */
+ #define CLKCTRL_FRQSEL_3M_gc (CLKCTRL_FREQSEL_3M_gc) /* 3 MHz system clock */
+ #define CLKCTRL_FRQSEL_4M_gc (CLKCTRL_FREQSEL_4M_gc) /* 4 MHz system clock default */
+ #define CLKCTRL_FRQSEL_8M_gc (CLKCTRL_FREQSEL_8M_gc) /* 8 MHz system clock */
+ #define CLKCTRL_FRQSEL_12M_gc (CLKCTRL_FREQSEL_12M_gc) /* 12 MHz system clock */
+ #define CLKCTRL_FRQSEL_16M_gc (CLKCTRL_FREQSEL_16M_gc) /* 16 MHz system clock */
+ #define CLKCTRL_FRQSEL_20M_gc (CLKCTRL_FREQSEL_20M_gc) /* 20 MHz system clock */
+ #define CLKCTRL_FRQSEL_24M_gc (CLKCTRL_FREQSEL_24M_gc) /* 24 MHz system clock */
+ #define CLKCTRL_FRQSEL_28M_gc (CLKCTRL_FREQSEL_28M_gc) /* 28 MHz system clock unofficial - this will just error out if used since it will replace one undefined symbol with another */
+ #define CLKCTRL_FRQSEL_32M_gc (CLKCTRL_FREQSEL_32M_gc) /* 32 MHz system clock unofficial - this will just error out if used since it will replace one undefined symbol with another */
+ #endif
+ // Note that it is intended to not hide the fact that 28 and 32 MHz are not official. If you choose it from the menu, it says "Overclocked" next to the speed too. We refer to them with the numeric constants in the wiring.c, so it doesn't matter when used that way.
+ // And now the most freaking boneheaded move from Microchip in a long while: They realized that they should have had some sort of delimiter between the bit number within a bitfield, and the name of the bitfield, since the names of many bitfields end in numbers,
+ // So they went ahead and made that change. That is what's called a "breaking change", really for no reason except codes style. Most companies even if they decided to go that route, would never do that without introducuing a compatibility layer.
+ // That wanton disregard for backwards compatibility is not acceptable in an Arduino core nor in a commercial product.
+ // Using the old names will produce warnings. These deprecated names should be fixed as support for these FOUR THOUSAND LINES of bandaids WILL BE REMOBVED in 1.6.0!
+ // typedef const uint8_t __attribute__ ((deprecated("\nMicrochip changed the spelling of bits within a bitfiels (macros that end in the bitnumber followed by _bm or _bp), you are using the old name, ex PERIPH_BITFIRLD1_bm.\nYou should use PERIPH_BITFIELD_1_bm; we do not guarantee that this 4000-line bandaid will not be removed in the future.\r\nWhy did they do this? Beats me. Ask their support folks - if enough of us do it, they might hesitate next time they have the urge to mass rename things in their headers"))) deprecated_constant_name;
+
+ // Okay, well that fix didn't work so well. back to plan A.
+
+ // TCA V1.0 - tinyAVR 0/1, megaAVR 0
+ // this only has one event input, but code needs to be able to flow smoothly
+ // so we define macros named after he the new version pointing to the old version of event input A.
+ // Obviously, we can't do anything about the unfortunate soul who tries to use input B.
+ #if !defined(TCA_SINGLE_CNTAEI_bm)
+ #define TCA_SINGLE_CNTAEI_bm TCA_SINGLE_CNTEI_bm
+ #define TCA_SINGLE_EVACTA_POSEDGE_gc TCA_SINGLE_EVACTA_CNT_POSEDGE_gc
+ #define TCA_SINGLE_EVACTA_CNT_ANYEDGE_gc TCA_SINGLE_EVACTA_CNT_ANYEDGE_gc
+ #define TCA_SINGLE_EVACTA_CNT_HIGHLVL_gc TCA_SINGLE_EVACTA_CNT_HIGHLVL_gc
+ #define TCA_SINGLE_EVACTA_UPDOWN_gc TCA_SINGLE_EVACTA_UPDOWN_gc
+ #endif
+ // TCA V1.1 - DA, DB, tinyAVR 2?
+ // with two inputs changes the names the existing ones to specify channel A
+ // We add in the non-postfixed ana
+ #if !defined(TCA_SINGLE_CNTEI_bm)
+ #define _TCA_
+ #define TCA_SINGLE_CNTEI_bm TCA_SINGLE_CNTAEI_bm
+ #define TCA_SINGLE_EVACT_POSEDGE_gc TCA_SINGLE_EVACTA_CNT_POSEDGE_gc
+ #define TCA_SINGLE_EVACT_CNT_ANYEDGE_gc TCA_SINGLE_EVACTA_CNT_ANYEDGE_gc
+ #define TCA_SINGLE_EVACT_CNT_HIGHLVL_gc TCA_SINGLE_EVACTA_CNT_HIGHLVL_gc
+ #define TCA_SINGLE_EVACT_UPDOWN_gc TCA_SINGLE_EVACTA_UPDOWN_gc
+ #endif
+
+ #if (!defined(MEGATINYCORE) || MEGATINYCORE_SERIES >= 2)
+ #define TCB_CLKSEL_CLKDIV1_gc TCB_CLKSEL_DIV1_gc
+ #define TCB_CLKSEL_CLKDIV2_gc TCB_CLKSEL_DIV2_gc
+ #define TCB_CLKSEL_CLKTCA_gc TCB_CLKSEL_TCA0_gc
+ #else
+ #define TCB_CLKSEL_DIV1_gc TCB_CLKSEL_CLKDIV1_gc
+ #define TCB_CLKSEL_DIV2_gc TCB_CLKSEL_CLKDIV2_gc
+ #define TCB_CLKSEL_TCA0_gc TCB_CLKSEL_CLKTCA_gc
+ #define TCB_CLKSEL_EVENT_gc (badCall("This processor does not support TCB count on event mode. Only Dx, Ex, and 2-series tiny support that"))
+ #endif
+ /* Make sure we error out quickly if told to use an RTC timing option that isn't available. */
+ #if (defined(MILLIS_USE_TIMERRTC_XTAL) || defined(MILLIS_USE_TIMERRTC_XOSC))
+ #if (MEGATINYCORE_SERIES == 0 || defined(__AVR_ATtinyxy2__))
+ #error "Only the tinyAVR 1-series and 2-series parts with at least 14 pins support external RTC timebase"
+ #endif
+ #endif
+ // And now, it it appears that they realized that they should have had some sort of delimiter between the bit number within a bitfield, and the name of the bitfield, since the names of many bitfields end in numbers,
+ // So they went ahead and made that change. Without any compatibility layer.
+
+ // Well, I'd wanted to make deprecation warnings come up only if they were used. I was unuccessful.
+
+ // typedef const uint8_t __attribute__ ((deprecated("\nMicrochip changed the spelling of bits within a bitfiels (macros that end in the bitnumber followed by _bm or _bp), you are using the old name, ex PERIPH_BITFIRLD1_bm.\nYou should use PERIPH_BITFIELD_1_bm; we do not guarantee that this 4000-line bandaid will not be removed in the future.\r\nWhy did they do this? Beats me. Ask their support folks - if enough of us do it, they might hesitate next time they have the urge to mass rename things in their headers"))) deprecated_constant_name;
+
+ // Okay, well that fix didn't work so well. back to plan A.
+ /* ======= ACs ======= */
+ #if !defined(AC_HYSMODE_0_bm) && defined(AC_HYSMODE0_bm)
+ #define AC_HYSMODE_0_bm AC_HYSMODE0_bm
+ #elif defined(AC_HYSMODE_0_bm)
+ //deprecated_constant_name AC_HYSMODE0_bm = AC_HYSMODE_0_bm;
+ #define AC_HYSMODE0_bm AC_HYSMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_HYSMODE_0_bp) && defined(AC_HYSMODE0_bp)
+ #define AC_HYSMODE_0_bp AC_HYSMODE0_bp
+ #elif defined(AC_HYSMODE_0_bp)
+ //deprecated_constant_name AC_HYSMODE0_bp = AC_HYSMODE_0_bp;
+ #define AC_HYSMODE0_bp AC_HYSMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_HYSMODE_1_bm) && defined(AC_HYSMODE1_bm)
+ #define AC_HYSMODE_1_bm AC_HYSMODE1_bm
+ #elif defined(AC_HYSMODE_1_bm)
+ //deprecated_constant_name AC_HYSMODE1_bm = AC_HYSMODE_1_bm;
+ #define AC_HYSMODE1_bm AC_HYSMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_HYSMODE_1_bp) && defined(AC_HYSMODE1_bp)
+ #define AC_HYSMODE_1_bp AC_HYSMODE1_bp
+ #elif defined(AC_HYSMODE_1_bp)
+ //deprecated_constant_name AC_HYSMODE1_bp = AC_HYSMODE_1_bp;
+ #define AC_HYSMODE1_bp AC_HYSMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_POWER_0_bm) && defined(AC_POWER0_bm)
+ #define AC_POWER_0_bm AC_POWER0_bm
+ #elif defined(AC_POWER_0_bm)
+ //deprecated_constant_name AC_POWER0_bm = AC_POWER_0_bm;
+ #define AC_POWER0_bm AC_POWER_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_POWER_0_bp) && defined(AC_POWER0_bp)
+ #define AC_POWER_0_bp AC_POWER0_bp
+ #elif defined(AC_POWER_0_bp)
+ //deprecated_constant_name AC_POWER0_bp = AC_POWER_0_bp;
+ #define AC_POWER0_bp AC_POWER_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_POWER_1_bm) && defined(AC_POWER1_bm)
+ #define AC_POWER_1_bm AC_POWER1_bm
+ #elif defined(AC_POWER_1_bm)
+ //deprecated_constant_name AC_POWER1_bm = AC_POWER_1_bm;
+ #define AC_POWER1_bm AC_POWER_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_POWER_1_bp) && defined(AC_POWER1_bp)
+ #define AC_POWER_1_bp AC_POWER1_bp
+ #elif defined(AC_POWER_1_bp)
+ //deprecated_constant_name AC_POWER1_bp = AC_POWER_1_bp;
+ #define AC_POWER1_bp AC_POWER_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSEL_0_bm) && defined(AC_WINSEL0_bm)
+ #define AC_WINSEL_0_bm AC_WINSEL0_bm
+ #elif defined(AC_WINSEL_0_bm)
+ //deprecated_constant_name AC_WINSEL0_bm = AC_WINSEL_0_bm;
+ #define AC_WINSEL0_bm AC_WINSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSEL_0_bp) && defined(AC_WINSEL0_bp)
+ #define AC_WINSEL_0_bp AC_WINSEL0_bp
+ #elif defined(AC_WINSEL_0_bp)
+ //deprecated_constant_name AC_WINSEL0_bp = AC_WINSEL_0_bp;
+ #define AC_WINSEL0_bp AC_WINSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSEL_1_bm) && defined(AC_WINSEL1_bm)
+ #define AC_WINSEL_1_bm AC_WINSEL1_bm
+ #elif defined(AC_WINSEL_1_bm)
+ //deprecated_constant_name AC_WINSEL1_bm = AC_WINSEL_1_bm;
+ #define AC_WINSEL1_bm AC_WINSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSEL_1_bp) && defined(AC_WINSEL1_bp)
+ #define AC_WINSEL_1_bp AC_WINSEL1_bp
+ #elif defined(AC_WINSEL_1_bp)
+ //deprecated_constant_name AC_WINSEL1_bp = AC_WINSEL_1_bp;
+ #define AC_WINSEL1_bp AC_WINSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXNEG_0_bm) && defined(AC_MUXNEG0_bm)
+ #define AC_MUXNEG_0_bm AC_MUXNEG0_bm
+ #elif defined(AC_MUXNEG_0_bm)
+ //deprecated_constant_name AC_MUXNEG0_bm = AC_MUXNEG_0_bm;
+ #define AC_MUXNEG0_bm AC_MUXNEG_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXNEG_0_bp) && defined(AC_MUXNEG0_bp)
+ #define AC_MUXNEG_0_bp AC_MUXNEG0_bp
+ #elif defined(AC_MUXNEG_0_bp)
+ //deprecated_constant_name AC_MUXNEG0_bp = AC_MUXNEG_0_bp;
+ #define AC_MUXNEG0_bp AC_MUXNEG_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXNEG_1_bm) && defined(AC_MUXNEG1_bm)
+ #define AC_MUXNEG_1_bm AC_MUXNEG1_bm
+ #elif defined(AC_MUXNEG_1_bm)
+ //deprecated_constant_name AC_MUXNEG1_bm = AC_MUXNEG_1_bm;
+ #define AC_MUXNEG1_bm AC_MUXNEG_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXNEG_1_bp) && defined(AC_MUXNEG1_bp)
+ #define AC_MUXNEG_1_bp AC_MUXNEG1_bp
+ #elif defined(AC_MUXNEG_1_bp)
+ //deprecated_constant_name AC_MUXNEG1_bp = AC_MUXNEG_1_bp;
+ #define AC_MUXNEG1_bp AC_MUXNEG_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXNEG_2_bm) && defined(AC_MUXNEG2_bm)
+ #define AC_MUXNEG_2_bm AC_MUXNEG2_bm
+ #elif defined(AC_MUXNEG_2_bm)
+ //deprecated_constant_name AC_MUXNEG2_bm = AC_MUXNEG_2_bm;
+ #define AC_MUXNEG2_bm AC_MUXNEG_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXNEG_2_bp) && defined(AC_MUXNEG2_bp)
+ #define AC_MUXNEG_2_bp AC_MUXNEG2_bp
+ #elif defined(AC_MUXNEG_2_bp)
+ //deprecated_constant_name AC_MUXNEG2_bp = AC_MUXNEG_2_bp;
+ #define AC_MUXNEG2_bp AC_MUXNEG_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXPOS_0_bm) && defined(AC_MUXPOS0_bm)
+ #define AC_MUXPOS_0_bm AC_MUXPOS0_bm
+ #elif defined(AC_MUXPOS_0_bm)
+ //deprecated_constant_name AC_MUXPOS0_bm = AC_MUXPOS_0_bm;
+ #define AC_MUXPOS0_bm AC_MUXPOS_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXPOS_0_bp) && defined(AC_MUXPOS0_bp)
+ #define AC_MUXPOS_0_bp AC_MUXPOS0_bp
+ #elif defined(AC_MUXPOS_0_bp)
+ //deprecated_constant_name AC_MUXPOS0_bp = AC_MUXPOS_0_bp;
+ #define AC_MUXPOS0_bp AC_MUXPOS_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXPOS_1_bm) && defined(AC_MUXPOS1_bm)
+ #define AC_MUXPOS_1_bm AC_MUXPOS1_bm
+ #elif defined(AC_MUXPOS_1_bm)
+ //deprecated_constant_name AC_MUXPOS1_bm = AC_MUXPOS_1_bm;
+ #define AC_MUXPOS1_bm AC_MUXPOS_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXPOS_1_bp) && defined(AC_MUXPOS1_bp)
+ #define AC_MUXPOS_1_bp AC_MUXPOS1_bp
+ #elif defined(AC_MUXPOS_1_bp)
+ //deprecated_constant_name AC_MUXPOS1_bp = AC_MUXPOS_1_bp;
+ #define AC_MUXPOS1_bp AC_MUXPOS_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXPOS_2_bm) && defined(AC_MUXPOS2_bm)
+ #define AC_MUXPOS_2_bm AC_MUXPOS2_bm
+ #elif defined(AC_MUXPOS_2_bm)
+ //deprecated_constant_name AC_MUXPOS2_bm = AC_MUXPOS_2_bm;
+ #define AC_MUXPOS2_bm AC_MUXPOS_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_MUXPOS_2_bp) && defined(AC_MUXPOS2_bp)
+ #define AC_MUXPOS_2_bp AC_MUXPOS2_bp
+ #elif defined(AC_MUXPOS_2_bp)
+ //deprecated_constant_name AC_MUXPOS2_bp = AC_MUXPOS_2_bp;
+ #define AC_MUXPOS2_bp AC_MUXPOS_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_NORMAL_0_bm) && defined(AC_INTMODE_NORMAL0_bm)
+ #define AC_INTMODE_NORMAL_0_bm AC_INTMODE_NORMAL0_bm
+ #elif defined(AC_INTMODE_NORMAL_0_bm)
+ //deprecated_constant_name AC_INTMODE_NORMAL0_bm = AC_INTMODE_NORMAL_0_bm;
+ #define AC_INTMODE_NORMAL0_bm AC_INTMODE_NORMAL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_NORMAL_0_bp) && defined(AC_INTMODE_NORMAL0_bp)
+ #define AC_INTMODE_NORMAL_0_bp AC_INTMODE_NORMAL0_bp
+ #elif defined(AC_INTMODE_NORMAL_0_bp)
+ //deprecated_constant_name AC_INTMODE_NORMAL0_bp = AC_INTMODE_NORMAL_0_bp;
+ #define AC_INTMODE_NORMAL0_bp AC_INTMODE_NORMAL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_NORMAL_1_bm) && defined(AC_INTMODE_NORMAL1_bm)
+ #define AC_INTMODE_NORMAL_1_bm AC_INTMODE_NORMAL1_bm
+ #elif defined(AC_INTMODE_NORMAL_1_bm)
+ //deprecated_constant_name AC_INTMODE_NORMAL1_bm = AC_INTMODE_NORMAL_1_bm;
+ #define AC_INTMODE_NORMAL1_bm AC_INTMODE_NORMAL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_NORMAL_1_bp) && defined(AC_INTMODE_NORMAL1_bp)
+ #define AC_INTMODE_NORMAL_1_bp AC_INTMODE_NORMAL1_bp
+ #elif defined(AC_INTMODE_NORMAL_1_bp)
+ //deprecated_constant_name AC_INTMODE_NORMAL1_bp = AC_INTMODE_NORMAL_1_bp;
+ #define AC_INTMODE_NORMAL1_bp AC_INTMODE_NORMAL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_WINDOW_0_bm) && defined(AC_INTMODE_WINDOW0_bm)
+ #define AC_INTMODE_WINDOW_0_bm AC_INTMODE_WINDOW0_bm
+ #elif defined(AC_INTMODE_WINDOW_0_bm)
+ //deprecated_constant_name AC_INTMODE_WINDOW0_bm = AC_INTMODE_WINDOW_0_bm;
+ #define AC_INTMODE_WINDOW0_bm AC_INTMODE_WINDOW_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_WINDOW_0_bp) && defined(AC_INTMODE_WINDOW0_bp)
+ #define AC_INTMODE_WINDOW_0_bp AC_INTMODE_WINDOW0_bp
+ #elif defined(AC_INTMODE_WINDOW_0_bp)
+ //deprecated_constant_name AC_INTMODE_WINDOW0_bp = AC_INTMODE_WINDOW_0_bp;
+ #define AC_INTMODE_WINDOW0_bp AC_INTMODE_WINDOW_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_WINDOW_1_bm) && defined(AC_INTMODE_WINDOW1_bm)
+ #define AC_INTMODE_WINDOW_1_bm AC_INTMODE_WINDOW1_bm
+ #elif defined(AC_INTMODE_WINDOW_1_bm)
+ //deprecated_constant_name AC_INTMODE_WINDOW1_bm = AC_INTMODE_WINDOW_1_bm;
+ #define AC_INTMODE_WINDOW1_bm AC_INTMODE_WINDOW_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_INTMODE_WINDOW_1_bp) && defined(AC_INTMODE_WINDOW1_bp)
+ #define AC_INTMODE_WINDOW_1_bp AC_INTMODE_WINDOW1_bp
+ #elif defined(AC_INTMODE_WINDOW_1_bp)
+ //deprecated_constant_name AC_INTMODE_WINDOW1_bp = AC_INTMODE_WINDOW_1_bp;
+ #define AC_INTMODE_WINDOW1_bp AC_INTMODE_WINDOW_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSTATE_0_bm) && defined(AC_WINSTATE0_bm)
+ #define AC_WINSTATE_0_bm AC_WINSTATE0_bm
+ #elif defined(AC_WINSTATE_0_bm)
+ //deprecated_constant_name AC_WINSTATE0_bm = AC_WINSTATE_0_bm;
+ #define AC_WINSTATE0_bm AC_WINSTATE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSTATE_0_bp) && defined(AC_WINSTATE0_bp)
+ #define AC_WINSTATE_0_bp AC_WINSTATE0_bp
+ #elif defined(AC_WINSTATE_0_bp)
+ //deprecated_constant_name AC_WINSTATE0_bp = AC_WINSTATE_0_bp;
+ #define AC_WINSTATE0_bp AC_WINSTATE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSTATE_1_bm) && defined(AC_WINSTATE1_bm)
+ #define AC_WINSTATE_1_bm AC_WINSTATE1_bm
+ #elif defined(AC_WINSTATE_1_bm)
+ //deprecated_constant_name AC_WINSTATE1_bm = AC_WINSTATE_1_bm;
+ #define AC_WINSTATE1_bm AC_WINSTATE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(AC_WINSTATE_1_bp) && defined(AC_WINSTATE1_bp)
+ #define AC_WINSTATE_1_bp AC_WINSTATE1_bp
+ #elif defined(AC_WINSTATE_1_bp)
+ //deprecated_constant_name AC_WINSTATE1_bp = AC_WINSTATE_1_bp;
+ #define AC_WINSTATE1_bp AC_WINSTATE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= ADC ======= */
+ // alter the way the header's compatibility layer works to actually *show* the deprecation warning.
+ #if !defined(ADC_RESSEL_0_bm) && defined(ADC_RESSEL0_bm)
+ #define ADC_RESSEL_0_bm ADC_RESSEL0_bm
+ #elif defined(ADC_RESSEL_0_bm)
+ #undef ADC_RESSEL0_bm /* this special case does have a compatibility layer, but the deprecation is only provided by a comement so users will not be warned that the compatibility layer may be removed in the future. So we undefine in and handle as above */
+ //deprecated_constant_name ADC_RESSEL0_bm = ADC_RESSEL_0_bm;
+ #define ADC_RESSEL0_bm ADC_RESSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_RESSEL_0_bp) && defined(ADC_RESSEL0_bp)
+ #define ADC_RESSEL_0_bp ADC_RESSEL0_bp
+ #elif defined(ADC_RESSEL_0_bp)
+ #undef ADC_RESSEL0_bp /* this special case does have a compatibility layer, but the deprecation is only provided by a comement so users will not be warned that the compatibility layer may be removed in the future. So we undefine in and handle as above */
+ //deprecated_constant_name ADC_RESSEL0_bp = ADC_RESSEL_0_bp;
+ #define ADC_RESSEL0_bp ADC_RESSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_RESSEL_1_bm) && defined(ADC_RESSEL1_bm)
+ #define ADC_RESSEL_1_bm ADC_RESSEL1_bm
+ #elif defined(ADC_RESSEL_1_bm)
+ #undef ADC_RESSEL1_bm /* this special case does have a compatibility layer, but the deprecation is only provided by a comement so users will not be warned that the compatibility layer may be removed in the future. So we undefine in and handle as above */
+ //deprecated_constant_name ADC_RESSEL1_bm = ADC_RESSEL_1_bm;
+ #define ADC_RESSEL1_bm ADC_RESSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_RESSEL_1_bp) && defined(ADC_RESSEL1_bp)
+ #define ADC_RESSEL_1_bp ADC_RESSEL1_bp
+ #elif defined(ADC_RESSEL_1_bp)
+ #undef ADC_RESSEL1_bp /* this special case does have a compatibility layer, but the deprecation is only provided by a comement so users will not be warned that the compatibility layer may be removed in the future. So we undefine in and handle as above */
+ //deprecated_constant_name ADC_RESSEL1_bp = ADC_RESSEL_1_bp;
+ #define ADC_RESSEL1_bp ADC_RESSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(ADC_SAMPNUM_0_bm) && defined(ADC_SAMPNUM0_bm)
+ #define ADC_SAMPNUM_0_bm ADC_SAMPNUM0_bm
+ #elif defined(ADC_SAMPNUM_0_bm)
+ //deprecated_constant_name ADC_SAMPNUM0_bm = ADC_SAMPNUM_0_bm;
+ #define ADC_SAMPNUM0_bm ADC_SAMPNUM_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPNUM_0_bp) && defined(ADC_SAMPNUM0_bp)
+ #define ADC_SAMPNUM_0_bp ADC_SAMPNUM0_bp
+ #elif defined(ADC_SAMPNUM_0_bp)
+ //deprecated_constant_name ADC_SAMPNUM0_bp = ADC_SAMPNUM_0_bp;
+ #define ADC_SAMPNUM0_bp ADC_SAMPNUM_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPNUM_1_bm) && defined(ADC_SAMPNUM1_bm)
+ #define ADC_SAMPNUM_1_bm ADC_SAMPNUM1_bm
+ #elif defined(ADC_SAMPNUM_1_bm)
+ //deprecated_constant_name ADC_SAMPNUM1_bm = ADC_SAMPNUM_1_bm;
+ #define ADC_SAMPNUM1_bm ADC_SAMPNUM_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPNUM_1_bp) && defined(ADC_SAMPNUM1_bp)
+ #define ADC_SAMPNUM_1_bp ADC_SAMPNUM1_bp
+ #elif defined(ADC_SAMPNUM_1_bp)
+ //deprecated_constant_name ADC_SAMPNUM1_bp = ADC_SAMPNUM_1_bp;
+ #define ADC_SAMPNUM1_bp ADC_SAMPNUM_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPNUM_2_bm) && defined(ADC_SAMPNUM2_bm)
+ #define ADC_SAMPNUM_2_bm ADC_SAMPNUM2_bm
+ #elif defined(ADC_SAMPNUM_2_bm)
+ //deprecated_constant_name ADC_SAMPNUM2_bm = ADC_SAMPNUM_2_bm;
+ #define ADC_SAMPNUM2_bm ADC_SAMPNUM_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPNUM_2_bp) && defined(ADC_SAMPNUM2_bp)
+ #define ADC_SAMPNUM_2_bp ADC_SAMPNUM2_bp
+ #elif defined(ADC_SAMPNUM_2_bp)
+ //deprecated_constant_name ADC_SAMPNUM2_bp = ADC_SAMPNUM_2_bp;
+ #define ADC_SAMPNUM2_bp ADC_SAMPNUM_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(ADC_PRESC_0_bm) && defined(ADC_PRESC0_bm)
+ #define ADC_PRESC_0_bm ADC_PRESC0_bm
+ #elif defined(ADC_PRESC_0_bm)
+ //deprecated_constant_name ADC_PRESC0_bm = ADC_PRESC_0_bm;
+ #define ADC_PRESC0_bm ADC_PRESC_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_PRESC_0_bp) && defined(ADC_PRESC0_bp)
+ #define ADC_PRESC_0_bp ADC_PRESC0_bp
+ #elif defined(ADC_PRESC_0_bp)
+ //deprecated_constant_name ADC_PRESC0_bp = ADC_PRESC_0_bp;
+ #define ADC_PRESC0_bp ADC_PRESC_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_PRESC_1_bm) && defined(ADC_PRESC1_bm)
+ #define ADC_PRESC_1_bm ADC_PRESC1_bm
+ #elif defined(ADC_PRESC_1_bm)
+ //deprecated_constant_name ADC_PRESC1_bm = ADC_PRESC_1_bm;
+ #define ADC_PRESC1_bm ADC_PRESC_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_PRESC_1_bp) && defined(ADC_PRESC1_bp)
+ #define ADC_PRESC_1_bp ADC_PRESC1_bp
+ #elif defined(ADC_PRESC_1_bp)
+ //deprecated_constant_name ADC_PRESC1_bp = ADC_PRESC_1_bp;
+ #define ADC_PRESC1_bp ADC_PRESC_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_PRESC_2_bm) && defined(ADC_PRESC2_bm)
+ #define ADC_PRESC_2_bm ADC_PRESC2_bm
+ #elif defined(ADC_PRESC_2_bm)
+ //deprecated_constant_name ADC_PRESC2_bm = ADC_PRESC_2_bm;
+ #define ADC_PRESC2_bm ADC_PRESC_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_PRESC_2_bp) && defined(ADC_PRESC2_bp)
+ #define ADC_PRESC_2_bp ADC_PRESC2_bp
+ #elif defined(ADC_PRESC_2_bp)
+ //deprecated_constant_name ADC_PRESC2_bp = ADC_PRESC_2_bp;
+ #define ADC_PRESC2_bp ADC_PRESC_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_PRESC_3_bm) && defined(ADC_PRESC3_bm)
+ #define ADC_PRESC_3_bm ADC_PRESC3_bm
+ #elif defined(ADC_PRESC_3_bm)
+ //deprecated_constant_name ADC_PRESC3_bm = ADC_PRESC_3_bm;
+ #define ADC_PRESC3_bm ADC_PRESC_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_PRESC_3_bp) && defined(ADC_PRESC3_bp)
+ #define ADC_PRESC_3_bp ADC_PRESC3_bp
+ #elif defined(ADC_PRESC_3_bp)
+ //deprecated_constant_name ADC_PRESC3_bp = ADC_PRESC_3_bp;
+ #define ADC_PRESC3_bp ADC_PRESC_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(ADC_SAMPDLY_0_bm) && defined(ADC_SAMPDLY0_bm)
+ #define ADC_SAMPDLY_0_bm ADC_SAMPDLY0_bm
+ #elif defined(ADC_SAMPDLY_0_bm)
+ //deprecated_constant_name ADC_SAMPDLY0_bm = ADC_SAMPDLY_0_bm;
+ #define ADC_SAMPDLY0_bm ADC_SAMPDLY_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPDLY_0_bp) && defined(ADC_SAMPDLY0_bp)
+ #define ADC_SAMPDLY_0_bp ADC_SAMPDLY0_bp
+ #elif defined(ADC_SAMPDLY_0_bp)
+ //deprecated_constant_name ADC_SAMPDLY0_bp = ADC_SAMPDLY_0_bp;
+ #define ADC_SAMPDLY0_bp ADC_SAMPDLY_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPDLY_1_bm) && defined(ADC_SAMPDLY1_bm)
+ #define ADC_SAMPDLY_1_bm ADC_SAMPDLY1_bm
+ #elif defined(ADC_SAMPDLY_1_bm)
+ //deprecated_constant_name ADC_SAMPDLY1_bm = ADC_SAMPDLY_1_bm;
+ #define ADC_SAMPDLY1_bm ADC_SAMPDLY_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPDLY_1_bp) && defined(ADC_SAMPDLY1_bp)
+ #define ADC_SAMPDLY_1_bp ADC_SAMPDLY1_bp
+ #elif defined(ADC_SAMPDLY_1_bp)
+ //deprecated_constant_name ADC_SAMPDLY1_bp = ADC_SAMPDLY_1_bp;
+ #define ADC_SAMPDLY1_bp ADC_SAMPDLY_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPDLY_2_bm) && defined(ADC_SAMPDLY2_bm)
+ #define ADC_SAMPDLY_2_bm ADC_SAMPDLY2_bm
+ #elif defined(ADC_SAMPDLY_2_bm)
+ //deprecated_constant_name ADC_SAMPDLY2_bm = ADC_SAMPDLY_2_bm;
+ #define ADC_SAMPDLY2_bm ADC_SAMPDLY_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPDLY_2_bp) && defined(ADC_SAMPDLY2_bp)
+ #define ADC_SAMPDLY_2_bp ADC_SAMPDLY2_bp
+ #elif defined(ADC_SAMPDLY_2_bp)
+ //deprecated_constant_name ADC_SAMPDLY2_bp = ADC_SAMPDLY_2_bp;
+ #define ADC_SAMPDLY2_bp ADC_SAMPDLY_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPDLY_3_bm) && defined(ADC_SAMPDLY3_bm)
+ #define ADC_SAMPDLY_3_bm ADC_SAMPDLY3_bm
+ #elif defined(ADC_SAMPDLY_3_bm)
+ //deprecated_constant_name ADC_SAMPDLY3_bm = ADC_SAMPDLY_3_bm;
+ #define ADC_SAMPDLY3_bm ADC_SAMPDLY_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_SAMPDLY_3_bp) && defined(ADC_SAMPDLY3_bp)
+ #define ADC_SAMPDLY_3_bp ADC_SAMPDLY3_bp
+ #elif defined(ADC_SAMPDLY_3_bp)
+ //deprecated_constant_name ADC_SAMPDLY3_bp = ADC_SAMPDLY_3_bp;
+ #define ADC_SAMPDLY3_bp ADC_SAMPDLY_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(ADC_INITDLY_0_bm) && defined(ADC_INITDLY0_bm)
+ #define ADC_INITDLY_0_bm ADC_INITDLY0_bm
+ #elif defined(ADC_INITDLY_0_bm)
+ //deprecated_constant_name ADC_INITDLY0_bm = ADC_INITDLY_0_bm;
+ #define ADC_INITDLY0_bm ADC_INITDLY_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_INITDLY_0_bp) && defined(ADC_INITDLY0_bp)
+ #define ADC_INITDLY_0_bp ADC_INITDLY0_bp
+ #elif defined(ADC_INITDLY_0_bp)
+ //deprecated_constant_name ADC_INITDLY0_bp = ADC_INITDLY_0_bp;
+ #define ADC_INITDLY0_bp ADC_INITDLY_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_INITDLY_1_bm) && defined(ADC_INITDLY1_bm)
+ #define ADC_INITDLY_1_bm ADC_INITDLY1_bm
+ #elif defined(ADC_INITDLY_1_bm)
+ //deprecated_constant_name ADC_INITDLY1_bm = ADC_INITDLY_1_bm;
+ #define ADC_INITDLY1_bm ADC_INITDLY_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_INITDLY_1_bp) && defined(ADC_INITDLY1_bp)
+ #define ADC_INITDLY_1_bp ADC_INITDLY1_bp
+ #elif defined(ADC_INITDLY_1_bp)
+ //deprecated_constant_name ADC_INITDLY1_bp = ADC_INITDLY_1_bp;
+ #define ADC_INITDLY1_bp ADC_INITDLY_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_INITDLY_2_bm) && defined(ADC_INITDLY2_bm)
+ #define ADC_INITDLY_2_bm ADC_INITDLY2_bm
+ #elif defined(ADC_INITDLY_2_bm)
+ //deprecated_constant_name ADC_INITDLY2_bm = ADC_INITDLY_2_bm;
+ #define ADC_INITDLY2_bm ADC_INITDLY_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_INITDLY_2_bp) && defined(ADC_INITDLY2_bp)
+ #define ADC_INITDLY_2_bp ADC_INITDLY2_bp
+ #elif defined(ADC_INITDLY_2_bp)
+ //deprecated_constant_name ADC_INITDLY2_bp = ADC_INITDLY_2_bp;
+ #define ADC_INITDLY2_bp ADC_INITDLY_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(ADC_WINCM_0_bm) && defined(ADC_WINCM0_bm)
+ #define ADC_WINCM_0_bm ADC_WINCM0_bm
+ #elif defined(ADC_WINCM_0_bm)
+ //deprecated_constant_name ADC_WINCM0_bm = ADC_WINCM_0_bm;
+ #define ADC_WINCM0_bm ADC_WINCM_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_WINCM_0_bp) && defined(ADC_WINCM0_bp)
+ #define ADC_WINCM_0_bp ADC_WINCM0_bp
+ #elif defined(ADC_WINCM_0_bp)
+ //deprecated_constant_name ADC_WINCM0_bp = ADC_WINCM_0_bp;
+ #define ADC_WINCM0_bp ADC_WINCM_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_WINCM_1_bm) && defined(ADC_WINCM1_bm)
+ #define ADC_WINCM_1_bm ADC_WINCM1_bm
+ #elif defined(ADC_WINCM_1_bm)
+ //deprecated_constant_name ADC_WINCM1_bm = ADC_WINCM_1_bm;
+ #define ADC_WINCM1_bm ADC_WINCM_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_WINCM_1_bp) && defined(ADC_WINCM1_bp)
+ #define ADC_WINCM_1_bp ADC_WINCM1_bp
+ #elif defined(ADC_WINCM_1_bp)
+ //deprecated_constant_name ADC_WINCM1_bp = ADC_WINCM_1_bp;
+ #define ADC_WINCM1_bp ADC_WINCM_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_WINCM_2_bm) && defined(ADC_WINCM2_bm)
+ #define ADC_WINCM_2_bm ADC_WINCM2_bm
+ #elif defined(ADC_WINCM_2_bm)
+ //deprecated_constant_name ADC_WINCM2_bm = ADC_WINCM_2_bm;
+ #define ADC_WINCM2_bm ADC_WINCM_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(ADC_WINCM_2_bp) && defined(ADC_WINCM2_bp)
+ #define ADC_WINCM_2_bp ADC_WINCM2_bp
+ #elif defined(ADC_WINCM_2_bp)
+ //deprecated_constant_name ADC_WINCM2_bp = ADC_WINCM_2_bp;
+ #define ADC_WINCM2_bp ADC_WINCM_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= BOD ======= */
+ #if !defined(BOD_SLEEP_0_bm) && defined(BOD_SLEEP0_bm)
+ #define BOD_SLEEP_0_bm BOD_SLEEP0_bm
+ #elif defined(BOD_SLEEP_0_bm)
+ //deprecated_constant_name BOD_SLEEP0_bm = BOD_SLEEP_0_bm;
+ #define BOD_SLEEP0_bm BOD_SLEEP_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_SLEEP_0_bp) && defined(BOD_SLEEP0_bp)
+ #define BOD_SLEEP_0_bp BOD_SLEEP0_bp
+ #elif defined(BOD_SLEEP_0_bp)
+ //deprecated_constant_name BOD_SLEEP0_bp = BOD_SLEEP_0_bp;
+ #define BOD_SLEEP0_bp BOD_SLEEP_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_SLEEP_1_bm) && defined(BOD_SLEEP1_bm)
+ #define BOD_SLEEP_1_bm BOD_SLEEP1_bm
+ #elif defined(BOD_SLEEP_1_bm)
+ //deprecated_constant_name BOD_SLEEP1_bm = BOD_SLEEP_1_bm;
+ #define BOD_SLEEP1_bm BOD_SLEEP_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_SLEEP_1_bp) && defined(BOD_SLEEP1_bp)
+ #define BOD_SLEEP_1_bp BOD_SLEEP1_bp
+ #elif defined(BOD_SLEEP_1_bp)
+ //deprecated_constant_name BOD_SLEEP1_bp = BOD_SLEEP_1_bp;
+ #define BOD_SLEEP1_bp BOD_SLEEP_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(BOD_ACTIVE_0_bm) && defined(BOD_ACTIVE0_bm)
+ #define BOD_ACTIVE_0_bm BOD_ACTIVE0_bm
+ #elif defined(BOD_ACTIVE_0_bm)
+ //deprecated_constant_name BOD_ACTIVE0_bm = BOD_ACTIVE_0_bm;
+ #define BOD_ACTIVE0_bm BOD_ACTIVE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_ACTIVE_0_bp) && defined(BOD_ACTIVE0_bp)
+ #define BOD_ACTIVE_0_bp BOD_ACTIVE0_bp
+ #elif defined(BOD_ACTIVE_0_bp)
+ //deprecated_constant_name BOD_ACTIVE0_bp = BOD_ACTIVE_0_bp;
+ #define BOD_ACTIVE0_bp BOD_ACTIVE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_ACTIVE_1_bm) && defined(BOD_ACTIVE1_bm)
+ #define BOD_ACTIVE_1_bm BOD_ACTIVE1_bm
+ #elif defined(BOD_ACTIVE_1_bm)
+ //deprecated_constant_name BOD_ACTIVE1_bm = BOD_ACTIVE_1_bm;
+ #define BOD_ACTIVE1_bm BOD_ACTIVE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_ACTIVE_1_bp) && defined(BOD_ACTIVE1_bp)
+ #define BOD_ACTIVE_1_bp BOD_ACTIVE1_bp
+ #elif defined(BOD_ACTIVE_1_bp)
+ //deprecated_constant_name BOD_ACTIVE1_bp = BOD_ACTIVE_1_bp;
+ #define BOD_ACTIVE1_bp BOD_ACTIVE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(BOD_LVL_0_bm) && defined(BOD_LVL0_bm)
+ #define BOD_LVL_0_bm BOD_LVL0_bm
+ #elif defined(BOD_LVL_0_bm)
+ //deprecated_constant_name BOD_LVL0_bm = BOD_LVL_0_bm;
+ #define BOD_LVL0_bm BOD_LVL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_LVL_0_bp) && defined(BOD_LVL0_bp)
+ #define BOD_LVL_0_bp BOD_LVL0_bp
+ #elif defined(BOD_LVL_0_bp)
+ //deprecated_constant_name BOD_LVL0_bp = BOD_LVL_0_bp;
+ #define BOD_LVL0_bp BOD_LVL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_LVL_1_bm) && defined(BOD_LVL1_bm)
+ #define BOD_LVL_1_bm BOD_LVL1_bm
+ #elif defined(BOD_LVL_1_bm)
+ //deprecated_constant_name BOD_LVL1_bm = BOD_LVL_1_bm;
+ #define BOD_LVL1_bm BOD_LVL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_LVL_1_bp) && defined(BOD_LVL1_bp)
+ #define BOD_LVL_1_bp BOD_LVL1_bp
+ #elif defined(BOD_LVL_1_bp)
+ //deprecated_constant_name BOD_LVL1_bp = BOD_LVL_1_bp;
+ #define BOD_LVL1_bp BOD_LVL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_LVL_2_bm) && defined(BOD_LVL2_bm)
+ #define BOD_LVL_2_bm BOD_LVL2_bm
+ #elif defined(BOD_LVL_2_bm)
+ //deprecated_constant_name BOD_LVL2_bm = BOD_LVL_2_bm;
+ #define BOD_LVL2_bm BOD_LVL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_LVL_2_bp) && defined(BOD_LVL2_bp)
+ #define BOD_LVL_2_bp BOD_LVL2_bp
+ #elif defined(BOD_LVL_2_bp)
+ //deprecated_constant_name BOD_LVL2_bp = BOD_LVL_2_bp;
+ #define BOD_LVL2_bp BOD_LVL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(BOD_VLMLVL_0_bm) && defined(BOD_VLMLVL0_bm)
+ #define BOD_VLMLVL_0_bm BOD_VLMLVL0_bm
+ #elif defined(BOD_VLMLVL_0_bm)
+ //deprecated_constant_name BOD_VLMLVL0_bm = BOD_VLMLVL_0_bm;
+ #define BOD_VLMLVL0_bm BOD_VLMLVL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_VLMLVL_0_bp) && defined(BOD_VLMLVL0_bp)
+ #define BOD_VLMLVL_0_bp BOD_VLMLVL0_bp
+ #elif defined(BOD_VLMLVL_0_bp)
+ //deprecated_constant_name BOD_VLMLVL0_bp = BOD_VLMLVL_0_bp;
+ #define BOD_VLMLVL0_bp BOD_VLMLVL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_VLMLVL_1_bm) && defined(BOD_VLMLVL1_bm)
+ #define BOD_VLMLVL_1_bm BOD_VLMLVL1_bm
+ #elif defined(BOD_VLMLVL_1_bm)
+ //deprecated_constant_name BOD_VLMLVL1_bm = BOD_VLMLVL_1_bm;
+ #define BOD_VLMLVL1_bm BOD_VLMLVL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_VLMLVL_1_bp) && defined(BOD_VLMLVL1_bp)
+ #define BOD_VLMLVL_1_bp BOD_VLMLVL1_bp
+ #elif defined(BOD_VLMLVL_1_bp)
+ //deprecated_constant_name BOD_VLMLVL1_bp = BOD_VLMLVL_1_bp;
+ #define BOD_VLMLVL1_bp BOD_VLMLVL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(BOD_VLMCFG_0_bm) && defined(BOD_VLMCFG0_bm)
+ #define BOD_VLMCFG_0_bm BOD_VLMCFG0_bm
+ #elif defined(BOD_VLMCFG_0_bm)
+ //deprecated_constant_name BOD_VLMCFG0_bm = BOD_VLMCFG_0_bm;
+ #define BOD_VLMCFG0_bm BOD_VLMCFG_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_VLMCFG_0_bp) && defined(BOD_VLMCFG0_bp)
+ #define BOD_VLMCFG_0_bp BOD_VLMCFG0_bp
+ #elif defined(BOD_VLMCFG_0_bp)
+ //deprecated_constant_name BOD_VLMCFG0_bp = BOD_VLMCFG_0_bp;
+ #define BOD_VLMCFG0_bp BOD_VLMCFG_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_VLMCFG_1_bm) && defined(BOD_VLMCFG1_bm)
+ #define BOD_VLMCFG_1_bm BOD_VLMCFG1_bm
+ #elif defined(BOD_VLMCFG_1_bm)
+ //deprecated_constant_name BOD_VLMCFG1_bm = BOD_VLMCFG_1_bm;
+ #define BOD_VLMCFG1_bm BOD_VLMCFG_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(BOD_VLMCFG_1_bp) && defined(BOD_VLMCFG1_bp)
+ #define BOD_VLMCFG_1_bp BOD_VLMCFG1_bp
+ #elif defined(BOD_VLMCFG_1_bp)
+ //deprecated_constant_name BOD_VLMCFG1_bp = BOD_VLMCFG_1_bp;
+ #define BOD_VLMCFG1_bp BOD_VLMCFG_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= CCL ======= */
+ #if !defined(CCL_SEQSEL_0_bm) && defined(CCL_SEQSEL0_bm)
+ #define CCL_SEQSEL_0_bm CCL_SEQSEL0_bm
+ #elif defined(CCL_SEQSEL_0_bm)
+ //deprecated_constant_name CCL_SEQSEL0_bm = CCL_SEQSEL_0_bm;
+ #define CCL_SEQSEL0_bm CCL_SEQSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_SEQSEL_0_bp) && defined(CCL_SEQSEL0_bp)
+ #define CCL_SEQSEL_0_bp CCL_SEQSEL0_bp
+ #elif defined(CCL_SEQSEL_0_bp)
+ //deprecated_constant_name CCL_SEQSEL0_bp = CCL_SEQSEL_0_bp;
+ #define CCL_SEQSEL0_bp CCL_SEQSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_SEQSEL_1_bm) && defined(CCL_SEQSEL1_bm)
+ #define CCL_SEQSEL_1_bm CCL_SEQSEL1_bm
+ #elif defined(CCL_SEQSEL_1_bm)
+ //deprecated_constant_name CCL_SEQSEL1_bm = CCL_SEQSEL_1_bm;
+ #define CCL_SEQSEL1_bm CCL_SEQSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_SEQSEL_1_bp) && defined(CCL_SEQSEL1_bp)
+ #define CCL_SEQSEL_1_bp CCL_SEQSEL1_bp
+ #elif defined(CCL_SEQSEL_1_bp)
+ //deprecated_constant_name CCL_SEQSEL1_bp = CCL_SEQSEL_1_bp;
+ #define CCL_SEQSEL1_bp CCL_SEQSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_SEQSEL_2_bm) && defined(CCL_SEQSEL2_bm)
+ #define CCL_SEQSEL_2_bm CCL_SEQSEL2_bm
+ #elif defined(CCL_SEQSEL_2_bm)
+ //deprecated_constant_name CCL_SEQSEL2_bm = CCL_SEQSEL_2_bm;
+ #define CCL_SEQSEL2_bm CCL_SEQSEL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_SEQSEL_2_bp) && defined(CCL_SEQSEL2_bp)
+ #define CCL_SEQSEL_2_bp CCL_SEQSEL2_bp
+ #elif defined(CCL_SEQSEL_2_bp)
+ //deprecated_constant_name CCL_SEQSEL2_bp = CCL_SEQSEL_2_bp;
+ #define CCL_SEQSEL2_bp CCL_SEQSEL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(CCL_INTMODE0_0_bm) && defined(CCL_INTMODE00_bm)
+ #define CCL_INTMODE0_0_bm CCL_INTMODE00_bm
+ #elif defined(CCL_INTMODE0_0_bm)
+ //deprecated_constant_name CCL_INTMODE00_bm = CCL_INTMODE0_0_bm;
+ #define CCL_INTMODE00_bm CCL_INTMODE0_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE0_0_bp) && defined(CCL_INTMODE00_bp)
+ #define CCL_INTMODE0_0_bp CCL_INTMODE00_bp
+ #elif defined(CCL_INTMODE0_0_bp)
+ //deprecated_constant_name CCL_INTMODE00_bp = CCL_INTMODE0_0_bp;
+ #define CCL_INTMODE00_bp CCL_INTMODE0_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE0_1_bm) && defined(CCL_INTMODE01_bm)
+ #define CCL_INTMODE0_1_bm CCL_INTMODE01_bm
+ #elif defined(CCL_INTMODE0_1_bm)
+ //deprecated_constant_name CCL_INTMODE01_bm = CCL_INTMODE0_1_bm;
+ #define CCL_INTMODE01_bm CCL_INTMODE0_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE0_1_bp) && defined(CCL_INTMODE01_bp)
+ #define CCL_INTMODE0_1_bp CCL_INTMODE01_bp
+ #elif defined(CCL_INTMODE0_1_bp)
+ //deprecated_constant_name CCL_INTMODE01_bp = CCL_INTMODE0_1_bp;
+ #define CCL_INTMODE01_bp CCL_INTMODE0_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE1_0_bm) && defined(CCL_INTMODE10_bm)
+ #define CCL_INTMODE1_0_bm CCL_INTMODE10_bm
+ #elif defined(CCL_INTMODE1_0_bm)
+ //deprecated_constant_name CCL_INTMODE10_bm = CCL_INTMODE1_0_bm;
+ #define CCL_INTMODE10_bm CCL_INTMODE1_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE1_0_bp) && defined(CCL_INTMODE10_bp)
+ #define CCL_INTMODE1_0_bp CCL_INTMODE10_bp
+ #elif defined(CCL_INTMODE1_0_bp)
+ //deprecated_constant_name CCL_INTMODE10_bp = CCL_INTMODE1_0_bp;
+ #define CCL_INTMODE10_bp CCL_INTMODE1_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE1_1_bm) && defined(CCL_INTMODE11_bm)
+ #define CCL_INTMODE1_1_bm CCL_INTMODE11_bm
+ #elif defined(CCL_INTMODE1_1_bm)
+ //deprecated_constant_name CCL_INTMODE11_bm = CCL_INTMODE1_1_bm;
+ #define CCL_INTMODE11_bm CCL_INTMODE1_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE1_1_bp) && defined(CCL_INTMODE11_bp)
+ #define CCL_INTMODE1_1_bp CCL_INTMODE11_bp
+ #elif defined(CCL_INTMODE1_1_bp)
+ //deprecated_constant_name CCL_INTMODE11_bp = CCL_INTMODE1_1_bp;
+ #define CCL_INTMODE11_bp CCL_INTMODE1_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE2_0_bm) && defined(CCL_INTMODE20_bm)
+ #define CCL_INTMODE2_0_bm CCL_INTMODE20_bm
+ #elif defined(CCL_INTMODE2_0_bm)
+ //deprecated_constant_name CCL_INTMODE20_bm = CCL_INTMODE2_0_bm;
+ #define CCL_INTMODE20_bm CCL_INTMODE2_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE2_0_bp) && defined(CCL_INTMODE20_bp)
+ #define CCL_INTMODE2_0_bp CCL_INTMODE20_bp
+ #elif defined(CCL_INTMODE2_0_bp)
+ //deprecated_constant_name CCL_INTMODE20_bp = CCL_INTMODE2_0_bp;
+ #define CCL_INTMODE20_bp CCL_INTMODE2_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE2_1_bm) && defined(CCL_INTMODE21_bm)
+ #define CCL_INTMODE2_1_bm CCL_INTMODE21_bm
+ #elif defined(CCL_INTMODE2_1_bm)
+ //deprecated_constant_name CCL_INTMODE21_bm = CCL_INTMODE2_1_bm;
+ #define CCL_INTMODE21_bm CCL_INTMODE2_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE2_1_bp) && defined(CCL_INTMODE21_bp)
+ #define CCL_INTMODE2_1_bp CCL_INTMODE21_bp
+ #elif defined(CCL_INTMODE2_1_bp)
+ //deprecated_constant_name CCL_INTMODE21_bp = CCL_INTMODE2_1_bp;
+ #define CCL_INTMODE21_bp CCL_INTMODE2_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE3_0_bm) && defined(CCL_INTMODE30_bm)
+ #define CCL_INTMODE3_0_bm CCL_INTMODE30_bm
+ #elif defined(CCL_INTMODE3_0_bm)
+ //deprecated_constant_name CCL_INTMODE30_bm = CCL_INTMODE3_0_bm;
+ #define CCL_INTMODE30_bm CCL_INTMODE3_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE3_0_bp) && defined(CCL_INTMODE30_bp)
+ #define CCL_INTMODE3_0_bp CCL_INTMODE30_bp
+ #elif defined(CCL_INTMODE3_0_bp)
+ //deprecated_constant_name CCL_INTMODE30_bp = CCL_INTMODE3_0_bp;
+ #define CCL_INTMODE30_bp CCL_INTMODE3_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE3_1_bm) && defined(CCL_INTMODE31_bm)
+ #define CCL_INTMODE3_1_bm CCL_INTMODE31_bm
+ #elif defined(CCL_INTMODE3_1_bm)
+ //deprecated_constant_name CCL_INTMODE31_bm = CCL_INTMODE3_1_bm;
+ #define CCL_INTMODE31_bm CCL_INTMODE3_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE3_1_bp) && defined(CCL_INTMODE31_bp)
+ #define CCL_INTMODE3_1_bp CCL_INTMODE31_bp
+ #elif defined(CCL_INTMODE3_1_bp)
+ //deprecated_constant_name CCL_INTMODE31_bp = CCL_INTMODE3_1_bp;
+ #define CCL_INTMODE31_bp CCL_INTMODE3_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE4_0_bm) && defined(CCL_INTMODE40_bm)
+ #define CCL_INTMODE4_0_bm CCL_INTMODE40_bm
+ #elif defined(CCL_INTMODE4_0_bm)
+ //deprecated_constant_name CCL_INTMODE40_bm = CCL_INTMODE4_0_bm;
+ #define CCL_INTMODE40_bm CCL_INTMODE4_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE4_0_bp) && defined(CCL_INTMODE40_bp)
+ #define CCL_INTMODE4_0_bp CCL_INTMODE40_bp
+ #elif defined(CCL_INTMODE4_0_bp)
+ //deprecated_constant_name CCL_INTMODE40_bp = CCL_INTMODE4_0_bp;
+ #define CCL_INTMODE40_bp CCL_INTMODE4_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE4_1_bm) && defined(CCL_INTMODE41_bm)
+ #define CCL_INTMODE4_1_bm CCL_INTMODE41_bm
+ #elif defined(CCL_INTMODE4_1_bm)
+ //deprecated_constant_name CCL_INTMODE41_bm = CCL_INTMODE4_1_bm;
+ #define CCL_INTMODE41_bm CCL_INTMODE4_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE4_1_bp) && defined(CCL_INTMODE41_bp)
+ #define CCL_INTMODE4_1_bp CCL_INTMODE41_bp
+ #elif defined(CCL_INTMODE4_1_bp)
+ //deprecated_constant_name CCL_INTMODE41_bp = CCL_INTMODE4_1_bp;
+ #define CCL_INTMODE41_bp CCL_INTMODE4_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE5_0_bm) && defined(CCL_INTMODE50_bm)
+ #define CCL_INTMODE5_0_bm CCL_INTMODE50_bm
+ #elif defined(CCL_INTMODE5_0_bm)
+ //deprecated_constant_name CCL_INTMODE50_bm = CCL_INTMODE5_0_bm;
+ #define CCL_INTMODE50_bm CCL_INTMODE5_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE5_0_bp) && defined(CCL_INTMODE50_bp)
+ #define CCL_INTMODE5_0_bp CCL_INTMODE50_bp
+ #elif defined(CCL_INTMODE5_0_bp)
+ //deprecated_constant_name CCL_INTMODE50_bp = CCL_INTMODE5_0_bp;
+ #define CCL_INTMODE50_bp CCL_INTMODE5_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE5_1_bm) && defined(CCL_INTMODE51_bm)
+ #define CCL_INTMODE5_1_bm CCL_INTMODE51_bm
+ #elif defined(CCL_INTMODE5_1_bm)
+ //deprecated_constant_name CCL_INTMODE51_bm = CCL_INTMODE5_1_bm;
+ #define CCL_INTMODE51_bm CCL_INTMODE5_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INTMODE5_1_bp) && defined(CCL_INTMODE51_bp)
+ #define CCL_INTMODE5_1_bp CCL_INTMODE51_bp
+ #elif defined(CCL_INTMODE5_1_bp)
+ //deprecated_constant_name CCL_INTMODE51_bp = CCL_INTMODE5_1_bp;
+ #define CCL_INTMODE51_bp CCL_INTMODE5_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(CCL_INT_0_bm) && defined(CCL_INT0_bm)
+ #define CCL_INT_0_bm CCL_INT0_bm
+ #elif defined(CCL_INT_0_bm)
+ #undef CCL_INT0_bm /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT0_bm = CCL_INT_0_bm;
+ #define CCL_INT0_bm CCL_INT_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_0_bp) && defined(CCL_INT0_bp)
+ #define CCL_INT_0_bp CCL_INT0_bp
+ #elif defined(CCL_INT_0_bp)
+ #undef CCL_INT0_bp /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT0_bp = CCL_INT_0_bp;
+ #define CCL_INT0_bp CCL_INT_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_1_bm) && defined(CCL_INT1_bm)
+ #define CCL_INT_1_bm CCL_INT1_bm
+ #elif defined(CCL_INT_1_bm)
+ #undef CCL_INT1_bm /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT1_bm = CCL_INT_1_bm;
+ #define CCL_INT1_bm CCL_INT_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_1_bp) && defined(CCL_INT1_bp)
+ #define CCL_INT_1_bp CCL_INT1_bp
+ #elif defined(CCL_INT_1_bp)
+ #undef CCL_INT1_bp /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT1_bp = CCL_INT_1_bp;
+ #define CCL_INT1_bp CCL_INT_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_2_bm) && defined(CCL_INT2_bm)
+ #define CCL_INT_2_bm CCL_INT2_bm
+ #elif defined(CCL_INT_2_bm)
+ #undef CCL_INT2_bm /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT2_bm = CCL_INT_2_bm;
+ #define CCL_INT2_bm CCL_INT_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_2_bp) && defined(CCL_INT2_bp)
+ #define CCL_INT_2_bp CCL_INT2_bp
+ #elif defined(CCL_INT_2_bp)
+ #undef CCL_INT2_bp /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT2_bp = CCL_INT_2_bp;
+ #define CCL_INT2_bp CCL_INT_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_3_bm) && defined(CCL_INT3_bm)
+ #define CCL_INT_3_bm CCL_INT3_bm
+ #elif defined(CCL_INT_3_bm)
+ #undef CCL_INT3_bm /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT3_bm = CCL_INT_3_bm;
+ #define CCL_INT3_bm CCL_INT_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_3_bp) && defined(CCL_INT3_bp)
+ #define CCL_INT_3_bp CCL_INT3_bp
+ #elif defined(CCL_INT_3_bp)
+ #undef CCL_INT3_bp /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT3_bp = CCL_INT_3_bp;
+ #define CCL_INT3_bp CCL_INT_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_4_bm) && defined(CCL_INT4_bm)
+ #define CCL_INT_4_bm CCL_INT4_bm
+ #elif defined(CCL_INT_4_bm)
+ #undef CCL_INT4_bm /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT4_bm = CCL_INT_4_bm;
+ #define CCL_INT4_bm CCL_INT_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_4_bp) && defined(CCL_INT4_bp)
+ #define CCL_INT_4_bp CCL_INT4_bp
+ #elif defined(CCL_INT_4_bp)
+ #undef CCL_INT4_bp /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT4_bp = CCL_INT_4_bp;
+ #define CCL_INT4_bp CCL_INT_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_5_bm) && defined(CCL_INT5_bm)
+ #define CCL_INT_5_bm CCL_INT5_bm
+ #elif defined(CCL_INT_5_bm)
+ #undef CCL_INT5_bm /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT5_bm = CCL_INT_5_bm;
+ #define CCL_INT5_bm CCL_INT_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INT_5_bp) && defined(CCL_INT5_bp)
+ #define CCL_INT_5_bp CCL_INT5_bp
+ #elif defined(CCL_INT_5_bp)
+ #undef CCL_INT5_bp /* Another round of placews where they decided to put a compatibility layer the wrong way*/
+ //deprecated_constant_name CCL_INT5_bp = CCL_INT_5_bp;
+ #define CCL_INT5_bp CCL_INT_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_CLKSRC_0_bm) && defined(CCL_CLKSRC0_bm)
+ #define CCL_CLKSRC_0_bm CCL_CLKSRC0_bm
+ #elif defined(CCL_CLKSRC_0_bm)
+ //deprecated_constant_name CCL_CLKSRC0_bm = CCL_CLKSRC_0_bm;
+ #define CCL_CLKSRC0_bm CCL_CLKSRC_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_CLKSRC_0_bp) && defined(CCL_CLKSRC0_bp)
+ #define CCL_CLKSRC_0_bp CCL_CLKSRC0_bp
+ #elif defined(CCL_CLKSRC_0_bp)
+ //deprecated_constant_name CCL_CLKSRC0_bp = CCL_CLKSRC_0_bp;
+ #define CCL_CLKSRC0_bp CCL_CLKSRC_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_CLKSRC_1_bm) && defined(CCL_CLKSRC1_bm)
+ #define CCL_CLKSRC_1_bm CCL_CLKSRC1_bm
+ #elif defined(CCL_CLKSRC_1_bm)
+ //deprecated_constant_name CCL_CLKSRC1_bm = CCL_CLKSRC_1_bm;
+ #define CCL_CLKSRC1_bm CCL_CLKSRC_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_CLKSRC_1_bp) && defined(CCL_CLKSRC1_bp)
+ #define CCL_CLKSRC_1_bp CCL_CLKSRC1_bp
+ #elif defined(CCL_CLKSRC_1_bp)
+ //deprecated_constant_name CCL_CLKSRC1_bp = CCL_CLKSRC_1_bp;
+ #define CCL_CLKSRC1_bp CCL_CLKSRC_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_CLKSRC_2_bm) && defined(CCL_CLKSRC2_bm)
+ #define CCL_CLKSRC_2_bm CCL_CLKSRC2_bm
+ #elif defined(CCL_CLKSRC_2_bm)
+ //deprecated_constant_name CCL_CLKSRC2_bm = CCL_CLKSRC_2_bm;
+ #define CCL_CLKSRC2_bm CCL_CLKSRC_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_CLKSRC_2_bp) && defined(CCL_CLKSRC2_bp)
+ #define CCL_CLKSRC_2_bp CCL_CLKSRC2_bp
+ #elif defined(CCL_CLKSRC_2_bp)
+ //deprecated_constant_name CCL_CLKSRC2_bp = CCL_CLKSRC_2_bp;
+ #define CCL_CLKSRC2_bp CCL_CLKSRC_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_FILTSEL_0_bm) && defined(CCL_FILTSEL0_bm)
+ #define CCL_FILTSEL_0_bm CCL_FILTSEL0_bm
+ #elif defined(CCL_FILTSEL_0_bm)
+ //deprecated_constant_name CCL_FILTSEL0_bm = CCL_FILTSEL_0_bm;
+ #define CCL_FILTSEL0_bm CCL_FILTSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_FILTSEL_0_bp) && defined(CCL_FILTSEL0_bp)
+ #define CCL_FILTSEL_0_bp CCL_FILTSEL0_bp
+ #elif defined(CCL_FILTSEL_0_bp)
+ //deprecated_constant_name CCL_FILTSEL0_bp = CCL_FILTSEL_0_bp;
+ #define CCL_FILTSEL0_bp CCL_FILTSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_FILTSEL_1_bm) && defined(CCL_FILTSEL1_bm)
+ #define CCL_FILTSEL_1_bm CCL_FILTSEL1_bm
+ #elif defined(CCL_FILTSEL_1_bm)
+ //deprecated_constant_name CCL_FILTSEL1_bm = CCL_FILTSEL_1_bm;
+ #define CCL_FILTSEL1_bm CCL_FILTSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_FILTSEL_1_bp) && defined(CCL_FILTSEL1_bp)
+ #define CCL_FILTSEL_1_bp CCL_FILTSEL1_bp
+ #elif defined(CCL_FILTSEL_1_bp)
+ //deprecated_constant_name CCL_FILTSEL1_bp = CCL_FILTSEL_1_bp;
+ #define CCL_FILTSEL1_bp CCL_FILTSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_0_bm) && defined(CCL_INSEL00_bm)
+ #define CCL_INSEL0_0_bm CCL_INSEL00_bm
+ #elif defined(CCL_INSEL0_0_bm)
+ //deprecated_constant_name CCL_INSEL00_bm = CCL_INSEL0_0_bm;
+ #define CCL_INSEL00_bm CCL_INSEL0_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_0_bp) && defined(CCL_INSEL00_bp)
+ #define CCL_INSEL0_0_bp CCL_INSEL00_bp
+ #elif defined(CCL_INSEL0_0_bp)
+ //deprecated_constant_name CCL_INSEL00_bp = CCL_INSEL0_0_bp;
+ #define CCL_INSEL00_bp CCL_INSEL0_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_1_bm) && defined(CCL_INSEL01_bm)
+ #define CCL_INSEL0_1_bm CCL_INSEL01_bm
+ #elif defined(CCL_INSEL0_1_bm)
+ //deprecated_constant_name CCL_INSEL01_bm = CCL_INSEL0_1_bm;
+ #define CCL_INSEL01_bm CCL_INSEL0_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_1_bp) && defined(CCL_INSEL01_bp)
+ #define CCL_INSEL0_1_bp CCL_INSEL01_bp
+ #elif defined(CCL_INSEL0_1_bp)
+ //deprecated_constant_name CCL_INSEL01_bp = CCL_INSEL0_1_bp;
+ #define CCL_INSEL01_bp CCL_INSEL0_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_2_bm) && defined(CCL_INSEL02_bm)
+ #define CCL_INSEL0_2_bm CCL_INSEL02_bm
+ #elif defined(CCL_INSEL0_2_bm)
+ //deprecated_constant_name CCL_INSEL02_bm = CCL_INSEL0_2_bm;
+ #define CCL_INSEL02_bm CCL_INSEL0_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_2_bp) && defined(CCL_INSEL02_bp)
+ #define CCL_INSEL0_2_bp CCL_INSEL02_bp
+ #elif defined(CCL_INSEL0_2_bp)
+ //deprecated_constant_name CCL_INSEL02_bp = CCL_INSEL0_2_bp;
+ #define CCL_INSEL02_bp CCL_INSEL0_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_3_bm) && defined(CCL_INSEL03_bm)
+ #define CCL_INSEL0_3_bm CCL_INSEL03_bm
+ #elif defined(CCL_INSEL0_3_bm)
+ //deprecated_constant_name CCL_INSEL03_bm = CCL_INSEL0_3_bm;
+ #define CCL_INSEL03_bm CCL_INSEL0_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL0_3_bp) && defined(CCL_INSEL03_bp)
+ #define CCL_INSEL0_3_bp CCL_INSEL03_bp
+ #elif defined(CCL_INSEL0_3_bp)
+ //deprecated_constant_name CCL_INSEL03_bp = CCL_INSEL0_3_bp;
+ #define CCL_INSEL03_bp CCL_INSEL0_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_0_bm) && defined(CCL_INSEL10_bm)
+ #define CCL_INSEL1_0_bm CCL_INSEL10_bm
+ #elif defined(CCL_INSEL1_0_bm)
+ //deprecated_constant_name CCL_INSEL10_bm = CCL_INSEL1_0_bm;
+ #define CCL_INSEL10_bm CCL_INSEL1_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_0_bp) && defined(CCL_INSEL10_bp)
+ #define CCL_INSEL1_0_bp CCL_INSEL10_bp
+ #elif defined(CCL_INSEL1_0_bp)
+ //deprecated_constant_name CCL_INSEL10_bp = CCL_INSEL1_0_bp;
+ #define CCL_INSEL10_bp CCL_INSEL1_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_1_bm) && defined(CCL_INSEL11_bm)
+ #define CCL_INSEL1_1_bm CCL_INSEL11_bm
+ #elif defined(CCL_INSEL1_1_bm)
+ //deprecated_constant_name CCL_INSEL11_bm = CCL_INSEL1_1_bm;
+ #define CCL_INSEL11_bm CCL_INSEL1_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_1_bp) && defined(CCL_INSEL11_bp)
+ #define CCL_INSEL1_1_bp CCL_INSEL11_bp
+ #elif defined(CCL_INSEL1_1_bp)
+ //deprecated_constant_name CCL_INSEL11_bp = CCL_INSEL1_1_bp;
+ #define CCL_INSEL11_bp CCL_INSEL1_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_2_bm) && defined(CCL_INSEL12_bm)
+ #define CCL_INSEL1_2_bm CCL_INSEL12_bm
+ #elif defined(CCL_INSEL1_2_bm)
+ //deprecated_constant_name CCL_INSEL12_bm = CCL_INSEL1_2_bm;
+ #define CCL_INSEL12_bm CCL_INSEL1_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_2_bp) && defined(CCL_INSEL12_bp)
+ #define CCL_INSEL1_2_bp CCL_INSEL12_bp
+ #elif defined(CCL_INSEL1_2_bp)
+ //deprecated_constant_name CCL_INSEL12_bp = CCL_INSEL1_2_bp;
+ #define CCL_INSEL12_bp CCL_INSEL1_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_3_bm) && defined(CCL_INSEL13_bm)
+ #define CCL_INSEL1_3_bm CCL_INSEL13_bm
+ #elif defined(CCL_INSEL1_3_bm)
+ //deprecated_constant_name CCL_INSEL13_bm = CCL_INSEL1_3_bm;
+ #define CCL_INSEL13_bm CCL_INSEL1_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL1_3_bp) && defined(CCL_INSEL13_bp)
+ #define CCL_INSEL1_3_bp CCL_INSEL13_bp
+ #elif defined(CCL_INSEL1_3_bp)
+ //deprecated_constant_name CCL_INSEL13_bp = CCL_INSEL1_3_bp;
+ #define CCL_INSEL13_bp CCL_INSEL1_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_0_bm) && defined(CCL_INSEL20_bm)
+ #define CCL_INSEL2_0_bm CCL_INSEL20_bm
+ #elif defined(CCL_INSEL2_0_bm)
+ //deprecated_constant_name CCL_INSEL20_bm = CCL_INSEL2_0_bm;
+ #define CCL_INSEL20_bm CCL_INSEL2_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_0_bp) && defined(CCL_INSEL20_bp)
+ #define CCL_INSEL2_0_bp CCL_INSEL20_bp
+ #elif defined(CCL_INSEL2_0_bp)
+ //deprecated_constant_name CCL_INSEL20_bp = CCL_INSEL2_0_bp;
+ #define CCL_INSEL20_bp CCL_INSEL2_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_1_bm) && defined(CCL_INSEL21_bm)
+ #define CCL_INSEL2_1_bm CCL_INSEL21_bm
+ #elif defined(CCL_INSEL2_1_bm)
+ //deprecated_constant_name CCL_INSEL21_bm = CCL_INSEL2_1_bm;
+ #define CCL_INSEL21_bm CCL_INSEL2_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_1_bp) && defined(CCL_INSEL21_bp)
+ #define CCL_INSEL2_1_bp CCL_INSEL21_bp
+ #elif defined(CCL_INSEL2_1_bp)
+ //deprecated_constant_name CCL_INSEL21_bp = CCL_INSEL2_1_bp;
+ #define CCL_INSEL21_bp CCL_INSEL2_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_2_bm) && defined(CCL_INSEL22_bm)
+ #define CCL_INSEL2_2_bm CCL_INSEL22_bm
+ #elif defined(CCL_INSEL2_2_bm)
+ //deprecated_constant_name CCL_INSEL22_bm = CCL_INSEL2_2_bm;
+ #define CCL_INSEL22_bm CCL_INSEL2_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_2_bp) && defined(CCL_INSEL22_bp)
+ #define CCL_INSEL2_2_bp CCL_INSEL22_bp
+ #elif defined(CCL_INSEL2_2_bp)
+ //deprecated_constant_name CCL_INSEL22_bp = CCL_INSEL2_2_bp;
+ #define CCL_INSEL22_bp CCL_INSEL2_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_3_bm) && defined(CCL_INSEL23_bm)
+ #define CCL_INSEL2_3_bm CCL_INSEL23_bm
+ #elif defined(CCL_INSEL2_3_bm)
+ //deprecated_constant_name CCL_INSEL23_bm = CCL_INSEL2_3_bm;
+ #define CCL_INSEL23_bm CCL_INSEL2_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CCL_INSEL2_3_bp) && defined(CCL_INSEL23_bp)
+ #define CCL_INSEL2_3_bp CCL_INSEL23_bp
+ #elif defined(CCL_INSEL2_3_bp)
+ //deprecated_constant_name CCL_INSEL23_bp = CCL_INSEL2_3_bp;
+ #define CCL_INSEL23_bp CCL_INSEL2_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= CLKCTRL ======= */
+ #if !defined(CLKCTRL_FRQSEL_0_bm) && defined(CLKCTRL_FRQSEL0_bm)
+ #define CLKCTRL_FRQSEL_0_bm CLKCTRL_FRQSEL0_bm
+ #elif defined(CLKCTRL_FRQSEL_0_bm)
+ //deprecated_constant_name CLKCTRL_FRQSEL0_bm = CLKCTRL_FRQSEL_0_bm;
+ #define CLKCTRL_FRQSEL0_bm CLKCTRL_FRQSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_FRQSEL_0_bp) && defined(CLKCTRL_FRQSEL0_bp)
+ #define CLKCTRL_FRQSEL_0_bp CLKCTRL_FRQSEL0_bp
+ #elif defined(CLKCTRL_FRQSEL_0_bp)
+ //deprecated_constant_name CLKCTRL_FRQSEL0_bp = CLKCTRL_FRQSEL_0_bp;
+ #define CLKCTRL_FRQSEL0_bp CLKCTRL_FRQSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_FRQSEL_1_bm) && defined(CLKCTRL_FRQSEL1_bm)
+ #define CLKCTRL_FRQSEL_1_bm CLKCTRL_FRQSEL1_bm
+ #elif defined(CLKCTRL_FRQSEL_1_bm)
+ //deprecated_constant_name CLKCTRL_FRQSEL1_bm = CLKCTRL_FRQSEL_1_bm;
+ #define CLKCTRL_FRQSEL1_bm CLKCTRL_FRQSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_FRQSEL_1_bp) && defined(CLKCTRL_FRQSEL1_bp)
+ #define CLKCTRL_FRQSEL_1_bp CLKCTRL_FRQSEL1_bp
+ #elif defined(CLKCTRL_FRQSEL_1_bp)
+ //deprecated_constant_name CLKCTRL_FRQSEL1_bp = CLKCTRL_FRQSEL_1_bp;
+ #define CLKCTRL_FRQSEL1_bp CLKCTRL_FRQSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_FRQSEL_2_bm) && defined(CLKCTRL_FRQSEL2_bm)
+ #define CLKCTRL_FRQSEL_2_bm CLKCTRL_FRQSEL2_bm
+ #elif defined(CLKCTRL_FRQSEL_2_bm)
+ //deprecated_constant_name CLKCTRL_FRQSEL2_bm = CLKCTRL_FRQSEL_2_bm;
+ #define CLKCTRL_FRQSEL2_bm CLKCTRL_FRQSEL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_FRQSEL_2_bp) && defined(CLKCTRL_FRQSEL2_bp)
+ #define CLKCTRL_FRQSEL_2_bp CLKCTRL_FRQSEL2_bp
+ #elif defined(CLKCTRL_FRQSEL_2_bp)
+ //deprecated_constant_name CLKCTRL_FRQSEL2_bp = CLKCTRL_FRQSEL_2_bp;
+ #define CLKCTRL_FRQSEL2_bp CLKCTRL_FRQSEL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_FRQSEL_3_bm) && defined(CLKCTRL_FRQSEL3_bm)
+ #define CLKCTRL_FRQSEL_3_bm CLKCTRL_FRQSEL3_bm
+ #elif defined(CLKCTRL_FRQSEL_3_bm)
+ //deprecated_constant_name CLKCTRL_FRQSEL3_bm = CLKCTRL_FRQSEL_3_bm;
+ #define CLKCTRL_FRQSEL3_bm CLKCTRL_FRQSEL_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_FRQSEL_3_bp) && defined(CLKCTRL_FRQSEL3_bp)
+ #define CLKCTRL_FRQSEL_3_bp CLKCTRL_FRQSEL3_bp
+ #elif defined(CLKCTRL_FRQSEL_3_bp)
+ //deprecated_constant_name CLKCTRL_FRQSEL3_bp = CLKCTRL_FRQSEL_3_bp;
+ #define CLKCTRL_FRQSEL3_bp CLKCTRL_FRQSEL_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_MULFAC_0_bm) && defined(CLKCTRL_MULFAC0_bm)
+ #define CLKCTRL_MULFAC_0_bm CLKCTRL_MULFAC0_bm
+ #elif defined(CLKCTRL_MULFAC_0_bm)
+ //deprecated_constant_name CLKCTRL_MULFAC0_bm = CLKCTRL_MULFAC_0_bm;
+ #define CLKCTRL_MULFAC0_bm CLKCTRL_MULFAC_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(CLKCTRL_MULFAC_0_bp) && defined(CLKCTRL_MULFAC0_bp)
+ #define CLKCTRL_MULFAC_0_bp CLKCTRL_MULFAC0_bp
+ #elif defined(CLKCTRL_MULFAC_0_bp)
+ //deprecated_constant_name CLKCTRL_MULFAC0_bp = CLKCTRL_MULFAC_0_bp;
+ #define CLKCTRL_MULFAC0_bp CLKCTRL_MULFAC_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_MULFAC_1_bm) && defined(CLKCTRL_MULFAC1_bm)
+ #define CLKCTRL_MULFAC_1_bm CLKCTRL_MULFAC1_bm
+ #elif defined(CLKCTRL_MULFAC_1_bm)
+ //deprecated_constant_name CLKCTRL_MULFAC1_bm = CLKCTRL_MULFAC_1_bm;
+ #define CLKCTRL_MULFAC1_bm CLKCTRL_MULFAC_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_MULFAC_1_bp) && defined(CLKCTRL_MULFAC1_bp)
+ #define CLKCTRL_MULFAC_1_bp CLKCTRL_MULFAC1_bp
+ #elif defined(CLKCTRL_MULFAC_1_bp)
+ //deprecated_constant_name CLKCTRL_MULFAC1_bp = CLKCTRL_MULFAC_1_bp;
+ #define CLKCTRL_MULFAC1_bp CLKCTRL_MULFAC_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(CLKCTRL_CSUT_0_bm) && defined(CLKCTRL_CSUT0_bm)
+ #define CLKCTRL_CSUT_0_bm CLKCTRL_CSUT0_bm
+ #elif defined(CLKCTRL_CSUT_0_bm)
+ //deprecated_constant_name CLKCTRL_CSUT0_bm = CLKCTRL_CSUT_0_bm;
+ #define CLKCTRL_CSUT0_bm CLKCTRL_CSUT_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_CSUT_0_bp) && defined(CLKCTRL_CSUT0_bp)
+ #define CLKCTRL_CSUT_0_bp CLKCTRL_CSUT0_bp
+ #elif defined(CLKCTRL_CSUT_0_bp)
+ //deprecated_constant_name CLKCTRL_CSUT0_bp = CLKCTRL_CSUT_0_bp;
+ #define CLKCTRL_CSUT0_bp CLKCTRL_CSUT_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_CSUT_1_bm) && defined(CLKCTRL_CSUT1_bm)
+ #define CLKCTRL_CSUT_1_bm CLKCTRL_CSUT1_bm
+ #elif defined(CLKCTRL_CSUT_1_bm)
+ //deprecated_constant_name CLKCTRL_CSUT1_bm = CLKCTRL_CSUT_1_bm;
+ #define CLKCTRL_CSUT1_bm CLKCTRL_CSUT_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(CLKCTRL_CSUT_1_bp) && defined(CLKCTRL_CSUT1_bp)
+ #define CLKCTRL_CSUT_1_bp CLKCTRL_CSUT1_bp
+ #elif defined(CLKCTRL_CSUT_1_bp)
+ //deprecated_constant_name CLKCTRL_CSUT1_bp = CLKCTRL_CSUT_1_bp;
+ #define CLKCTRL_CSUT1_bp CLKCTRL_CSUT_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= Fuses ======= */
+ #if !defined(FUSE_PERIOD_0_bm) && defined(FUSE_PERIOD0_bm)
+ #define FUSE_PERIOD_0_bm FUSE_PERIOD0_bm
+ #elif defined(FUSE_PERIOD_0_bm)
+ //deprecated_constant_name FUSE_PERIOD0_bm = FUSE_PERIOD_0_bm;
+ #define FUSE_PERIOD0_bm FUSE_PERIOD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_PERIOD_0_bp) && defined(FUSE_PERIOD0_bp)
+ #define FUSE_PERIOD_0_bp FUSE_PERIOD0_bp
+ #elif defined(FUSE_PERIOD_0_bp)
+ //deprecated_constant_name FUSE_PERIOD0_bp = FUSE_PERIOD_0_bp;
+ #define FUSE_PERIOD0_bp FUSE_PERIOD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_PERIOD_1_bm) && defined(FUSE_PERIOD1_bm)
+ #define FUSE_PERIOD_1_bm FUSE_PERIOD1_bm
+ #elif defined(FUSE_PERIOD_1_bm)
+ //deprecated_constant_name FUSE_PERIOD1_bm = FUSE_PERIOD_1_bm;
+ #define FUSE_PERIOD1_bm FUSE_PERIOD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_PERIOD_1_bp) && defined(FUSE_PERIOD1_bp)
+ #define FUSE_PERIOD_1_bp FUSE_PERIOD1_bp
+ #elif defined(FUSE_PERIOD_1_bp)
+ //deprecated_constant_name FUSE_PERIOD1_bp = FUSE_PERIOD_1_bp;
+ #define FUSE_PERIOD1_bp FUSE_PERIOD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_PERIOD_2_bm) && defined(FUSE_PERIOD2_bm)
+ #define FUSE_PERIOD_2_bm FUSE_PERIOD2_bm
+ #elif defined(FUSE_PERIOD_2_bm)
+ //deprecated_constant_name FUSE_PERIOD2_bm = FUSE_PERIOD_2_bm;
+ #define FUSE_PERIOD2_bm FUSE_PERIOD_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_PERIOD_2_bp) && defined(FUSE_PERIOD2_bp)
+ #define FUSE_PERIOD_2_bp FUSE_PERIOD2_bp
+ #elif defined(FUSE_PERIOD_2_bp)
+ //deprecated_constant_name FUSE_PERIOD2_bp = FUSE_PERIOD_2_bp;
+ #define FUSE_PERIOD2_bp FUSE_PERIOD_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_PERIOD_3_bm) && defined(FUSE_PERIOD3_bm)
+ #define FUSE_PERIOD_3_bm FUSE_PERIOD3_bm
+ #elif defined(FUSE_PERIOD_3_bm)
+ //deprecated_constant_name FUSE_PERIOD3_bm = FUSE_PERIOD_3_bm;
+ #define FUSE_PERIOD3_bm FUSE_PERIOD_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_PERIOD_3_bp) && defined(FUSE_PERIOD3_bp)
+ #define FUSE_PERIOD_3_bp FUSE_PERIOD3_bp
+ #elif defined(FUSE_PERIOD_3_bp)
+ //deprecated_constant_name FUSE_PERIOD3_bp = FUSE_PERIOD_3_bp;
+ #define FUSE_PERIOD3_bp FUSE_PERIOD_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_WINDOW_0_bm) && defined(FUSE_WINDOW0_bm)
+ #define FUSE_WINDOW_0_bm FUSE_WINDOW0_bm
+ #elif defined(FUSE_WINDOW_0_bm)
+ //deprecated_constant_name FUSE_WINDOW0_bm = FUSE_WINDOW_0_bm;
+ #define FUSE_WINDOW0_bm FUSE_WINDOW_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_WINDOW_0_bp) && defined(FUSE_WINDOW0_bp)
+ #define FUSE_WINDOW_0_bp FUSE_WINDOW0_bp
+ #elif defined(FUSE_WINDOW_0_bp)
+ //deprecated_constant_name FUSE_WINDOW0_bp = FUSE_WINDOW_0_bp;
+ #define FUSE_WINDOW0_bp FUSE_WINDOW_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_WINDOW_1_bm) && defined(FUSE_WINDOW1_bm)
+ #define FUSE_WINDOW_1_bm FUSE_WINDOW1_bm
+ #elif defined(FUSE_WINDOW_1_bm)
+ //deprecated_constant_name FUSE_WINDOW1_bm = FUSE_WINDOW_1_bm;
+ #define FUSE_WINDOW1_bm FUSE_WINDOW_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_WINDOW_1_bp) && defined(FUSE_WINDOW1_bp)
+ #define FUSE_WINDOW_1_bp FUSE_WINDOW1_bp
+ #elif defined(FUSE_WINDOW_1_bp)
+ //deprecated_constant_name FUSE_WINDOW1_bp = FUSE_WINDOW_1_bp;
+ #define FUSE_WINDOW1_bp FUSE_WINDOW_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_WINDOW_2_bm) && defined(FUSE_WINDOW2_bm)
+ #define FUSE_WINDOW_2_bm FUSE_WINDOW2_bm
+ #elif defined(FUSE_WINDOW_2_bm)
+ //deprecated_constant_name FUSE_WINDOW2_bm = FUSE_WINDOW_2_bm;
+ #define FUSE_WINDOW2_bm FUSE_WINDOW_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_WINDOW_2_bp) && defined(FUSE_WINDOW2_bp)
+ #define FUSE_WINDOW_2_bp FUSE_WINDOW2_bp
+ #elif defined(FUSE_WINDOW_2_bp)
+ //deprecated_constant_name FUSE_WINDOW2_bp = FUSE_WINDOW_2_bp;
+ #define FUSE_WINDOW2_bp FUSE_WINDOW_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_WINDOW_3_bm) && defined(FUSE_WINDOW3_bm)
+ #define FUSE_WINDOW_3_bm FUSE_WINDOW3_bm
+ #elif defined(FUSE_WINDOW_3_bm)
+ //deprecated_constant_name FUSE_WINDOW3_bm = FUSE_WINDOW_3_bm;
+ #define FUSE_WINDOW3_bm FUSE_WINDOW_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_WINDOW_3_bp) && defined(FUSE_WINDOW3_bp)
+ #define FUSE_WINDOW_3_bp FUSE_WINDOW3_bp
+ #elif defined(FUSE_WINDOW_3_bp)
+ //deprecated_constant_name FUSE_WINDOW3_bp = FUSE_WINDOW_3_bp;
+ #define FUSE_WINDOW3_bp FUSE_WINDOW_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_SLEEP_0_bm) && defined(FUSE_SLEEP0_bm)
+ #define FUSE_SLEEP_0_bm FUSE_SLEEP0_bm
+ #elif defined(FUSE_SLEEP_0_bm)
+ //deprecated_constant_name FUSE_SLEEP0_bm = FUSE_SLEEP_0_bm;
+ #define FUSE_SLEEP0_bm FUSE_SLEEP_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SLEEP_0_bp) && defined(FUSE_SLEEP0_bp)
+ #define FUSE_SLEEP_0_bp FUSE_SLEEP0_bp
+ #elif defined(FUSE_SLEEP_0_bp)
+ //deprecated_constant_name FUSE_SLEEP0_bp = FUSE_SLEEP_0_bp;
+ #define FUSE_SLEEP0_bp FUSE_SLEEP_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SLEEP_1_bm) && defined(FUSE_SLEEP1_bm)
+ #define FUSE_SLEEP_1_bm FUSE_SLEEP1_bm
+ #elif defined(FUSE_SLEEP_1_bm)
+ //deprecated_constant_name FUSE_SLEEP1_bm = FUSE_SLEEP_1_bm;
+ #define FUSE_SLEEP1_bm FUSE_SLEEP_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SLEEP_1_bp) && defined(FUSE_SLEEP1_bp)
+ #define FUSE_SLEEP_1_bp FUSE_SLEEP1_bp
+ #elif defined(FUSE_SLEEP_1_bp)
+ //deprecated_constant_name FUSE_SLEEP1_bp = FUSE_SLEEP_1_bp;
+ #define FUSE_SLEEP1_bp FUSE_SLEEP_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_ACTIVE_0_bm) && defined(FUSE_ACTIVE0_bm)
+ #define FUSE_ACTIVE_0_bm FUSE_ACTIVE0_bm
+ #elif defined(FUSE_ACTIVE_0_bm)
+ //deprecated_constant_name FUSE_ACTIVE0_bm = FUSE_ACTIVE_0_bm;
+ #define FUSE_ACTIVE0_bm FUSE_ACTIVE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_ACTIVE_0_bp) && defined(FUSE_ACTIVE0_bp)
+ #define FUSE_ACTIVE_0_bp FUSE_ACTIVE0_bp
+ #elif defined(FUSE_ACTIVE_0_bp)
+ //deprecated_constant_name FUSE_ACTIVE0_bp = FUSE_ACTIVE_0_bp;
+ #define FUSE_ACTIVE0_bp FUSE_ACTIVE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_ACTIVE_1_bm) && defined(FUSE_ACTIVE1_bm)
+ #define FUSE_ACTIVE_1_bm FUSE_ACTIVE1_bm
+ #elif defined(FUSE_ACTIVE_1_bm)
+ //deprecated_constant_name FUSE_ACTIVE1_bm = FUSE_ACTIVE_1_bm;
+ #define FUSE_ACTIVE1_bm FUSE_ACTIVE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_ACTIVE_1_bp) && defined(FUSE_ACTIVE1_bp)
+ #define FUSE_ACTIVE_1_bp FUSE_ACTIVE1_bp
+ #elif defined(FUSE_ACTIVE_1_bp)
+ //deprecated_constant_name FUSE_ACTIVE1_bp = FUSE_ACTIVE_1_bp;
+ #define FUSE_ACTIVE1_bp FUSE_ACTIVE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_LVL_0_bm) && defined(FUSE_LVL0_bm)
+ #define FUSE_LVL_0_bm FUSE_LVL0_bm
+ #elif defined(FUSE_LVL_0_bm)
+ //deprecated_constant_name FUSE_LVL0_bm = FUSE_LVL_0_bm;
+ #define FUSE_LVL0_bm FUSE_LVL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_LVL_0_bp) && defined(FUSE_LVL0_bp)
+ #define FUSE_LVL_0_bp FUSE_LVL0_bp
+ #elif defined(FUSE_LVL_0_bp)
+ //deprecated_constant_name FUSE_LVL0_bp = FUSE_LVL_0_bp;
+ #define FUSE_LVL0_bp FUSE_LVL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_LVL_1_bm) && defined(FUSE_LVL1_bm)
+ #define FUSE_LVL_1_bm FUSE_LVL1_bm
+ #elif defined(FUSE_LVL_1_bm)
+ //deprecated_constant_name FUSE_LVL1_bm = FUSE_LVL_1_bm;
+ #define FUSE_LVL1_bm FUSE_LVL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_LVL_1_bp) && defined(FUSE_LVL1_bp)
+ #define FUSE_LVL_1_bp FUSE_LVL1_bp
+ #elif defined(FUSE_LVL_1_bp)
+ //deprecated_constant_name FUSE_LVL1_bp = FUSE_LVL_1_bp;
+ #define FUSE_LVL1_bp FUSE_LVL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_LVL_2_bm) && defined(FUSE_LVL2_bm)
+ #define FUSE_LVL_2_bm FUSE_LVL2_bm
+ #elif defined(FUSE_LVL_2_bm)
+ //deprecated_constant_name FUSE_LVL2_bm = FUSE_LVL_2_bm;
+ #define FUSE_LVL2_bm FUSE_LVL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_LVL_2_bp) && defined(FUSE_LVL2_bp)
+ #define FUSE_LVL_2_bp FUSE_LVL2_bp
+ #elif defined(FUSE_LVL_2_bp)
+ //deprecated_constant_name FUSE_LVL2_bp = FUSE_LVL_2_bp;
+ #define FUSE_LVL2_bp FUSE_LVL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_CLKSEL_0_bm) && defined(FUSE_CLKSEL0_bm)
+ #define FUSE_CLKSEL_0_bm FUSE_CLKSEL0_bm
+ #elif defined(FUSE_CLKSEL_0_bm)
+ //deprecated_constant_name FUSE_CLKSEL0_bm = FUSE_CLKSEL_0_bm;
+ #define FUSE_CLKSEL0_bm FUSE_CLKSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_CLKSEL_0_bp) && defined(FUSE_CLKSEL0_bp)
+ #define FUSE_CLKSEL_0_bp FUSE_CLKSEL0_bp
+ #elif defined(FUSE_CLKSEL_0_bp)
+ //deprecated_constant_name FUSE_CLKSEL0_bp = FUSE_CLKSEL_0_bp;
+ #define FUSE_CLKSEL0_bp FUSE_CLKSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_CLKSEL_1_bm) && defined(FUSE_CLKSEL1_bm)
+ #define FUSE_CLKSEL_1_bm FUSE_CLKSEL1_bm
+ #elif defined(FUSE_CLKSEL_1_bm)
+ //deprecated_constant_name FUSE_CLKSEL1_bm = FUSE_CLKSEL_1_bm;
+ #define FUSE_CLKSEL1_bm FUSE_CLKSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_CLKSEL_1_bp) && defined(FUSE_CLKSEL1_bp)
+ #define FUSE_CLKSEL_1_bp FUSE_CLKSEL1_bp
+ #elif defined(FUSE_CLKSEL_1_bp)
+ //deprecated_constant_name FUSE_CLKSEL1_bp = FUSE_CLKSEL_1_bp;
+ #define FUSE_CLKSEL1_bp FUSE_CLKSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_CLKSEL_2_bm) && defined(FUSE_CLKSEL2_bm)
+ #define FUSE_CLKSEL_2_bm FUSE_CLKSEL2_bm
+ #elif defined(FUSE_CLKSEL_2_bm)
+ //deprecated_constant_name FUSE_CLKSEL2_bm = FUSE_CLKSEL_2_bm;
+ #define FUSE_CLKSEL2_bm FUSE_CLKSEL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_CLKSEL_2_bp) && defined(FUSE_CLKSEL2_bp)
+ #define FUSE_CLKSEL_2_bp FUSE_CLKSEL2_bp
+ #elif defined(FUSE_CLKSEL_2_bp)
+ //deprecated_constant_name FUSE_CLKSEL2_bp = FUSE_CLKSEL_2_bp;
+ #define FUSE_CLKSEL2_bp FUSE_CLKSEL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_RSTPINCFG_0_bm) && defined(FUSE_RSTPINCFG0_bm)
+ #define FUSE_RSTPINCFG_0_bm FUSE_RSTPINCFG0_bm
+ #elif defined(FUSE_RSTPINCFG_0_bm)
+ //deprecated_constant_name FUSE_RSTPINCFG0_bm = FUSE_RSTPINCFG_0_bm;
+ #define FUSE_RSTPINCFG0_bm FUSE_RSTPINCFG_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_RSTPINCFG_0_bp) && defined(FUSE_RSTPINCFG0_bp)
+ #define FUSE_RSTPINCFG_0_bp FUSE_RSTPINCFG0_bp
+ #elif defined(FUSE_RSTPINCFG_0_bp)
+ //deprecated_constant_name FUSE_RSTPINCFG0_bp = FUSE_RSTPINCFG_0_bp;
+ #define FUSE_RSTPINCFG0_bp FUSE_RSTPINCFG_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_RSTPINCFG_1_bm) && defined(FUSE_RSTPINCFG1_bm)
+ #define FUSE_RSTPINCFG_1_bm FUSE_RSTPINCFG1_bm
+ #elif defined(FUSE_RSTPINCFG_1_bm)
+ //deprecated_constant_name FUSE_RSTPINCFG1_bm = FUSE_RSTPINCFG_1_bm;
+ #define FUSE_RSTPINCFG1_bm FUSE_RSTPINCFG_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_RSTPINCFG_1_bp) && defined(FUSE_RSTPINCFG1_bp)
+ #define FUSE_RSTPINCFG_1_bp FUSE_RSTPINCFG1_bp
+ #elif defined(FUSE_RSTPINCFG_1_bp)
+ //deprecated_constant_name FUSE_RSTPINCFG1_bp = FUSE_RSTPINCFG_1_bp;
+ #define FUSE_RSTPINCFG1_bp FUSE_RSTPINCFG_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_CRCSRC_0_bm) && defined(FUSE_CRCSRC0_bm)
+ #define FUSE_CRCSRC_0_bm FUSE_CRCSRC0_bm
+ #elif defined(FUSE_CRCSRC_0_bm)
+ //deprecated_constant_name FUSE_CRCSRC0_bm = FUSE_CRCSRC_0_bm;
+ #define FUSE_CRCSRC0_bm FUSE_CRCSRC_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_CRCSRC_0_bp) && defined(FUSE_CRCSRC0_bp)
+ #define FUSE_CRCSRC_0_bp FUSE_CRCSRC0_bp
+ #elif defined(FUSE_CRCSRC_0_bp)
+ //deprecated_constant_name FUSE_CRCSRC0_bp = FUSE_CRCSRC_0_bp;
+ #define FUSE_CRCSRC0_bp FUSE_CRCSRC_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_CRCSRC_1_bm) && defined(FUSE_CRCSRC1_bm)
+ #define FUSE_CRCSRC_1_bm FUSE_CRCSRC1_bm
+ #elif defined(FUSE_CRCSRC_1_bm)
+ //deprecated_constant_name FUSE_CRCSRC1_bm = FUSE_CRCSRC_1_bm;
+ #define FUSE_CRCSRC1_bm FUSE_CRCSRC_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_CRCSRC_1_bp) && defined(FUSE_CRCSRC1_bp)
+ #define FUSE_CRCSRC_1_bp FUSE_CRCSRC1_bp
+ #elif defined(FUSE_CRCSRC_1_bp)
+ //deprecated_constant_name FUSE_CRCSRC1_bp = FUSE_CRCSRC_1_bp;
+ #define FUSE_CRCSRC1_bp FUSE_CRCSRC_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(FUSE_SUT_0_bm) && defined(FUSE_SUT0_bm)
+ #define FUSE_SUT_0_bm FUSE_SUT0_bm
+ #elif defined(FUSE_SUT_0_bm)
+ //deprecated_constant_name FUSE_SUT0_bm = FUSE_SUT_0_bm;
+ #define FUSE_SUT0_bm FUSE_SUT_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SUT_0_bp) && defined(FUSE_SUT0_bp)
+ #define FUSE_SUT_0_bp FUSE_SUT0_bp
+ #elif defined(FUSE_SUT_0_bp)
+ //deprecated_constant_name FUSE_SUT0_bp = FUSE_SUT_0_bp;
+ #define FUSE_SUT0_bp FUSE_SUT_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SUT_1_bm) && defined(FUSE_SUT1_bm)
+ #define FUSE_SUT_1_bm FUSE_SUT1_bm
+ #elif defined(FUSE_SUT_1_bm)
+ //deprecated_constant_name FUSE_SUT1_bm = FUSE_SUT_1_bm;
+ #define FUSE_SUT1_bm FUSE_SUT_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SUT_1_bp) && defined(FUSE_SUT1_bp)
+ #define FUSE_SUT_1_bp FUSE_SUT1_bp
+ #elif defined(FUSE_SUT_1_bp)
+ //deprecated_constant_name FUSE_SUT1_bp = FUSE_SUT_1_bp;
+ #define FUSE_SUT1_bp FUSE_SUT_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SUT_2_bm) && defined(FUSE_SUT2_bm)
+ #define FUSE_SUT_2_bm FUSE_SUT2_bm
+ #elif defined(FUSE_SUT_2_bm)
+ //deprecated_constant_name FUSE_SUT2_bm = FUSE_SUT_2_bm;
+ #define FUSE_SUT2_bm FUSE_SUT_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(FUSE_SUT_2_bp) && defined(FUSE_SUT2_bp)
+ #define FUSE_SUT_2_bp FUSE_SUT2_bp
+ #elif defined(FUSE_SUT_2_bp)
+ //deprecated_constant_name FUSE_SUT2_bp = FUSE_SUT_2_bp;
+ #define FUSE_SUT2_bp FUSE_SUT_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= NVMCTRL ======= */
+ #if !defined(NVMCTRL_CMD_0_bm) && defined(NVMCTRL_CMD0_bm)
+ #define NVMCTRL_CMD_0_bm NVMCTRL_CMD0_bm
+ #elif defined(NVMCTRL_CMD_0_bm)
+ //deprecated_constant_name NVMCTRL_CMD0_bm = NVMCTRL_CMD_0_bm;
+ #define NVMCTRL_CMD0_bm NVMCTRL_CMD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_0_bp) && defined(NVMCTRL_CMD0_bp)
+ #define NVMCTRL_CMD_0_bp NVMCTRL_CMD0_bp
+ #elif defined(NVMCTRL_CMD_0_bp)
+ //deprecated_constant_name NVMCTRL_CMD0_bp = NVMCTRL_CMD_0_bp;
+ #define NVMCTRL_CMD0_bp NVMCTRL_CMD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_1_bm) && defined(NVMCTRL_CMD1_bm)
+ #define NVMCTRL_CMD_1_bm NVMCTRL_CMD1_bm
+ #elif defined(NVMCTRL_CMD_1_bm)
+ //deprecated_constant_name NVMCTRL_CMD1_bm = NVMCTRL_CMD_1_bm;
+ #define NVMCTRL_CMD1_bm NVMCTRL_CMD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_1_bp) && defined(NVMCTRL_CMD1_bp)
+ #define NVMCTRL_CMD_1_bp NVMCTRL_CMD1_bp
+ #elif defined(NVMCTRL_CMD_1_bp)
+ //deprecated_constant_name NVMCTRL_CMD1_bp = NVMCTRL_CMD_1_bp;
+ #define NVMCTRL_CMD1_bp NVMCTRL_CMD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_2_bm) && defined(NVMCTRL_CMD2_bm)
+ #define NVMCTRL_CMD_2_bm NVMCTRL_CMD2_bm
+ #elif defined(NVMCTRL_CMD_2_bm)
+ //deprecated_constant_name NVMCTRL_CMD2_bm = NVMCTRL_CMD_2_bm;
+ #define NVMCTRL_CMD2_bm NVMCTRL_CMD_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_2_bp) && defined(NVMCTRL_CMD2_bp)
+ #define NVMCTRL_CMD_2_bp NVMCTRL_CMD2_bp
+ #elif defined(NVMCTRL_CMD_2_bp)
+ //deprecated_constant_name NVMCTRL_CMD2_bp = NVMCTRL_CMD_2_bp;
+ #define NVMCTRL_CMD2_bp NVMCTRL_CMD_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_3_bm) && defined(NVMCTRL_CMD3_bm)
+ #define NVMCTRL_CMD_3_bm NVMCTRL_CMD3_bm
+ #elif defined(NVMCTRL_CMD_3_bm)
+ //deprecated_constant_name NVMCTRL_CMD3_bm = NVMCTRL_CMD_3_bm;
+ #define NVMCTRL_CMD3_bm NVMCTRL_CMD_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_3_bp) && defined(NVMCTRL_CMD3_bp)
+ #define NVMCTRL_CMD_3_bp NVMCTRL_CMD3_bp
+ #elif defined(NVMCTRL_CMD_3_bp)
+ //deprecated_constant_name NVMCTRL_CMD3_bp = NVMCTRL_CMD_3_bp;
+ #define NVMCTRL_CMD3_bp NVMCTRL_CMD_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_4_bm) && defined(NVMCTRL_CMD4_bm)
+ #define NVMCTRL_CMD_4_bm NVMCTRL_CMD4_bm
+ #elif defined(NVMCTRL_CMD_4_bm)
+ //deprecated_constant_name NVMCTRL_CMD4_bm = NVMCTRL_CMD_4_bm;
+ #define NVMCTRL_CMD4_bm NVMCTRL_CMD_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_4_bp) && defined(NVMCTRL_CMD4_bp)
+ #define NVMCTRL_CMD_4_bp NVMCTRL_CMD4_bp
+ #elif defined(NVMCTRL_CMD_4_bp)
+ //deprecated_constant_name NVMCTRL_CMD4_bp = NVMCTRL_CMD_4_bp;
+ #define NVMCTRL_CMD4_bp NVMCTRL_CMD_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_5_bm) && defined(NVMCTRL_CMD5_bm)
+ #define NVMCTRL_CMD_5_bm NVMCTRL_CMD5_bm
+ #elif defined(NVMCTRL_CMD_5_bm)
+ //deprecated_constant_name NVMCTRL_CMD5_bm = NVMCTRL_CMD_5_bm;
+ #define NVMCTRL_CMD5_bm NVMCTRL_CMD_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_5_bp) && defined(NVMCTRL_CMD5_bp)
+ #define NVMCTRL_CMD_5_bp NVMCTRL_CMD5_bp
+ #elif defined(NVMCTRL_CMD_5_bp)
+ //deprecated_constant_name NVMCTRL_CMD5_bp = NVMCTRL_CMD_5_bp;
+ #define NVMCTRL_CMD5_bp NVMCTRL_CMD_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_6_bm) && defined(NVMCTRL_CMD6_bm)
+ #define NVMCTRL_CMD_6_bm NVMCTRL_CMD6_bm
+ #elif defined(NVMCTRL_CMD_6_bm)
+ //deprecated_constant_name NVMCTRL_CMD6_bm = NVMCTRL_CMD_6_bm;
+ #define NVMCTRL_CMD6_bm NVMCTRL_CMD_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_CMD_6_bp) && defined(NVMCTRL_CMD6_bp)
+ #define NVMCTRL_CMD_6_bp NVMCTRL_CMD6_bp
+ #elif defined(NVMCTRL_CMD_6_bp)
+ //deprecated_constant_name NVMCTRL_CMD6_bp = NVMCTRL_CMD_6_bp;
+ #define NVMCTRL_CMD6_bp NVMCTRL_CMD_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(NVMCTRL_FLMAP_0_bm) && defined(NVMCTRL_FLMAP0_bm)
+ #define NVMCTRL_FLMAP_0_bm NVMCTRL_FLMAP0_bm
+ #elif defined(NVMCTRL_FLMAP_0_bm)
+ //deprecated_constant_name NVMCTRL_FLMAP0_bm = NVMCTRL_FLMAP_0_bm;
+ #define NVMCTRL_FLMAP0_bm NVMCTRL_FLMAP_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_FLMAP_0_bp) && defined(NVMCTRL_FLMAP0_bp)
+ #define NVMCTRL_FLMAP_0_bp NVMCTRL_FLMAP0_bp
+ #elif defined(NVMCTRL_FLMAP_0_bp)
+ //deprecated_constant_name NVMCTRL_FLMAP0_bp = NVMCTRL_FLMAP_0_bp;
+ #define NVMCTRL_FLMAP0_bp NVMCTRL_FLMAP_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_FLMAP_1_bm) && defined(NVMCTRL_FLMAP1_bm)
+ #define NVMCTRL_FLMAP_1_bm NVMCTRL_FLMAP1_bm
+ #elif defined(NVMCTRL_FLMAP_1_bm)
+ //deprecated_constant_name NVMCTRL_FLMAP1_bm = NVMCTRL_FLMAP_1_bm;
+ #define NVMCTRL_FLMAP1_bm NVMCTRL_FLMAP_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_FLMAP_1_bp) && defined(NVMCTRL_FLMAP1_bp)
+ #define NVMCTRL_FLMAP_1_bp NVMCTRL_FLMAP1_bp
+ #elif defined(NVMCTRL_FLMAP_1_bp)
+ //deprecated_constant_name NVMCTRL_FLMAP1_bp = NVMCTRL_FLMAP_1_bp;
+ #define NVMCTRL_FLMAP1_bp NVMCTRL_FLMAP_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(NVMCTRL_ERROR_0_bm) && defined(NVMCTRL_ERROR0_bm)
+ #define NVMCTRL_ERROR_0_bm NVMCTRL_ERROR0_bm
+ #elif defined(NVMCTRL_ERROR_0_bm)
+ //deprecated_constant_name NVMCTRL_ERROR0_bm = NVMCTRL_ERROR_0_bm;
+ #define NVMCTRL_ERROR0_bm NVMCTRL_ERROR_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_ERROR_0_bp) && defined(NVMCTRL_ERROR0_bp)
+ #define NVMCTRL_ERROR_0_bp NVMCTRL_ERROR0_bp
+ #elif defined(NVMCTRL_ERROR_0_bp)
+ //deprecated_constant_name NVMCTRL_ERROR0_bp = NVMCTRL_ERROR_0_bp;
+ #define NVMCTRL_ERROR0_bp NVMCTRL_ERROR_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_ERROR_1_bm) && defined(NVMCTRL_ERROR1_bm)
+ #define NVMCTRL_ERROR_1_bm NVMCTRL_ERROR1_bm
+ #elif defined(NVMCTRL_ERROR_1_bm)
+ //deprecated_constant_name NVMCTRL_ERROR1_bm = NVMCTRL_ERROR_1_bm;
+ #define NVMCTRL_ERROR1_bm NVMCTRL_ERROR_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_ERROR_1_bp) && defined(NVMCTRL_ERROR1_bp)
+ #define NVMCTRL_ERROR_1_bp NVMCTRL_ERROR1_bp
+ #elif defined(NVMCTRL_ERROR_1_bp)
+ //deprecated_constant_name NVMCTRL_ERROR1_bp = NVMCTRL_ERROR_1_bp;
+ #define NVMCTRL_ERROR1_bp NVMCTRL_ERROR_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_ERROR_2_bm) && defined(NVMCTRL_ERROR2_bm)
+ #define NVMCTRL_ERROR_2_bm NVMCTRL_ERROR2_bm
+ #elif defined(NVMCTRL_ERROR_2_bm)
+ //deprecated_constant_name NVMCTRL_ERROR2_bm = NVMCTRL_ERROR_2_bm;
+ #define NVMCTRL_ERROR2_bm NVMCTRL_ERROR_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(NVMCTRL_ERROR_2_bp) && defined(NVMCTRL_ERROR2_bp)
+ #define NVMCTRL_ERROR_2_bp NVMCTRL_ERROR2_bp
+ #elif defined(NVMCTRL_ERROR_2_bp)
+ //deprecated_constant_name NVMCTRL_ERROR2_bp = NVMCTRL_ERROR_2_bp;
+ #define NVMCTRL_ERROR2_bp NVMCTRL_ERROR_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= PORT ======= */
+ #if !defined(PORT_INT_0_bm) && defined(PORT_INT0_bm)
+ #define PORT_INT_0_bm PORT_INT0_bm
+ #elif defined(PORT_INT_0_bm)
+ //deprecated_constant_name PORT_INT0_bm = PORT_INT_0_bm;
+ #define PORT_INT0_bm PORT_INT_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_0_bp) && defined(PORT_INT0_bp)
+ #define PORT_INT_0_bp PORT_INT0_bp
+ #elif defined(PORT_INT_0_bp)
+ //deprecated_constant_name PORT_INT0_bp = PORT_INT_0_bp;
+ #define PORT_INT0_bp PORT_INT_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_1_bm) && defined(PORT_INT1_bm)
+ #define PORT_INT_1_bm PORT_INT1_bm
+ #elif defined(PORT_INT_1_bm)
+ //deprecated_constant_name PORT_INT1_bm = PORT_INT_1_bm;
+ #define PORT_INT1_bm PORT_INT_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_1_bp) && defined(PORT_INT1_bp)
+ #define PORT_INT_1_bp PORT_INT1_bp
+ #elif defined(PORT_INT_1_bp)
+ //deprecated_constant_name PORT_INT1_bp = PORT_INT_1_bp;
+ #define PORT_INT1_bp PORT_INT_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_2_bm) && defined(PORT_INT2_bm)
+ #define PORT_INT_2_bm PORT_INT2_bm
+ #elif defined(PORT_INT_2_bm)
+ //deprecated_constant_name PORT_INT2_bm = PORT_INT_2_bm;
+ #define PORT_INT2_bm PORT_INT_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_2_bp) && defined(PORT_INT2_bp)
+ #define PORT_INT_2_bp PORT_INT2_bp
+ #elif defined(PORT_INT_2_bp)
+ //deprecated_constant_name PORT_INT2_bp = PORT_INT_2_bp;
+ #define PORT_INT2_bp PORT_INT_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_3_bm) && defined(PORT_INT3_bm)
+ #define PORT_INT_3_bm PORT_INT3_bm
+ #elif defined(PORT_INT_3_bm)
+ //deprecated_constant_name PORT_INT3_bm = PORT_INT_3_bm;
+ #define PORT_INT3_bm PORT_INT_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_3_bp) && defined(PORT_INT3_bp)
+ #define PORT_INT_3_bp PORT_INT3_bp
+ #elif defined(PORT_INT_3_bp)
+ //deprecated_constant_name PORT_INT3_bp = PORT_INT_3_bp;
+ #define PORT_INT3_bp PORT_INT_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_4_bm) && defined(PORT_INT4_bm)
+ #define PORT_INT_4_bm PORT_INT4_bm
+ #elif defined(PORT_INT_4_bm)
+ //deprecated_constant_name PORT_INT4_bm = PORT_INT_4_bm;
+ #define PORT_INT4_bm PORT_INT_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_4_bp) && defined(PORT_INT4_bp)
+ #define PORT_INT_4_bp PORT_INT4_bp
+ #elif defined(PORT_INT_4_bp)
+ //deprecated_constant_name PORT_INT4_bp = PORT_INT_4_bp;
+ #define PORT_INT4_bp PORT_INT_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_5_bm) && defined(PORT_INT5_bm)
+ #define PORT_INT_5_bm PORT_INT5_bm
+ #elif defined(PORT_INT_5_bm)
+ //deprecated_constant_name PORT_INT5_bm = PORT_INT_5_bm;
+ #define PORT_INT5_bm PORT_INT_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_5_bp) && defined(PORT_INT5_bp)
+ #define PORT_INT_5_bp PORT_INT5_bp
+ #elif defined(PORT_INT_5_bp)
+ //deprecated_constant_name PORT_INT5_bp = PORT_INT_5_bp;
+ #define PORT_INT5_bp PORT_INT_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_6_bm) && defined(PORT_INT6_bm)
+ #define PORT_INT_6_bm PORT_INT6_bm
+ #elif defined(PORT_INT_6_bm)
+ //deprecated_constant_name PORT_INT6_bm = PORT_INT_6_bm;
+ #define PORT_INT6_bm PORT_INT_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_6_bp) && defined(PORT_INT6_bp)
+ #define PORT_INT_6_bp PORT_INT6_bp
+ #elif defined(PORT_INT_6_bp)
+ //deprecated_constant_name PORT_INT6_bp = PORT_INT_6_bp;
+ #define PORT_INT6_bp PORT_INT_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_7_bm) && defined(PORT_INT7_bm)
+ #define PORT_INT_7_bm PORT_INT7_bm
+ #elif defined(PORT_INT_7_bm)
+ //deprecated_constant_name PORT_INT7_bm = PORT_INT_7_bm;
+ #define PORT_INT7_bm PORT_INT_7_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_INT_7_bp) && defined(PORT_INT7_bp)
+ #define PORT_INT_7_bp PORT_INT7_bp
+ #elif defined(PORT_INT_7_bp)
+ //deprecated_constant_name PORT_INT7_bp = PORT_INT_7_bp;
+ #define PORT_INT7_bp PORT_INT_7_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_ISC_0_bm) && defined(PORT_ISC0_bm)
+ #define PORT_ISC_0_bm PORT_ISC0_bm
+ #elif defined(PORT_ISC_0_bm)
+ //deprecated_constant_name PORT_ISC0_bm = PORT_ISC_0_bm;
+ #define PORT_ISC0_bm PORT_ISC_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_ISC_0_bp) && defined(PORT_ISC0_bp)
+ #define PORT_ISC_0_bp PORT_ISC0_bp
+ #elif defined(PORT_ISC_0_bp)
+ //deprecated_constant_name PORT_ISC0_bp = PORT_ISC_0_bp;
+ #define PORT_ISC0_bp PORT_ISC_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_ISC_1_bm) && defined(PORT_ISC1_bm)
+ #define PORT_ISC_1_bm PORT_ISC1_bm
+ #elif defined(PORT_ISC_1_bm)
+ //deprecated_constant_name PORT_ISC1_bm = PORT_ISC_1_bm;
+ #define PORT_ISC1_bm PORT_ISC_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_ISC_1_bp) && defined(PORT_ISC1_bp)
+ #define PORT_ISC_1_bp PORT_ISC1_bp
+ #elif defined(PORT_ISC_1_bp)
+ //deprecated_constant_name PORT_ISC1_bp = PORT_ISC_1_bp;
+ #define PORT_ISC1_bp PORT_ISC_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_ISC_2_bm) && defined(PORT_ISC2_bm)
+ #define PORT_ISC_2_bm PORT_ISC2_bm
+ #elif defined(PORT_ISC_2_bm)
+ //deprecated_constant_name PORT_ISC2_bm = PORT_ISC_2_bm;
+ #define PORT_ISC2_bm PORT_ISC_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORT_ISC_2_bp) && defined(PORT_ISC2_bp)
+ #define PORT_ISC_2_bp PORT_ISC2_bp
+ #elif defined(PORT_ISC_2_bp)
+ //deprecated_constant_name PORT_ISC2_bp = PORT_ISC_2_bp;
+ #define PORT_ISC2_bp PORT_ISC_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= PORTMUX ======= */
+ #if !defined(PORTMUX_USART0_0_bm) && defined(PORTMUX_USART00_bm)
+ #define PORTMUX_USART0_0_bm PORTMUX_USART00_bm
+ #elif defined(PORTMUX_USART0_0_bm)
+ //deprecated_constant_name PORTMUX_USART00_bm = PORTMUX_USART0_0_bm;
+ #define PORTMUX_USART00_bm PORTMUX_USART0_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART0_0_bp) && defined(PORTMUX_USART00_bp)
+ #define PORTMUX_USART0_0_bp PORTMUX_USART00_bp
+ #elif defined(PORTMUX_USART0_0_bp)
+ //deprecated_constant_name PORTMUX_USART00_bp = PORTMUX_USART0_0_bp;
+ #define PORTMUX_USART00_bp PORTMUX_USART0_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART0_1_bm) && defined(PORTMUX_USART01_bm)
+ #define PORTMUX_USART0_1_bm PORTMUX_USART01_bm
+ #elif defined(PORTMUX_USART0_1_bm)
+ //deprecated_constant_name PORTMUX_USART01_bm = PORTMUX_USART0_1_bm;
+ #define PORTMUX_USART01_bm PORTMUX_USART0_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART0_1_bp) && defined(PORTMUX_USART01_bp)
+ #define PORTMUX_USART0_1_bp PORTMUX_USART01_bp
+ #elif defined(PORTMUX_USART0_1_bp)
+ //deprecated_constant_name PORTMUX_USART01_bp = PORTMUX_USART0_1_bp;
+ #define PORTMUX_USART01_bp PORTMUX_USART0_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART1_0_bm) && defined(PORTMUX_USART10_bm)
+ #define PORTMUX_USART1_0_bm PORTMUX_USART10_bm
+ #elif defined(PORTMUX_USART1_0_bm)
+ //deprecated_constant_name PORTMUX_USART10_bm = PORTMUX_USART1_0_bm;
+ #define PORTMUX_USART10_bm PORTMUX_USART1_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART1_0_bp) && defined(PORTMUX_USART10_bp)
+ #define PORTMUX_USART1_0_bp PORTMUX_USART10_bp
+ #elif defined(PORTMUX_USART1_0_bp)
+ //deprecated_constant_name PORTMUX_USART10_bp = PORTMUX_USART1_0_bp;
+ #define PORTMUX_USART10_bp PORTMUX_USART1_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART1_1_bm) && defined(PORTMUX_USART11_bm)
+ #define PORTMUX_USART1_1_bm PORTMUX_USART11_bm
+ #elif defined(PORTMUX_USART1_1_bm)
+ //deprecated_constant_name PORTMUX_USART11_bm = PORTMUX_USART1_1_bm;
+ #define PORTMUX_USART11_bm PORTMUX_USART1_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART1_1_bp) && defined(PORTMUX_USART11_bp)
+ #define PORTMUX_USART1_1_bp PORTMUX_USART11_bp
+ #elif defined(PORTMUX_USART1_1_bp)
+ //deprecated_constant_name PORTMUX_USART11_bp = PORTMUX_USART1_1_bp;
+ #define PORTMUX_USART11_bp PORTMUX_USART1_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART2_0_bm) && defined(PORTMUX_USART20_bm)
+ #define PORTMUX_USART2_0_bm PORTMUX_USART20_bm
+ #elif defined(PORTMUX_USART2_0_bm)
+ //deprecated_constant_name PORTMUX_USART20_bm = PORTMUX_USART2_0_bm;
+ #define PORTMUX_USART20_bm PORTMUX_USART2_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART2_0_bp) && defined(PORTMUX_USART20_bp)
+ #define PORTMUX_USART2_0_bp PORTMUX_USART20_bp
+ #elif defined(PORTMUX_USART2_0_bp)
+ //deprecated_constant_name PORTMUX_USART20_bp = PORTMUX_USART2_0_bp;
+ #define PORTMUX_USART20_bp PORTMUX_USART2_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART2_1_bm) && defined(PORTMUX_USART21_bm)
+ #define PORTMUX_USART2_1_bm PORTMUX_USART21_bm
+ #elif defined(PORTMUX_USART2_1_bm)
+ //deprecated_constant_name PORTMUX_USART21_bm = PORTMUX_USART2_1_bm;
+ #define PORTMUX_USART21_bm PORTMUX_USART2_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART2_1_bp) && defined(PORTMUX_USART21_bp)
+ #define PORTMUX_USART2_1_bp PORTMUX_USART21_bp
+ #elif defined(PORTMUX_USART2_1_bp)
+ //deprecated_constant_name PORTMUX_USART21_bp = PORTMUX_USART2_1_bp;
+ #define PORTMUX_USART21_bp PORTMUX_USART2_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART3_0_bm) && defined(PORTMUX_USART30_bm)
+ #define PORTMUX_USART3_0_bm PORTMUX_USART30_bm
+ #elif defined(PORTMUX_USART3_0_bm)
+ //deprecated_constant_name PORTMUX_USART30_bm = PORTMUX_USART3_0_bm;
+ #define PORTMUX_USART30_bm PORTMUX_USART3_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART3_0_bp) && defined(PORTMUX_USART30_bp)
+ #define PORTMUX_USART3_0_bp PORTMUX_USART30_bp
+ #elif defined(PORTMUX_USART3_0_bp)
+ //deprecated_constant_name PORTMUX_USART30_bp = PORTMUX_USART3_0_bp;
+ #define PORTMUX_USART30_bp PORTMUX_USART3_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART3_1_bm) && defined(PORTMUX_USART31_bm)
+ #define PORTMUX_USART3_1_bm PORTMUX_USART31_bm
+ #elif defined(PORTMUX_USART3_1_bm)
+ //deprecated_constant_name PORTMUX_USART31_bm = PORTMUX_USART3_1_bm;
+ #define PORTMUX_USART31_bm PORTMUX_USART3_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART3_1_bp) && defined(PORTMUX_USART31_bp)
+ #define PORTMUX_USART3_1_bp PORTMUX_USART31_bp
+ #elif defined(PORTMUX_USART3_1_bp)
+ //deprecated_constant_name PORTMUX_USART31_bp = PORTMUX_USART3_1_bp;
+ #define PORTMUX_USART31_bp PORTMUX_USART3_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART4_0_bm) && defined(PORTMUX_USART40_bm)
+ #define PORTMUX_USART4_0_bm PORTMUX_USART40_bm
+ #elif defined(PORTMUX_USART4_0_bm)
+ //deprecated_constant_name PORTMUX_USART40_bm = PORTMUX_USART4_0_bm;
+ #define PORTMUX_USART40_bm PORTMUX_USART4_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART4_0_bp) && defined(PORTMUX_USART40_bp)
+ #define PORTMUX_USART4_0_bp PORTMUX_USART40_bp
+ #elif defined(PORTMUX_USART4_0_bp)
+ //deprecated_constant_name PORTMUX_USART40_bp = PORTMUX_USART4_0_bp;
+ #define PORTMUX_USART40_bp PORTMUX_USART4_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART4_1_bm) && defined(PORTMUX_USART41_bm)
+ #define PORTMUX_USART4_1_bm PORTMUX_USART41_bm
+ #elif defined(PORTMUX_USART4_1_bm)
+ //deprecated_constant_name PORTMUX_USART41_bm = PORTMUX_USART4_1_bm;
+ #define PORTMUX_USART41_bm PORTMUX_USART4_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART4_1_bp) && defined(PORTMUX_USART41_bp)
+ #define PORTMUX_USART4_1_bp PORTMUX_USART41_bp
+ #elif defined(PORTMUX_USART4_1_bp)
+ //deprecated_constant_name PORTMUX_USART41_bp = PORTMUX_USART4_1_bp;
+ #define PORTMUX_USART41_bp PORTMUX_USART4_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART5_0_bm) && defined(PORTMUX_USART50_bm)
+ #define PORTMUX_USART5_0_bm PORTMUX_USART50_bm
+ #elif defined(PORTMUX_USART5_0_bm)
+ //deprecated_constant_name PORTMUX_USART50_bm = PORTMUX_USART5_0_bm;
+ #define PORTMUX_USART50_bm PORTMUX_USART5_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART5_0_bp) && defined(PORTMUX_USART50_bp)
+ #define PORTMUX_USART5_0_bp PORTMUX_USART50_bp
+ #elif defined(PORTMUX_USART5_0_bp)
+ //deprecated_constant_name PORTMUX_USART50_bp = PORTMUX_USART5_0_bp;
+ #define PORTMUX_USART50_bp PORTMUX_USART5_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART5_1_bm) && defined(PORTMUX_USART51_bm)
+ #define PORTMUX_USART5_1_bm PORTMUX_USART51_bm
+ #elif defined(PORTMUX_USART5_1_bm)
+ //deprecated_constant_name PORTMUX_USART51_bm = PORTMUX_USART5_1_bm;
+ #define PORTMUX_USART51_bm PORTMUX_USART5_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_USART5_1_bp) && defined(PORTMUX_USART51_bp)
+ #define PORTMUX_USART5_1_bp PORTMUX_USART51_bp
+ #elif defined(PORTMUX_USART5_1_bp)
+ //deprecated_constant_name PORTMUX_USART51_bp = PORTMUX_USART5_1_bp;
+ #define PORTMUX_USART51_bp PORTMUX_USART5_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORTMUX_SPI0_0_bm) && defined(PORTMUX_SPI00_bm)
+ #define PORTMUX_SPI0_0_bm PORTMUX_SPI00_bm
+ #elif defined(PORTMUX_SPI0_0_bm)
+ //deprecated_constant_name PORTMUX_SPI00_bm = PORTMUX_SPI0_0_bm;
+ #define PORTMUX_SPI00_bm PORTMUX_SPI0_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_SPI0_0_bp) && defined(PORTMUX_SPI00_bp)
+ #define PORTMUX_SPI0_0_bp PORTMUX_SPI00_bp
+ #elif defined(PORTMUX_SPI0_0_bp)
+ //deprecated_constant_name PORTMUX_SPI00_bp = PORTMUX_SPI0_0_bp;
+ #define PORTMUX_SPI00_bp PORTMUX_SPI0_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_SPI0_1_bm) && defined(PORTMUX_SPI01_bm)
+ #define PORTMUX_SPI0_1_bm PORTMUX_SPI01_bm
+ #elif defined(PORTMUX_SPI0_1_bm)
+ //deprecated_constant_name PORTMUX_SPI01_bm = PORTMUX_SPI0_1_bm;
+ #define PORTMUX_SPI01_bm PORTMUX_SPI0_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_SPI0_1_bp) && defined(PORTMUX_SPI01_bp)
+ #define PORTMUX_SPI0_1_bp PORTMUX_SPI01_bp
+ #elif defined(PORTMUX_SPI0_1_bp)
+ //deprecated_constant_name PORTMUX_SPI01_bp = PORTMUX_SPI0_1_bp;
+ #define PORTMUX_SPI01_bp PORTMUX_SPI0_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_SPI1_0_bm) && defined(PORTMUX_SPI10_bm)
+ #define PORTMUX_SPI1_0_bm PORTMUX_SPI10_bm
+ #elif defined(PORTMUX_SPI1_0_bm)
+ //deprecated_constant_name PORTMUX_SPI10_bm = PORTMUX_SPI1_0_bm;
+ #define PORTMUX_SPI10_bm PORTMUX_SPI1_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_SPI1_0_bp) && defined(PORTMUX_SPI10_bp)
+ #define PORTMUX_SPI1_0_bp PORTMUX_SPI10_bp
+ #elif defined(PORTMUX_SPI1_0_bp)
+ //deprecated_constant_name PORTMUX_SPI10_bp = PORTMUX_SPI1_0_bp;
+ #define PORTMUX_SPI10_bp PORTMUX_SPI1_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_SPI1_1_bm) && defined(PORTMUX_SPI11_bm)
+ #define PORTMUX_SPI1_1_bm PORTMUX_SPI11_bm
+ #elif defined(PORTMUX_SPI1_1_bm)
+ //deprecated_constant_name PORTMUX_SPI11_bm = PORTMUX_SPI1_1_bm;
+ #define PORTMUX_SPI11_bm PORTMUX_SPI1_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_SPI1_1_bp) && defined(PORTMUX_SPI11_bp)
+ #define PORTMUX_SPI1_1_bp PORTMUX_SPI11_bp
+ #elif defined(PORTMUX_SPI1_1_bp)
+ //deprecated_constant_name PORTMUX_SPI11_bp = PORTMUX_SPI1_1_bp;
+ #define PORTMUX_SPI11_bp PORTMUX_SPI1_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORTMUX_TWI0_0_bm) && defined(PORTMUX_TWI00_bm)
+ #define PORTMUX_TWI0_0_bm PORTMUX_TWI00_bm
+ #elif defined(PORTMUX_TWI0_0_bm)
+ //deprecated_constant_name PORTMUX_TWI00_bm = PORTMUX_TWI0_0_bm;
+ #define PORTMUX_TWI00_bm PORTMUX_TWI0_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TWI0_0_bp) && defined(PORTMUX_TWI00_bp)
+ #define PORTMUX_TWI0_0_bp PORTMUX_TWI00_bp
+ #elif defined(PORTMUX_TWI0_0_bp)
+ //deprecated_constant_name PORTMUX_TWI00_bp = PORTMUX_TWI0_0_bp;
+ #define PORTMUX_TWI00_bp PORTMUX_TWI0_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TWI0_1_bm) && defined(PORTMUX_TWI01_bm)
+ #define PORTMUX_TWI0_1_bm PORTMUX_TWI01_bm
+ #elif defined(PORTMUX_TWI0_1_bm)
+ //deprecated_constant_name PORTMUX_TWI01_bm = PORTMUX_TWI0_1_bm;
+ #define PORTMUX_TWI01_bm PORTMUX_TWI0_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TWI0_1_bp) && defined(PORTMUX_TWI01_bp)
+ #define PORTMUX_TWI0_1_bp PORTMUX_TWI01_bp
+ #elif defined(PORTMUX_TWI0_1_bp)
+ //deprecated_constant_name PORTMUX_TWI01_bp = PORTMUX_TWI0_1_bp;
+ #define PORTMUX_TWI01_bp PORTMUX_TWI0_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TWI1_0_bm) && defined(PORTMUX_TWI10_bm)
+ #define PORTMUX_TWI1_0_bm PORTMUX_TWI10_bm
+ #elif defined(PORTMUX_TWI1_0_bm)
+ //deprecated_constant_name PORTMUX_TWI10_bm = PORTMUX_TWI1_0_bm;
+ #define PORTMUX_TWI10_bm PORTMUX_TWI1_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TWI1_0_bp) && defined(PORTMUX_TWI10_bp)
+ #define PORTMUX_TWI1_0_bp PORTMUX_TWI10_bp
+ #elif defined(PORTMUX_TWI1_0_bp)
+ //deprecated_constant_name PORTMUX_TWI10_bp = PORTMUX_TWI1_0_bp;
+ #define PORTMUX_TWI10_bp PORTMUX_TWI1_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TWI1_1_bm) && defined(PORTMUX_TWI11_bm)
+ #define PORTMUX_TWI1_1_bm PORTMUX_TWI11_bm
+ #elif defined(PORTMUX_TWI1_1_bm)
+ //deprecated_constant_name PORTMUX_TWI11_bm = PORTMUX_TWI1_1_bm;
+ #define PORTMUX_TWI11_bm PORTMUX_TWI1_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TWI1_1_bp) && defined(PORTMUX_TWI11_bp)
+ #define PORTMUX_TWI1_1_bp PORTMUX_TWI11_bp
+ #elif defined(PORTMUX_TWI1_1_bp)
+ //deprecated_constant_name PORTMUX_TWI11_bp = PORTMUX_TWI1_1_bp;
+ #define PORTMUX_TWI11_bp PORTMUX_TWI1_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORTMUX_TCA0_0_bm) && defined(PORTMUX_TCA00_bm)
+ #define PORTMUX_TCA0_0_bm PORTMUX_TCA00_bm
+ #elif defined(PORTMUX_TCA0_0_bm)
+ //deprecated_constant_name PORTMUX_TCA00_bm = PORTMUX_TCA0_0_bm;
+ #define PORTMUX_TCA00_bm PORTMUX_TCA0_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA0_0_bp) && defined(PORTMUX_TCA00_bp)
+ #define PORTMUX_TCA0_0_bp PORTMUX_TCA00_bp
+ #elif defined(PORTMUX_TCA0_0_bp)
+ //deprecated_constant_name PORTMUX_TCA00_bp = PORTMUX_TCA0_0_bp;
+ #define PORTMUX_TCA00_bp PORTMUX_TCA0_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA0_1_bm) && defined(PORTMUX_TCA01_bm)
+ #define PORTMUX_TCA0_1_bm PORTMUX_TCA01_bm
+ #elif defined(PORTMUX_TCA0_1_bm)
+ //deprecated_constant_name PORTMUX_TCA01_bm = PORTMUX_TCA0_1_bm;
+ #define PORTMUX_TCA01_bm PORTMUX_TCA0_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA0_1_bp) && defined(PORTMUX_TCA01_bp)
+ #define PORTMUX_TCA0_1_bp PORTMUX_TCA01_bp
+ #elif defined(PORTMUX_TCA0_1_bp)
+ //deprecated_constant_name PORTMUX_TCA01_bp = PORTMUX_TCA0_1_bp;
+ #define PORTMUX_TCA01_bp PORTMUX_TCA0_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA0_2_bm) && defined(PORTMUX_TCA02_bm)
+ #define PORTMUX_TCA0_2_bm PORTMUX_TCA02_bm
+ #elif defined(PORTMUX_TCA0_2_bm)
+ //deprecated_constant_name PORTMUX_TCA02_bm = PORTMUX_TCA0_2_bm;
+ #define PORTMUX_TCA02_bm PORTMUX_TCA0_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA0_2_bp) && defined(PORTMUX_TCA02_bp)
+ #define PORTMUX_TCA0_2_bp PORTMUX_TCA02_bp
+ #elif defined(PORTMUX_TCA0_2_bp)
+ //deprecated_constant_name PORTMUX_TCA02_bp = PORTMUX_TCA0_2_bp;
+ #define PORTMUX_TCA02_bp PORTMUX_TCA0_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA1_0_bm) && defined(PORTMUX_TCA10_bm)
+ #define PORTMUX_TCA1_0_bm PORTMUX_TCA10_bm
+ #elif defined(PORTMUX_TCA1_0_bm)
+ //deprecated_constant_name PORTMUX_TCA10_bm = PORTMUX_TCA1_0_bm;
+ #define PORTMUX_TCA10_bm PORTMUX_TCA1_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA1_0_bp) && defined(PORTMUX_TCA10_bp)
+ #define PORTMUX_TCA1_0_bp PORTMUX_TCA10_bp
+ #elif defined(PORTMUX_TCA1_0_bp)
+ //deprecated_constant_name PORTMUX_TCA10_bp = PORTMUX_TCA1_0_bp;
+ #define PORTMUX_TCA10_bp PORTMUX_TCA1_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA1_1_bm) && defined(PORTMUX_TCA11_bm)
+ #define PORTMUX_TCA1_1_bm PORTMUX_TCA11_bm
+ #elif defined(PORTMUX_TCA1_1_bm)
+ //deprecated_constant_name PORTMUX_TCA11_bm = PORTMUX_TCA1_1_bm;
+ #define PORTMUX_TCA11_bm PORTMUX_TCA1_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA1_1_bp) && defined(PORTMUX_TCA11_bp)
+ #define PORTMUX_TCA1_1_bp PORTMUX_TCA11_bp
+ #elif defined(PORTMUX_TCA1_1_bp)
+ //deprecated_constant_name PORTMUX_TCA11_bp = PORTMUX_TCA1_1_bp;
+ #define PORTMUX_TCA11_bp PORTMUX_TCA1_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA1_2_bm) && defined(PORTMUX_TCA12_bm)
+ #define PORTMUX_TCA1_2_bm PORTMUX_TCA12_bm
+ #elif defined(PORTMUX_TCA1_2_bm)
+ //deprecated_constant_name PORTMUX_TCA12_bm = PORTMUX_TCA1_2_bm;
+ #define PORTMUX_TCA12_bm PORTMUX_TCA1_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCA1_2_bp) && defined(PORTMUX_TCA12_bp)
+ #define PORTMUX_TCA1_2_bp PORTMUX_TCA12_bp
+ #elif defined(PORTMUX_TCA1_2_bp)
+ //deprecated_constant_name PORTMUX_TCA12_bp = PORTMUX_TCA1_2_bp;
+ #define PORTMUX_TCA12_bp PORTMUX_TCA1_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(PORTMUX_TCD0_0_bm) && defined(PORTMUX_TCD00_bm)
+ #define PORTMUX_TCD0_0_bm PORTMUX_TCD00_bm
+ #elif defined(PORTMUX_TCD0_0_bm)
+ //deprecated_constant_name PORTMUX_TCD00_bm = PORTMUX_TCD0_0_bm;
+ #define PORTMUX_TCD00_bm PORTMUX_TCD0_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCD0_0_bp) && defined(PORTMUX_TCD00_bp)
+ #define PORTMUX_TCD0_0_bp PORTMUX_TCD00_bp
+ #elif defined(PORTMUX_TCD0_0_bp)
+ //deprecated_constant_name PORTMUX_TCD00_bp = PORTMUX_TCD0_0_bp;
+ #define PORTMUX_TCD00_bp PORTMUX_TCD0_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCD0_1_bm) && defined(PORTMUX_TCD01_bm)
+ #define PORTMUX_TCD0_1_bm PORTMUX_TCD01_bm
+ #elif defined(PORTMUX_TCD0_1_bm)
+ //deprecated_constant_name PORTMUX_TCD01_bm = PORTMUX_TCD0_1_bm;
+ #define PORTMUX_TCD01_bm PORTMUX_TCD0_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCD0_1_bp) && defined(PORTMUX_TCD01_bp)
+ #define PORTMUX_TCD0_1_bp PORTMUX_TCD01_bp
+ #elif defined(PORTMUX_TCD0_1_bp)
+ //deprecated_constant_name PORTMUX_TCD01_bp = PORTMUX_TCD0_1_bp;
+ #define PORTMUX_TCD01_bp PORTMUX_TCD0_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCD0_2_bm) && defined(PORTMUX_TCD02_bm)
+ #define PORTMUX_TCD0_2_bm PORTMUX_TCD02_bm
+ #elif defined(PORTMUX_TCD0_2_bm)
+ //deprecated_constant_name PORTMUX_TCD02_bm = PORTMUX_TCD0_2_bm;
+ #define PORTMUX_TCD02_bm PORTMUX_TCD0_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(PORTMUX_TCD0_2_bp) && defined(PORTMUX_TCD02_bp)
+ #define PORTMUX_TCD0_2_bp PORTMUX_TCD02_bp
+ #elif defined(PORTMUX_TCD0_2_bp)
+ //deprecated_constant_name PORTMUX_TCD02_bp = PORTMUX_TCD0_2_bp;
+ #define PORTMUX_TCD02_bp PORTMUX_TCD0_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= RTC ======= */
+ #if !defined(RTC_PRESCALER_0_bm) && defined(RTC_PRESCALER0_bm)
+ #define RTC_PRESCALER_0_bm RTC_PRESCALER0_bm
+ #elif defined(RTC_PRESCALER_0_bm)
+ //deprecated_constant_name RTC_PRESCALER0_bm = RTC_PRESCALER_0_bm;
+ #define RTC_PRESCALER0_bm RTC_PRESCALER_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PRESCALER_0_bp) && defined(RTC_PRESCALER0_bp)
+ #define RTC_PRESCALER_0_bp RTC_PRESCALER0_bp
+ #elif defined(RTC_PRESCALER_0_bp)
+ //deprecated_constant_name RTC_PRESCALER0_bp = RTC_PRESCALER_0_bp;
+ #define RTC_PRESCALER0_bp RTC_PRESCALER_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PRESCALER_1_bm) && defined(RTC_PRESCALER1_bm)
+ #define RTC_PRESCALER_1_bm RTC_PRESCALER1_bm
+ #elif defined(RTC_PRESCALER_1_bm)
+ //deprecated_constant_name RTC_PRESCALER1_bm = RTC_PRESCALER_1_bm;
+ #define RTC_PRESCALER1_bm RTC_PRESCALER_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PRESCALER_1_bp) && defined(RTC_PRESCALER1_bp)
+ #define RTC_PRESCALER_1_bp RTC_PRESCALER1_bp
+ #elif defined(RTC_PRESCALER_1_bp)
+ //deprecated_constant_name RTC_PRESCALER1_bp = RTC_PRESCALER_1_bp;
+ #define RTC_PRESCALER1_bp RTC_PRESCALER_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PRESCALER_2_bm) && defined(RTC_PRESCALER2_bm)
+ #define RTC_PRESCALER_2_bm RTC_PRESCALER2_bm
+ #elif defined(RTC_PRESCALER_2_bm)
+ //deprecated_constant_name RTC_PRESCALER2_bm = RTC_PRESCALER_2_bm;
+ #define RTC_PRESCALER2_bm RTC_PRESCALER_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PRESCALER_2_bp) && defined(RTC_PRESCALER2_bp)
+ #define RTC_PRESCALER_2_bp RTC_PRESCALER2_bp
+ #elif defined(RTC_PRESCALER_2_bp)
+ //deprecated_constant_name RTC_PRESCALER2_bp = RTC_PRESCALER_2_bp;
+ #define RTC_PRESCALER2_bp RTC_PRESCALER_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PRESCALER_3_bm) && defined(RTC_PRESCALER3_bm)
+ #define RTC_PRESCALER_3_bm RTC_PRESCALER3_bm
+ #elif defined(RTC_PRESCALER_3_bm)
+ //deprecated_constant_name RTC_PRESCALER3_bm = RTC_PRESCALER_3_bm;
+ #define RTC_PRESCALER3_bm RTC_PRESCALER_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PRESCALER_3_bp) && defined(RTC_PRESCALER3_bp)
+ #define RTC_PRESCALER_3_bp RTC_PRESCALER3_bp
+ #elif defined(RTC_PRESCALER_3_bp)
+ //deprecated_constant_name RTC_PRESCALER3_bp = RTC_PRESCALER_3_bp;
+ #define RTC_PRESCALER3_bp RTC_PRESCALER_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(RTC_ERROR_0_bm) && defined(RTC_ERROR0_bm)
+ #define RTC_ERROR_0_bm RTC_ERROR0_bm
+ #elif defined(RTC_ERROR_0_bm)
+ //deprecated_constant_name RTC_ERROR0_bm = RTC_ERROR_0_bm;
+ #define RTC_ERROR0_bm RTC_ERROR_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_0_bp) && defined(RTC_ERROR0_bp)
+ #define RTC_ERROR_0_bp RTC_ERROR0_bp
+ #elif defined(RTC_ERROR_0_bp)
+ //deprecated_constant_name RTC_ERROR0_bp = RTC_ERROR_0_bp;
+ #define RTC_ERROR0_bp RTC_ERROR_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_1_bm) && defined(RTC_ERROR1_bm)
+ #define RTC_ERROR_1_bm RTC_ERROR1_bm
+ #elif defined(RTC_ERROR_1_bm)
+ //deprecated_constant_name RTC_ERROR1_bm = RTC_ERROR_1_bm;
+ #define RTC_ERROR1_bm RTC_ERROR_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_1_bp) && defined(RTC_ERROR1_bp)
+ #define RTC_ERROR_1_bp RTC_ERROR1_bp
+ #elif defined(RTC_ERROR_1_bp)
+ //deprecated_constant_name RTC_ERROR1_bp = RTC_ERROR_1_bp;
+ #define RTC_ERROR1_bp RTC_ERROR_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_2_bm) && defined(RTC_ERROR2_bm)
+ #define RTC_ERROR_2_bm RTC_ERROR2_bm
+ #elif defined(RTC_ERROR_2_bm)
+ //deprecated_constant_name RTC_ERROR2_bm = RTC_ERROR_2_bm;
+ #define RTC_ERROR2_bm RTC_ERROR_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_2_bp) && defined(RTC_ERROR2_bp)
+ #define RTC_ERROR_2_bp RTC_ERROR2_bp
+ #elif defined(RTC_ERROR_2_bp)
+ //deprecated_constant_name RTC_ERROR2_bp = RTC_ERROR_2_bp;
+ #define RTC_ERROR2_bp RTC_ERROR_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_3_bm) && defined(RTC_ERROR3_bm)
+ #define RTC_ERROR_3_bm RTC_ERROR3_bm
+ #elif defined(RTC_ERROR_3_bm)
+ //deprecated_constant_name RTC_ERROR3_bm = RTC_ERROR_3_bm;
+ #define RTC_ERROR3_bm RTC_ERROR_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_3_bp) && defined(RTC_ERROR3_bp)
+ #define RTC_ERROR_3_bp RTC_ERROR3_bp
+ #elif defined(RTC_ERROR_3_bp)
+ //deprecated_constant_name RTC_ERROR3_bp = RTC_ERROR_3_bp;
+ #define RTC_ERROR3_bp RTC_ERROR_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_4_bm) && defined(RTC_ERROR4_bm)
+ #define RTC_ERROR_4_bm RTC_ERROR4_bm
+ #elif defined(RTC_ERROR_4_bm)
+ //deprecated_constant_name RTC_ERROR4_bm = RTC_ERROR_4_bm;
+ #define RTC_ERROR4_bm RTC_ERROR_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_4_bp) && defined(RTC_ERROR4_bp)
+ #define RTC_ERROR_4_bp RTC_ERROR4_bp
+ #elif defined(RTC_ERROR_4_bp)
+ //deprecated_constant_name RTC_ERROR4_bp = RTC_ERROR_4_bp;
+ #define RTC_ERROR4_bp RTC_ERROR_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_5_bm) && defined(RTC_ERROR5_bm)
+ #define RTC_ERROR_5_bm RTC_ERROR5_bm
+ #elif defined(RTC_ERROR_5_bm)
+ //deprecated_constant_name RTC_ERROR5_bm = RTC_ERROR_5_bm;
+ #define RTC_ERROR5_bm RTC_ERROR_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_5_bp) && defined(RTC_ERROR5_bp)
+ #define RTC_ERROR_5_bp RTC_ERROR5_bp
+ #elif defined(RTC_ERROR_5_bp)
+ //deprecated_constant_name RTC_ERROR5_bp = RTC_ERROR_5_bp;
+ #define RTC_ERROR5_bp RTC_ERROR_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_6_bm) && defined(RTC_ERROR6_bm)
+ #define RTC_ERROR_6_bm RTC_ERROR6_bm
+ #elif defined(RTC_ERROR_6_bm)
+ //deprecated_constant_name RTC_ERROR6_bm = RTC_ERROR_6_bm;
+ #define RTC_ERROR6_bm RTC_ERROR_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_ERROR_6_bp) && defined(RTC_ERROR6_bp)
+ #define RTC_ERROR_6_bp RTC_ERROR6_bp
+ #elif defined(RTC_ERROR_6_bp)
+ //deprecated_constant_name RTC_ERROR6_bp = RTC_ERROR_6_bp;
+ #define RTC_ERROR6_bp RTC_ERROR_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(RTC_CLKSEL_0_bm) && defined(RTC_CLKSEL0_bm)
+ #define RTC_CLKSEL_0_bm RTC_CLKSEL0_bm
+ #elif defined(RTC_CLKSEL_0_bm)
+ //deprecated_constant_name RTC_CLKSEL0_bm = RTC_CLKSEL_0_bm;
+ #define RTC_CLKSEL0_bm RTC_CLKSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_CLKSEL_0_bp) && defined(RTC_CLKSEL0_bp)
+ #define RTC_CLKSEL_0_bp RTC_CLKSEL0_bp
+ #elif defined(RTC_CLKSEL_0_bp)
+ //deprecated_constant_name RTC_CLKSEL0_bp = RTC_CLKSEL_0_bp;
+ #define RTC_CLKSEL0_bp RTC_CLKSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_CLKSEL_1_bm) && defined(RTC_CLKSEL1_bm)
+ #define RTC_CLKSEL_1_bm RTC_CLKSEL1_bm
+ #elif defined(RTC_CLKSEL_1_bm)
+ //deprecated_constant_name RTC_CLKSEL1_bm = RTC_CLKSEL_1_bm;
+ #define RTC_CLKSEL1_bm RTC_CLKSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_CLKSEL_1_bp) && defined(RTC_CLKSEL1_bp)
+ #define RTC_CLKSEL_1_bp RTC_CLKSEL1_bp
+ #elif defined(RTC_CLKSEL_1_bp)
+ //deprecated_constant_name RTC_CLKSEL1_bp = RTC_CLKSEL_1_bp;
+ #define RTC_CLKSEL1_bp RTC_CLKSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(RTC_PERIOD_0_bm) && defined(RTC_PERIOD0_bm)
+ #define RTC_PERIOD_0_bm RTC_PERIOD0_bm
+ #elif defined(RTC_PERIOD_0_bm)
+ //deprecated_constant_name RTC_PERIOD0_bm = RTC_PERIOD_0_bm;
+ #define RTC_PERIOD0_bm RTC_PERIOD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PERIOD_0_bp) && defined(RTC_PERIOD0_bp)
+ #define RTC_PERIOD_0_bp RTC_PERIOD0_bp
+ #elif defined(RTC_PERIOD_0_bp)
+ //deprecated_constant_name RTC_PERIOD0_bp = RTC_PERIOD_0_bp;
+ #define RTC_PERIOD0_bp RTC_PERIOD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PERIOD_1_bm) && defined(RTC_PERIOD1_bm)
+ #define RTC_PERIOD_1_bm RTC_PERIOD1_bm
+ #elif defined(RTC_PERIOD_1_bm)
+ //deprecated_constant_name RTC_PERIOD1_bm = RTC_PERIOD_1_bm;
+ #define RTC_PERIOD1_bm RTC_PERIOD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PERIOD_1_bp) && defined(RTC_PERIOD1_bp)
+ #define RTC_PERIOD_1_bp RTC_PERIOD1_bp
+ #elif defined(RTC_PERIOD_1_bp)
+ //deprecated_constant_name RTC_PERIOD1_bp = RTC_PERIOD_1_bp;
+ #define RTC_PERIOD1_bp RTC_PERIOD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PERIOD_2_bm) && defined(RTC_PERIOD2_bm)
+ #define RTC_PERIOD_2_bm RTC_PERIOD2_bm
+ #elif defined(RTC_PERIOD_2_bm)
+ //deprecated_constant_name RTC_PERIOD2_bm = RTC_PERIOD_2_bm;
+ #define RTC_PERIOD2_bm RTC_PERIOD_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PERIOD_2_bp) && defined(RTC_PERIOD2_bp)
+ #define RTC_PERIOD_2_bp RTC_PERIOD2_bp
+ #elif defined(RTC_PERIOD_2_bp)
+ //deprecated_constant_name RTC_PERIOD2_bp = RTC_PERIOD_2_bp;
+ #define RTC_PERIOD2_bp RTC_PERIOD_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PERIOD_3_bm) && defined(RTC_PERIOD3_bm)
+ #define RTC_PERIOD_3_bm RTC_PERIOD3_bm
+ #elif defined(RTC_PERIOD_3_bm)
+ //deprecated_constant_name RTC_PERIOD3_bm = RTC_PERIOD_3_bm;
+ #define RTC_PERIOD3_bm RTC_PERIOD_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(RTC_PERIOD_3_bp) && defined(RTC_PERIOD3_bp)
+ #define RTC_PERIOD_3_bp RTC_PERIOD3_bp
+ #elif defined(RTC_PERIOD_3_bp)
+ //deprecated_constant_name RTC_PERIOD3_bp = RTC_PERIOD_3_bp;
+ #define RTC_PERIOD3_bp RTC_PERIOD_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= SLPCTRL ======= */
+ #if !defined(SLPCTRL_SMODE_0_bm) && defined(SLPCTRL_SMODE0_bm)
+ #define SLPCTRL_SMODE_0_bm SLPCTRL_SMODE0_bm
+ #elif defined(SLPCTRL_SMODE_0_bm)
+ //deprecated_constant_name SLPCTRL_SMODE0_bm = SLPCTRL_SMODE_0_bm;
+ #define SLPCTRL_SMODE0_bm SLPCTRL_SMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_SMODE_0_bp) && defined(SLPCTRL_SMODE0_bp)
+ #define SLPCTRL_SMODE_0_bp SLPCTRL_SMODE0_bp
+ #elif defined(SLPCTRL_SMODE_0_bp)
+ //deprecated_constant_name SLPCTRL_SMODE0_bp = SLPCTRL_SMODE_0_bp;
+ #define SLPCTRL_SMODE0_bp SLPCTRL_SMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_SMODE_1_bm) && defined(SLPCTRL_SMODE1_bm)
+ #define SLPCTRL_SMODE_1_bm SLPCTRL_SMODE1_bm
+ #elif defined(SLPCTRL_SMODE_1_bm)
+ //deprecated_constant_name SLPCTRL_SMODE1_bm = SLPCTRL_SMODE_1_bm;
+ #define SLPCTRL_SMODE1_bm SLPCTRL_SMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_SMODE_1_bp) && defined(SLPCTRL_SMODE1_bp)
+ #define SLPCTRL_SMODE_1_bp SLPCTRL_SMODE1_bp
+ #elif defined(SLPCTRL_SMODE_1_bp)
+ //deprecated_constant_name SLPCTRL_SMODE1_bp = SLPCTRL_SMODE_1_bp;
+ #define SLPCTRL_SMODE1_bp SLPCTRL_SMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_PMODE_0_bm) && defined(SLPCTRL_PMODE0_bm)
+ #define SLPCTRL_PMODE_0_bm SLPCTRL_PMODE0_bm
+ #elif defined(SLPCTRL_PMODE_0_bm)
+ //deprecated_constant_name SLPCTRL_PMODE0_bm = SLPCTRL_PMODE_0_bm;
+ #define SLPCTRL_PMODE0_bm SLPCTRL_PMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_PMODE_0_bp) && defined(SLPCTRL_PMODE0_bp)
+ #define SLPCTRL_PMODE_0_bp SLPCTRL_PMODE0_bp
+ #elif defined(SLPCTRL_PMODE_0_bp)
+ //deprecated_constant_name SLPCTRL_PMODE0_bp = SLPCTRL_PMODE_0_bp;
+ #define SLPCTRL_PMODE0_bp SLPCTRL_PMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_PMODE_1_bm) && defined(SLPCTRL_PMODE1_bm)
+ #define SLPCTRL_PMODE_1_bm SLPCTRL_PMODE1_bm
+ #elif defined(SLPCTRL_PMODE_1_bm)
+ //deprecated_constant_name SLPCTRL_PMODE1_bm = SLPCTRL_PMODE_1_bm;
+ #define SLPCTRL_PMODE1_bm SLPCTRL_PMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_PMODE_1_bp) && defined(SLPCTRL_PMODE1_bp)
+ #define SLPCTRL_PMODE_1_bp SLPCTRL_PMODE1_bp
+ #elif defined(SLPCTRL_PMODE_1_bp)
+ //deprecated_constant_name SLPCTRL_PMODE1_bp = SLPCTRL_PMODE_1_bp;
+ #define SLPCTRL_PMODE1_bp SLPCTRL_PMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_PMODE_2_bm) && defined(SLPCTRL_PMODE2_bm)
+ #define SLPCTRL_PMODE_2_bm SLPCTRL_PMODE2_bm
+ #elif defined(SLPCTRL_PMODE_2_bm)
+ //deprecated_constant_name SLPCTRL_PMODE2_bm = SLPCTRL_PMODE_2_bm;
+ #define SLPCTRL_PMODE2_bm SLPCTRL_PMODE_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SLPCTRL_PMODE_2_bp) && defined(SLPCTRL_PMODE2_bp)
+ #define SLPCTRL_PMODE_2_bp SLPCTRL_PMODE2_bp
+ #elif defined(SLPCTRL_PMODE_2_bp)
+ //deprecated_constant_name SLPCTRL_PMODE2_bp = SLPCTRL_PMODE_2_bp;
+ #define SLPCTRL_PMODE2_bp SLPCTRL_PMODE_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= SPI ======= */
+ #if !defined(SPI_PRESC_0_bm) && defined(SPI_PRESC0_bm)
+ #define SPI_PRESC_0_bm SPI_PRESC0_bm
+ #elif defined(SPI_PRESC_0_bm)
+ //deprecated_constant_name SPI_PRESC0_bm = SPI_PRESC_0_bm;
+ #define SPI_PRESC0_bm SPI_PRESC_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SPI_PRESC_0_bp) && defined(SPI_PRESC0_bp)
+ #define SPI_PRESC_0_bp SPI_PRESC0_bp
+ #elif defined(SPI_PRESC_0_bp)
+ //deprecated_constant_name SPI_PRESC0_bp = SPI_PRESC_0_bp;
+ #define SPI_PRESC0_bp SPI_PRESC_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SPI_PRESC_1_bm) && defined(SPI_PRESC1_bm)
+ #define SPI_PRESC_1_bm SPI_PRESC1_bm
+ #elif defined(SPI_PRESC_1_bm)
+ //deprecated_constant_name SPI_PRESC1_bm = SPI_PRESC_1_bm;
+ #define SPI_PRESC1_bm SPI_PRESC_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SPI_PRESC_1_bp) && defined(SPI_PRESC1_bp)
+ #define SPI_PRESC_1_bp SPI_PRESC1_bp
+ #elif defined(SPI_PRESC_1_bp)
+ //deprecated_constant_name SPI_PRESC1_bp = SPI_PRESC_1_bp;
+ #define SPI_PRESC1_bp SPI_PRESC_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(SPI_MODE_0_bm) && defined(SPI_MODE0_bm)
+ #define SPI_MODE_0_bm SPI_MODE0_bm
+ #elif defined(SPI_MODE_0_bm)
+ //deprecated_constant_name SPI_MODE0_bm = SPI_MODE_0_bm;
+ #define SPI_MODE0_bm SPI_MODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SPI_MODE_0_bp) && defined(SPI_MODE0_bp)
+ #define SPI_MODE_0_bp SPI_MODE0_bp
+ #elif defined(SPI_MODE_0_bp)
+ //deprecated_constant_name SPI_MODE0_bp = SPI_MODE_0_bp;
+ #define SPI_MODE0_bp SPI_MODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SPI_MODE_1_bm) && defined(SPI_MODE1_bm)
+ #define SPI_MODE_1_bm SPI_MODE1_bm
+ #elif defined(SPI_MODE_1_bm)
+ //deprecated_constant_name SPI_MODE1_bm = SPI_MODE_1_bm;
+ #define SPI_MODE1_bm SPI_MODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(SPI_MODE_1_bp) && defined(SPI_MODE1_bp)
+ #define SPI_MODE_1_bp SPI_MODE1_bp
+ #elif defined(SPI_MODE_1_bp)
+ //deprecated_constant_name SPI_MODE1_bp = SPI_MODE_1_bp;
+ #define SPI_MODE1_bp SPI_MODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= TCA ======= */
+ #if !defined(TCA_SINGLE_CLKSEL_0_bm) && defined(TCA_SINGLE_CLKSEL0_bm)
+ #define TCA_SINGLE_CLKSEL_0_bm TCA_SINGLE_CLKSEL0_bm
+ #elif defined(TCA_SINGLE_CLKSEL_0_bm)
+ //deprecated_constant_name TCA_SINGLE_CLKSEL0_bm = TCA_SINGLE_CLKSEL_0_bm;
+ #define TCA_SINGLE_CLKSEL0_bm TCA_SINGLE_CLKSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CLKSEL_0_bp) && defined(TCA_SINGLE_CLKSEL0_bp)
+ #define TCA_SINGLE_CLKSEL_0_bp TCA_SINGLE_CLKSEL0_bp
+ #elif defined(TCA_SINGLE_CLKSEL_0_bp)
+ //deprecated_constant_name TCA_SINGLE_CLKSEL0_bp = TCA_SINGLE_CLKSEL_0_bp;
+ #define TCA_SINGLE_CLKSEL0_bp TCA_SINGLE_CLKSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CLKSEL_1_bm) && defined(TCA_SINGLE_CLKSEL1_bm)
+ #define TCA_SINGLE_CLKSEL_1_bm TCA_SINGLE_CLKSEL1_bm
+ #elif defined(TCA_SINGLE_CLKSEL_1_bm)
+ //deprecated_constant_name TCA_SINGLE_CLKSEL1_bm = TCA_SINGLE_CLKSEL_1_bm;
+ #define TCA_SINGLE_CLKSEL1_bm TCA_SINGLE_CLKSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CLKSEL_1_bp) && defined(TCA_SINGLE_CLKSEL1_bp)
+ #define TCA_SINGLE_CLKSEL_1_bp TCA_SINGLE_CLKSEL1_bp
+ #elif defined(TCA_SINGLE_CLKSEL_1_bp)
+ //deprecated_constant_name TCA_SINGLE_CLKSEL1_bp = TCA_SINGLE_CLKSEL_1_bp;
+ #define TCA_SINGLE_CLKSEL1_bp TCA_SINGLE_CLKSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CLKSEL_2_bm) && defined(TCA_SINGLE_CLKSEL2_bm)
+ #define TCA_SINGLE_CLKSEL_2_bm TCA_SINGLE_CLKSEL2_bm
+ #elif defined(TCA_SINGLE_CLKSEL_2_bm)
+ //deprecated_constant_name TCA_SINGLE_CLKSEL2_bm = TCA_SINGLE_CLKSEL_2_bm;
+ #define TCA_SINGLE_CLKSEL2_bm TCA_SINGLE_CLKSEL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CLKSEL_2_bp) && defined(TCA_SINGLE_CLKSEL2_bp)
+ #define TCA_SINGLE_CLKSEL_2_bp TCA_SINGLE_CLKSEL2_bp
+ #elif defined(TCA_SINGLE_CLKSEL_2_bp)
+ //deprecated_constant_name TCA_SINGLE_CLKSEL2_bp = TCA_SINGLE_CLKSEL_2_bp;
+ #define TCA_SINGLE_CLKSEL2_bp TCA_SINGLE_CLKSEL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCA_SINGLE_WGMODE_0_bm) && defined(TCA_SINGLE_WGMODE0_bm)
+ #define TCA_SINGLE_WGMODE_0_bm TCA_SINGLE_WGMODE0_bm
+ #elif defined(TCA_SINGLE_WGMODE_0_bm)
+ //deprecated_constant_name TCA_SINGLE_WGMODE0_bm = TCA_SINGLE_WGMODE_0_bm;
+ #define TCA_SINGLE_WGMODE0_bm TCA_SINGLE_WGMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_WGMODE_0_bp) && defined(TCA_SINGLE_WGMODE0_bp)
+ #define TCA_SINGLE_WGMODE_0_bp TCA_SINGLE_WGMODE0_bp
+ #elif defined(TCA_SINGLE_WGMODE_0_bp)
+ //deprecated_constant_name TCA_SINGLE_WGMODE0_bp = TCA_SINGLE_WGMODE_0_bp;
+ #define TCA_SINGLE_WGMODE0_bp TCA_SINGLE_WGMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_WGMODE_1_bm) && defined(TCA_SINGLE_WGMODE1_bm)
+ #define TCA_SINGLE_WGMODE_1_bm TCA_SINGLE_WGMODE1_bm
+ #elif defined(TCA_SINGLE_WGMODE_1_bm)
+ //deprecated_constant_name TCA_SINGLE_WGMODE1_bm = TCA_SINGLE_WGMODE_1_bm;
+ #define TCA_SINGLE_WGMODE1_bm TCA_SINGLE_WGMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_WGMODE_1_bp) && defined(TCA_SINGLE_WGMODE1_bp)
+ #define TCA_SINGLE_WGMODE_1_bp TCA_SINGLE_WGMODE1_bp
+ #elif defined(TCA_SINGLE_WGMODE_1_bp)
+ //deprecated_constant_name TCA_SINGLE_WGMODE1_bp = TCA_SINGLE_WGMODE_1_bp;
+ #define TCA_SINGLE_WGMODE1_bp TCA_SINGLE_WGMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_WGMODE_2_bm) && defined(TCA_SINGLE_WGMODE2_bm)
+ #define TCA_SINGLE_WGMODE_2_bm TCA_SINGLE_WGMODE2_bm
+ #elif defined(TCA_SINGLE_WGMODE_2_bm)
+ //deprecated_constant_name TCA_SINGLE_WGMODE2_bm = TCA_SINGLE_WGMODE_2_bm;
+ #define TCA_SINGLE_WGMODE2_bm TCA_SINGLE_WGMODE_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_WGMODE_2_bp) && defined(TCA_SINGLE_WGMODE2_bp)
+ #define TCA_SINGLE_WGMODE_2_bp TCA_SINGLE_WGMODE2_bp
+ #elif defined(TCA_SINGLE_WGMODE_2_bp)
+ //deprecated_constant_name TCA_SINGLE_WGMODE2_bp = TCA_SINGLE_WGMODE_2_bp;
+ #define TCA_SINGLE_WGMODE2_bp TCA_SINGLE_WGMODE_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCA_SINGLE_CMD_0_bm) && defined(TCA_SINGLE_CMD0_bm)
+ #define TCA_SINGLE_CMD_0_bm TCA_SINGLE_CMD0_bm
+ #elif defined(TCA_SINGLE_CMD_0_bm)
+ //deprecated_constant_name TCA_SINGLE_CMD0_bm = TCA_SINGLE_CMD_0_bm;
+ #define TCA_SINGLE_CMD0_bm TCA_SINGLE_CMD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CMD_0_bp) && defined(TCA_SINGLE_CMD0_bp)
+ #define TCA_SINGLE_CMD_0_bp TCA_SINGLE_CMD0_bp
+ #elif defined(TCA_SINGLE_CMD_0_bp)
+ //deprecated_constant_name TCA_SINGLE_CMD0_bp = TCA_SINGLE_CMD_0_bp;
+ #define TCA_SINGLE_CMD0_bp TCA_SINGLE_CMD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CMD_1_bm) && defined(TCA_SINGLE_CMD1_bm)
+ #define TCA_SINGLE_CMD_1_bm TCA_SINGLE_CMD1_bm
+ #elif defined(TCA_SINGLE_CMD_1_bm)
+ //deprecated_constant_name TCA_SINGLE_CMD1_bm = TCA_SINGLE_CMD_1_bm;
+ #define TCA_SINGLE_CMD1_bm TCA_SINGLE_CMD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_CMD_1_bp) && defined(TCA_SINGLE_CMD1_bp)
+ #define TCA_SINGLE_CMD_1_bp TCA_SINGLE_CMD1_bp
+ #elif defined(TCA_SINGLE_CMD_1_bp)
+ //deprecated_constant_name TCA_SINGLE_CMD1_bp = TCA_SINGLE_CMD_1_bp;
+ #define TCA_SINGLE_CMD1_bp TCA_SINGLE_CMD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCA_SINGLE_EVACTA_0_bm) && defined(TCA_SINGLE_EVACTA0_bm)
+ #define TCA_SINGLE_EVACTA_0_bm TCA_SINGLE_EVACTA0_bm
+ #elif defined(TCA_SINGLE_EVACTA_0_bm)
+ //deprecated_constant_name TCA_SINGLE_EVACTA0_bm = TCA_SINGLE_EVACTA_0_bm;
+ #define TCA_SINGLE_EVACTA0_bm TCA_SINGLE_EVACTA_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTA_0_bp) && defined(TCA_SINGLE_EVACTA0_bp)
+ #define TCA_SINGLE_EVACTA_0_bp TCA_SINGLE_EVACTA0_bp
+ #elif defined(TCA_SINGLE_EVACTA_0_bp)
+ //deprecated_constant_name TCA_SINGLE_EVACTA0_bp = TCA_SINGLE_EVACTA_0_bp;
+ #define TCA_SINGLE_EVACTA0_bp TCA_SINGLE_EVACTA_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTA_1_bm) && defined(TCA_SINGLE_EVACTA1_bm)
+ #define TCA_SINGLE_EVACTA_1_bm TCA_SINGLE_EVACTA1_bm
+ #elif defined(TCA_SINGLE_EVACTA_1_bm)
+ //deprecated_constant_name TCA_SINGLE_EVACTA1_bm = TCA_SINGLE_EVACTA_1_bm;
+ #define TCA_SINGLE_EVACTA1_bm TCA_SINGLE_EVACTA_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTA_1_bp) && defined(TCA_SINGLE_EVACTA1_bp)
+ #define TCA_SINGLE_EVACTA_1_bp TCA_SINGLE_EVACTA1_bp
+ #elif defined(TCA_SINGLE_EVACTA_1_bp)
+ //deprecated_constant_name TCA_SINGLE_EVACTA1_bp = TCA_SINGLE_EVACTA_1_bp;
+ #define TCA_SINGLE_EVACTA1_bp TCA_SINGLE_EVACTA_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTA_2_bm) && defined(TCA_SINGLE_EVACTA2_bm)
+ #define TCA_SINGLE_EVACTA_2_bm TCA_SINGLE_EVACTA2_bm
+ #elif defined(TCA_SINGLE_EVACTA_2_bm)
+ //deprecated_constant_name TCA_SINGLE_EVACTA2_bm = TCA_SINGLE_EVACTA_2_bm;
+ #define TCA_SINGLE_EVACTA2_bm TCA_SINGLE_EVACTA_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTA_2_bp) && defined(TCA_SINGLE_EVACTA2_bp)
+ #define TCA_SINGLE_EVACTA_2_bp TCA_SINGLE_EVACTA2_bp
+ #elif defined(TCA_SINGLE_EVACTA_2_bp)
+ //deprecated_constant_name TCA_SINGLE_EVACTA2_bp = TCA_SINGLE_EVACTA_2_bp;
+ #define TCA_SINGLE_EVACTA2_bp TCA_SINGLE_EVACTA_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTB_0_bm) && defined(TCA_SINGLE_EVACTB0_bm)
+ #define TCA_SINGLE_EVACTB_0_bm TCA_SINGLE_EVACTB0_bm
+ #elif defined(TCA_SINGLE_EVACTB_0_bm)
+ //deprecated_constant_name TCA_SINGLE_EVACTB0_bm = TCA_SINGLE_EVACTB_0_bm;
+ #define TCA_SINGLE_EVACTB0_bm TCA_SINGLE_EVACTB_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTB_0_bp) && defined(TCA_SINGLE_EVACTB0_bp)
+ #define TCA_SINGLE_EVACTB_0_bp TCA_SINGLE_EVACTB0_bp
+ #elif defined(TCA_SINGLE_EVACTB_0_bp)
+ //deprecated_constant_name TCA_SINGLE_EVACTB0_bp = TCA_SINGLE_EVACTB_0_bp;
+ #define TCA_SINGLE_EVACTB0_bp TCA_SINGLE_EVACTB_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTB_1_bm) && defined(TCA_SINGLE_EVACTB1_bm)
+ #define TCA_SINGLE_EVACTB_1_bm TCA_SINGLE_EVACTB1_bm
+ #elif defined(TCA_SINGLE_EVACTB_1_bm)
+ //deprecated_constant_name TCA_SINGLE_EVACTB1_bm = TCA_SINGLE_EVACTB_1_bm;
+ #define TCA_SINGLE_EVACTB1_bm TCA_SINGLE_EVACTB_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTB_1_bp) && defined(TCA_SINGLE_EVACTB1_bp)
+ #define TCA_SINGLE_EVACTB_1_bp TCA_SINGLE_EVACTB1_bp
+ #elif defined(TCA_SINGLE_EVACTB_1_bp)
+ //deprecated_constant_name TCA_SINGLE_EVACTB1_bp = TCA_SINGLE_EVACTB_1_bp;
+ #define TCA_SINGLE_EVACTB1_bp TCA_SINGLE_EVACTB_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTB_2_bm) && defined(TCA_SINGLE_EVACTB2_bm)
+ #define TCA_SINGLE_EVACTB_2_bm TCA_SINGLE_EVACTB2_bm
+ #elif defined(TCA_SINGLE_EVACTB_2_bm)
+ //deprecated_constant_name TCA_SINGLE_EVACTB2_bm = TCA_SINGLE_EVACTB_2_bm;
+ #define TCA_SINGLE_EVACTB2_bm TCA_SINGLE_EVACTB_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SINGLE_EVACTB_2_bp) && defined(TCA_SINGLE_EVACTB2_bp)
+ #define TCA_SINGLE_EVACTB_2_bp TCA_SINGLE_EVACTB2_bp
+ #elif defined(TCA_SINGLE_EVACTB_2_bp)
+ //deprecated_constant_name TCA_SINGLE_EVACTB2_bp = TCA_SINGLE_EVACTB_2_bp;
+ #define TCA_SINGLE_EVACTB2_bp TCA_SINGLE_EVACTB_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCA_SPLIT_CLKSEL_0_bm) && defined(TCA_SPLIT_CLKSEL0_bm)
+ #define TCA_SPLIT_CLKSEL_0_bm TCA_SPLIT_CLKSEL0_bm
+ #elif defined(TCA_SPLIT_CLKSEL_0_bm)
+ //deprecated_constant_name TCA_SPLIT_CLKSEL0_bm = TCA_SPLIT_CLKSEL_0_bm;
+ #define TCA_SPLIT_CLKSEL0_bm TCA_SPLIT_CLKSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CLKSEL_0_bp) && defined(TCA_SPLIT_CLKSEL0_bp)
+ #define TCA_SPLIT_CLKSEL_0_bp TCA_SPLIT_CLKSEL0_bp
+ #elif defined(TCA_SPLIT_CLKSEL_0_bp)
+ //deprecated_constant_name TCA_SPLIT_CLKSEL0_bp = TCA_SPLIT_CLKSEL_0_bp;
+ #define TCA_SPLIT_CLKSEL0_bp TCA_SPLIT_CLKSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CLKSEL_1_bm) && defined(TCA_SPLIT_CLKSEL1_bm)
+ #define TCA_SPLIT_CLKSEL_1_bm TCA_SPLIT_CLKSEL1_bm
+ #elif defined(TCA_SPLIT_CLKSEL_1_bm)
+ //deprecated_constant_name TCA_SPLIT_CLKSEL1_bm = TCA_SPLIT_CLKSEL_1_bm;
+ #define TCA_SPLIT_CLKSEL1_bm TCA_SPLIT_CLKSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CLKSEL_1_bp) && defined(TCA_SPLIT_CLKSEL1_bp)
+ #define TCA_SPLIT_CLKSEL_1_bp TCA_SPLIT_CLKSEL1_bp
+ #elif defined(TCA_SPLIT_CLKSEL_1_bp)
+ //deprecated_constant_name TCA_SPLIT_CLKSEL1_bp = TCA_SPLIT_CLKSEL_1_bp;
+ #define TCA_SPLIT_CLKSEL1_bp TCA_SPLIT_CLKSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CLKSEL_2_bm) && defined(TCA_SPLIT_CLKSEL2_bm)
+ #define TCA_SPLIT_CLKSEL_2_bm TCA_SPLIT_CLKSEL2_bm
+ #elif defined(TCA_SPLIT_CLKSEL_2_bm)
+ //deprecated_constant_name TCA_SPLIT_CLKSEL2_bm = TCA_SPLIT_CLKSEL_2_bm;
+ #define TCA_SPLIT_CLKSEL2_bm TCA_SPLIT_CLKSEL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CLKSEL_2_bp) && defined(TCA_SPLIT_CLKSEL2_bp)
+ #define TCA_SPLIT_CLKSEL_2_bp TCA_SPLIT_CLKSEL2_bp
+ #elif defined(TCA_SPLIT_CLKSEL_2_bp)
+ //deprecated_constant_name TCA_SPLIT_CLKSEL2_bp = TCA_SPLIT_CLKSEL_2_bp;
+ #define TCA_SPLIT_CLKSEL2_bp TCA_SPLIT_CLKSEL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCA_SPLIT_CMDEN_0_bm) && defined(TCA_SPLIT_CMDEN0_bm)
+ #define TCA_SPLIT_CMDEN_0_bm TCA_SPLIT_CMDEN0_bm
+ #elif defined(TCA_SPLIT_CMDEN_0_bm)
+ //deprecated_constant_name TCA_SPLIT_CMDEN0_bm = TCA_SPLIT_CMDEN_0_bm;
+ #define TCA_SPLIT_CMDEN0_bm TCA_SPLIT_CMDEN_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CMDEN_0_bp) && defined(TCA_SPLIT_CMDEN0_bp)
+ #define TCA_SPLIT_CMDEN_0_bp TCA_SPLIT_CMDEN0_bp
+ #elif defined(TCA_SPLIT_CMDEN_0_bp)
+ //deprecated_constant_name TCA_SPLIT_CMDEN0_bp = TCA_SPLIT_CMDEN_0_bp;
+ #define TCA_SPLIT_CMDEN0_bp TCA_SPLIT_CMDEN_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CMDEN_1_bm) && defined(TCA_SPLIT_CMDEN1_bm)
+ #define TCA_SPLIT_CMDEN_1_bm TCA_SPLIT_CMDEN1_bm
+ #elif defined(TCA_SPLIT_CMDEN_1_bm)
+ //deprecated_constant_name TCA_SPLIT_CMDEN1_bm = TCA_SPLIT_CMDEN_1_bm;
+ #define TCA_SPLIT_CMDEN1_bm TCA_SPLIT_CMDEN_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CMDEN_1_bp) && defined(TCA_SPLIT_CMDEN1_bp)
+ #define TCA_SPLIT_CMDEN_1_bp TCA_SPLIT_CMDEN1_bp
+ #elif defined(TCA_SPLIT_CMDEN_1_bp)
+ //deprecated_constant_name TCA_SPLIT_CMDEN1_bp = TCA_SPLIT_CMDEN_1_bp;
+ #define TCA_SPLIT_CMDEN1_bp TCA_SPLIT_CMDEN_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CMD_0_bm) && defined(TCA_SPLIT_CMD0_bm)
+ #define TCA_SPLIT_CMD_0_bm TCA_SPLIT_CMD0_bm
+ #elif defined(TCA_SPLIT_CMD_0_bm)
+ //deprecated_constant_name TCA_SPLIT_CMD0_bm = TCA_SPLIT_CMD_0_bm;
+ #define TCA_SPLIT_CMD0_bm TCA_SPLIT_CMD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CMD_0_bp) && defined(TCA_SPLIT_CMD0_bp)
+ #define TCA_SPLIT_CMD_0_bp TCA_SPLIT_CMD0_bp
+ #elif defined(TCA_SPLIT_CMD_0_bp)
+ //deprecated_constant_name TCA_SPLIT_CMD0_bp = TCA_SPLIT_CMD_0_bp;
+ #define TCA_SPLIT_CMD0_bp TCA_SPLIT_CMD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CMD_1_bm) && defined(TCA_SPLIT_CMD1_bm)
+ #define TCA_SPLIT_CMD_1_bm TCA_SPLIT_CMD1_bm
+ #elif defined(TCA_SPLIT_CMD_1_bm)
+ //deprecated_constant_name TCA_SPLIT_CMD1_bm = TCA_SPLIT_CMD_1_bm;
+ #define TCA_SPLIT_CMD1_bm TCA_SPLIT_CMD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCA_SPLIT_CMD_1_bp) && defined(TCA_SPLIT_CMD1_bp)
+ #define TCA_SPLIT_CMD_1_bp TCA_SPLIT_CMD1_bp
+ #elif defined(TCA_SPLIT_CMD_1_bp)
+ //deprecated_constant_name TCA_SPLIT_CMD1_bp = TCA_SPLIT_CMD_1_bp;
+ #define TCA_SPLIT_CMD1_bp TCA_SPLIT_CMD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= TCBs ======= */
+ #if !defined(TCB_CLKSEL_0_bm) && defined(TCB_CLKSEL0_bm)
+ #define TCB_CLKSEL_0_bm TCB_CLKSEL0_bm
+ #elif defined(TCB_CLKSEL_0_bm)
+ //deprecated_constant_name TCB_CLKSEL0_bm = TCB_CLKSEL_0_bm;
+ #define TCB_CLKSEL0_bm TCB_CLKSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CLKSEL_0_bp) && defined(TCB_CLKSEL0_bp)
+ #define TCB_CLKSEL_0_bp TCB_CLKSEL0_bp
+ #elif defined(TCB_CLKSEL_0_bp)
+ //deprecated_constant_name TCB_CLKSEL0_bp = TCB_CLKSEL_0_bp;
+ #define TCB_CLKSEL0_bp TCB_CLKSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CLKSEL_1_bm) && defined(TCB_CLKSEL1_bm)
+ #define TCB_CLKSEL_1_bm TCB_CLKSEL1_bm
+ #elif defined(TCB_CLKSEL_1_bm)
+ //deprecated_constant_name TCB_CLKSEL1_bm = TCB_CLKSEL_1_bm;
+ #define TCB_CLKSEL1_bm TCB_CLKSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CLKSEL_1_bp) && defined(TCB_CLKSEL1_bp)
+ #define TCB_CLKSEL_1_bp TCB_CLKSEL1_bp
+ #elif defined(TCB_CLKSEL_1_bp)
+ //deprecated_constant_name TCB_CLKSEL1_bp = TCB_CLKSEL_1_bp;
+ #define TCB_CLKSEL1_bp TCB_CLKSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CLKSEL_2_bm) && defined(TCB_CLKSEL2_bm)
+ #define TCB_CLKSEL_2_bm TCB_CLKSEL2_bm
+ #elif defined(TCB_CLKSEL_2_bm)
+ //deprecated_constant_name TCB_CLKSEL2_bm = TCB_CLKSEL_2_bm;
+ #define TCB_CLKSEL2_bm TCB_CLKSEL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CLKSEL_2_bp) && defined(TCB_CLKSEL2_bp)
+ #define TCB_CLKSEL_2_bp TCB_CLKSEL2_bp
+ #elif defined(TCB_CLKSEL_2_bp)
+ //deprecated_constant_name TCB_CLKSEL2_bp = TCB_CLKSEL_2_bp;
+ #define TCB_CLKSEL2_bp TCB_CLKSEL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCB_CNTMODE_0_bm) && defined(TCB_CNTMODE0_bm)
+ #define TCB_CNTMODE_0_bm TCB_CNTMODE0_bm
+ #elif defined(TCB_CNTMODE_0_bm)
+ //deprecated_constant_name TCB_CNTMODE0_bm = TCB_CNTMODE_0_bm;
+ #define TCB_CNTMODE0_bm TCB_CNTMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CNTMODE_0_bp) && defined(TCB_CNTMODE0_bp)
+ #define TCB_CNTMODE_0_bp TCB_CNTMODE0_bp
+ #elif defined(TCB_CNTMODE_0_bp)
+ //deprecated_constant_name TCB_CNTMODE0_bp = TCB_CNTMODE_0_bp;
+ #define TCB_CNTMODE0_bp TCB_CNTMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CNTMODE_1_bm) && defined(TCB_CNTMODE1_bm)
+ #define TCB_CNTMODE_1_bm TCB_CNTMODE1_bm
+ #elif defined(TCB_CNTMODE_1_bm)
+ //deprecated_constant_name TCB_CNTMODE1_bm = TCB_CNTMODE_1_bm;
+ #define TCB_CNTMODE1_bm TCB_CNTMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CNTMODE_1_bp) && defined(TCB_CNTMODE1_bp)
+ #define TCB_CNTMODE_1_bp TCB_CNTMODE1_bp
+ #elif defined(TCB_CNTMODE_1_bp)
+ //deprecated_constant_name TCB_CNTMODE1_bp = TCB_CNTMODE_1_bp;
+ #define TCB_CNTMODE1_bp TCB_CNTMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CNTMODE_2_bm) && defined(TCB_CNTMODE2_bm)
+ #define TCB_CNTMODE_2_bm TCB_CNTMODE2_bm
+ #elif defined(TCB_CNTMODE_2_bm)
+ //deprecated_constant_name TCB_CNTMODE2_bm = TCB_CNTMODE_2_bm;
+ #define TCB_CNTMODE2_bm TCB_CNTMODE_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCB_CNTMODE_2_bp) && defined(TCB_CNTMODE2_bp)
+ #define TCB_CNTMODE_2_bp TCB_CNTMODE2_bp
+ #elif defined(TCB_CNTMODE_2_bp)
+ //deprecated_constant_name TCB_CNTMODE2_bp = TCB_CNTMODE_2_bp;
+ #define TCB_CNTMODE2_bp TCB_CNTMODE_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= TCD ======= */
+ #if !defined(TCD_SYNCPRES_0_bm) && defined(TCD_SYNCPRES0_bm)
+ #define TCD_SYNCPRES_0_bm TCD_SYNCPRES0_bm
+ #elif defined(TCD_SYNCPRES_0_bm)
+ //deprecated_constant_name TCD_SYNCPRES0_bm = TCD_SYNCPRES_0_bm;
+ #define TCD_SYNCPRES0_bm TCD_SYNCPRES_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_SYNCPRES_0_bp) && defined(TCD_SYNCPRES0_bp)
+ #define TCD_SYNCPRES_0_bp TCD_SYNCPRES0_bp
+ #elif defined(TCD_SYNCPRES_0_bp)
+ //deprecated_constant_name TCD_SYNCPRES0_bp = TCD_SYNCPRES_0_bp;
+ #define TCD_SYNCPRES0_bp TCD_SYNCPRES_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_SYNCPRES_1_bm) && defined(TCD_SYNCPRES1_bm)
+ #define TCD_SYNCPRES_1_bm TCD_SYNCPRES1_bm
+ #elif defined(TCD_SYNCPRES_1_bm)
+ //deprecated_constant_name TCD_SYNCPRES1_bm = TCD_SYNCPRES_1_bm;
+ #define TCD_SYNCPRES1_bm TCD_SYNCPRES_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_SYNCPRES_1_bp) && defined(TCD_SYNCPRES1_bp)
+ #define TCD_SYNCPRES_1_bp TCD_SYNCPRES1_bp
+ #elif defined(TCD_SYNCPRES_1_bp)
+ //deprecated_constant_name TCD_SYNCPRES1_bp = TCD_SYNCPRES_1_bp;
+ #define TCD_SYNCPRES1_bp TCD_SYNCPRES_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_CNTPRES_0_bm) && defined(TCD_CNTPRES0_bm)
+ #define TCD_CNTPRES_0_bm TCD_CNTPRES0_bm
+ #elif defined(TCD_CNTPRES_0_bm)
+ //deprecated_constant_name TCD_CNTPRES0_bm = TCD_CNTPRES_0_bm;
+ #define TCD_CNTPRES0_bm TCD_CNTPRES_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CNTPRES_0_bp) && defined(TCD_CNTPRES0_bp)
+ #define TCD_CNTPRES_0_bp TCD_CNTPRES0_bp
+ #elif defined(TCD_CNTPRES_0_bp)
+ //deprecated_constant_name TCD_CNTPRES0_bp = TCD_CNTPRES_0_bp;
+ #define TCD_CNTPRES0_bp TCD_CNTPRES_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CNTPRES_1_bm) && defined(TCD_CNTPRES1_bm)
+ #define TCD_CNTPRES_1_bm TCD_CNTPRES1_bm
+ #elif defined(TCD_CNTPRES_1_bm)
+ //deprecated_constant_name TCD_CNTPRES1_bm = TCD_CNTPRES_1_bm;
+ #define TCD_CNTPRES1_bm TCD_CNTPRES_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CNTPRES_1_bp) && defined(TCD_CNTPRES1_bp)
+ #define TCD_CNTPRES_1_bp TCD_CNTPRES1_bp
+ #elif defined(TCD_CNTPRES_1_bp)
+ //deprecated_constant_name TCD_CNTPRES1_bp = TCD_CNTPRES_1_bp;
+ #define TCD_CNTPRES1_bp TCD_CNTPRES_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_CLKSEL_0_bm) && defined(TCD_CLKSEL0_bm)
+ #define TCD_CLKSEL_0_bm TCD_CLKSEL0_bm
+ #elif defined(TCD_CLKSEL_0_bm)
+ //deprecated_constant_name TCD_CLKSEL0_bm = TCD_CLKSEL_0_bm;
+ #define TCD_CLKSEL0_bm TCD_CLKSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CLKSEL_0_bp) && defined(TCD_CLKSEL0_bp)
+ #define TCD_CLKSEL_0_bp TCD_CLKSEL0_bp
+ #elif defined(TCD_CLKSEL_0_bp)
+ //deprecated_constant_name TCD_CLKSEL0_bp = TCD_CLKSEL_0_bp;
+ #define TCD_CLKSEL0_bp TCD_CLKSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CLKSEL_1_bm) && defined(TCD_CLKSEL1_bm)
+ #define TCD_CLKSEL_1_bm TCD_CLKSEL1_bm
+ #elif defined(TCD_CLKSEL_1_bm)
+ //deprecated_constant_name TCD_CLKSEL1_bm = TCD_CLKSEL_1_bm;
+ #define TCD_CLKSEL1_bm TCD_CLKSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CLKSEL_1_bp) && defined(TCD_CLKSEL1_bp)
+ #define TCD_CLKSEL_1_bp TCD_CLKSEL1_bp
+ #elif defined(TCD_CLKSEL_1_bp)
+ //deprecated_constant_name TCD_CLKSEL1_bp = TCD_CLKSEL_1_bp;
+ #define TCD_CLKSEL1_bp TCD_CLKSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_WGMODE_0_bm) && defined(TCD_WGMODE0_bm)
+ #define TCD_WGMODE_0_bm TCD_WGMODE0_bm
+ #elif defined(TCD_WGMODE_0_bm)
+ //deprecated_constant_name TCD_WGMODE0_bm = TCD_WGMODE_0_bm;
+ #define TCD_WGMODE0_bm TCD_WGMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_WGMODE_0_bp) && defined(TCD_WGMODE0_bp)
+ #define TCD_WGMODE_0_bp TCD_WGMODE0_bp
+ #elif defined(TCD_WGMODE_0_bp)
+ //deprecated_constant_name TCD_WGMODE0_bp = TCD_WGMODE_0_bp;
+ #define TCD_WGMODE0_bp TCD_WGMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_WGMODE_1_bm) && defined(TCD_WGMODE1_bm)
+ #define TCD_WGMODE_1_bm TCD_WGMODE1_bm
+ #elif defined(TCD_WGMODE_1_bm)
+ //deprecated_constant_name TCD_WGMODE1_bm = TCD_WGMODE_1_bm;
+ #define TCD_WGMODE1_bm TCD_WGMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_WGMODE_1_bp) && defined(TCD_WGMODE1_bp)
+ #define TCD_WGMODE_1_bp TCD_WGMODE1_bp
+ #elif defined(TCD_WGMODE_1_bp)
+ //deprecated_constant_name TCD_WGMODE1_bp = TCD_WGMODE_1_bp;
+ #define TCD_WGMODE1_bp TCD_WGMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_CMPAVAL_0_bm) && defined(TCD_CMPAVAL0_bm)
+ #define TCD_CMPAVAL_0_bm TCD_CMPAVAL0_bm
+ #elif defined(TCD_CMPAVAL_0_bm)
+ //deprecated_constant_name TCD_CMPAVAL0_bm = TCD_CMPAVAL_0_bm;
+ #define TCD_CMPAVAL0_bm TCD_CMPAVAL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPAVAL_0_bp) && defined(TCD_CMPAVAL0_bp)
+ #define TCD_CMPAVAL_0_bp TCD_CMPAVAL0_bp
+ #elif defined(TCD_CMPAVAL_0_bp)
+ //deprecated_constant_name TCD_CMPAVAL0_bp = TCD_CMPAVAL_0_bp;
+ #define TCD_CMPAVAL0_bp TCD_CMPAVAL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPAVAL_1_bm) && defined(TCD_CMPAVAL1_bm)
+ #define TCD_CMPAVAL_1_bm TCD_CMPAVAL1_bm
+ #elif defined(TCD_CMPAVAL_1_bm)
+ //deprecated_constant_name TCD_CMPAVAL1_bm = TCD_CMPAVAL_1_bm;
+ #define TCD_CMPAVAL1_bm TCD_CMPAVAL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPAVAL_1_bp) && defined(TCD_CMPAVAL1_bp)
+ #define TCD_CMPAVAL_1_bp TCD_CMPAVAL1_bp
+ #elif defined(TCD_CMPAVAL_1_bp)
+ //deprecated_constant_name TCD_CMPAVAL1_bp = TCD_CMPAVAL_1_bp;
+ #define TCD_CMPAVAL1_bp TCD_CMPAVAL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPAVAL_2_bm) && defined(TCD_CMPAVAL2_bm)
+ #define TCD_CMPAVAL_2_bm TCD_CMPAVAL2_bm
+ #elif defined(TCD_CMPAVAL_2_bm)
+ //deprecated_constant_name TCD_CMPAVAL2_bm = TCD_CMPAVAL_2_bm;
+ #define TCD_CMPAVAL2_bm TCD_CMPAVAL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPAVAL_2_bp) && defined(TCD_CMPAVAL2_bp)
+ #define TCD_CMPAVAL_2_bp TCD_CMPAVAL2_bp
+ #elif defined(TCD_CMPAVAL_2_bp)
+ //deprecated_constant_name TCD_CMPAVAL2_bp = TCD_CMPAVAL_2_bp;
+ #define TCD_CMPAVAL2_bp TCD_CMPAVAL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPAVAL_3_bm) && defined(TCD_CMPAVAL3_bm)
+ #define TCD_CMPAVAL_3_bm TCD_CMPAVAL3_bm
+ #elif defined(TCD_CMPAVAL_3_bm)
+ //deprecated_constant_name TCD_CMPAVAL3_bm = TCD_CMPAVAL_3_bm;
+ #define TCD_CMPAVAL3_bm TCD_CMPAVAL_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPAVAL_3_bp) && defined(TCD_CMPAVAL3_bp)
+ #define TCD_CMPAVAL_3_bp TCD_CMPAVAL3_bp
+ #elif defined(TCD_CMPAVAL_3_bp)
+ //deprecated_constant_name TCD_CMPAVAL3_bp = TCD_CMPAVAL_3_bp;
+ #define TCD_CMPAVAL3_bp TCD_CMPAVAL_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_0_bm) && defined(TCD_CMPBVAL0_bm)
+ #define TCD_CMPBVAL_0_bm TCD_CMPBVAL0_bm
+ #elif defined(TCD_CMPBVAL_0_bm)
+ //deprecated_constant_name TCD_CMPBVAL0_bm = TCD_CMPBVAL_0_bm;
+ #define TCD_CMPBVAL0_bm TCD_CMPBVAL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_0_bp) && defined(TCD_CMPBVAL0_bp)
+ #define TCD_CMPBVAL_0_bp TCD_CMPBVAL0_bp
+ #elif defined(TCD_CMPBVAL_0_bp)
+ //deprecated_constant_name TCD_CMPBVAL0_bp = TCD_CMPBVAL_0_bp;
+ #define TCD_CMPBVAL0_bp TCD_CMPBVAL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_1_bm) && defined(TCD_CMPBVAL1_bm)
+ #define TCD_CMPBVAL_1_bm TCD_CMPBVAL1_bm
+ #elif defined(TCD_CMPBVAL_1_bm)
+ //deprecated_constant_name TCD_CMPBVAL1_bm = TCD_CMPBVAL_1_bm;
+ #define TCD_CMPBVAL1_bm TCD_CMPBVAL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_1_bp) && defined(TCD_CMPBVAL1_bp)
+ #define TCD_CMPBVAL_1_bp TCD_CMPBVAL1_bp
+ #elif defined(TCD_CMPBVAL_1_bp)
+ //deprecated_constant_name TCD_CMPBVAL1_bp = TCD_CMPBVAL_1_bp;
+ #define TCD_CMPBVAL1_bp TCD_CMPBVAL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_2_bm) && defined(TCD_CMPBVAL2_bm)
+ #define TCD_CMPBVAL_2_bm TCD_CMPBVAL2_bm
+ #elif defined(TCD_CMPBVAL_2_bm)
+ //deprecated_constant_name TCD_CMPBVAL2_bm = TCD_CMPBVAL_2_bm;
+ #define TCD_CMPBVAL2_bm TCD_CMPBVAL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_2_bp) && defined(TCD_CMPBVAL2_bp)
+ #define TCD_CMPBVAL_2_bp TCD_CMPBVAL2_bp
+ #elif defined(TCD_CMPBVAL_2_bp)
+ //deprecated_constant_name TCD_CMPBVAL2_bp = TCD_CMPBVAL_2_bp;
+ #define TCD_CMPBVAL2_bp TCD_CMPBVAL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_3_bm) && defined(TCD_CMPBVAL3_bm)
+ #define TCD_CMPBVAL_3_bm TCD_CMPBVAL3_bm
+ #elif defined(TCD_CMPBVAL_3_bm)
+ //deprecated_constant_name TCD_CMPBVAL3_bm = TCD_CMPBVAL_3_bm;
+ #define TCD_CMPBVAL3_bm TCD_CMPBVAL_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CMPBVAL_3_bp) && defined(TCD_CMPBVAL3_bp)
+ #define TCD_CMPBVAL_3_bp TCD_CMPBVAL3_bp
+ #elif defined(TCD_CMPBVAL_3_bp)
+ //deprecated_constant_name TCD_CMPBVAL3_bp = TCD_CMPBVAL_3_bp;
+ #define TCD_CMPBVAL3_bp TCD_CMPBVAL_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_CFG_0_bm) && defined(TCD_CFG0_bm)
+ #define TCD_CFG_0_bm TCD_CFG0_bm
+ #elif defined(TCD_CFG_0_bm)
+ //deprecated_constant_name TCD_CFG0_bm = TCD_CFG_0_bm;
+ #define TCD_CFG0_bm TCD_CFG_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CFG_0_bp) && defined(TCD_CFG0_bp)
+ #define TCD_CFG_0_bp TCD_CFG0_bp
+ #elif defined(TCD_CFG_0_bp)
+ //deprecated_constant_name TCD_CFG0_bp = TCD_CFG_0_bp;
+ #define TCD_CFG0_bp TCD_CFG_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CFG_1_bm) && defined(TCD_CFG1_bm)
+ #define TCD_CFG_1_bm TCD_CFG1_bm
+ #elif defined(TCD_CFG_1_bm)
+ //deprecated_constant_name TCD_CFG1_bm = TCD_CFG_1_bm;
+ #define TCD_CFG1_bm TCD_CFG_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_CFG_1_bp) && defined(TCD_CFG1_bp)
+ #define TCD_CFG_1_bp TCD_CFG1_bp
+ #elif defined(TCD_CFG_1_bp)
+ //deprecated_constant_name TCD_CFG1_bp = TCD_CFG_1_bp;
+ #define TCD_CFG1_bp TCD_CFG_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_INPUTMODE_0_bm) && defined(TCD_INPUTMODE0_bm)
+ #define TCD_INPUTMODE_0_bm TCD_INPUTMODE0_bm
+ #elif defined(TCD_INPUTMODE_0_bm)
+ //deprecated_constant_name TCD_INPUTMODE0_bm = TCD_INPUTMODE_0_bm;
+ #define TCD_INPUTMODE0_bm TCD_INPUTMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_INPUTMODE_0_bp) && defined(TCD_INPUTMODE0_bp)
+ #define TCD_INPUTMODE_0_bp TCD_INPUTMODE0_bp
+ #elif defined(TCD_INPUTMODE_0_bp)
+ //deprecated_constant_name TCD_INPUTMODE0_bp = TCD_INPUTMODE_0_bp;
+ #define TCD_INPUTMODE0_bp TCD_INPUTMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_INPUTMODE_1_bm) && defined(TCD_INPUTMODE1_bm)
+ #define TCD_INPUTMODE_1_bm TCD_INPUTMODE1_bm
+ #elif defined(TCD_INPUTMODE_1_bm)
+ //deprecated_constant_name TCD_INPUTMODE1_bm = TCD_INPUTMODE_1_bm;
+ #define TCD_INPUTMODE1_bm TCD_INPUTMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_INPUTMODE_1_bp) && defined(TCD_INPUTMODE1_bp)
+ #define TCD_INPUTMODE_1_bp TCD_INPUTMODE1_bp
+ #elif defined(TCD_INPUTMODE_1_bp)
+ //deprecated_constant_name TCD_INPUTMODE1_bp = TCD_INPUTMODE_1_bp;
+ #define TCD_INPUTMODE1_bp TCD_INPUTMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_INPUTMODE_2_bm) && defined(TCD_INPUTMODE2_bm)
+ #define TCD_INPUTMODE_2_bm TCD_INPUTMODE2_bm
+ #elif defined(TCD_INPUTMODE_2_bm)
+ //deprecated_constant_name TCD_INPUTMODE2_bm = TCD_INPUTMODE_2_bm;
+ #define TCD_INPUTMODE2_bm TCD_INPUTMODE_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_INPUTMODE_2_bp) && defined(TCD_INPUTMODE2_bp)
+ #define TCD_INPUTMODE_2_bp TCD_INPUTMODE2_bp
+ #elif defined(TCD_INPUTMODE_2_bp)
+ //deprecated_constant_name TCD_INPUTMODE2_bp = TCD_INPUTMODE_2_bp;
+ #define TCD_INPUTMODE2_bp TCD_INPUTMODE_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_INPUTMODE_3_bm) && defined(TCD_INPUTMODE3_bm)
+ #define TCD_INPUTMODE_3_bm TCD_INPUTMODE3_bm
+ #elif defined(TCD_INPUTMODE_3_bm)
+ //deprecated_constant_name TCD_INPUTMODE3_bm = TCD_INPUTMODE_3_bm;
+ #define TCD_INPUTMODE3_bm TCD_INPUTMODE_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_INPUTMODE_3_bp) && defined(TCD_INPUTMODE3_bp)
+ #define TCD_INPUTMODE_3_bp TCD_INPUTMODE3_bp
+ #elif defined(TCD_INPUTMODE_3_bp)
+ //deprecated_constant_name TCD_INPUTMODE3_bp = TCD_INPUTMODE_3_bp;
+ #define TCD_INPUTMODE3_bp TCD_INPUTMODE_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_DLYSEL_0_bm) && defined(TCD_DLYSEL0_bm)
+ #define TCD_DLYSEL_0_bm TCD_DLYSEL0_bm
+ #elif defined(TCD_DLYSEL_0_bm)
+ //deprecated_constant_name TCD_DLYSEL0_bm = TCD_DLYSEL_0_bm;
+ #define TCD_DLYSEL0_bm TCD_DLYSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYSEL_0_bp) && defined(TCD_DLYSEL0_bp)
+ #define TCD_DLYSEL_0_bp TCD_DLYSEL0_bp
+ #elif defined(TCD_DLYSEL_0_bp)
+ //deprecated_constant_name TCD_DLYSEL0_bp = TCD_DLYSEL_0_bp;
+ #define TCD_DLYSEL0_bp TCD_DLYSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_DLYSEL_1_bm) && defined(TCD_DLYSEL1_bm)
+ #define TCD_DLYSEL_1_bm TCD_DLYSEL1_bm
+ #elif defined(TCD_DLYSEL_1_bm)
+ //deprecated_constant_name TCD_DLYSEL1_bm = TCD_DLYSEL_1_bm;
+ #define TCD_DLYSEL1_bm TCD_DLYSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYSEL_1_bp) && defined(TCD_DLYSEL1_bp)
+ #define TCD_DLYSEL_1_bp TCD_DLYSEL1_bp
+ #elif defined(TCD_DLYSEL_1_bp)
+ //deprecated_constant_name TCD_DLYSEL1_bp = TCD_DLYSEL_1_bp;
+ #define TCD_DLYSEL1_bp TCD_DLYSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_DLYTRIG_0_bm) && defined(TCD_DLYTRIG0_bm)
+ #define TCD_DLYTRIG_0_bm TCD_DLYTRIG0_bm
+ #elif defined(TCD_DLYTRIG_0_bm)
+ //deprecated_constant_name TCD_DLYTRIG0_bm = TCD_DLYTRIG_0_bm;
+ #define TCD_DLYTRIG0_bm TCD_DLYTRIG_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYTRIG_0_bp) && defined(TCD_DLYTRIG0_bp)
+ #define TCD_DLYTRIG_0_bp TCD_DLYTRIG0_bp
+ #elif defined(TCD_DLYTRIG_0_bp)
+ //deprecated_constant_name TCD_DLYTRIG0_bp = TCD_DLYTRIG_0_bp;
+ #define TCD_DLYTRIG0_bp TCD_DLYTRIG_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYTRIG_1_bm) && defined(TCD_DLYTRIG1_bm)
+ #define TCD_DLYTRIG_1_bm TCD_DLYTRIG1_bm
+ #elif defined(TCD_DLYTRIG_1_bm)
+ //deprecated_constant_name TCD_DLYTRIG1_bm = TCD_DLYTRIG_1_bm;
+ #define TCD_DLYTRIG1_bm TCD_DLYTRIG_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYTRIG_1_bp) && defined(TCD_DLYTRIG1_bp)
+ #define TCD_DLYTRIG_1_bp TCD_DLYTRIG1_bp
+ #elif defined(TCD_DLYTRIG_1_bp)
+ //deprecated_constant_name TCD_DLYTRIG1_bp = TCD_DLYTRIG_1_bp;
+ #define TCD_DLYTRIG1_bp TCD_DLYTRIG_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_DLYPRESC_0_bm) && defined(TCD_DLYPRESC0_bm)
+ #define TCD_DLYPRESC_0_bm TCD_DLYPRESC0_bm
+ #elif defined(TCD_DLYPRESC_0_bm)
+ //deprecated_constant_name TCD_DLYPRESC0_bm = TCD_DLYPRESC_0_bm;
+ #define TCD_DLYPRESC0_bm TCD_DLYPRESC_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYPRESC_0_bp) && defined(TCD_DLYPRESC0_bp)
+ #define TCD_DLYPRESC_0_bp TCD_DLYPRESC0_bp
+ #elif defined(TCD_DLYPRESC_0_bp)
+ //deprecated_constant_name TCD_DLYPRESC0_bp = TCD_DLYPRESC_0_bp;
+ #define TCD_DLYPRESC0_bp TCD_DLYPRESC_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYPRESC_1_bm) && defined(TCD_DLYPRESC1_bm)
+ #define TCD_DLYPRESC_1_bm TCD_DLYPRESC1_bm
+ #elif defined(TCD_DLYPRESC_1_bm)
+ //deprecated_constant_name TCD_DLYPRESC1_bm = TCD_DLYPRESC_1_bm;
+ #define TCD_DLYPRESC1_bm TCD_DLYPRESC_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYPRESC_1_bp) && defined(TCD_DLYPRESC1_bp)
+ #define TCD_DLYPRESC_1_bp TCD_DLYPRESC1_bp
+ #elif defined(TCD_DLYPRESC_1_bp)
+ //deprecated_constant_name TCD_DLYPRESC1_bp = TCD_DLYPRESC_1_bp;
+ #define TCD_DLYPRESC1_bp TCD_DLYPRESC_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_DLYVAL_0_bm) && defined(TCD_DLYVAL0_bm)
+ #define TCD_DLYVAL_0_bm TCD_DLYVAL0_bm
+ #elif defined(TCD_DLYVAL_0_bm)
+ //deprecated_constant_name TCD_DLYVAL0_bm = TCD_DLYVAL_0_bm;
+ #define TCD_DLYVAL0_bm TCD_DLYVAL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_0_bp) && defined(TCD_DLYVAL0_bp)
+ #define TCD_DLYVAL_0_bp TCD_DLYVAL0_bp
+ #elif defined(TCD_DLYVAL_0_bp)
+ //deprecated_constant_name TCD_DLYVAL0_bp = TCD_DLYVAL_0_bp;
+ #define TCD_DLYVAL0_bp TCD_DLYVAL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_1_bm) && defined(TCD_DLYVAL1_bm)
+ #define TCD_DLYVAL_1_bm TCD_DLYVAL1_bm
+ #elif defined(TCD_DLYVAL_1_bm)
+ //deprecated_constant_name TCD_DLYVAL1_bm = TCD_DLYVAL_1_bm;
+ #define TCD_DLYVAL1_bm TCD_DLYVAL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_1_bp) && defined(TCD_DLYVAL1_bp)
+ #define TCD_DLYVAL_1_bp TCD_DLYVAL1_bp
+ #elif defined(TCD_DLYVAL_1_bp)
+ //deprecated_constant_name TCD_DLYVAL1_bp = TCD_DLYVAL_1_bp;
+ #define TCD_DLYVAL1_bp TCD_DLYVAL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_2_bm) && defined(TCD_DLYVAL2_bm)
+ #define TCD_DLYVAL_2_bm TCD_DLYVAL2_bm
+ #elif defined(TCD_DLYVAL_2_bm)
+ //deprecated_constant_name TCD_DLYVAL2_bm = TCD_DLYVAL_2_bm;
+ #define TCD_DLYVAL2_bm TCD_DLYVAL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_2_bp) && defined(TCD_DLYVAL2_bp)
+ #define TCD_DLYVAL_2_bp TCD_DLYVAL2_bp
+ #elif defined(TCD_DLYVAL_2_bp)
+ //deprecated_constant_name TCD_DLYVAL2_bp = TCD_DLYVAL_2_bp;
+ #define TCD_DLYVAL2_bp TCD_DLYVAL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_3_bm) && defined(TCD_DLYVAL3_bm)
+ #define TCD_DLYVAL_3_bm TCD_DLYVAL3_bm
+ #elif defined(TCD_DLYVAL_3_bm)
+ //deprecated_constant_name TCD_DLYVAL3_bm = TCD_DLYVAL_3_bm;
+ #define TCD_DLYVAL3_bm TCD_DLYVAL_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_3_bp) && defined(TCD_DLYVAL3_bp)
+ #define TCD_DLYVAL_3_bp TCD_DLYVAL3_bp
+ #elif defined(TCD_DLYVAL_3_bp)
+ //deprecated_constant_name TCD_DLYVAL3_bp = TCD_DLYVAL_3_bp;
+ #define TCD_DLYVAL3_bp TCD_DLYVAL_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_4_bm) && defined(TCD_DLYVAL4_bm)
+ #define TCD_DLYVAL_4_bm TCD_DLYVAL4_bm
+ #elif defined(TCD_DLYVAL_4_bm)
+ //deprecated_constant_name TCD_DLYVAL4_bm = TCD_DLYVAL_4_bm;
+ #define TCD_DLYVAL4_bm TCD_DLYVAL_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_4_bp) && defined(TCD_DLYVAL4_bp)
+ #define TCD_DLYVAL_4_bp TCD_DLYVAL4_bp
+ #elif defined(TCD_DLYVAL_4_bp)
+ //deprecated_constant_name TCD_DLYVAL4_bp = TCD_DLYVAL_4_bp;
+ #define TCD_DLYVAL4_bp TCD_DLYVAL_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_5_bm) && defined(TCD_DLYVAL5_bm)
+ #define TCD_DLYVAL_5_bm TCD_DLYVAL5_bm
+ #elif defined(TCD_DLYVAL_5_bm)
+ //deprecated_constant_name TCD_DLYVAL5_bm = TCD_DLYVAL_5_bm;
+ #define TCD_DLYVAL5_bm TCD_DLYVAL_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_5_bp) && defined(TCD_DLYVAL5_bp)
+ #define TCD_DLYVAL_5_bp TCD_DLYVAL5_bp
+ #elif defined(TCD_DLYVAL_5_bp)
+ //deprecated_constant_name TCD_DLYVAL5_bp = TCD_DLYVAL_5_bp;
+ #define TCD_DLYVAL5_bp TCD_DLYVAL_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_6_bm) && defined(TCD_DLYVAL6_bm)
+ #define TCD_DLYVAL_6_bm TCD_DLYVAL6_bm
+ #elif defined(TCD_DLYVAL_6_bm)
+ //deprecated_constant_name TCD_DLYVAL6_bm = TCD_DLYVAL_6_bm;
+ #define TCD_DLYVAL6_bm TCD_DLYVAL_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_6_bp) && defined(TCD_DLYVAL6_bp)
+ #define TCD_DLYVAL_6_bp TCD_DLYVAL6_bp
+ #elif defined(TCD_DLYVAL_6_bp)
+ //deprecated_constant_name TCD_DLYVAL6_bp = TCD_DLYVAL_6_bp;
+ #define TCD_DLYVAL6_bp TCD_DLYVAL_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_7_bm) && defined(TCD_DLYVAL7_bm)
+ #define TCD_DLYVAL_7_bm TCD_DLYVAL7_bm
+ #elif defined(TCD_DLYVAL_7_bm)
+ //deprecated_constant_name TCD_DLYVAL7_bm = TCD_DLYVAL_7_bm;
+ #define TCD_DLYVAL7_bm TCD_DLYVAL_7_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DLYVAL_7_bp) && defined(TCD_DLYVAL7_bp)
+ #define TCD_DLYVAL_7_bp TCD_DLYVAL7_bp
+ #elif defined(TCD_DLYVAL_7_bp)
+ //deprecated_constant_name TCD_DLYVAL7_bp = TCD_DLYVAL_7_bp;
+ #define TCD_DLYVAL7_bp TCD_DLYVAL_7_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_DITHERSEL_0_bm) && defined(TCD_DITHERSEL0_bm)
+ #define TCD_DITHERSEL_0_bm TCD_DITHERSEL0_bm
+ #elif defined(TCD_DITHERSEL_0_bm)
+ //deprecated_constant_name TCD_DITHERSEL0_bm = TCD_DITHERSEL_0_bm;
+ #define TCD_DITHERSEL0_bm TCD_DITHERSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHERSEL_0_bp) && defined(TCD_DITHERSEL0_bp)
+ #define TCD_DITHERSEL_0_bp TCD_DITHERSEL0_bp
+ #elif defined(TCD_DITHERSEL_0_bp)
+ //deprecated_constant_name TCD_DITHERSEL0_bp = TCD_DITHERSEL_0_bp;
+ #define TCD_DITHERSEL0_bp TCD_DITHERSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHERSEL_1_bm) && defined(TCD_DITHERSEL1_bm)
+ #define TCD_DITHERSEL_1_bm TCD_DITHERSEL1_bm
+ #elif defined(TCD_DITHERSEL_1_bm)
+ //deprecated_constant_name TCD_DITHERSEL1_bm = TCD_DITHERSEL_1_bm;
+ #define TCD_DITHERSEL1_bm TCD_DITHERSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHERSEL_1_bp) && defined(TCD_DITHERSEL1_bp)
+ #define TCD_DITHERSEL_1_bp TCD_DITHERSEL1_bp
+ #elif defined(TCD_DITHERSEL_1_bp)
+ //deprecated_constant_name TCD_DITHERSEL1_bp = TCD_DITHERSEL_1_bp;
+ #define TCD_DITHERSEL1_bp TCD_DITHERSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TCD_DITHER_0_bm) && defined(TCD_DITHER0_bm)
+ #define TCD_DITHER_0_bm TCD_DITHER0_bm
+ #elif defined(TCD_DITHER_0_bm)
+ //deprecated_constant_name TCD_DITHER0_bm = TCD_DITHER_0_bm;
+ #define TCD_DITHER0_bm TCD_DITHER_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHER_0_bp) && defined(TCD_DITHER0_bp)
+ #define TCD_DITHER_0_bp TCD_DITHER0_bp
+ #elif defined(TCD_DITHER_0_bp)
+ //deprecated_constant_name TCD_DITHER0_bp = TCD_DITHER_0_bp;
+ #define TCD_DITHER0_bp TCD_DITHER_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHER_1_bm) && defined(TCD_DITHER1_bm)
+ #define TCD_DITHER_1_bm TCD_DITHER1_bm
+ #elif defined(TCD_DITHER_1_bm)
+ //deprecated_constant_name TCD_DITHER1_bm = TCD_DITHER_1_bm;
+ #define TCD_DITHER1_bm TCD_DITHER_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHER_1_bp) && defined(TCD_DITHER1_bp)
+ #define TCD_DITHER_1_bp TCD_DITHER1_bp
+ #elif defined(TCD_DITHER_1_bp)
+ //deprecated_constant_name TCD_DITHER1_bp = TCD_DITHER_1_bp;
+ #define TCD_DITHER1_bp TCD_DITHER_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHER_2_bm) && defined(TCD_DITHER2_bm)
+ #define TCD_DITHER_2_bm TCD_DITHER2_bm
+ #elif defined(TCD_DITHER_2_bm)
+ //deprecated_constant_name TCD_DITHER2_bm = TCD_DITHER_2_bm;
+ #define TCD_DITHER2_bm TCD_DITHER_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHER_2_bp) && defined(TCD_DITHER2_bp)
+ #define TCD_DITHER_2_bp TCD_DITHER2_bp
+ #elif defined(TCD_DITHER_2_bp)
+ //deprecated_constant_name TCD_DITHER2_bp = TCD_DITHER_2_bp;
+ #define TCD_DITHER2_bp TCD_DITHER_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHER_3_bm) && defined(TCD_DITHER3_bm)
+ #define TCD_DITHER_3_bm TCD_DITHER3_bm
+ #elif defined(TCD_DITHER_3_bm)
+ //deprecated_constant_name TCD_DITHER3_bm = TCD_DITHER_3_bm;
+ #define TCD_DITHER3_bm TCD_DITHER_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TCD_DITHER_3_bp) && defined(TCD_DITHER3_bp)
+ #define TCD_DITHER_3_bp TCD_DITHER3_bp
+ #elif defined(TCD_DITHER_3_bp)
+ //deprecated_constant_name TCD_DITHER3_bp = TCD_DITHER_3_bp;
+ #define TCD_DITHER3_bp TCD_DITHER_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= TWI ======= */
+ #if !defined(TWI_SDAHOLD_0_bm) && defined(TWI_SDAHOLD0_bm)
+ #define TWI_SDAHOLD_0_bm TWI_SDAHOLD0_bm
+ #elif defined(TWI_SDAHOLD_0_bm)
+ //deprecated_constant_name TWI_SDAHOLD0_bm = TWI_SDAHOLD_0_bm;
+ #define TWI_SDAHOLD0_bm TWI_SDAHOLD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_SDAHOLD_0_bp) && defined(TWI_SDAHOLD0_bp)
+ #define TWI_SDAHOLD_0_bp TWI_SDAHOLD0_bp
+ #elif defined(TWI_SDAHOLD_0_bp)
+ //deprecated_constant_name TWI_SDAHOLD0_bp = TWI_SDAHOLD_0_bp;
+ #define TWI_SDAHOLD0_bp TWI_SDAHOLD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_SDAHOLD_1_bm) && defined(TWI_SDAHOLD1_bm)
+ #define TWI_SDAHOLD_1_bm TWI_SDAHOLD1_bm
+ #elif defined(TWI_SDAHOLD_1_bm)
+ //deprecated_constant_name TWI_SDAHOLD1_bm = TWI_SDAHOLD_1_bm;
+ #define TWI_SDAHOLD1_bm TWI_SDAHOLD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_SDAHOLD_1_bp) && defined(TWI_SDAHOLD1_bp)
+ #define TWI_SDAHOLD_1_bp TWI_SDAHOLD1_bp
+ #elif defined(TWI_SDAHOLD_1_bp)
+ //deprecated_constant_name TWI_SDAHOLD1_bp = TWI_SDAHOLD_1_bp;
+ #define TWI_SDAHOLD1_bp TWI_SDAHOLD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TWI_TIMEOUT_0_bm) && defined(TWI_TIMEOUT0_bm)
+ #define TWI_TIMEOUT_0_bm TWI_TIMEOUT0_bm
+ #elif defined(TWI_TIMEOUT_0_bm)
+ //deprecated_constant_name TWI_TIMEOUT0_bm = TWI_TIMEOUT_0_bm;
+ #define TWI_TIMEOUT0_bm TWI_TIMEOUT_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_TIMEOUT_0_bp) && defined(TWI_TIMEOUT0_bp)
+ #define TWI_TIMEOUT_0_bp TWI_TIMEOUT0_bp
+ #elif defined(TWI_TIMEOUT_0_bp)
+ //deprecated_constant_name TWI_TIMEOUT0_bp = TWI_TIMEOUT_0_bp;
+ #define TWI_TIMEOUT0_bp TWI_TIMEOUT_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_TIMEOUT_1_bm) && defined(TWI_TIMEOUT1_bm)
+ #define TWI_TIMEOUT_1_bm TWI_TIMEOUT1_bm
+ #elif defined(TWI_TIMEOUT_1_bm)
+ //deprecated_constant_name TWI_TIMEOUT1_bm = TWI_TIMEOUT_1_bm;
+ #define TWI_TIMEOUT1_bm TWI_TIMEOUT_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_TIMEOUT_1_bp) && defined(TWI_TIMEOUT1_bp)
+ #define TWI_TIMEOUT_1_bp TWI_TIMEOUT1_bp
+ #elif defined(TWI_TIMEOUT_1_bp)
+ //deprecated_constant_name TWI_TIMEOUT1_bp = TWI_TIMEOUT_1_bp;
+ #define TWI_TIMEOUT1_bp TWI_TIMEOUT_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TWI_MCMD_0_bm) && defined(TWI_MCMD0_bm)
+ #define TWI_MCMD_0_bm TWI_MCMD0_bm
+ #elif defined(TWI_MCMD_0_bm)
+ //deprecated_constant_name TWI_MCMD0_bm = TWI_MCMD_0_bm;
+ #define TWI_MCMD0_bm TWI_MCMD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_MCMD_0_bp) && defined(TWI_MCMD0_bp)
+ #define TWI_MCMD_0_bp TWI_MCMD0_bp
+ #elif defined(TWI_MCMD_0_bp)
+ //deprecated_constant_name TWI_MCMD0_bp = TWI_MCMD_0_bp;
+ #define TWI_MCMD0_bp TWI_MCMD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_MCMD_1_bm) && defined(TWI_MCMD1_bm)
+ #define TWI_MCMD_1_bm TWI_MCMD1_bm
+ #elif defined(TWI_MCMD_1_bm)
+ //deprecated_constant_name TWI_MCMD1_bm = TWI_MCMD_1_bm;
+ #define TWI_MCMD1_bm TWI_MCMD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_MCMD_1_bp) && defined(TWI_MCMD1_bp)
+ #define TWI_MCMD_1_bp TWI_MCMD1_bp
+ #elif defined(TWI_MCMD_1_bp)
+ //deprecated_constant_name TWI_MCMD1_bp = TWI_MCMD_1_bp;
+ #define TWI_MCMD1_bp TWI_MCMD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TWI_BUSSTATE_0_bm) && defined(TWI_BUSSTATE0_bm)
+ #define TWI_BUSSTATE_0_bm TWI_BUSSTATE0_bm
+ #elif defined(TWI_BUSSTATE_0_bm)
+ //deprecated_constant_name TWI_BUSSTATE0_bm = TWI_BUSSTATE_0_bm;
+ #define TWI_BUSSTATE0_bm TWI_BUSSTATE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_BUSSTATE_0_bp) && defined(TWI_BUSSTATE0_bp)
+ #define TWI_BUSSTATE_0_bp TWI_BUSSTATE0_bp
+ #elif defined(TWI_BUSSTATE_0_bp)
+ //deprecated_constant_name TWI_BUSSTATE0_bp = TWI_BUSSTATE_0_bp;
+ #define TWI_BUSSTATE0_bp TWI_BUSSTATE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_BUSSTATE_1_bm) && defined(TWI_BUSSTATE1_bm)
+ #define TWI_BUSSTATE_1_bm TWI_BUSSTATE1_bm
+ #elif defined(TWI_BUSSTATE_1_bm)
+ //deprecated_constant_name TWI_BUSSTATE1_bm = TWI_BUSSTATE_1_bm;
+ #define TWI_BUSSTATE1_bm TWI_BUSSTATE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_BUSSTATE_1_bp) && defined(TWI_BUSSTATE1_bp)
+ #define TWI_BUSSTATE_1_bp TWI_BUSSTATE1_bp
+ #elif defined(TWI_BUSSTATE_1_bp)
+ //deprecated_constant_name TWI_BUSSTATE1_bp = TWI_BUSSTATE_1_bp;
+ #define TWI_BUSSTATE1_bp TWI_BUSSTATE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ #if !defined(TWI_SCMD_0_bm) && defined(TWI_SCMD0_bm)
+ #define TWI_SCMD_0_bm TWI_SCMD0_bm
+ #elif defined(TWI_SCMD_0_bm)
+ //deprecated_constant_name TWI_SCMD0_bm = TWI_SCMD_0_bm;
+ #define TWI_SCMD0_bm TWI_SCMD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_SCMD_0_bp) && defined(TWI_SCMD0_bp)
+ #define TWI_SCMD_0_bp TWI_SCMD0_bp
+ #elif defined(TWI_SCMD_0_bp)
+ //deprecated_constant_name TWI_SCMD0_bp = TWI_SCMD_0_bp;
+ #define TWI_SCMD0_bp TWI_SCMD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_SCMD_1_bm) && defined(TWI_SCMD1_bm)
+ #define TWI_SCMD_1_bm TWI_SCMD1_bm
+ #elif defined(TWI_SCMD_1_bm)
+ //deprecated_constant_name TWI_SCMD1_bm = TWI_SCMD_1_bm;
+ #define TWI_SCMD1_bm TWI_SCMD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_SCMD_1_bp) && defined(TWI_SCMD1_bp)
+ #define TWI_SCMD_1_bp TWI_SCMD1_bp
+ #elif defined(TWI_SCMD_1_bp)
+ //deprecated_constant_name TWI_SCMD1_bp = TWI_SCMD_1_bp;
+ #define TWI_SCMD1_bp TWI_SCMD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_0_bm) && defined(TWI_ADDRMASK0_bm)
+ #define TWI_ADDRMASK_0_bm TWI_ADDRMASK0_bm
+ #elif defined(TWI_ADDRMASK_0_bm)
+ //deprecated_constant_name TWI_ADDRMASK0_bm = TWI_ADDRMASK_0_bm;
+ #define TWI_ADDRMASK0_bm TWI_ADDRMASK_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_0_bp) && defined(TWI_ADDRMASK0_bp)
+ #define TWI_ADDRMASK_0_bp TWI_ADDRMASK0_bp
+ #elif defined(TWI_ADDRMASK_0_bp)
+ //deprecated_constant_name TWI_ADDRMASK0_bp = TWI_ADDRMASK_0_bp;
+ #define TWI_ADDRMASK0_bp TWI_ADDRMASK_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_1_bm) && defined(TWI_ADDRMASK1_bm)
+ #define TWI_ADDRMASK_1_bm TWI_ADDRMASK1_bm
+ #elif defined(TWI_ADDRMASK_1_bm)
+ //deprecated_constant_name TWI_ADDRMASK1_bm = TWI_ADDRMASK_1_bm;
+ #define TWI_ADDRMASK1_bm TWI_ADDRMASK_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_1_bp) && defined(TWI_ADDRMASK1_bp)
+ #define TWI_ADDRMASK_1_bp TWI_ADDRMASK1_bp
+ #elif defined(TWI_ADDRMASK_1_bp)
+ //deprecated_constant_name TWI_ADDRMASK1_bp = TWI_ADDRMASK_1_bp;
+ #define TWI_ADDRMASK1_bp TWI_ADDRMASK_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_2_bm) && defined(TWI_ADDRMASK2_bm)
+ #define TWI_ADDRMASK_2_bm TWI_ADDRMASK2_bm
+ #elif defined(TWI_ADDRMASK_2_bm)
+ //deprecated_constant_name TWI_ADDRMASK2_bm = TWI_ADDRMASK_2_bm;
+ #define TWI_ADDRMASK2_bm TWI_ADDRMASK_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_2_bp) && defined(TWI_ADDRMASK2_bp)
+ #define TWI_ADDRMASK_2_bp TWI_ADDRMASK2_bp
+ #elif defined(TWI_ADDRMASK_2_bp)
+ //deprecated_constant_name TWI_ADDRMASK2_bp = TWI_ADDRMASK_2_bp;
+ #define TWI_ADDRMASK2_bp TWI_ADDRMASK_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_3_bm) && defined(TWI_ADDRMASK3_bm)
+ #define TWI_ADDRMASK_3_bm TWI_ADDRMASK3_bm
+ #elif defined(TWI_ADDRMASK_3_bm)
+ //deprecated_constant_name TWI_ADDRMASK3_bm = TWI_ADDRMASK_3_bm;
+ #define TWI_ADDRMASK3_bm TWI_ADDRMASK_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_3_bp) && defined(TWI_ADDRMASK3_bp)
+ #define TWI_ADDRMASK_3_bp TWI_ADDRMASK3_bp
+ #elif defined(TWI_ADDRMASK_3_bp)
+ //deprecated_constant_name TWI_ADDRMASK3_bp = TWI_ADDRMASK_3_bp;
+ #define TWI_ADDRMASK3_bp TWI_ADDRMASK_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_4_bm) && defined(TWI_ADDRMASK4_bm)
+ #define TWI_ADDRMASK_4_bm TWI_ADDRMASK4_bm
+ #elif defined(TWI_ADDRMASK_4_bm)
+ //deprecated_constant_name TWI_ADDRMASK4_bm = TWI_ADDRMASK_4_bm;
+ #define TWI_ADDRMASK4_bm TWI_ADDRMASK_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_4_bp) && defined(TWI_ADDRMASK4_bp)
+ #define TWI_ADDRMASK_4_bp TWI_ADDRMASK4_bp
+ #elif defined(TWI_ADDRMASK_4_bp)
+ //deprecated_constant_name TWI_ADDRMASK4_bp = TWI_ADDRMASK_4_bp;
+ #define TWI_ADDRMASK4_bp TWI_ADDRMASK_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_5_bm) && defined(TWI_ADDRMASK5_bm)
+ #define TWI_ADDRMASK_5_bm TWI_ADDRMASK5_bm
+ #elif defined(TWI_ADDRMASK_5_bm)
+ //deprecated_constant_name TWI_ADDRMASK5_bm = TWI_ADDRMASK_5_bm;
+ #define TWI_ADDRMASK5_bm TWI_ADDRMASK_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_5_bp) && defined(TWI_ADDRMASK5_bp)
+ #define TWI_ADDRMASK_5_bp TWI_ADDRMASK5_bp
+ #elif defined(TWI_ADDRMASK_5_bp)
+ //deprecated_constant_name TWI_ADDRMASK5_bp = TWI_ADDRMASK_5_bp;
+ #define TWI_ADDRMASK5_bp TWI_ADDRMASK_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_6_bm) && defined(TWI_ADDRMASK6_bm)
+ #define TWI_ADDRMASK_6_bm TWI_ADDRMASK6_bm
+ #elif defined(TWI_ADDRMASK_6_bm)
+ //deprecated_constant_name TWI_ADDRMASK6_bm = TWI_ADDRMASK_6_bm;
+ #define TWI_ADDRMASK6_bm TWI_ADDRMASK_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(TWI_ADDRMASK_6_bp) && defined(TWI_ADDRMASK6_bp)
+ #define TWI_ADDRMASK_6_bp TWI_ADDRMASK6_bp
+ #elif defined(TWI_ADDRMASK_6_bp)
+ //deprecated_constant_name TWI_ADDRMASK6_bp = TWI_ADDRMASK_6_bp;
+ #define TWI_ADDRMASK6_bp TWI_ADDRMASK_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+
+ /* ======= USART ======= */
+ #if !defined(USART_RXMODE_0_bm) && defined(USART_RXMODE0_bm)
+ #define USART_RXMODE_0_bm USART_RXMODE0_bm
+ #elif defined(USART_RXMODE_0_bm)
+ //deprecated_constant_name USART_RXMODE0_bm = USART_RXMODE_0_bm;
+ #define USART_RXMODE0_bm USART_RXMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXMODE_0_bp) && defined(USART_RXMODE0_bp)
+ #define USART_RXMODE_0_bp USART_RXMODE0_bp
+ #elif defined(USART_RXMODE_0_bp)
+ //deprecated_constant_name USART_RXMODE0_bp = USART_RXMODE_0_bp;
+ #define USART_RXMODE0_bp USART_RXMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXMODE_1_bm) && defined(USART_RXMODE1_bm)
+ #define USART_RXMODE_1_bm USART_RXMODE1_bm
+ #elif defined(USART_RXMODE_1_bm)
+ //deprecated_constant_name USART_RXMODE1_bm = USART_RXMODE_1_bm;
+ #define USART_RXMODE1_bm USART_RXMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXMODE_1_bp) && defined(USART_RXMODE1_bp)
+ #define USART_RXMODE_1_bp USART_RXMODE1_bp
+ #elif defined(USART_RXMODE_1_bp)
+ //deprecated_constant_name USART_RXMODE1_bp = USART_RXMODE_1_bp;
+ #define USART_RXMODE1_bp USART_RXMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CHSIZE_0_bm) && defined(USART_CHSIZE0_bm)
+ #define USART_CHSIZE_0_bm USART_CHSIZE0_bm
+ #elif defined(USART_CHSIZE_0_bm)
+ //deprecated_constant_name USART_CHSIZE0_bm = USART_CHSIZE_0_bm;
+ #define USART_CHSIZE0_bm USART_CHSIZE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CHSIZE_0_bp) && defined(USART_CHSIZE0_bp)
+ #define USART_CHSIZE_0_bp USART_CHSIZE0_bp
+ #elif defined(USART_CHSIZE_0_bp)
+ //deprecated_constant_name USART_CHSIZE0_bp = USART_CHSIZE_0_bp;
+ #define USART_CHSIZE0_bp USART_CHSIZE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CHSIZE_1_bm) && defined(USART_CHSIZE1_bm)
+ #define USART_CHSIZE_1_bm USART_CHSIZE1_bm
+ #elif defined(USART_CHSIZE_1_bm)
+ //deprecated_constant_name USART_CHSIZE1_bm = USART_CHSIZE_1_bm;
+ #define USART_CHSIZE1_bm USART_CHSIZE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CHSIZE_1_bp) && defined(USART_CHSIZE1_bp)
+ #define USART_CHSIZE_1_bp USART_CHSIZE1_bp
+ #elif defined(USART_CHSIZE_1_bp)
+ //deprecated_constant_name USART_CHSIZE1_bp = USART_CHSIZE_1_bp;
+ #define USART_CHSIZE1_bp USART_CHSIZE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CHSIZE_2_bm) && defined(USART_CHSIZE2_bm)
+ #define USART_CHSIZE_2_bm USART_CHSIZE2_bm
+ #elif defined(USART_CHSIZE_2_bm)
+ //deprecated_constant_name USART_CHSIZE2_bm = USART_CHSIZE_2_bm;
+ #define USART_CHSIZE2_bm USART_CHSIZE_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CHSIZE_2_bp) && defined(USART_CHSIZE2_bp)
+ #define USART_CHSIZE_2_bp USART_CHSIZE2_bp
+ #elif defined(USART_CHSIZE_2_bp)
+ //deprecated_constant_name USART_CHSIZE2_bp = USART_CHSIZE_2_bp;
+ #define USART_CHSIZE2_bp USART_CHSIZE_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_PMODE_0_bm) && defined(USART_PMODE0_bm)
+ #define USART_PMODE_0_bm USART_PMODE0_bm
+ #elif defined(USART_PMODE_0_bm)
+ //deprecated_constant_name USART_PMODE0_bm = USART_PMODE_0_bm;
+ #define USART_PMODE0_bm USART_PMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_PMODE_0_bp) && defined(USART_PMODE0_bp)
+ #define USART_PMODE_0_bp USART_PMODE0_bp
+ #elif defined(USART_PMODE_0_bp)
+ //deprecated_constant_name USART_PMODE0_bp = USART_PMODE_0_bp;
+ #define USART_PMODE0_bp USART_PMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_PMODE_1_bm) && defined(USART_PMODE1_bm)
+ #define USART_PMODE_1_bm USART_PMODE1_bm
+ #elif defined(USART_PMODE_1_bm)
+ //deprecated_constant_name USART_PMODE1_bm = USART_PMODE_1_bm;
+ #define USART_PMODE1_bm USART_PMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_PMODE_1_bp) && defined(USART_PMODE1_bp)
+ #define USART_PMODE_1_bp USART_PMODE1_bp
+ #elif defined(USART_PMODE_1_bp)
+ //deprecated_constant_name USART_PMODE1_bp = USART_PMODE_1_bp;
+ #define USART_PMODE1_bp USART_PMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CMODE_0_bm) && defined(USART_CMODE0_bm)
+ #define USART_CMODE_0_bm USART_CMODE0_bm
+ #elif defined(USART_CMODE_0_bm)
+ //deprecated_constant_name USART_CMODE0_bm = USART_CMODE_0_bm;
+ #define USART_CMODE0_bm USART_CMODE_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CMODE_0_bp) && defined(USART_CMODE0_bp)
+ #define USART_CMODE_0_bp USART_CMODE0_bp
+ #elif defined(USART_CMODE_0_bp)
+ //deprecated_constant_name USART_CMODE0_bp = USART_CMODE_0_bp;
+ #define USART_CMODE0_bp USART_CMODE_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CMODE_1_bm) && defined(USART_CMODE1_bm)
+ #define USART_CMODE_1_bm USART_CMODE1_bm
+ #elif defined(USART_CMODE_1_bm)
+ //deprecated_constant_name USART_CMODE1_bm = USART_CMODE_1_bm;
+ #define USART_CMODE1_bm USART_CMODE_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_CMODE_1_bp) && defined(USART_CMODE1_bp)
+ #define USART_CMODE_1_bp USART_CMODE1_bp
+ #elif defined(USART_CMODE_1_bp)
+ //deprecated_constant_name USART_CMODE1_bp = USART_CMODE_1_bp;
+ #define USART_CMODE1_bp USART_CMODE_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_ABW_0_bm) && defined(USART_ABW0_bm)
+ #define USART_ABW_0_bm USART_ABW0_bm
+ #elif defined(USART_ABW_0_bm)
+ //deprecated_constant_name USART_ABW0_bm = USART_ABW_0_bm;
+ #define USART_ABW0_bm USART_ABW_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_ABW_0_bp) && defined(USART_ABW0_bp)
+ #define USART_ABW_0_bp USART_ABW0_bp
+ #elif defined(USART_ABW_0_bp)
+ //deprecated_constant_name USART_ABW0_bp = USART_ABW_0_bp;
+ #define USART_ABW0_bp USART_ABW_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_ABW_1_bm) && defined(USART_ABW1_bm)
+ #define USART_ABW_1_bm USART_ABW1_bm
+ #elif defined(USART_ABW_1_bm)
+ //deprecated_constant_name USART_ABW1_bm = USART_ABW_1_bm;
+ #define USART_ABW1_bm USART_ABW_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_ABW_1_bp) && defined(USART_ABW1_bp)
+ #define USART_ABW_1_bp USART_ABW1_bp
+ #elif defined(USART_ABW_1_bp)
+ //deprecated_constant_name USART_ABW1_bp = USART_ABW_1_bp;
+ #define USART_ABW1_bp USART_ABW_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_0_bm) && defined(USART_TXPL0_bm)
+ #define USART_TXPL_0_bm USART_TXPL0_bm
+ #elif defined(USART_TXPL_0_bm)
+ //deprecated_constant_name USART_TXPL0_bm = USART_TXPL_0_bm;
+ #define USART_TXPL0_bm USART_TXPL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_0_bp) && defined(USART_TXPL0_bp)
+ #define USART_TXPL_0_bp USART_TXPL0_bp
+ #elif defined(USART_TXPL_0_bp)
+ //deprecated_constant_name USART_TXPL0_bp = USART_TXPL_0_bp;
+ #define USART_TXPL0_bp USART_TXPL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_1_bm) && defined(USART_TXPL1_bm)
+ #define USART_TXPL_1_bm USART_TXPL1_bm
+ #elif defined(USART_TXPL_1_bm)
+ //deprecated_constant_name USART_TXPL1_bm = USART_TXPL_1_bm;
+ #define USART_TXPL1_bm USART_TXPL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_1_bp) && defined(USART_TXPL1_bp)
+ #define USART_TXPL_1_bp USART_TXPL1_bp
+ #elif defined(USART_TXPL_1_bp)
+ //deprecated_constant_name USART_TXPL1_bp = USART_TXPL_1_bp;
+ #define USART_TXPL1_bp USART_TXPL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_2_bm) && defined(USART_TXPL2_bm)
+ #define USART_TXPL_2_bm USART_TXPL2_bm
+ #elif defined(USART_TXPL_2_bm)
+ //deprecated_constant_name USART_TXPL2_bm = USART_TXPL_2_bm;
+ #define USART_TXPL2_bm USART_TXPL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_2_bp) && defined(USART_TXPL2_bp)
+ #define USART_TXPL_2_bp USART_TXPL2_bp
+ #elif defined(USART_TXPL_2_bp)
+ //deprecated_constant_name USART_TXPL2_bp = USART_TXPL_2_bp;
+ #define USART_TXPL2_bp USART_TXPL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_3_bm) && defined(USART_TXPL3_bm)
+ #define USART_TXPL_3_bm USART_TXPL3_bm
+ #elif defined(USART_TXPL_3_bm)
+ //deprecated_constant_name USART_TXPL3_bm = USART_TXPL_3_bm;
+ #define USART_TXPL3_bm USART_TXPL_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_3_bp) && defined(USART_TXPL3_bp)
+ #define USART_TXPL_3_bp USART_TXPL3_bp
+ #elif defined(USART_TXPL_3_bp)
+ //deprecated_constant_name USART_TXPL3_bp = USART_TXPL_3_bp;
+ #define USART_TXPL3_bp USART_TXPL_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_4_bm) && defined(USART_TXPL4_bm)
+ #define USART_TXPL_4_bm USART_TXPL4_bm
+ #elif defined(USART_TXPL_4_bm)
+ //deprecated_constant_name USART_TXPL4_bm = USART_TXPL_4_bm;
+ #define USART_TXPL4_bm USART_TXPL_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_4_bp) && defined(USART_TXPL4_bp)
+ #define USART_TXPL_4_bp USART_TXPL4_bp
+ #elif defined(USART_TXPL_4_bp)
+ //deprecated_constant_name USART_TXPL4_bp = USART_TXPL_4_bp;
+ #define USART_TXPL4_bp USART_TXPL_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_5_bm) && defined(USART_TXPL5_bm)
+ #define USART_TXPL_5_bm USART_TXPL5_bm
+ #elif defined(USART_TXPL_5_bm)
+ //deprecated_constant_name USART_TXPL5_bm = USART_TXPL_5_bm;
+ #define USART_TXPL5_bm USART_TXPL_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_5_bp) && defined(USART_TXPL5_bp)
+ #define USART_TXPL_5_bp USART_TXPL5_bp
+ #elif defined(USART_TXPL_5_bp)
+ //deprecated_constant_name USART_TXPL5_bp = USART_TXPL_5_bp;
+ #define USART_TXPL5_bp USART_TXPL_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_6_bm) && defined(USART_TXPL6_bm)
+ #define USART_TXPL_6_bm USART_TXPL6_bm
+ #elif defined(USART_TXPL_6_bm)
+ //deprecated_constant_name USART_TXPL6_bm = USART_TXPL_6_bm;
+ #define USART_TXPL6_bm USART_TXPL_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_6_bp) && defined(USART_TXPL6_bp)
+ #define USART_TXPL_6_bp USART_TXPL6_bp
+ #elif defined(USART_TXPL_6_bp)
+ //deprecated_constant_name USART_TXPL6_bp = USART_TXPL_6_bp;
+ #define USART_TXPL6_bp USART_TXPL_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_7_bm) && defined(USART_TXPL7_bm)
+ #define USART_TXPL_7_bm USART_TXPL7_bm
+ #elif defined(USART_TXPL_7_bm)
+ //deprecated_constant_name USART_TXPL7_bm = USART_TXPL_7_bm;
+ #define USART_TXPL7_bm USART_TXPL_7_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_TXPL_7_bp) && defined(USART_TXPL7_bp)
+ #define USART_TXPL_7_bp USART_TXPL7_bp
+ #elif defined(USART_TXPL_7_bp)
+ //deprecated_constant_name USART_TXPL7_bp = USART_TXPL_7_bp;
+ #define USART_TXPL7_bp USART_TXPL_7_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_0_bm) && defined(USART_RXPL0_bm)
+ #define USART_RXPL_0_bm USART_RXPL0_bm
+ #elif defined(USART_RXPL_0_bm)
+ //deprecated_constant_name USART_RXPL0_bm = USART_RXPL_0_bm;
+ #define USART_RXPL0_bm USART_RXPL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_0_bp) && defined(USART_RXPL0_bp)
+ #define USART_RXPL_0_bp USART_RXPL0_bp
+ #elif defined(USART_RXPL_0_bp)
+ //deprecated_constant_name USART_RXPL0_bp = USART_RXPL_0_bp;
+ #define USART_RXPL0_bp USART_RXPL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_1_bm) && defined(USART_RXPL1_bm)
+ #define USART_RXPL_1_bm USART_RXPL1_bm
+ #elif defined(USART_RXPL_1_bm)
+ //deprecated_constant_name USART_RXPL1_bm = USART_RXPL_1_bm;
+ #define USART_RXPL1_bm USART_RXPL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_1_bp) && defined(USART_RXPL1_bp)
+ #define USART_RXPL_1_bp USART_RXPL1_bp
+ #elif defined(USART_RXPL_1_bp)
+ //deprecated_constant_name USART_RXPL1_bp = USART_RXPL_1_bp;
+ #define USART_RXPL1_bp USART_RXPL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_2_bm) && defined(USART_RXPL2_bm)
+ #define USART_RXPL_2_bm USART_RXPL2_bm
+ #elif defined(USART_RXPL_2_bm)
+ //deprecated_constant_name USART_RXPL2_bm = USART_RXPL_2_bm;
+ #define USART_RXPL2_bm USART_RXPL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_2_bp) && defined(USART_RXPL2_bp)
+ #define USART_RXPL_2_bp USART_RXPL2_bp
+ #elif defined(USART_RXPL_2_bp)
+ //deprecated_constant_name USART_RXPL2_bp = USART_RXPL_2_bp;
+ #define USART_RXPL2_bp USART_RXPL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_3_bm) && defined(USART_RXPL3_bm)
+ #define USART_RXPL_3_bm USART_RXPL3_bm
+ #elif defined(USART_RXPL_3_bm)
+ //deprecated_constant_name USART_RXPL3_bm = USART_RXPL_3_bm;
+ #define USART_RXPL3_bm USART_RXPL_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_3_bp) && defined(USART_RXPL3_bp)
+ #define USART_RXPL_3_bp USART_RXPL3_bp
+ #elif defined(USART_RXPL_3_bp)
+ //deprecated_constant_name USART_RXPL3_bp = USART_RXPL_3_bp;
+ #define USART_RXPL3_bp USART_RXPL_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_4_bm) && defined(USART_RXPL4_bm)
+ #define USART_RXPL_4_bm USART_RXPL4_bm
+ #elif defined(USART_RXPL_4_bm)
+ //deprecated_constant_name USART_RXPL4_bm = USART_RXPL_4_bm;
+ #define USART_RXPL4_bm USART_RXPL_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_4_bp) && defined(USART_RXPL4_bp)
+ #define USART_RXPL_4_bp USART_RXPL4_bp
+ #elif defined(USART_RXPL_4_bp)
+ //deprecated_constant_name USART_RXPL4_bp = USART_RXPL_4_bp;
+ #define USART_RXPL4_bp USART_RXPL_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_5_bm) && defined(USART_RXPL5_bm)
+ #define USART_RXPL_5_bm USART_RXPL5_bm
+ #elif defined(USART_RXPL_5_bm)
+ //deprecated_constant_name USART_RXPL5_bm = USART_RXPL_5_bm;
+ #define USART_RXPL5_bm USART_RXPL_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_5_bp) && defined(USART_RXPL5_bp)
+ #define USART_RXPL_5_bp USART_RXPL5_bp
+ #elif defined(USART_RXPL_5_bp)
+ //deprecated_constant_name USART_RXPL5_bp = USART_RXPL_5_bp;
+ #define USART_RXPL5_bp USART_RXPL_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_6_bm) && defined(USART_RXPL6_bm)
+ #define USART_RXPL_6_bm USART_RXPL6_bm
+ #elif defined(USART_RXPL_6_bm)
+ //deprecated_constant_name USART_RXPL6_bm = USART_RXPL_6_bm;
+ #define USART_RXPL6_bm USART_RXPL_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(USART_RXPL_6_bp) && defined(USART_RXPL6_bp)
+ #define USART_RXPL_6_bp USART_RXPL6_bp
+ #elif defined(USART_RXPL_6_bp)
+ //deprecated_constant_name USART_RXPL6_bp = USART_RXPL_6_bp;
+ #define USART_RXPL6_bp USART_RXPL_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+/* VPORT.INTFLAGS */
+ #if !defined(VPORT_INT_0_bm) && defined(VPORT_INT0_bm)
+ #define VPORT_INT_0_bm VPORT_INT0_bm
+ #elif defined(VPORT_INT_0_bm)
+ //deprecated_constant_name VPORT_INT0_bm = VPORT_INT_0_bm;
+ #define VPORT_INT0_bm VPORT_INT_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_0_bp) && defined(VPORT_INT0_bp)
+ #define VPORT_INT_0_bp VPORT_INT0_bp
+ #elif defined(VPORT_INT_0_bp)
+ //deprecated_constant_name VPORT_INT0_bp = VPORT_INT_0_bp;
+ #define VPORT_INT0_bp VPORT_INT_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_1_bm) && defined(VPORT_INT1_bm)
+ #define VPORT_INT_1_bm VPORT_INT1_bm
+ #elif defined(VPORT_INT_1_bm)
+ //deprecated_constant_name VPORT_INT1_bm = VPORT_INT_1_bm;
+ #define VPORT_INT1_bm VPORT_INT_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_1_bp) && defined(VPORT_INT1_bp)
+ #define VPORT_INT_1_bp VPORT_INT1_bp
+ #elif defined(VPORT_INT_1_bp)
+ //deprecated_constant_name VPORT_INT1_bp = VPORT_INT_1_bp;
+ #define VPORT_INT1_bp VPORT_INT_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_2_bm) && defined(VPORT_INT2_bm)
+ #define VPORT_INT_2_bm VPORT_INT2_bm
+ #elif defined(VPORT_INT_2_bm)
+ //deprecated_constant_name VPORT_INT2_bm = VPORT_INT_2_bm;
+ #define VPORT_INT2_bm VPORT_INT_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_2_bp) && defined(VPORT_INT2_bp)
+ #define VPORT_INT_2_bp VPORT_INT2_bp
+ #elif defined(VPORT_INT_2_bp)
+ //deprecated_constant_name VPORT_INT2_bp = VPORT_INT_2_bp;
+ #define VPORT_INT2_bp VPORT_INT_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_3_bm) && defined(VPORT_INT3_bm)
+ #define VPORT_INT_3_bm VPORT_INT3_bm
+ #elif defined(VPORT_INT_3_bm)
+ //deprecated_constant_name VPORT_INT3_bm = VPORT_INT_3_bm;
+ #define VPORT_INT3_bm VPORT_INT_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_3_bp) && defined(VPORT_INT3_bp)
+ #define VPORT_INT_3_bp VPORT_INT3_bp
+ #elif defined(VPORT_INT_3_bp)
+ //deprecated_constant_name VPORT_INT3_bp = VPORT_INT_3_bp;
+ #define VPORT_INT3_bp VPORT_INT_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_4_bm) && defined(VPORT_INT4_bm)
+ #define VPORT_INT_4_bm VPORT_INT4_bm
+ #elif defined(VPORT_INT_4_bm)
+ //deprecated_constant_name VPORT_INT4_bm = VPORT_INT_4_bm;
+ #define VPORT_INT4_bm VPORT_INT_4_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_4_bp) && defined(VPORT_INT4_bp)
+ #define VPORT_INT_4_bp VPORT_INT4_bp
+ #elif defined(VPORT_INT_4_bp)
+ //deprecated_constant_name VPORT_INT4_bp = VPORT_INT_4_bp;
+ #define VPORT_INT4_bp VPORT_INT_4_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_5_bm) && defined(VPORT_INT5_bm)
+ #define VPORT_INT_5_bm VPORT_INT5_bm
+ #elif defined(VPORT_INT_5_bm)
+ //deprecated_constant_name VPORT_INT5_bm = VPORT_INT_5_bm;
+ #define VPORT_INT5_bm VPORT_INT_5_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_5_bp) && defined(VPORT_INT5_bp)
+ #define VPORT_INT_5_bp VPORT_INT5_bp
+ #elif defined(VPORT_INT_5_bp)
+ //deprecated_constant_name VPORT_INT5_bp = VPORT_INT_5_bp;
+ #define VPORT_INT5_bp VPORT_INT_5_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_6_bm) && defined(VPORT_INT6_bm)
+ #define VPORT_INT_6_bm VPORT_INT6_bm
+ #elif defined(VPORT_INT_6_bm)
+ //deprecated_constant_name VPORT_INT6_bm = VPORT_INT_6_bm;
+ #define VPORT_INT6_bm VPORT_INT_6_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_6_bp) && defined(VPORT_INT6_bp)
+ #define VPORT_INT_6_bp VPORT_INT6_bp
+ #elif defined(VPORT_INT_6_bp)
+ //deprecated_constant_name VPORT_INT6_bp = VPORT_INT_6_bp;
+ #define VPORT_INT6_bp VPORT_INT_6_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_7_bm) && defined(VPORT_INT7_bm)
+ #define VPORT_INT_7_bm VPORT_INT7_bm
+ #elif defined(VPORT_INT_7_bm)
+ //deprecated_constant_name VPORT_INT7_bm = VPORT_INT_7_bm;
+ #define VPORT_INT7_bm VPORT_INT_7_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VPORT_INT_7_bp) && defined(VPORT_INT7_bp)
+ #define VPORT_INT_7_bp VPORT_INT7_bp
+ #elif defined(VPORT_INT_7_bp)
+ //deprecated_constant_name VPORT_INT7_bp = VPORT_INT_7_bp;
+ #define VPORT_INT7_bp VPORT_INT_7_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ /* ======= VREF ======= */
+ #if !defined(VREF_REFSEL_0_bm) && defined(VREF_REFSEL0_bm)
+ #define VREF_REFSEL_0_bm VREF_REFSEL0_bm
+ #elif defined(VREF_REFSEL_0_bm)
+ //deprecated_constant_name VREF_REFSEL0_bm = VREF_REFSEL_0_bm;
+ #define VREF_REFSEL0_bm VREF_REFSEL_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VREF_REFSEL_0_bp) && defined(VREF_REFSEL0_bp)
+ #define VREF_REFSEL_0_bp VREF_REFSEL0_bp
+ #elif defined(VREF_REFSEL_0_bp)
+ //deprecated_constant_name VREF_REFSEL0_bp = VREF_REFSEL_0_bp;
+ #define VREF_REFSEL0_bp VREF_REFSEL_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VREF_REFSEL_1_bm) && defined(VREF_REFSEL1_bm)
+ #define VREF_REFSEL_1_bm VREF_REFSEL1_bm
+ #elif defined(VREF_REFSEL_1_bm)
+ //deprecated_constant_name VREF_REFSEL1_bm = VREF_REFSEL_1_bm;
+ #define VREF_REFSEL1_bm VREF_REFSEL_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VREF_REFSEL_1_bp) && defined(VREF_REFSEL1_bp)
+ #define VREF_REFSEL_1_bp VREF_REFSEL1_bp
+ #elif defined(VREF_REFSEL_1_bp)
+ //deprecated_constant_name VREF_REFSEL1_bp = VREF_REFSEL_1_bp;
+ #define VREF_REFSEL1_bp VREF_REFSEL_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VREF_REFSEL_2_bm) && defined(VREF_REFSEL2_bm)
+ #define VREF_REFSEL_2_bm VREF_REFSEL2_bm
+ #elif defined(VREF_REFSEL_2_bm)
+ //deprecated_constant_name VREF_REFSEL2_bm = VREF_REFSEL_2_bm;
+ #define VREF_REFSEL2_bm VREF_REFSEL_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(VREF_REFSEL_2_bp) && defined(VREF_REFSEL2_bp)
+ #define VREF_REFSEL_2_bp VREF_REFSEL2_bp
+ #elif defined(VREF_REFSEL_2_bp)
+ //deprecated_constant_name VREF_REFSEL2_bp = VREF_REFSEL_2_bp;
+ #define VREF_REFSEL2_bp VREF_REFSEL_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ /* ======= WDT ======= */
+ #if !defined(WDT_PERIOD_0_bm) && defined(WDT_PERIOD0_bm)
+ #define WDT_PERIOD_0_bm WDT_PERIOD0_bm
+ #elif defined(WDT_PERIOD_0_bm)
+ //deprecated_constant_name WDT_PERIOD0_bm = WDT_PERIOD_0_bm;
+ #define WDT_PERIOD0_bm WDT_PERIOD_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_PERIOD_0_bp) && defined(WDT_PERIOD0_bp)
+ #define WDT_PERIOD_0_bp WDT_PERIOD0_bp
+ #elif defined(WDT_PERIOD_0_bp)
+ //deprecated_constant_name WDT_PERIOD0_bp = WDT_PERIOD_0_bp;
+ #define WDT_PERIOD0_bp WDT_PERIOD_0_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_PERIOD_1_bm) && defined(WDT_PERIOD1_bm)
+ #define WDT_PERIOD_1_bm WDT_PERIOD1_bm
+ #elif defined(WDT_PERIOD_1_bm)
+ //deprecated_constant_name WDT_PERIOD1_bm = WDT_PERIOD_1_bm;
+ #define WDT_PERIOD1_bm WDT_PERIOD_1_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_PERIOD_1_bp) && defined(WDT_PERIOD1_bp)
+ #define WDT_PERIOD_1_bp WDT_PERIOD1_bp
+ #elif defined(WDT_PERIOD_1_bp)
+ //deprecated_constant_name WDT_PERIOD1_bp = WDT_PERIOD_1_bp;
+ #define WDT_PERIOD1_bp WDT_PERIOD_1_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_PERIOD_2_bm) && defined(WDT_PERIOD2_bm)
+ #define WDT_PERIOD_2_bm WDT_PERIOD2_bm
+ #elif defined(WDT_PERIOD_2_bm)
+ //deprecated_constant_name WDT_PERIOD2_bm = WDT_PERIOD_2_bm;
+ #define WDT_PERIOD2_bm WDT_PERIOD_2_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_PERIOD_2_bp) && defined(WDT_PERIOD2_bp)
+ #define WDT_PERIOD_2_bp WDT_PERIOD2_bp
+ #elif defined(WDT_PERIOD_2_bp)
+ //deprecated_constant_name WDT_PERIOD2_bp = WDT_PERIOD_2_bp;
+ #define WDT_PERIOD2_bp WDT_PERIOD_2_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_PERIOD_3_bm) && defined(WDT_PERIOD3_bm)
+ #define WDT_PERIOD_3_bm WDT_PERIOD3_bm
+ #elif defined(WDT_PERIOD_3_bm)
+ //deprecated_constant_name WDT_PERIOD3_bm = WDT_PERIOD_3_bm;
+ #define WDT_PERIOD3_bm WDT_PERIOD_3_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_PERIOD_3_bp) && defined(WDT_PERIOD3_bp)
+ #define WDT_PERIOD_3_bp WDT_PERIOD3_bp
+ #elif defined(WDT_PERIOD_3_bp)
+ //deprecated_constant_name WDT_PERIOD3_bp = WDT_PERIOD_3_bp;
+ #define WDT_PERIOD3_bp WDT_PERIOD_3_bp //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_WINDOW_0_bm) && defined(WDT_WINDOW0_bm)
+ #define WDT_WINDOW_0_bm WDT_WINDOW0_bm
+ #elif defined(WDT_WINDOW_0_bm)
+ #define WDT_WINDOW0_bm WDT_WINDOW_0_bm //Deprecated as of Q2 2022 header change.
+ #endif
+ #if !defined(WDT_WINDOW_0_bp) && defined(WDT_WINDOW0_bp)
+ #define WDT_WINDOW_0_bp WDT_WINDOW0_bp
+ #elif defined(WDT_WINDOW_0_bp)
+ #define WDT_WINDOW0_bp WDT_WINDOW_0_bp; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(WDT_WINDOW_1_bm) && defined(WDT_WINDOW1_bm)
+ #define WDT_WINDOW_1_bm WDT_WINDOW1_bm
+ #elif defined(WDT_WINDOW_1_bm)
+ #define WDT_WINDOW1_bm WDT_WINDOW_1_bm; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(WDT_WINDOW_1_bp) && defined(WDT_WINDOW1_bp)
+ #define WDT_WINDOW_1_bp WDT_WINDOW1_bp
+ #elif defined(WDT_WINDOW_1_bp)
+ #define WDT_WINDOW1_bp WDT_WINDOW_1_bp; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(WDT_WINDOW_2_bm) && defined(WDT_WINDOW2_bm)
+ #define WDT_WINDOW_2_bm WDT_WINDOW2_bm
+ #elif defined(WDT_WINDOW_2_bm)
+ #define WDT_WINDOW2_bm WDT_WINDOW_2_bm; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(WDT_WINDOW_2_bp) && defined(WDT_WINDOW2_bp)
+ #define WDT_WINDOW_2_bp WDT_WINDOW2_bp
+ #elif defined(WDT_WINDOW_2_bp)
+ #define WDT_WINDOW2_bp WDT_WINDOW_2_bp; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(WDT_WINDOW_3_bm) && defined(WDT_WINDOW3_bm)
+ #define WDT_WINDOW_3_bm WDT_WINDOW3_bm
+ #elif defined(WDT_WINDOW_3_bm)
+ #define WDT_WINDOW3_bm WDT_WINDOW_3_bm; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(WDT_WINDOW_3_bp) && defined(WDT_WINDOW3_bp)
+ #define WDT_WINDOW_3_bp WDT_WINDOW3_bp
+ #elif defined(WDT_WINDOW_3_bp)
+ #define WDT_WINDOW3_bp WDT_WINDOW_3_bp; //Deprecated as of Q2 2022 header change
+ #endif
+
+ /* ======= ZCD ======= */
+ #if !defined(ZCD_INTMODE_0_bm) && defined(ZCD_INTMODE0_bm)
+ #define ZCD_INTMODE_0_bm ZCD_INTMODE0_bm
+ #elif defined(ZCD_INTMODE_0_bm)
+ #define ZCD_INTMODE0_bm ZCD_INTMODE_0_bm; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(ZCD_INTMODE_0_bp) && defined(ZCD_INTMODE0_bp)
+ #define ZCD_INTMODE_0_bp ZCD_INTMODE0_bp
+ #elif defined(ZCD_INTMODE_0_bp)
+ #define ZCD_INTMODE0_bp ZCD_INTMODE_0_bp; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(ZCD_INTMODE_1_bm) && defined(ZCD_INTMODE1_bm)
+ #define ZCD_INTMODE_1_bm ZCD_INTMODE1_bm
+ #elif defined(ZCD_INTMODE_1_bm)
+ #define ZCD_INTMODE1_bm ZCD_INTMODE_1_bm; //Deprecated as of Q2 2022 header change
+ #endif
+ #if !defined(ZCD_INTMODE_1_bp) && defined(ZCD_INTMODE1_bp)
+ #define ZCD_INTMODE_1_bp ZCD_INTMODE1_bp
+ #elif defined(ZCD_INTMODE_1_bp)
+ #define ZCD_INTMODE1_bp ZCD_INTMODE_1_bp; //Deprecated as of Q2 2022 header change
+ #endif
+#endif /* this is the end of the backwards compatibility defines */
+#endif // end of core_devices
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/core_parameters.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/core_parameters.h
new file mode 100644
index 0000000..8e88830
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/core_parameters.h
@@ -0,0 +1,86 @@
+#ifndef __CORE_PARAMETERS_H__
+#define __CORE_PARAMETERS_H__
+
+#if !defined(MEGATINYCORE_NUM)
+ #if !(defined(MEGATINYCORE_MAJOR) && defined(MEGATINYCORE_MINOR) && defined(MEGATINYCORE_PATCH) && defined(MEGATINYCORE_RELEASED))
+ #warning "All of the version defines are missing, please correct your build environment; it is likely failing to define other critical values"
+ // Version related defines now handled in platform.txt
+ #else
+ #define MEGATINYCORE_NUM ((MEGATINYCORE_MAJOR << 24) + (MEGATINYCORE_MINOR << 16) + (MEGATINYCORE_PATCH << 8) + MEGATINYCORE_RELEASED)
+ #endif
+#endif
+
+#if !(defined(MEGATINYCORE) || defined(DXCORE) || defined(ATTIYNCORE))
+
+ // This define can get black-hole'ed somehow (reported on platformio) likely the ugly syntax to pass a string define from platform.txt via a -D
+ // directive passed to the compiler is getting mangled somehow, though I'm amazed it doesn't cause a compile error. But checking for defined(MEGATINYCORE)
+ // is the documented method to detect that megaTinyCore is in use, and without it things that tried to do conditional compilation based on that were not
+ // recognizing it as megaTinyCore and hence would fail to compile when that conditional compilation was required to make it build.
+ // From: https://github.com/adafruit/Adafruit_BusIO/issues/43
+
+ // The whole purpose of this file is largely for for the purpose of being something that can be included anywhere to make sure we know what core we are
+ // which becomes more and more important as more code is shared between the cores.
+
+ #define MEGATINYCORE "Unknown 2.6.9+"
+#else
+ #if defined(DXCORE) || defined(ATTINYCORE)
+ #error "This is megaTinyCore being compiled, but DXCORE and/or ATTINYCORE is defined already, something is way wrong."
+ #endif
+#endif
+
+
+/* Check for invalid options, mostly to help point the PIO and other third party IDE users in the right direction */
+
+#if defined(MILLIS_USE_TIMERA0) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERRTC_XTAL))
+ #error "MILLIS_USE_TIMERA0 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERA1) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA0) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERRTC_XTAL))
+ #error "MILLIS_USE_TIMERA1 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERB0) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERA0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERRTC_XTAL))
+ #error "MILLIS_USE_TIMERB0 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERB1) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERA0) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERRTC_XTAL))
+ #error "MILLIS_USE_TIMERB1 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERB2) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERA0) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERRTC_XTAL))
+ #error "MILLIS_USE_TIMERB2 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERB3) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERA0) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERRTC_XTAL))
+ #error "MILLIS_USE_TIMERB3 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERD0) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERA0) || defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERRTC_XTAL))
+ #error "MILLIS_USE_TIMERB5 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERRTC) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERA0))
+ #error "MILLIS_USE_TIMERE0 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERRTC_XTAL) && (defined(MILLIS_USE_TIMERNONE) || \
+ defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || \
+ defined(MILLIS_USE_TIMERA1) || defined(MILLIS_USE_TIMERD0) || defined(MILLIS_USE_TIMERA0))
+ #error "MILLIS_USE_TIMERF0 and another timer are set as the millis timer. Specify one only. If this occurred on the Arduino IDE, please report it promptly."
+#endif
+#if defined(MILLIS_USE_TIMERE0) || defined(MILLIS_USE_TIMERF0)
+ #error "A millis timer not supported on this core was passed. this should only be possible on third party IDEs. "
+#endif
+#if defined(UARTBAUD5V) || defined(UARTBAUD3V)
+ #warning "The UARTBAUDxV baud rate correction was removed in 2.3.0 because it had excessive overhead and negligible benefit. The define you specified does nothing."
+#endif
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/dirty_tricks.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/dirty_tricks.h
new file mode 100644
index 0000000..46715cd
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/dirty_tricks.h
@@ -0,0 +1,347 @@
+/* dirty_tricks.h - Where all the ugly asm macros live.
+ * Copyright Spence Konde 2023
+ * Part of DxCore and megaTinyCore, which are open source
+ * and released under the LGPL 2.1
+ * See LICENSE.txt for full legal boilerplate if you must
+ */
+
+/* Okay... This was getting absurd. We had too many piecemeal hacks to work around shit compiler output, the poor quality of which is was apparent immediately upon
+ * examination of the assembler listings early on, in code that was everywhere, and hence which I had to stare at any time I debugged anything.
+ * We (well, me and the one, maybe two other people here who speak fluent avr asm) all knew we needed unholy tricks like this.
+ * We wish we didn't. But while the GCC part of avr-gcc does a pretty thorough and consistent job optimizing..
+ * The AVR part is piss-poor. It's fucking awful. As I understand it, GCC from a big picture, first transforms the code into an idealized
+ * version that has standins for registers and is architecture agnostic, but tends to correspond very very nearly with machine instructions. Because there is
+ * a massive amount of stuff compiled with GCC and other tools built on the same foundations (they're the only game in town if aren't willing to use a proprietary
+ * one. I don't really understand the appeal of those... ) considerable effort has been directed towards improvement, in
+ * order to improve efficiency of high profile computing applications
+ * This happens in many passes to perform optimization that isn't machine specific (and hence have gotten resources lavished on them by everyone).
+ * Then, it has to go from that ideal world to reality, and start naming instructions and assigning registers. This is machine specific.
+ * And it is here that AVR hasn't gotten much love. The result is sometimes what might be termed pathological assembly (as in, it is indicative disease).
+ * If generated assembly like SBIW r26, 20 immediately followed by ADIW r26, 23 - (or any other constant integers 63 or lower) is not a sign of disease,
+ * I don't know what would be. That's when the compiler has generated code that assumes all three pointer registers can do displacement. Only two of them can,
+ * because there aren't enough unique instructions that can be expressed in 16 bits to implement ldd/std on all three pointer registers (ldd/std consume
+ * a huge number of opcodes. Each pointer worth of opcodes is 1/16th of the total (along with the six immediates plus rcall and rjmp.
+ * That is, these 10 instructions account for 62.5% of the opcodes in the avr instructionset! There are 4096 different opcodes for each of them!)
+ * and that's why while we have 3 pointer registers, we have only two that are fully functional, and which each have 2048 displaced load and 2048 displaced
+ * store opcodes (32 registers * 64 q's from 0-63), making a total of 4096 displaced ld/st's, plus 128 pre/post decremented ones, 4224 in total. The X register, the runt
+ * of the litter, has only ld/st X, ld/st X+ and ld/st -X, a mere 192 opcodes (we could have totally had a 4th pointer, too, in terms of instruction opcodes at least)
+ *
+ * Unfortunately, both Atmel and Microchip have been asleep at the switch here, and not much has been done to make sure that AVR code that gets output isn't terrible
+ * The compiler appears to be
+ * - Often blind to when a pointer is being used to access offsets and hence we should be using the y and z registers with ldd and std
+ * - Inept at combining bytes into larger data types.
+ * - Stupid about isr prologues and epilogs (it looks inside the ISR - and sees what registers need to be saved and restored in order to not corrupt the state of the registers, but it
+ * can't tell if tmp_reg, zero_reg, or SREG are changed by the body of the code so it always saves and restores those)
+ * - bad at bitshifts with multibyte datatypes.
+ *
+ * Since like any good programmer, we have some idea of what our code should be compiling to while writing it, there come to be times when we have to look at
+ * the assembly listing, and when we do we see the so-called optimizer butchering our code in unspeakable ways, wasting precious flash and excecuing slower than
+ * a slug trying to skateboard up a flight of stairs.
+ *
+ * The offences with speed are much larger in magnitude, though we often care less about this (though occasionally we care more about speed than anyything else)
+ * as compared to offenses against flash size, which on embedded systems must always be on our minds.
+ *
+ * To rectify the problems, assorted snippets of inline asm has been written which are an attempt to slap some sense into the compiler, and these have joined more
+ * prosaic assembly macros like the NOP gang.
+ *
+ * The macros were a fucking pain to type (all caps) and the names were both long and inconsistent.
+ *
+ * With this update, we are centralizing and documenting all the dirty assembler tricks.
+ *
+ * I know that mixing lowercase names and macros is sinful. Yes these are macros. Except for the classics (and we have appropriate duplicated of those), they are now lowercase.
+ * I know macros are supposed to be all uppercase. But we're prefixing them with an underscore, so you still know there's spooky shit involved, it's just
+ * too unpleasant to type and too ugly to read to have all these longass macro names, making a mess of all our core "speed matters" code - and besides that,
+ * while macros generally don't care what types they get passed, these totally will cast the arguments to specific types like functions do (actually, significantly more vigorously)
+ *
+ * General Advice:
+ * Don't use any of the wacky ones unless you know what the fuck you're doing. This is largely for internal use within the core, because we do, and we know that
+ * lots of people don't know nor want to know asm (even normal, polite asm, which this often isn't), and thus couldn't reproduce this performance enhancement
+ * if they needed or wanted it, and that describes most people who use the core. Essentially, I feel that when I see a way to silently make the core perform better, even if it looks
+ * heinous, do it, because if you don't, nobody else will, and surely someomne out there needs a bit more performance right?
+ * bit of code - either repeated a lot, and/or in a time-critical section of code that benefits from doing unholy things like this, we're going to do it to make
+ * the core better.
+ *
+ * Many of these hinge upon bullying the compiler into assigning registers less stupidly. These do not at all prevent the register allocator from
+ * smacking down the whole thing with a gigantic wad of fail if it thinks it has to (ie, when you're out of pointer registers). These should be used only with one eye
+ * on the compiler listings to spot this, because at that point they are usually causing harm instead of good.
+ *
+ * List of dirty trick macros
+ * Not dirty - cycle counting macros:
+ * _NOP()
+ * _NOP2()
+ * _NOPNOP()
+ * _NOP8()
+ * _NOP14()
+ *
+ * And in lower case:
+ * _nop()
+ * _nop2()
+ * _nop8()
+ * _nop14()
+ *
+ * Not particularly dirty - AVRs have a single instruction nybble-swap:
+ * _SWAP(n)
+ * _swap(n)
+ *
+ * And now all the hideously dirty ones:
+ * In all cases, pointer-like 16-bit values should be a local variable, either a pointer or uint16_t.
+ * These "tricks" allow us to
+ * _addLow(uint16_t a, uint8_t b)
+ * _subLow(uint16_t a, uint8_t b)
+ * _addHigh(uint16_t a, uint8_t b)
+ * _subHigh(uint16_t a, uint8_t b)
+ * _addLowConst(uint16_t a, const uint8_t b)
+ * _subLowConst(uint16_t a, const uint8_t b)
+ * _addHighConst(uint16_t a, const uint8_t b)
+ * _subHighConst(uint16_t a, const uint8_t b)
+ * _setHigh(uint16_t a, uint8_t b)
+ * _setHighConst(uint16_t a, const uint8_t b)
+ * _clrHigh(uint16_t a)
+ * _setLow(uint16_t a, uint8_t b)
+ * _setLowConst(uint16_t a, const uint8_t b)
+ * _clrLow(uint16_t a)
+ * _fastPtr_z(uint16_t __localVar__, uint16_t __pointer__)
+ * _fastPtr_y(uint16_t __localVar__, uint16_t __pointer__)
+ * _fastPtr_x(uint16_t __localVar__, uint16_t __pointer__)
+ * _fastPtr_d(uint16_t __localVar__, uint16_t __pointer__)
+ * _fastPtr(uint16_t __localVar__, uint16_t __pointer__)
+ * _makeFastPtr_d(uint8_t * newptt, const uint8_t highbyte, uint8_t lowbyte)
+ * _makeFastPtr(uint8_t * newptt, const uint8_t highbyte, uint8_t lowbyte)
+ */
+
+
+
+
+#ifndef DIRTY_TRICKS_H
+#define DIRTY_TRICKS_H
+;
+#ifndef _NOP
+ #define _NOP() __asm__ __volatile__ ("nop")
+#endif
+#ifndef _NOP2
+ #define _NOP2() __asm__ __volatile__ ("rjmp .+0")
+#endif
+#ifndef _NOPNOP
+ #define _NOPNOP() __asm__ __volatile__ ("rjmp .+0")
+#endif
+#ifndef _NOP8
+ #define _NOP8() __asm__ __volatile__ ("rjmp .+2" "\n\t" /* 2 clk jump over next instruction */ \
+ "ret" "\n\t" /* 4 clk return "wha? why here?" */ \
+ "rcall .-4" "\n\t" ) /* 2 clk "Oh, I see. We jump over a return (2 clock) call it, and then immediately return." */
+#endif
+
+/*
+Not enabled. Ugly ways to get delays at very small flash cost.
+#ifndef _NOP6
+ #define _NOP6() __asm__ __volatile__ ("rcall lonereturn") // 2 bytes of flash. 2+4=6 clk only works if you've got _LONE_RETURN() somewhere. Only guaranteed to work on 8k and smaller parts.
+ #define _NOP7() __asm__ __volatile__ ("call lonereturn") // 4 bytes of flash. 3+4=7 clk and see above, except that this will only work w/>8k flash.
+ #define _LONE_RETURN() __asm__ __volatile__ ("rjmp .+2" "\n\t" \ // 4 bytes of flash overhead, but must exist once and only once for NOP6/7 (but not any others) . Don't trip over thr ret. Note that if you're writing inline assembly with ret elsewhere, just proceed
+ "lonereturn:" "\n\t" \ // it with a a label and jump to it to save 2 bytes vs this methodMust exist somwehere for
+ "ret" "\n\t" )
+ // It could be put into it's own function and marked with the "used" attribute. This allows elimination of the initial rjmp, at the cost of making an ugly hack even uglier.
+ // Or even worse, you have other inline assembly, and you just stick the label right before the return!
+ // Really, these are things you shoudnt do unless you have your back against the flash/RAM limits and a gun to your head.
+ #endif
+*/
+
+
+/* Beyond this, just use a loop.
+ * If you don't need submicrosecond accuracy, just use delayMicroseconds(), which uses very similar methods. See Ref_Timers
+ * (eg, ldi (any upper register), n; dec r0; brne .-4)
+ * and pad with rjmp or nop if needed to get target delay.
+ * Simplest form takes a uint8_t and runs for 3n cycles in 3 words. Padded with `nop` or `rjmp .+0`for 3n + 1 or 3n + 2 if outside the loop, 4n or 5n if padded inside the loop
+ * And so on. You will likely end up doing something like
+ *
+ #define CLOCKS_PER_US (F_CPU / 1000000); // preprocessed away
+ #define DELAYCLOCKS (0.8 * CLOCKS_PER_US) // say we wanted a 0.8 us delay.
+ uint8_t x = DELAYCLOCKS / 3; // preprocessed into a constant
+ __asm__ __volatile__ ("dec %0" "\n\t" // before this, an ldi is used to load x into the input operand %0
+ "brne .-4" "\n\t"
+ #if (DELAYCLOCKS % 3 == 2) // 2 clocks extra needed at end
+ "rjmp .+0" "\n\t"
+ #elif (DELAYCLOCKS % 3 == 1) // 1 clock extra needed at end
+ "nop" "\n\t"
+ #endif
+ : "+d"((uint8_t)(x));
+ *
+ * The above will take very close to 0.8us under most any conditions. Notice how all the calculation was moved to the preprocessor.
+ *
+ *
+ * You can extend the length of the iterations by adding nop between the dec and brne, and branching 2 bytes further. that makes it 4 clocks per iteration.
+ * You can go for much longer by using 16-bits:
+ * uint16_t x = 2000; * overall takes 8 bytrsd
+ * __asm__ __volatile__ ("sbiw %0,1" "\n\t" // Line is preceded by 2 implied LDI's to fill that upper register pair, Much higher chance of having to push and pop.
+ * \"brne .-4 \"\n\t\" // SBIW takes 2 clocks. branch takes 2 clocks unless it doesn't branch, when it only takes one
+ * : +w"((uint16_t)(x)) // hence this takes 4N+1 clocks (4 per iteration, except for last one which is only 3, plus 2 for the pair of LDI's)
+ *
+ */
+
+
+// The fastest way to swap nybbles
+#ifndef _SWAP
+ #define _SWAP(n) __asm__ __volatile__ ("swap %0" "\n\t" :"+r"((uint8_t)(n)))
+#endif
+/* Lowercase versions, in keeping with the theme that will be used for these macros now, to make the code less hideous and easier to type. */
+#define _swap(n) __asm__ __volatile__ ("swap %0" "\n\t" :"+r"((uint8_t)(n)))
+#define _nop() __asm__ __volatile__ ("nop")
+#define _nop2() __asm__ __volatile__ ("rjmp .+0")
+#define _nop8() __asm__ __volatile__ ("rjmp .+2" "\n\t" "ret" "\n\t" "rcall .-4" "\n\t")
+#define _nop14() __asm__ __volatile__ ("rjmp .+2" "\n\t" "ret" "\n\t" "rcall .-4" "\n\t" "rcall .-6" "\n\t")
+
+/*********************/
+/* Low and high Math */
+/*********************/
+/* These are dirty, ugly hacky things. What is the point of them? They save a single clock each when used at a point where they are relevant and correct.
+ By prohibiting the crossing of a 256b barier (the high versions are less useful I daresay...), you save a clock cycle. Note that wraparound behavior is predictable
+
+ A big part of this was just how often the stock code was doing this, over and over and over:
+ adiw r26, 10
+ ld X, rwhatever
+ sbiw r26, 10
+ adiw r26, 12
+ ld X, rsomeother
+ sbit r26, 12
+ ADIW and SBIW are both 2 clock instructions, and a load is 2, so that's 6 clocks; you can do it in 3n+1 instead of 6n clocks as long as they're in the same block of 256 addresses, which is often guaranteed.
+ Other times you may be subtracting values that are mathematically certain to never result in an over or underflow
+*/
+
+#define _addLow(a,b) __asm__ __volatile__ ("add %0A, %1" "\n\t" :"+r"((uint16_t)(a)):"r"((uint8_t) b))
+#define _subLow(a,b) __asm__ __volatile__ ("sub %0A, %1" "\n\t" :"+r"((uint16_t)(a)):"r"((uint8_t) b))
+#define _addHigh(a,b) __asm__ __volatile__ ("add %0B, %1" "\n\t" :"+r"((uint16_t)(a)):"r"((uint8_t) b))
+#define _subHigh(a,b) __asm__ __volatile__ ("sub %0B, %1" "\n\t" :"+r"((uint16_t)(a)):"r"((uint8_t) b))
+#define _addLowConst(a,b) __asm__ __volatile__ ("subi %0A, %1" "\n\t" :"+r"((uint16_t)(a)):"M"((uint8_t) (0x00 - ((uint8_t) b))))
+#define _subLowConst(a,b) __asm__ __volatile__ ("subi %0A, %1" "\n\t" :"+r"((uint16_t)(a)):"M"((uint8_t) b))
+#define _addHighConst(a,b) __asm__ __volatile__ ("subi %0B, %1" "\n\t" :"+r"((uint16_t)(a)):"M"((uint8_t) (0x00 - ((uint8_t) b))))
+#define _subHighConst(a,b) __asm__ __volatile__ ("subi %0B, %1" "\n\t" :"+r"((uint16_t)(a)):"M"((uint8_t) b))
+
+/* _addLow(uint16_t a, uint8_t b) // note that a only needs to be something that can be cast to a 16-bit unsigned value
+ * _subLow(uint16_t a, uint8_t b) // It's type is not changed, but it's value is changed, and the math is done as though it were a uint16_t
+ * _addHigh(uint16_t a, uint8_t b) // Much less often useful - this is exactly analogous to above, except operating on high byte
+ * _subHigh(uint16_t a, uint8_t b) // But you do occasionally need to do it.
+ *
+ * These perform a subtraction on the low (or high) byte. That's it. They do not make any sort of attempt to handle over/underflow.
+ * It saves a clock cycle and an instruction word when you are doing math where are adding or subtracting an 8-bit value to/from a 16-bit one.
+ * but you KNOW there will never be a carry or borrow, and thus, you can do the math on the low byte in isolation.
+ * Why do you want to do this? Probably because the thing you're adding or subtracting a little to/from is a pointer to a memory address, like
+ * the start of an instance of a peripheral and you're adding the offset to it. The peripherals are all aligned on 16, 32, 64, or 128 byte bounds
+ * and have at most that many registers. There may be times when you have 256-byte aligned pointers, too. When you want to offset them and either
+ * you need an offset of more than 63, or you know that you're already out of pointer pairs that can do displacement (and you're not working
+ * with a straight up constant. If the address can be constant-folded, and you are only using it once, this doesn't help and actually makes it worse)
+ *
+ * In that case, while normally you'd do:
+ *
+ * uint8_t foo = *(base_pointer + 17);
+ *
+ * and it would perform an std z+17 or std y+17 depending on whether it's in the z or y pointer.
+ * But std requires q to be 0-63 (you may need more), and the base pointer to be y or z (you may know that those two pointers have to already be
+ * in use), and that the offset be constant (if it was, say, a number between 0x10 and 0x17 because you're writing to a PORTx.PINnCTRL register)
+ * If x and y are unavailable but the offset is constant, then you get a 2-word 4-clock penalty as std becomes adiw, st, sbiw. If the offset isn't
+ * constant, it's add adc st sub subc, still 4 clock penalty, but now 4 words too (same if it's a constant larger than 63, except with subi instead
+ * of add and sub) This reduces it to 1 clock and 1 word - though you need to remember it's now pointing to a different place, and correct for that
+ * next time you use it.
+ * (note: If base_pointer is a compile time constant and is used only once it's better to just do the normal way too, because then it comes out as a
+ * 2-word 2-clock sts, instead of 2 words to ldi the address then one more to st to it).
+ *
+ * Finally, be aware that you're still going to get a lot of overhead (though some is not avoidable) if you are already using all three pointers.
+ */
+
+/*********************/
+/* Low and high Set */
+/*********************/
+#define _setHigh(a,b) __asm__ __volatile__ ("mov %0B, %1" "\n\t" :"+r"((uint16_t)(a)):"r"((uint8_t) b))
+#define _setHighConst(a,b) __asm__ __volatile__ ("ldi %0B, %1" "\n\t" :"+d"((uint16_t)(a)):"M"((uint8_t) b))
+#define _clrHigh(a) __asm__ __volatile__ ("eor %0B, %0B" "\n\t" :"+r"((uint16_t)(a)))
+#define _setLow(a,b) __asm__ __volatile__ ("mov %0A, %1" "\n\t" :"+r"((uint16_t)(a)):"r"((uint8_t) b))
+#define _setLowConst(a,b) __asm__ __volatile__ ("ldi %0A, %1" "\n\t" :"+d"((uint16_t)(a)):"M"((uint8_t) b))
+#define _clrLow(a) __asm__ __volatile__ ("eor %0A, %0A" "\n\t" :"+r"((uint16_t)(a)))
+/* _setHigh(uint16_t a, uint8_t b)
+ * _setHighConst(uint16_t a, const uint8_t b)
+ * _clrHigh(uint16_t a)
+ * _setLow(uint16_t a, uint8_t b)
+ * _setLowConst(uint16_t a, const uint8_t b)
+ * _clrLow(uint16_t a)
+ *
+ * Note that a can be any 16-bit value (likely a pointer), and it will be changed in place.
+ *
+ * Constants must use the const version, otherwise you will pay a 1-clock 1-word penalty, and you were trying to avoid that.
+ *
+ * These allow you to perform surgery on a 16-bit values that already exist, where you wish to change the high or low byte
+ * without altering the other byte. Amazingly, the compiler doesn't optimize this like you'd expect it to (likely because
+ * of C type promotion rules).
+ */
+
+/************/
+/* _fastPtr */
+/************/
+#define _checkType(_varA_, _varB_) if (!__builtin_types_compatible_p(__typeof__(_varA_), __typeof__(_varB_))) { badArg("Non-compatible types"); }
+#define _fastPtr_z(_localVar_, _pointer_) _checkType(_localVar_, _pointer_); __asm__ __volatile__("\n\t": "=&z"(_localVar_) : "0"(_pointer_)); // r30:r31
+#define _fastPtr_y(_localVar_, _pointer_) _checkType(_localVar_, _pointer_); __asm__ __volatile__("\n\t": "=&y"(_localVar_) : "0"(_pointer_)); // r28:r29
+#define _fastPtr_x(_localVar_, _pointer_) _checkType(_localVar_, _pointer_); __asm__ __volatile__("\n\t": "=&x"(_localVar_) : "0"(_pointer_)); // r26:r27
+#define _fastPtr_d(_localVar_, _pointer_) _checkType(_localVar_, _pointer_); __asm__ __volatile__("\n\t": "=&b"(_localVar_) : "0"(_pointer_)); // Y or Z
+#define _fastPtr(_localVar_, _pointer_) _checkType(_localVar_, _pointer_); __asm__ __volatile__("\n\t": "=&e"(_localVar_) : "0"(_pointer_)); // X,Y or Z
+/* _fastPtr_z(__localVar__, __pointer__)
+ * _fastPtr_y(__localVar__, __pointer__)
+ * _fastPtr_x(__localVar__, __pointer__)
+ * _fastPtr_d(__localVar__, __pointer__)
+ * _fastPtr(__localVar__, __pointer__)
+ *
+ * GCC fails to optimize memory accesses on AVR.
+ * When accessing memory, GCC is using STS/LDS, using 2 words per instruction and 2/3 clocks respectively.
+ * In some cases, the programmer knows in advance that the function will access multiple peripheral registers or a bigger struct. (<= +63)
+ * To convince GCC that loading the pointer in advance will be more efficient, this defines are provided. The inline assembly forces GCC
+ * To use the instruction STD/LDD that are just one word big and need only 1/2 clocks respectively, allowing for smaller code and faster execution.
+ * It should be considered, that the address has to be loaded into the register first, thus adding 2 words and 2 clocks overhead. Not to mention the compiler
+ * might use the register for something else already. As GCC simulates Displacement on X with adiw/sbiw, it is not recommended to use "E" or "X" for
+ * optimizations. They were added for completion.
+ *
+ * How to use:
+ * declare local pointer variable with the same type as the original pointer, e.g. ADC_t* pADC;
+ * use one of the defines below. e.g. FORCE_LOAD_POINTER_IN_B(pADC, &ADC0)
+ * and voila! all memory accesses to ADC0 are, e.g. Y+xx or Z+xx
+ * it is also possible to use a function argument as __localVar__ and __pointer__ (see twi.c slave ISR)
+ *
+ * How do the instructions work?
+ * '=' is a modifier, that signals the compiler that whatever was in the register beforehand will be overwritten. The compiler should save the value, if it will be needed afterwards
+ * '&' is a modifier, that makes the compiler add a prequel to the assembly where the value (the one in brackets) is loaded in the specified register
+ * 'z' is a constraint that tells the compiler what register to load a value into, in this case, the Z register.
+ * '0' is a matching constraint. It tells the compiler that this input constraint is the same thing as the (number-) matching output operand. basically saying __localVar__ = __pointer__;
+ * Note: The compiler is not prevented from shitting on these - it can still overrule you by moving the pointer to the register you ask and then moving it out, but if it's doing that,
+ * the overhead is probably not avoidable: you filled up all the pointers so no matter what happens will probably be bad; hence why we recommend keeping one eye on the asm listing.
+ * If you think you can do better in that scenario, you're probably going to have to write some assembly. At least it's AVR not something horrible like PIC!
+ *
+ */
+
+/****************/
+/* _makeFastPtr */
+/****************/
+#define _makeFastPtr_d(newptt, highbyte, lowbyte) (__asm__ __volitile("ldi %0B, %1 " "\n\t" "mov %0A, %2 " "\n\t":"+b"((uint16_t) newptr):"M" ((uint8_t) highbyte), "r" ((uint8_t ), lowbyte)
+#define _makeFastPtr(newptt, highbyte, lowbyte) (__asm__ __volitile("ldi %0B, %1 " "\n\t" "mov %0A, %2 " "\n\t":"+e"((uint16_t) newptr):"M" ((uint8_t) highbyte), "r" ((uint8_t ), lowbyte)
+/* _makeFastPtr_d(uint8_t * newptt, const uint8_t highbyte, uint8_t lowbyte)
+ * _makeFastPtr(uint8_t * newptt, const uint8_t highbyte, uint8_t lowbyte)
+ *
+ * Very similar to the above. Passed a pointer as two bytes, the high byte constant and the low byte not, this finds use in the same sort
+ * of situatios as high/low math. See the I/O headers: each class of peripherals often has the same high byte for all addresses. Ports (0x0400, 0x0420, 0x0440
+ * and so on. The most frequently used functions get special attention paid to this as a small gain adds up for the most commonly called functions
+ * usage is typically sdmething like
+ * lowbyte = (_SWAP(usartnbr)); // passed from,elsewhere io the code, which must be free of bugs!
+ * lowbyte <<= 1;
+ * volatile uint8_t *myptr l;
+ * _makeFastPtr_d(myptr. 0x08, lowbyte)
+ * Now, myptr points to the start of the specified USART, in just 2 clock cycles (4 counting the setup in the example), instead of the typical 4 (6) the compiler creates.
+ * This, like most of this file, is the sort of thing you should use under the most constrained conditions only (in an ISR, or a core function that gets called right and left
+ * or extreme-time-sensitive moments, or when you are using a part with less flash than you should, can't get one with larger flash (either they don't exist, or are
+ * backordered past next year), and you just desperately need a tiiiiiiny bit more flash, but you've exhausted the usual methods.
+ *
+ * SK: I've totally been desperate enough on a 16k part that I was replacing double-quoted strings 1 character long with single quoted characters
+ * in order to get rid of the space the null took up and pulling strings from progmem to RAM because that saved a word vs printing it with F() macro
+ * (it was a classic AVR, no memory mapped flash). I was told 500 of them were getting programmed the next day and we needed a feature added. One that I suspected
+ * weeks ago would be needed, but they'd finally realized it the evening before D-day at around 9pm with a few hundred byes of flash left. Good times! Would have been cake if I knew ASM then
+ * since then I could optimize the code.
+ *
+ * _makeFastPtr() should be used when you are only reading from that one address, or consecutive addresses starting there (eg, *ptr++ or *--ptr),
+ * so it can use the X, Y or Z register.
+ * _makeFastPtr_d() uses only X or Y register, and should be used if you expect to be accessing constant compile time known constant offsets
+ *
+ */
+
+ #endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/errata.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/errata.h
new file mode 100644
index 0000000..5303626
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/errata.h
@@ -0,0 +1,232 @@
+#ifndef _ERRATA_H
+#define _ERRATA_H
+
+#if defined(__AVR_Tiny_0__)
+ /* None of these have ever gotten a die rev that fixed bugs - the only "erratum"
+ * that they fixed involved something written during factory cal.
+ */
+ #if _AVR_FLASH == 16 || _AVR_FLASH == 8 /* 1604, 1606, 1607, 804, 806, 807 */
+
+ #define ERRATA_CCL_OUTEN (-1)
+ #define ERRATA_CCL_DLATCH (-1)
+ #define ERRATA_RTC_PITANDRTC (-1)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_USART_ONEWIRE_PINS (-1)
+ #define ERRATA_USART_WAKE (-1)
+ #define ERRATA_ADC_FREERUN (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_TCB_SYNCUPD (-1)
+ #define ERRATA_TCB_PULSELEN (-1)
+ #else /* 202, 204, 402, 404, 406 */
+ #define ERRATA_CCL_OUTEN (-1)
+ #define ERRATA_CCL_DLATCH (-1)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_ADC_FREERUN (-1)
+ #define ERRATA_RTC_PITANDRTC (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_TCB_SYNCUPD (-1)
+ #define ERRATA_TCB_PULSELEN (-1)
+ #define ERRATA_USART_ONEWIRE_PINS (-1)
+ #define ERRATA_USART_WAKE (-1)
+ #endif
+ #define ERRATA_USART_FRAMING (0)
+ #define ERRATA_TCD_ASYNC_COUNTPSC (-128) // Tiny 0 has no TCD
+ #define ERRATA_TCD_HALTANDRESTART (-128)
+ #define ERRATA_TCD_AUTOUPDATE (-128)
+ #define ERRATA_TWI_ASSORTED (0)
+ #define ERRATA_USART_ISFIF (0)
+ #define ERRATA_ADC_WCMP (0)
+ #define ERRATA_AC_FALSETRIGGER (0)
+ #define ERRATA_AC_INTFLAG (0)
+ #define ERRATA_ADC_ASDVSAMPLEN (0)
+ #define ERRATA_ADC_FLAGSRESH (0)
+ #define ERRATA_TWI_PINS (0) /* Not in any errata? Huh? */
+ #define ERRATA_TWI_FLUSH (0) /* Flush bug hasn't showed up on any 1-series errata */
+ #define ERRATA_ADC_LOWLAT (-128) /* There's no LOWLAT here cause the ADC doesn't have it*/
+#elif defined(__AVR_Tiny_1__)
+ #if _AVR_FLASH == 32 /* 3216 and 3217
+ * Them lucky 32k parts, they get all the breaks! Not only did they start with a less buggy design overall,
+ * they also have given it a die rev (to Rev. C - Rev. B was never shipped)
+ */
+ #define ERRATA_CCL_OUTEN (2)
+ #define ERRATA_CCL_DLATCH (2)
+ #define ERRATA_RTC_PITANDRTC (2)
+ #define ERRATA_AC_FALSETRIGGER (0)
+ #define ERRATA_AC_INTFLAG (0)
+ #define ERRATA_USART_ISFIF (-2)
+ #define ERRATA_USART_ONEWIRE_PINS (-1)
+ #define ERRATA_USART_FRAMING (2)
+ #define ERRATA_USART_WAKE (-2)
+ #define ERRATA_ADC_FREERUN (2)
+ #define ERRATA_AC_INTFLAG (0)
+ #define ERRATA_TCD_AUTOUPDATE (0)
+ #define ERRATA_ADC_ASDVSAMPLEN (0)
+ #define ERRATA_ADC_FLAGSRESH (0)
+ #define ERRATA_ADC_WCMP (0)
+ #define ERRATA_TWI_ASSORTED (0)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_TCB_SYNCUPD (-1)
+ #define ERRATA_TCB_PULSELEN (-1)
+ #define ERRATA_TCD_ASYNC_COUNTPSC (-1)
+ #define ERRATA_TCD_HALTANDRESTART (-1)
+ #elif _AVR_FLASH == 16 /* 1614, 1616, 1617
+ * The first and the worst - 34 errata are listed officially.
+ */
+ #define ERRATA_FUSE_OSCLOCK (-1)
+ #define ERRATA_CCL_OUTEN (-1)
+ #define ERRATA_CCL_DLATCH (-1)
+ #define ERRATA_RTC_PITANDRTC (-1)
+ #define ERRATA_AC_FALSETRIGGER (1)
+ #define ERRATA_AC_INTFLAG (-1)
+ #define ERRATA_USART_ISFIF (0)
+ #define ERRATA_USART_ONEWIRE_PINS (-1)
+ #define ERRATA_USART_FRAMING (-1)
+ #define ERRATA_USART_WAKE (0)
+ #define ERRATA_TCD_AUTOUPDATE (1)
+ #define ERRATA_ADC_FREERUN (-1)
+ #define ERRATA_ADC_ASDVSAMPLEN (-1)
+ #define ERRATA_ADC_FLAGSRESH (-1)
+ #define ERRATA_ADC_WCMP (-1)
+ #define ERRATA_TWI_ASSORTED (-1)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_TCB_SYNCUPD (-1)
+ #define ERRATA_TCB_PULSELEN (-1)
+ #define ERRATA_TCD_ASYNC_COUNTPSC (-1)
+ #define ERRATA_TCD_HALTANDRESTART (-1)
+ #elif _AVR_FLASH == 8 || _AVR_PINCOUNT == 24 /* 814, 816, 817, 417
+ * These are the second worst off of the 1-series.
+ */
+ #define ERRATA_CCL_OUTEN (-1)
+ #define ERRATA_CCL_DLATCH (-1)
+ #define ERRATA_RTC_PITANDRTC (-1)
+ #define ERRATA_AC_FALSETRIGGER (-1)
+ #define ERRATA_AC_INTFLAG (-1)
+ #define ERRATA_USART_ISFIF (-1)
+ #define ERRATA_USART_ONEWIRE_PINS (-1)
+ #define ERRATA_USART_FRAMING (-1)
+ #define ERRATA_USART_WAKE (-1)
+ #define ERRATA_ADC_FREERUN (-1)
+ #define ERRATA_AC_INTFLAG (-1)
+ #define ERRATA_TCD_AUTOUPDATE (-1)
+ #define ERRATA_ADC_ASDVSAMPLEN (0)
+ #define ERRATA_ADC_FLAGSRESH (0)
+ #define ERRATA_ADC_WCMP (-1)
+ #define ERRATA_TWI_ASSORTED (-1)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_TCB_SYNCUPD (-1)
+ #define ERRATA_TCB_PULSELEN (-1)
+ #define ERRATA_TCD_ASYNC_COUNTPSC (-1)
+ #define ERRATA_TCD_HALTANDRESTART (-1)
+ #else /* 212, 214, 412, 414, 416.
+ * There's a Rev. C, but they didn't fix any bugs \o/
+ * But Rev B fixed a number of them at least.
+ */
+ #define ERRATA_CCL_OUTEN (-1)
+ #define ERRATA_CCL_DLATCH (-1)
+ #define ERRATA_RTC_PITANDRTC (-1)
+ #define ERRATA_AC_FALSETRIGGER (1)
+ #define ERRATA_USART_ISFIF (0)
+ #define ERRATA_USART_ONEWIRE_PINS (-1)
+ #define ERRATA_USART_FRAMING (-1)
+ #define ERRATA_USART_WAKE (-1)
+ #define ERRATA_ADC_FREERUN (1)
+ #define ERRATA_AC_INTFLAG (1)
+ #define ERRATA_TCD_AUTOUPDATE (0)
+ #define ERRATA_ADC_ASDVSAMPLEN (1)
+ #define ERRATA_ADC_FLAGSRESH (1)
+ #define ERRATA_ADC_WCMP (1)
+ #define ERRATA_TWI_ASSORTED (1)
+ #define ERRATA_TCB_ICFPWM (1)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_TCB_SYNCUPD (-1)
+ #define ERRATA_TCB_PULSELEN (-1)
+ #define ERRATA_TCD_ASYNC_COUNTPSC (-1)
+ #define ERRATA_TCD_HALTANDRESTART (-1)
+ #endif
+ #define ERRATA_TWI_PINS (0) /* Not in any errata? Huh? */
+ #define ERRATA_TWI_FLUSH (0) /* Flush bug hasn't showed up on any 1-series errata */
+ #define ERRATA_ADC_LOWLAT (-128) /* There's no LOWLAT here */
+#elif defined(__AVR_Tiny_2__)
+ #define ERRATA_TCB_ICFPWM (0)
+ #define ERRATA_CCL_OUTEN (0)
+ #define ERRATA_CCL_DLATCH (0)
+ #define ERRATA_RTC_PITANDRTC (0)
+ #define ERRATA_AC_FALSETRIGGER (0)
+ #define ERRATA_USART_FRAMING (0)
+ #define ERRATA_USART_WAKE (0)
+ #define ERRATA_ADC_FREERUN (0)
+ #define ERRATA_AC_INTFLAG (0)
+ #define ERRATA_TCD_AUTOUPDATE (0)
+ #define ERRATA_ADC_ASDVSAMPLEN (0)
+ #define ERRATA_ADC_FLAGSRESH (0)
+ #define ERRATA_ADC_WCMP (0)
+ #define ERRATA_TWI_ASSORTED (0)
+ #define ERRATA_TCB_ICFPWM (0)
+ #define ERRATA_TCA_RESTART (0)
+ #define ERRATA_TCB_SYNCUPD (0)
+ #define ERRATA_TCB_PULSELEN (0) /* No TCD */
+ #define ERRATA_TCD_ASYNC_COUNTPSC (0) /* No TCD */
+ #define ERRATA_TCD_HALTANDRESTART (0) /* No TCD */
+ #define ERRATA_TWI_PINS (0) /* Not in any errata? Huh? */
+ #define ERRATA_TWI_FLUSH (0) /* Flush bug hasn't showed up on any 2-series errata */
+ #if _AVR_FLASH == 32
+ #define ERRATA_USART_ONEWIRE_PINS (0)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_USART_ISFIF (-1)
+ #define ERRATA_ADC_LOWLAT (-1)
+ #elif _AVR_FLASH == 16
+ /* 16k parts also have excessive current consumption in power-down mode */
+ #define ERRATA_USART_ONEWIRE_PINS (-1)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_USART_ISFIF (-1)
+ #define ERRATA_ADC_LOWLAT (-1)
+ #else /* 8k and 4k 2-series share die */
+ #define ERRATA_USART_ONEWIRE_PINS (0)
+ #define ERRATA_CCL_PROTECTION (-1)
+ #define ERRATA_TCA_RESTART (-1)
+ #define ERRATA_TCB_CCMP (-1)
+ #define ERRATA_USART_ISFIF (-1)
+ #define ERRATA_ADC_LOWLAT (-1)
+ #endif
+ #define ERRATA_TCD_ASYNC_COUNTPSC (-128)
+ #define ERRATA_TCD_AUTOUPDATE (-128)
+ #define ERRATA_TCD_HALTANDRESTART (-128)
+#endif
+
+inline bool __attribute__((always_inline)) checkErrata(int8_t errata) {
+/* We want
+ errata = 0, return 0/false.
+ errata = -1, return 1/true.
+ errata =
+
+*/
+
+ if (!(errata & 0x7F)) { // 0 or(-128)
+ return 0;
+ }
+ #if defined(__AVR_Tiny_1__) && _AVR_FLASH == 32
+ // These parts gained an 2 errata
+ uint8_t revid = SYSCFG.REVID;
+ if (errata == -2) {
+ return revid > 2;
+ }
+ #else
+ uint8_t revid = SYSCFG.REVID;
+ #endif
+ return revid < errata;
+}
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/hooks.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/hooks.c
new file mode 100644
index 0000000..a61b5ef
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/hooks.c
@@ -0,0 +1,31 @@
+/*
+ Copyright (c) 2012 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
+*/
+
+/**
+ * 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")));
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/main.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/main.cpp
new file mode 100644
index 0000000..1045b90
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/main.cpp
@@ -0,0 +1,200 @@
+/* main.cpp - Main loop for Arduino sketches
+ Part of megaTinyCore - github.com/SpenceKonde/megaTinyCore
+ Copyright (c) 2018~2021 Spence Konde, (c) 2005-2013 Arduino
+ Free Software - LGPL 2.1, please see LICENCE.md for details */
+
+#include
+
+/* Required by some libraries to compile successfully. Even though it's nonsense in Arduino. */
+int atexit(void ( * /*func*/)()) { return 0; }
+
+void initVariant() __attribute__((weak));
+/* Weak empty variant initialization function. The purpose is unclear. It sounds like it was intended
+ * initialize the variant, and specific variants would have their own implementation. But in practice
+ * it seems to be instead used as an initialization callback that libraries can use to run code before
+ * setup, like FreeRTOS - it would have been nice if the official API included such a callback. */
+void initVariant() { }
+
+void __attribute__((weak)) onPreMain();
+void __attribute__((weak)) onPreMain() {
+ /* Override with any user code that needs to run WAY early, in .init3 */
+}
+void __attribute__((weak)) onBeforeInit();
+void __attribute__((weak)) onBeforeInit() {
+ /* Override with any user code that needs to run before init() */
+}
+uint8_t __attribute__((weak)) onAfterInit();
+uint8_t __attribute__((weak)) onAfterInit() {
+ /* Override with any user code that needs to run before interrupts are
+ * enabled but after all other core initialization.
+ * return 1 to not enable interrupts) */
+ return 0;
+}
+
+
+
+
+
+
+
+int main() __attribute__((weak));
+/* The main function - call initialization functions (in wiring.c) then setup, and finally loop *
+ * repeatedly. If SerialEvent is enabled (which should be unusual, as it is no longer a menu *
+ * option even, that gets checked for after each call to loop). Note that _pre_main() is *
+ * called first in non-optiboot configurations (neither is needed on Optibooot configurations() *
+ * an extra bit of initialization code in .init3 to fix the vectors and still happen if user *
+ * overrides main. In the past there was a USB-related function here, that is removed, as work *
+ * will be needed in any event at the core level if VUSB-based "stuff" arrives, but really I'm *
+ * just waiting for the DU-series now */
+int main() {
+ onBeforeInit(); // Emnpty callback called before init but after the .init stuff. First normal code executed
+ init(); // Interrupts are turned on just prior to init() returning.
+ initVariant();
+ if (!onAfterInit()) sei(); // enable interrupts.
+ setup();
+ for (;;) {
+ loop();
+ }
+}
+
+
+
+
+#if (!defined(USING_OPTIBOOT))
+
+
+
+/*********************************** CHECK RESET FLAGS ******************************************/
+/* If we are not using Optiboot, we need to check the reset flagss, and reset via software for *
+ * a clean start. Unfortunately, if we clear the registers here, we'll prevent user code from *
+ * seeing them, which isn't helpful. As documented in the reset guide, we suggest overriding *
+ * this function with your own version. One example is included below and others in that guide *
+ * init_reset_Flags() should be overridden with one of the ones from the reset guide in any *
+ * production code. *
+ * If using optiboot, this will never be called, because Optiboot does the same thing. *
+ * By the time app runs, the flags will have been cleared and moved to GPIOR0* (it needs to *
+ * clear flags to honor bootloader entry conditions, so I didn't have a choice about that. *
+ * This function is called before *anything* else, so the chip is a blank slate - or it's *
+ * state is unknown. You're probably running at 4 MHz unless it was a dirty reset, in which *
+ * case it could be anything. No timekeeping is possible, period. The only exception is the *
+ * WDT reset timer with is independent of the HF oscillators and is designed to reset you out *
+ * of hangs amd bad states fthat you end up with when a bug causes the code but not the *
+ * hardware to reset, *
+ * Interrupts are disabled, or in event of dirty reset *
+ * LVL0EX bit will block them. In the event of a clean reset, nothing is set up. There is no *
+ * PWM, no timekeeping of any millis/micros/delay see no time passing and and all delays, *
+ * delay_microseconds, _delay_ms() and _delay_us(), are the wrong length because they are *
+ * based on F_CPU. *
+ * If you end up here from a dirty reset, you know nothing about the configuration of the *
+ * peripherals. Check the flags, save them if you need them, and maybe turn on an LED while *
+ * waiting for the WDT to trigger. If you're debugging something really nasty, you can try to *
+ * gather data about the nature of the fault. For example, turn on an LED if\ LVL0EX is set *
+ * meaning you got here from a missing ISR. With one of those little boards with 6 LEDs on *
+ * (many are available reasonably cheaply on aliexpress et al.) end up being very useful *
+ * for this sort of thing.
+ *
+ * * The register in question is GPIOR0 on megaTinyCore, GPR.GPR0 on Dx-series, but both names *
+ * are aliases of each other per core_devices for compatibility
+ */
+
+ /* Minimum: Reset if we wound up here through malfunction - this relies on user clearing the *
+ * register on startup, which is rarely done in Arduino land. */
+ void __attribute__((weak)) init_reset_flags() ;
+ void __attribute__((weak)) init_reset_flags() {
+ uint8_t flags = RSTCTRL.RSTFR;
+ RSTCTRL.RSTFR = flags;
+ if (flags == 0) {
+ _PROTECTED_WRITE(RSTCTRL.SWRR, 1);
+ }
+ GPIOR0 = flags;
+ }
+
+#endif
+
+/* If using SPM from app, but not actually using Optiboot, we need to point the vector tables in the right place.
+ * since the "application" is actually split across "boot" and "application" pages of flash... and it's vectors
+ * are all in the section defined as "boot" section, tell the interrupt controller that, otherwise nothing'll work!
+ * This could just as well be set in init() but for the fact that we support overriding main(). I don't know if
+ * anyone who is doing that wants to use my flashwrite library, but it seems plausible.
+ * And while we way you need to take full responsibility for setting up the part if you do, nobody is going
+ * to figure this out; that's not a reasonable expectation.
+ * We also at the same time make sure there's a reset flag. We can't clear it, even though that
+ * needs to be done becauwe then it wouldn't be there if user needed it. But we will document the
+ * need to clear it and suggest overriding init_reset_flags(), and give the examples.
+ */
+
+/* So we need to do 1 or 2 things - as long as we're not using Optiboot, we should force a *
+ * software reset if we don't see any reset flags on startup - init_reset_flags() does that, *
+ * Then if we're using SPM from app, we need to also flip the it that move s the interrupts *
+ * to the start of flash.
+ */
+
+/**************************************************************************************************
+ * INITIALIZATION FUNCTIONS LOCATED ANYWHERE SPECIAL GO HERE! *
+ * *
+ * They *MUST* be declared with both the ((naked)) ahd ((used)) attributes! Without the latter, *
+ * the optimizer will eliminate them. Without the former, the sketch will not start... *
+ * Wait what? Yeah, it was generating a and outputting a ret instruction, which caused the *
+ * sketch to return to nowhere under certain conditions and never reach main() at all. *
+ * I do not understand how the old vector fixer allowed the sketch to start ever... but *
+ * since it was only compiled in when flash write was enabled it could have been missed for a *
+ * long time. *
+ **************************************************************************************************/
+
+#if (!defined(USING_OPTIBOOT))
+ void _initThreeStuff() __attribute__ ((naked)) __attribute__((used)) __attribute__ ((section (".init3")));
+ // this runs, as the name implies, before the main() function is called.
+ #if !defined(SPM_FROM_APP)
+ // If we're not doing the SPM stuff, we need only check the flags
+ void _initThreeStuff() {
+ init_reset_flags();
+ onPreMain();
+ }
+ #else /* Otherwise, SPM_FROM_APP is defined */
+ #if defined(__AVR_Dx__) /* So this better be a Dx!!! */
+ /*******************************************
+ * THIS FUNCTIONALITY IS ONLY EXPOSED ON *
+ * DX-SERIES PARTS SO THIS CODE CANT-HAPPEN *
+ * megaTinyCore. You must write to flash *
+ * using optiboot if required *
+ *******************************************/
+ // if we are, we also need to move the vectors. See longwinded deascription above.
+ void _initThreeStuff() {
+ init_reset_flags();
+ _PROTECTED_WRITE(CPUINT_CTRLA,CPUINT_IVSEL_bm);
+ onPreMain();
+ }
+ #if (SPM_FROM_APP == -1) /* Unlimited SPM from app and no bootloader, means we need to stick entry point on page 0 */
+ /* Declared as being located in .trampolines so it gets put way at the start of the binary. This guarantees that
+ * it will be in the first page of flash. Must be marked ((used)) or LinkTime Optimization (LTO) will see
+ * that nothing actually calls it and optimize it away. The trick of course is that it can be called if
+ * the user wants to - but it's designed to be called via hideous methods like
+ * __asm__ __volatile__ ("call EntryPointSPM" : "+z" (zaddress))
+ * see Flash.h */
+ /* It must be located *before everything* - including PROGMEM, which the compiler puts ahead of .init.
+ * .trampolines however comes before progmem. The function must be naked, it must be used, and you need to guard it
+ * with the rjmp that hops over the spm and ret instructions unless you jump directly to the entrypoint. */
+ void __spm_entrypoint (void) __attribute__ ((naked)) __attribute__((used)) __attribute__ ((section (".trampolines")));
+ void __spm_entrypoint (void)
+ {
+ __asm__ __volatile__(
+ "rjmp .+4" "\n\t" // Jump over this if we got here the wrong way
+ "EntryPointSPM:" "\n\t" // this is the label we call
+ "spm z+" "\n\t" // write r0, r1 to location pointed to by r30,r31 with posrincewmwr
+ "ret"::); // by 2, and then return.
+ }
+ #endif /* SPM from app unlimited */
+ #else
+ #error "The selected part has SPM_FROM_APP = unlimited, isn't using Optiboot, or it's not a Dx-series. You must change one of those things"
+ #endif /* Only AVR Dx supports this */
+ /* End if DXCore only spm from app stuff */
+ #endif
+ // Finally, none of these three things need to be done if running optiboot!
+ // We want the vectors in the alt location, it checks, clears, and stashes the reset flags (in GPR0)
+ // and it providews the entrypoint we call to write to flash.
+#else
+ void _initThreeStuff() __attribute__ ((naked)) __attribute__((used)) __attribute__ ((section (".init3")));
+ void _initThreeStuff() {
+ onPreMain();
+ }
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/new b/fw/HackSpaceCon_AS7/Arduino/megatinycore/new
new file mode 100644
index 0000000..aa8ecb5
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/new
@@ -0,0 +1,5 @@
+/*
+this header is for compatibility with standard c++ header names
+so that #include works as expected
+*/
+#include "new.h"
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/new.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/new.cpp
new file mode 100644
index 0000000..d889ebd
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/new.cpp
@@ -0,0 +1,180 @@
+/*
+ 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
+
+ Updated 2020-21 Spence Konde to support C++ 14 sized
+ dealocations, and give useful compile errors when aligned
+ new and delete operators are referenced. I do not think adding
+ support for them is warranted at this time, though we have
+ candidates for the simplest of them, both were written by
+ @henrygab (Henry Gabryjelski, which is fitting because that's
+ who asked for C++ 17 mode, over on ATTinyCore, but releases
+ are more frequent for the new parts, and this is equally
+ applicable to all of the cores.)
+*/
+
+#include
+
+// For C++11, only need the following:
+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);
+}
+
+void * operator new (size_t size, void * ptr) noexcept {
+ (void)size;
+ return ptr;
+}
+
+void * operator new[](size_t size, void * ptr) noexcept {
+ (void)size;
+ return ptr;
+}
+
+// Since C++14, also need two more delete variants...
+// Note thnat this CAN break code that compiled amd worked in C++11.
+#if (__cpp_sized_deallocation >= 201309L)
+ void operator delete (void* ptr, size_t size) noexcept {
+ (void) size;
+ free(ptr);
+ }
+ void operator delete[](void* ptr, size_t size) noexcept {
+ (void) size;
+ free(ptr);
+ }
+#endif
+
+// Since C++17, there's four more each for new / delete, to support allocation
+// of objects with alignment greater than __STDCPP_DEFAULT_NEW_ALIGNMENT__.
+// Almost the entirety of AVR is using C++ 11. Any code that works elsewhere, but NOT on these cores and give these error messages either
+// is trying to get alignment that it doesn't actually need, or is - by sheet luck - ending up with the addresses which worked. E
+#if (__cpp_aligned_new >= 201606L)
+ #if !defined(LTODISABLED)
+ void badAlloc(const char*) __attribute__((error("")));
+ #endif
+
+ void* operator new (size_t size, std::align_val_t al) {
+ #if !defined(LTODISABLED)
+ badAlloc("Alignment aware new/delete operators, a C++ 17 feaure, are not supported by this core or any other AVR cores at this point in time");
+ #endif
+ (void) al;
+ return malloc(size);
+ }
+
+/*
+void* operator new (size_t size, std::align_val_t al) {
+
+ if (al <= alignof(std::max_align_t)) {
+ return malloc(size);
+ }
+
+ // how many extra bytes required to ensure can find an aligned pointer?
+ size_t toAllocate = size + (al - alignof(std::max_align_t)) - 1;
+ toAllocate += sizeof(uintptr_t); // to store the original pointer
+
+ uintptr_t allocated = malloc(toAllocate);
+
+ // ensure to save space for the back-pointer.
+ uintptr_t alignedPtr = allocated + sizeof(uintptr_t);
+
+ size_t mask = al 1; // alignment mask ... the bits that must be zero
+ uintptr_t alignedPtr =
+ (allocated & mask) == 0 ?
+ allocated :
+ (allocated & (~mask)) + al;
+
+ // save the original pointer just before the pointer value returned to caller
+ static_assert(alignof(uintptr_t) <= alignof(std::max_align_t), "" );
+ uintptr_t* storeOriginalPointerAt = (uintptr_t)(alignedPtr - sizeof(uintptr_t));
+ *storeOriginalPointerAt = allocated;
+
+ return alignedPtr;
+}
+*/
+
+ void* operator new[](size_t size, std::align_val_t al) {
+ #if !defined(LTODISABLED)
+ badAlloc("Alignment aware new/delete operators, a C++ 17 feaure, are not supported by this core or any other AVR cores at this point in time");
+ #endif
+ (void) al;
+ return malloc(size);
+ }
+ void operator delete (void* ptr, std::align_val_t al) noexcept {
+ #if !defined(LTODISABLED)
+ badAlloc("Alignment aware new/delete operators, a C++ 17 feaure, are not supported by this core or any other AVR cores at this point in time");
+ #endif
+ (void) al;
+ free(ptr);
+ }
+ /*
+ void operator delete (void* ptr, std::align_val_t al) noexcept {
+
+ if (al <= STDCPP_DEFAULT_NEW_ALIGNMENT) {
+ free(ptr);
+ return;
+ }
+
+ // Get the original pointer value from just prior to the provided pointer.
+ uintptr_t aligned = ptr;
+ uintptr_t tmp = aligned - sizeof(uintptr_t); // go back 2 bytes
+ uintptr_t original = *((uintptr_t *)tmp); // extract the original pointer
+
+ // sanity check the original value... for iot, infinite loop recommended
+ // as it's better than memory corruption!rhy
+ size_t overhead = (al - STDCPP_DEFAULT_NEW_ALIGNMENT) + sizeof(uintptr_t);
+ assert(original < aligned);
+ assert(original + overhead <= aligned);
+
+ // and finally free the original memory
+ free(original);
+ }
+ */
+ void operator delete[](void* ptr, std::align_val_t al) noexcept {
+ #if !defined(LTODISABLED)
+ badAlloc("Alignment aware new/delete operators, a C++ 17 feaure, are not supported by this core or any other AVR cores at this point in time");
+ #endif
+ (void) al;
+ free(ptr);
+ }
+ void operator delete (void* ptr, size_t size, std::align_val_t al) noexcept{
+ #if !defined(LTODISABLED)
+ badAlloc("Alignment aware new/delete operators, a C++ 17 feaure, are not supported by this core or any other AVR cores at this point in time");
+ #endif
+ (void) al;
+ (void) size;
+ free(ptr);
+ }
+ void operator delete[](void* ptr, size_t size, std::align_val_t al) noexcept {
+ #if !defined(LTODISABLED)
+ badAlloc("Overaligned allocation/deallocation is a C++ 17 feature, and is not supported by this or other AVR cores at this point in time");
+ #endif
+ (void) al;
+ (void) size;
+ free(ptr);
+ }
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/new.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/new.h
new file mode 100644
index 0000000..02b6540
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/new.h
@@ -0,0 +1,60 @@
+/* New version (c) Spence Konde 2021
+ * This file is part of megaTinyCore, DxCore, and ATTinyCore.
+ * This is free software (released under the LGPL 2.1). For more
+ * information, see the License.md file included with this core.
+ */
+
+/*
+ C++11 needed some new new and delete operators.
+ Since C++14, also needed two more delete variants taking a size argument.
+ Said size argument is ignored (cast to void), but on some architectures
+ it is an important way to give hints to the memory allocator for greater
+ efficiency.
+ Since C++17, there's four more each for new / delete, to support allocation
+ of objects with alignment greater than __STDCPP_DEFAULT_NEW_ALIGNMENT__.
+ This has two major differences from the C++14 sized deallocation.
+ 1. It cannot be simply ignored - they presumably wanted alignment for
+ a reason; this implementation is not impossible, but nor is it trivial.
+ 2. If code used on C++14 or earlier is asking for the alignment aware
+ versions of these operators, either it doesn't actually need it and
+ shouldn't be, or it was sheer happenstance that whatver address it
+ was getting worked within it's assumoptions.
+ Unless and until official cores or other cores in widespread use add support
+ for the alignment aware operators on AVRs, we have no plans to. While we
+ do not hesitate to offer users new features to take advantage of hardware
+ capabilities not present on older devices, this does not extend to new
+ compiler features which require modifications to code to take advantage
+ of. We have candidates for overaligned new and delete though, for when/if
+ they are required.
+ -Spence, 9/25/2021
+ */
+
+#ifndef NEW_H
+ #define NEW_H
+
+ #include
+ /* C++11 and later */
+ void* operator new (size_t size /* return malloc(size); */);
+ void* operator new[] (size_t size /* return malloc(size); */);
+ void* operator new (size_t size, void * ptr /* (void size); return ptr; */) noexcept;
+ void* operator new[] (size_t size, void * ptr /* (void size); return ptr; */) noexcept;
+ void operator delete (void* ptr /* free(ptr); */) noexcept;
+ void operator delete[] (void* ptr /* free(ptr); */) noexcept;
+
+ #if (__cpp_sized_deallocation >= 201309L) /* C++14 and later only */
+ void operator delete (void* ptr, size_t size /* (void)size; return ptr; */) noexcept;
+ void operator delete[] (void* ptr, size_t size /* (void)size; return ptr; */) noexcept;
+ #endif
+
+ #if (__cpp_aligned_new >= 201606L) /* C++17 and later only */
+ /* These are unsupported and just stubs that generate a more helpful error */
+ /* If it turns out that we do need them, we have a candidate for these */
+ void* operator new (size_t size, std::align_val_t al );
+ void operator delete (void* ptr,/* (void)al; return ptr; */std::align_val_t al) noexcept;
+ /* Not actually supported, these stubs just generate a more helpful error */
+ void* operator new[] (size_t size, std::align_val_t al );
+ void operator delete[](void* ptr,/* (void)al; return ptr; */std::align_val_t al) noexcept;
+ void operator delete (void* ptr, size_t size,/* above + */std::align_val_t al) noexcept;
+ void operator delete[](void* ptr, size_t size,/* (void)al;*/std::align_val_t al) noexcept;
+ #endif
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/timers.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/timers.h
new file mode 100644
index 0000000..7847c9e
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/timers.h
@@ -0,0 +1,343 @@
+#ifndef __TIMERS_H__
+#define __TIMERS_H__
+#include
+
+/*****************************************
+| # # ### # # ### ### |
+| ## ## # # # # # |
+| # # # # # # # ### |
+| # # # # # # # |
+| # # ### #### #### ### #### |
+|_______________________________________*/
+
+#ifdef MILLIS_USE_TIMERNONE
+ #define DISABLE_MILLIS
+#endif
+#if (defined(MILLIS_USE_TIMERRTC_XTAL) || defined(MILLIS_USE_TIMERRTC_XOSC))
+ #define MILLIS_USE_TIMERRTC
+#endif
+#if !defined(TCA_PORTMUX)
+ #define TCA_PORTMUX (0x00)
+#endif
+#define _TCA_USE_WO0
+#define _TCA_USE_WO1
+#define _TCA_USE_WO2
+#if TCA_PORTMUX & 0x01
+ #define _TCA_ALT_WO0
+#endif
+#if TCA_PORTMUX & 0x02
+ #define _TCA_ALT_WO1
+#endif
+#if TCA_PORTMUX & 0x04
+ #define _TCA_ALT_WO2
+#endif
+#if !defined(TCA_BUFFERED_3PIN)
+ #if TCA_PORTMUX & 0x08
+ #define _TCA_ALT_WO3
+ #else
+ #define _TCA_USE_WO3
+ #endif
+ #if TCA_PORTMUX & 0x10
+ #define _TCA_ALT_WO4
+ #else
+ #define _TCA_USE_WO4
+ #endif
+ #if TCA_PORTMUX & 0x20
+ #define _TCA_ALT_WO5
+ #else
+ #define _TCA_USE_WO5
+ #endif
+#endif
+#if defined(USE_TIMERD0_PWM)
+ #if !defined(TCD0)
+ #if defined(ARDUINO_MAIN)
+ #pragma message("Note: This part does not have a TCD, hence there is no PWM from TCD available.")
+ #endif
+ #undef USE_TIMERD0_PWM
+ #endif
+#endif
+
+#if (defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4) || defined(MILLIS_USE_TIMERB5) || defined(MILLIS_USE_TIMERB6) || defined(MILLIS_USE_TIMERB7))
+ #if (F_CPU == 1000000UL)
+ #define TIME_TRACKING_TIMER_DIVIDER (1)
+ #define TIME_TRACKING_TIMER_PERIOD ((F_CPU/500)-1)
+ #elif (F_CPU == 2000000UL)
+ #define TIME_TRACKING_TIMER_DIVIDER (2)
+ #define TIME_TRACKING_TIMER_PERIOD ((F_CPU/1000)-1)
+ #else
+ #define TIME_TRACKING_TIMER_DIVIDER (2)
+ #define TIME_TRACKING_TIMER_PERIOD ((F_CPU/2000)-1)
+ #endif
+#elif defined(MILLIS_USE_TIMERD0)
+ #define TIME_TRACKING_TIMER_PERIOD (0x1FD)
+ #if (F_CPU == 1000000UL)
+ #define TIME_TRACKING_TIMER_DIVIDER (64) /* Clock divider for TCD0 */
+ #else
+ #define TIME_TRACKING_TIMER_DIVIDER (32) /* Clock divider for TCD0 */
+ #endif
+#else // Otherwise it must be a TCA
+ #define TIME_TRACKING_TIMER_PERIOD (0xFE)
+ #if (F_CPU > 30000000UL)
+ #define TIME_TRACKING_TIMER_DIVIDER (256)
+ #elif (F_CPU <= 1000000UL)
+ #define TIME_TRACKING_TIMER_DIVIDER (8)
+ #elif (F_CPU <= 5000000UL)
+ #define TIME_TRACKING_TIMER_DIVIDER (16)
+ #else // 30000000UL >= F_CPU > 5000000
+ #define TIME_TRACKING_TIMER_DIVIDER (64)
+ #endif
+#endif
+
+#define TIME_TRACKING_TICKS_PER_OVF (TIME_TRACKING_TIMER_PERIOD + 1UL)
+#define TIME_TRACKING_CYCLES_PER_OVF (TIME_TRACKING_TICKS_PER_OVF * TIME_TRACKING_TIMER_DIVIDER)
+
+// For a type B timer as millis, these #defines aren't needed, but they're defined accurately anyway,
+
+
+#if defined(MILLIS_USE_TIMERA0)
+ #ifndef TCA0
+ #error "TCA0, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERA0
+ #define MILLIS_VECTOR TCA0_HUNF_vect
+#elif defined(MILLIS_USE_TIMERA1)
+ #ifndef TCA1
+ #error "TCA1, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERA1
+ #define MILLIS_VECTOR TCA1_HUNF_vect
+#elif defined(MILLIS_USE_TIMERB0)
+ #ifndef TCB0
+ #error "TCB0, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB0
+#elif defined(MILLIS_USE_TIMERB1)
+ #ifndef TCB1
+ #error "TCB1, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB1
+#elif defined(MILLIS_USE_TIMERB2)
+ #ifndef TCB2
+ #error "TCB2, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB2
+#elif defined(MILLIS_USE_TIMERB3)
+ #ifndef TCB3
+ #error "TCB3, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB3
+#elif defined(MILLIS_USE_TIMERB4)
+ #ifndef TCB4
+ #error "TCB4, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB4
+#elif defined(MILLIS_USE_TIMERB5)
+ #ifndef TCB5
+ #error "TCB5, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB5
+#elif defined(MILLIS_USE_TIMERB6)
+ #ifndef TCB6
+ #error "TCB6, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB6
+#elif defined(MILLIS_USE_TIMERB7)
+ #ifndef TCB7
+ #error "TCB7, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERB7
+#elif defined(MILLIS_USE_TIMERD0)
+ #ifndef TCD0
+ #error "TCD0, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERD0
+#elif defined(MILLIS_USE_TIMERRTC)
+ #ifndef RTC
+ #error "RTC, selected for millis, does not exist on this part"
+ #endif
+ #define MILLIS_TIMER TIMERRTC
+#elif defined(MILLIS_USE_TIMERNONE)
+ #define MILLIS_TIMER NOT_ON_TIMER
+#else
+ #error "Millis timer not specified, nor is millis disabled - can't happen!"
+#endif
+#endif
+
+/* These allow other libraries to detect whether timing functions are available with #ifdef */
+#define delay delay
+#define delayMicroseconds delayMicroseconds
+
+#if !defined(MILLIS_USE_TIMERNONE)
+ #define millis millis
+ #if !defined(MILLIS_USE_TIMERRTC)
+ #define micros micros
+ #endif
+#endif
+
+/****************************************
+| #### # # # # |
+| # # # # ## ## |
+| #### # # # # # # |
+| # # # # # # |
+| # # # # # |
+|______________________________________*/
+
+
+/* TYPE-A TIMERS */
+
+#define PWM_TIMER_PERIOD (0xFE) // For frequency
+#define PWM_TIMER_COMPARE (0x00) // For duty cycle - this is never used.
+/* The original implementation set the compare registers (all 6 of them, with an STS instruction),
+ * and also set a number of other TCA registers to their POR values. That was dumb, and is no longer done.
+ * TCA0 is present on all parts and always used for PWM.
+ * TCA1 is used for PWM on Dx-series parts that have it.
+ */
+
+/* TYPE-B TIMERS */
+#if defined(TCB2) && !defined(MEGATINYCORE)
+ // On tinyAVR, and the low pincount DD's TCB PWM isn't helpful and the timer is too valuable anyway.
+ // These use the same values as above for TCA, only they're only 1 channel each.
+ #define USE_TCB_PWM
+ #if defined(SUPPORT_TCB_MUX)
+ #undef SUPPORT_TCB_MUX
+ #pragma message("TCB autoMUXing is not yet supported")
+ #endif
+ /* If this feature is ever implemented, calling analogWrite() on a pin that has PWM controlled by a TCB
+ * it will automatically also set or clear the PORTMUX bit to point the TCB at the right place.
+ * These pins will be included in the pin timer table.
+ */
+#endif
+
+
+
+/* TYPE-D TIMERS */
+#if defined(MEGATINYCORE)
+ /* TCD0 on megaTinyCore is run from the unprescaled clock, at either 20 or 16 MHz depending on the fuse setting.
+ * It will always use a count prescale of 32. If the system clock is cranked all the way back to 1 MHz, though
+ * we knock it down by another factor of 2 because otherwise the interrupts were taking a large fraction of
+ * available CPU time. */
+ #if (defined(MILLIS_USE_TIMERD0) && F_CPU == 1000000)
+ #define TIMERD0_PRESCALER (TCD_CLKSEL_20MHZ_gc | TCD_CNTPRES_DIV32_gc | TCD_SYNCPRES_DIV2_gc)
+ // TODO: change to TIMERD0_CLOCK_SETTING here and elsewhere
+ // along with TIMERD0_TOP_SETTING and TIMERD0_WGMODE_SETTING
+ #else
+ #define TIMERD0_PRESCALER (TCD_CLKSEL_20MHZ_gc | TCD_CNTPRES_DIV32_gc)
+ #endif
+ // Pretty simple here!
+#elif defined(DXCORE)
+ #if defined(TIMERD0_TOP_SETTING)
+ #if (TIMERD0_TOP_SETTING == 254 || TIMERD0_TOP_SETTING == 509 ||TIMERD0_TOP_SETTING == 1019 ||TIMERD0_TOP_SETTING == 2039 ||TIMERD0_TOP_SETTING == 4079 )
+ #if defined(TCD0)
+ #define USE_TIMERD0_PWM
+ #endif
+ #endif
+ #else
+
+ #endif
+
+ /* On the DX-series parts, we can have a lot more fun with the Type D timer!
+ * This flexibility comes at the price of losing the use of TCD0 as a millis timer, but that was being done
+ * as a desperation move on the highly timer-constrained non-golden tinyAVR 1-series parts. The TCD0 on the
+ * tinyAVRs is also far less interesting - it's virtually identical as far as the timer itself, but here
+ * we have a much richer selection timing clock sources.
+ */
+ #if defined(USE_TIMERD0_PWM)
+ #if !defined(TIMERD0_WGMODE_SETTING)
+ #define TIMERD0_WGMODE_SETTING (TCD_WGMODE_ONERAMP_gc) // only WGMODE_ONERAMP and WGMODE_DUALSLOPE are supported by the core, as the other options
+ // cannot reproduce the behavior of analogWrite as they enforce PWM being non-overlapping. If you want those modes (I think 4 ramp mode has some
+ // relevant applications in combination with the TCD.CTRLD options, particularly in custom single wire protocols, particularly if you need to generate events
+ // at certain points in the cycle.
+ #endif
+ #if !defined(TIMERD0_CLOCK_SETTING)
+ #if (CLOCK_SOURCE != 0)
+ /*
+ Hey, we're not using the internal oscillator for the clock! We can totally run it at an ideal frequency from internal and use external for system clock!
+
+ There are at least five ways to slice this that look nearly identical. These are virtually indistinguishable from each other giving PWM at 980 Hz.
+ One runs the clock at 8 MHz with /32 division on the count prescaler and /1 on the synchronizer.
+ Another method drops the count prescaler back to /4, and compensates by increasing the sync prescaler to /8
+ A third way is to drop the count prescaler back to /4, sync prescale to /1, and set the FREQSEL to 1 MHz.
+ Sync prescale options of /2 and /4 can be paired with setting the osc to 2 or 4 MHz as well, with the same result
+ Lowering count prescale dodges some bugs, and there isn't exactly a wealth of options. (it goes /4 to /32, nothing in the middle,
+ and no undocumented fourth option (I checked :-P).
+ But /32 will get you right on target (that being ~1 kHz) if CLK_OSCHF / Sync prescale = 8 MHz
+ And /4 will get you right on target if CLK_OSCHF / Sync prescale = 1 MHz
+ There are still more equivalent settings if you consider that there are more than one way to get to 1 MHz from the internal HF oscillator.
+ Those settings are strictly worse if you aren't using the internal osc for anything else.
+ On the one hand, running with clock set to 1 MHz is probably more power efficient, though nothing using a crystal is going to set any records
+ for power consumption - and using an external clock, well, you have the power consumption of the clock to worry about, which is often larger
+ than the chip itself...
+ On the other hand, using the /32 count prescaling exposes us to some silicon errata on the DA/DB - but in weirdo features nobody uses.
+ On the third hand, if the crystal or clock is defective, and you were relying on overriding clock failure callbacks with your own functions
+ that enable the internal oscillator at a known speed to communicate that to you (because you got a killer deal on crystals that have
+ astonishingly high DOA rate or something?) If clock failure is a normal occurrence, you're doing something wrong...
+
+ Anyway, regarding how we get the same frequency, well... very few Arduino folks care!
+
+
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV4_gc | TCD_SYNCPRES_DIV8_gc | TCD_CLKSEL_OSCHF_gc)
+ #define TIMERD0_SET_CLOCK (CLKCTRL_FREQSEL_8M_gc)
+
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV4_gc | TCD_SYNCPRES_DIV4_gc | TCD_CLKSEL_OSCHF_gc)
+ #define TIMERD0_SET_CLOCK (CLKCTRL_FREQSEL_4M_gc)
+
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV4_gc | TCD_SYNCPRES_DIV2_gc | TCD_CLKSEL_OSCHF_gc)
+ #define TIMERD0_SET_CLOCK (CLKCTRL_FREQSEL_2M_gc)
+
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV4_gc | TCD_SYNCPRES_DIV1_gc | TCD_CLKSEL_OSCHF_gc)
+ #define TIMERD0_SET_CLOCK (CLKCTRL_FREQSEL_1M_gc)
+
+ Hell... we could even set TOP to 2039 and do
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV4_gc | TCD_SYNCPRES_DIV1_gc | TCD_CLKSEL_OSCHF_gc)
+ #define TIMERD0_SET_CLOCK (CLKCTRL_FREQSEL_1M_gc)
+ #define TIMERD0_TOP_SETTING (2039)
+
+
+
+ */
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV32_gc | TCD_SYNCPRES_DIV1_gc | TCD_CLKSEL_OSCHF_gc)
+ #define TIMERD0_SET_CLOCK (CLKCTRL_FREQSEL_8M_gc)
+ // And we can set TOP to the default 254.
+ #if !defined(TIMERD0_TOP_SETTING)
+ #define TIMERD0_TOP_SETTING (0xFE)
+ // that gives the target 980 kHz PWM freqwuency....
+ #endif
+ // if it's internal HF osc as system clock, it's more complicated.....
+ #elif (F_CPU == 5000000UL || F_CPU == 10000000UL || F_CPU == 6000000UL || F_CPU == 7000000UL || F_CPU == 14000000UL)
+ // These speeds are prescaled so we can run from unprescaled clock, and keep the same settings we use at higher clock.
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV32_gc | TCD_SYNCPRES_DIV1_gc | TCD_CLKSEL_OSCHF_gc)
+ #if !defined(TIMERD0_TOP_SETTING)
+ #if (F_CPU == 7000000 || F_CPU == 14000000)
+ #define TIMERD0_TOP_SETTING (1019)
+ #else
+ #define TIMERD0_TOP_SETTING (509)
+ #endif
+ #endif
+ #elif F_CPU < 4000000UL
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV4_gc | TCD_SYNCPRES_DIV1_gc | TCD_CLKSEL_CLKPER_gc)
+ #if !defined(TIMERD0_TOP_SETTING)
+ #if (F_CPU == 1000000)
+ #define TIMERD0_TOP_SETTING (254)
+ #else
+ #define TIMERD0_TOP_SETTING (509)
+ #endif
+ #endif
+ #else //catchall F_CPU speeds
+ #define TIMERD0_CLOCK_SETTING (TCD_CNTPRES_DIV32_gc | TCD_SYNCPRES_DIV1_gc | TCD_CLKSEL_CLKPER_gc)
+ #if !defined(TIMERD0_TOP_SETTING)
+ #if (F_CPU <= 8000000)
+ #define TIMERD0_TOP_SETTING (254)
+ #elif (F_CPU <= 20000000)
+ #define TIMERD0_TOP_SETTING (509)
+ #else
+ #define TIMERD0_TOP_SETTING (1019)
+ #endif
+ #endif
+ #endif // end of F_CPU tests
+ #else //CLOCK setting IS defined!! That is unusual indeed!
+ #if !defined(TIMERD0_TOP_SETTING)
+ #define TIMERD0_TOP_SETTING (254)
+ #endif
+ #endif
+ #endif // End of USE_TIMERD0_PWM
+#endif // end of DxCore TCD stuff - see why we don't support it for millis here?
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/tune_guesses.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/tune_guesses.h
new file mode 100644
index 0000000..872c103
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/tune_guesses.h
@@ -0,0 +1,295 @@
+/* These are the gusses at cal change needed to get these speeds untuned *
+ * They are concatenated with the sigrow reference, so + or - operator works.*
+ * Putting them all in one place allows better calculation of them as more *
+ * data is gathered and analyzed.
+ *
+ * Possible target frequencies supported by megaTinyCore are:
+ *
+ * 2-series, 20 MHz: 16,*20, 24, 25, 30, 32
+ * 16 MHz: 14,*16, 20, 24, 25, 30
+ * 1-series, 20 MHz: 14, 16,*20, 24, 25, 30
+ * 16 MHz: 12, 14,*16, 20, 24, 25
+ * Further, prescaled clocks derived by dividing those values by 2, 4, or 8 *
+ * are supported, provided that the number number of clocks per microsecond *
+ * is a whole number.
+ *
+ * Hence the overall list of speeds achievable is
+ * 2-series, 20 MHz: 1, 2, 3, 4, 5, 8, 10, 12, 16, 20, 24, 25, 30, 32 MHz
+ * 16 MHz: 1, 2, 3, 4, 5, 7, 8, 10, 12, 14, 16, 20, 24, 25, 30 MHz
+ * 1-series, 20 MHz: 1, 2, 3, 4, 5, 7, 8, 10, 12, 14, 16, 20, 24, 25, 30 MHz
+ * 16 MHz: 1, 2, 3, 4, 5, 7, 8, 10, 12, 14, 16, 20, 24, 25 MHz
+ *
+ */
+
+#define GUESS_DEFAULT (-1)
+
+#if MEGATINYCORE_SERIES == 2
+ #define GUESS_20_32 (62)
+ #define GUESS_20_30 (52)
+ #define GUESS_16_30 (90)
+ #define GUESS_20_25 (27)
+ #define GUESS_16_25 (59)
+ #define GUESS_20_24 (23)
+ #define GUESS_16_24 (53)
+ #define GUESS_20_20 (0)
+ #define GUESS_16_20 (27)
+ #define GUESS_20_16 (-23)
+ #define GUESS_20_14 (-1)
+ #define GUESS_16_16 (0)
+ #define GUESS_16_14 (-18)
+ #define MAX_TUNING (127)
+ #define HOME_TUNING_OFFSET (1)
+#else
+ #define GUESS_20_30 (33)
+ #define GUESS_20_25 (17)
+ #define GUESS_20_24 (13)
+ #define GUESS_20_16 (-14)
+ #define GUESS_20_14 (-19)
+ #define GUESS_16_25 (35)
+ #define GUESS_16_24 (31)
+ #define GUESS_16_20 (16)
+ #define GUESS_16_14 (-14)
+ #define GUESS_16_12 (-28)
+ #define MAX_TUNING (63)
+ #define HOME_TUNING_OFFSET (2)
+#endif
+/* Here we pick the correct one to use for the requested frequency. *
+ * First TUNE_PRESCALE is determined to permit tuning to very low speeds, which is used if*
+ * a tuned clock is requested at a speed requiring the tuned clock to be
+ *ble) "
+ * Note the _ - outside of this file, we don't want anyone to know about this */
+
+
+#if _CLOCKSPERUS > 12
+ #define TUNE_PRESCALE (0)
+#elif _CLOCKSPERUS == 10 || _CLOCKSPERUS == 12 || _CLOCKSPERUS == 7
+ #define TUNE_PRESCALE (1) //enable with 2x prescale
+#elif _CLOCKSPERUS == 4 || _CLOCKSPERUS == 5 || _CLOCKSPERUS == 6
+ #define TUNE_PRESCALE (3) //enable with 4x prescale
+#elif _CLOCKSPERUS > 1 // This is the 2 (or 3) MHz case.
+ #define TUNE_PRESCALE (5)
+#elif _CLOCKSPERUS == 1
+ #define TUNE_PRESCALE (7)
+#else
+ #define TUNE_PRESCALE (0)
+#endif
+uint8_t GUESSCAL;
+uint8_t TUNED_CALIBRATION_OFFSET;
+
+#if MEGATINYCORE_SERIES == 2
+ if (_osccfg == 1) { //Don't worry, CLOCKSPERUS is constant and gets folded!
+ if (_CLOCKSPERUS == 32) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_32 );
+ TUNED_CALIBRATION_OFFSET = (5);
+ } else if (_CLOCKSPERUS == 30) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_30 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 25) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_25 );
+ TUNED_CALIBRATION_OFFSET = (3);
+ } else if (_CLOCKSPERUS == 24) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_24 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 20 ) {// or 5 MHz
+ GUESSCAL = (SIGROW_OSCCAL20M0 );
+ TUNED_CALIBRATION_OFFSET = (1);
+ } else if (_CLOCKSPERUS == 16 ) {// or 8 or 4 MHz
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else if (_CLOCKSPERUS == 12) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_24 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 10) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 );
+ TUNED_CALIBRATION_OFFSET = (1);
+ } else if (_CLOCKSPERUS == 8) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else if (_CLOCKSPERUS == 6) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_24 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 5) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 );
+ TUNED_CALIBRATION_OFFSET = (1);
+ } else if (_CLOCKSPERUS == 4) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else if (_CLOCKSPERUS == 2) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else if (_CLOCKSPERUS == 1) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else {
+ TUNED_CALIBRATION_OFFSET = (-1);
+ }
+ } else if(_osccfg == 0) {
+ if (_CLOCKSPERUS == 30) {
+ GUESSCAL = (-1);
+ TUNED_CALIBRATION_OFFSET = (-1);
+ } else if (_CLOCKSPERUS == 25) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_25 );
+ TUNED_CALIBRATION_OFFSET = (5);
+ } else if (_CLOCKSPERUS == 24) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_24 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 20 ) {// or 5 MHz
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_20 );
+ TUNED_CALIBRATION_OFFSET = (3);
+ } else if (_CLOCKSPERUS == 16 ) {// or 8 or 4 MHz
+ GUESSCAL = (SIGROW_OSCCAL16M0 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 14 ) {// or 8 or 4 MHz
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_14 );
+ TUNED_CALIBRATION_OFFSET = (1);
+ } else if (_CLOCKSPERUS == 12) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_24 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else if (_CLOCKSPERUS == 10) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_20 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 8) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 7) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_14 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 6) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_24 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 5) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_16 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 4) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 2) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 1) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else {
+ TUNED_CALIBRATION_OFFSET = (-1);
+ }
+ }
+/* These are the gusses at cal change needed to get these speeds untuned *
+ * They are concatenated with the sigrow reference, so + or - operator works.*
+ * Putting them all in one place allows better calculation of them as more *
+ * data is gathered and analyzed.
+ *
+ * Possible Freq's are:
+ * Prescaled clock options | Tuned clock options reached directly
+ * 2-series, 20 MHz: 1, 2, 4, 5, 6, - 8, 10, 12 | 16,~20, 24, 25, 30, 32 -- no 14 MHz option (no room, and 14/7 MHz is a highly unwise choice of operating frequency,
+ * 16 MHz: 1, 2, 4, 5, 6, 7, 8, 10, 12 | 14,~16, 20, 24, 25, 30 -- no 32 MHz option, and isn't even officially supported. but what else could I put in this slot?
+ * 1-series, 20 MHz: 1, 2, 4, 5, 6, 7, 8, 10, 12 | 14, 16,~20, 24, 25, 30 -- no 32 MHz option, and not all parts can hit 30.
+ * 16 MHz: 1, 2, 4, 5, 6, 7, 8, 10, - | 12, 14,~16, 20, 24, 25 -- no 30 or 32 MHz options. Not all parts can even hit 24.10 prescaled from 20 the usual way.
+
+ */
+#else /* 0/1-series! */
+ if(_osccfg == 1) {
+ if (_CLOCKSPERUS > 30) {
+ GUESSCAL = (-1);
+ TUNED_CALIBRATION_OFFSET = (-1);
+ } else if (_CLOCKSPERUS == 30) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_30 );
+ TUNED_CALIBRATION_OFFSET = (5);
+ } else if (_CLOCKSPERUS == 25) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_25 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 24) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_24 );
+ TUNED_CALIBRATION_OFFSET = (3);
+ } else if (_CLOCKSPERUS == 20) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 16) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (1);
+ } else if (_CLOCKSPERUS == 14) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_14 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else if (_CLOCKSPERUS == 12) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_24 );
+ TUNED_CALIBRATION_OFFSET = (3);
+ } else if (_CLOCKSPERUS == 10) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 8) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 7) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_24 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 6) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_24 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 5) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 4) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 2) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 1) {
+ GUESSCAL = (SIGROW_OSCCAL20M0 + GUESS_20_16 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else {
+ GUESSCAL = (-1);
+ TUNED_CALIBRATION_OFFSET = (-1);
+ }
+ } else if(_osccfg == 0) {
+ if (_CLOCKSPERUS >= 30) {
+ GUESSCAL = (-1);
+ TUNED_CALIBRATION_OFFSET = (-1);
+ } else if (_CLOCKSPERUS == 25) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_25 );
+ TUNED_CALIBRATION_OFFSET = (5);
+ } else if (_CLOCKSPERUS == 24) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_24 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 20 ) {// or 5 MHz
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_20 );
+ TUNED_CALIBRATION_OFFSET = (3);
+ } else if (_CLOCKSPERUS == 16 ) {// or 8 or 4 MHz
+ GUESSCAL = (SIGROW_OSCCAL16M0 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 14 ) {// or 8 or 4 MHz
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_14 );
+ TUNED_CALIBRATION_OFFSET = (1);
+ } else if (_CLOCKSPERUS == 12) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_12 );
+ TUNED_CALIBRATION_OFFSET = (0);
+ } else if (_CLOCKSPERUS == 10) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_20 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 8) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 7) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_20_14 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 6) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_12 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 5) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 + GUESS_16_20 );
+ TUNED_CALIBRATION_OFFSET = (4);
+ } else if (_CLOCKSPERUS == 4) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 2) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else if (_CLOCKSPERUS == 1) {
+ GUESSCAL = (SIGROW_OSCCAL16M0 );
+ TUNED_CALIBRATION_OFFSET = (2);
+ } else {
+ GUESSCAL = (-1);
+ TUNED_CALIBRATION_OFFSET = (-1);
+ }
+ }
+#endif
+// if no prescaling needed, remember we need to turn it off!
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring.c
new file mode 100644
index 0000000..a8cebd5
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring.c
@@ -0,0 +1,1749 @@
+/*
+ wiring.c - Partial implementation of the Wiring API
+ Originally part of Arduino - http://www.arduino.cc/
+ Copyright (c) 2005-2006 David A. Mellis
+
+
+ Copyright (c) 2018-2021 Spence Konde
+ This has been ported to modern AVRs (Arduino team did that)
+ Almost every part of it has since been rewritten for
+ megaTinyCore and DxCore. This is the megaTinyCore version, and is
+ part of megaTinyCore.
+
+ 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
+*/
+
+#include "wiring_private.h"
+#include "util/delay.h"
+
+void init_timers();
+
+#ifndef F_CPU
+ #error "F_CPU not defined. F_CPU must always be defined as the clock frequency in Hz"
+#endif
+#ifndef CLOCK_SOURCE
+ #error "CLOCK_SOURCE not defined. Must be 0 for internal, 1 for crystal, or 2 for external clock"
+#endif
+
+/* __PeripheralControl is used to mark peripherals as being "taken over" by the user
+ * 0x40 = TIMERD0
+ * 0x10 = TIMERA0
+ * 0x08 = TIMERA1
+ * Implementation and use is not portable between cores - tradeoffs are made which
+ * trade generalizability for low resource use
+ */
+uint8_t __PeripheralControl = 0xFF;
+
+// the prescaler is set so that timer ticks every 64 clock cycles, and the
+// the overflow handler is called every 256 ticks.
+
+/* Use prescale appropriate for system clock speed
+ * Detect conflict between wiring.c and timers.h if we spot them, as that indicates
+ * a defect in the core and would result in extremely bad behavior
+ */
+#if (F_CPU > 30000000) // use 256 divider when clocked over 30 MHz
+ #if defined(MILLIS_USE_TIMERA0) && (TIME_TRACKING_TIMER_DIVIDER != 256)
+ #error "wiring.c and timers.h want to set millis timer TCA0 to different divider"
+ #endif
+ #define TIMERA_PRESCALER_bm (TCA_SPLIT_CLKSEL_DIV256_gc)
+#elif (F_CPU > 5000000) // use 64 divider unless it's 5 MHz or under
+ #if defined(MILLIS_USE_TIMERA0) && (TIME_TRACKING_TIMER_DIVIDER != 64)
+ #error "wiring.c and timers.h want to set millis timer TCA0 to different divider"
+ #endif
+ #define TIMERA_PRESCALER_bm (TCA_SPLIT_CLKSEL_DIV64_gc)
+#elif (F_CPU > 1000000) // anything above 1 MHz
+ #if defined(MILLIS_USE_TIMERA0) && (TIME_TRACKING_TIMER_DIVIDER != 16)
+ #error "wiring.c and timers.h want to set millis timer TCA0 to different divider"
+ #endif
+ #define TIMERA_PRESCALER_bm (TCA_SPLIT_CLKSEL_DIV16_gc)
+#else /* for 1 MHz and lower */
+ #if defined(MILLIS_USE_TIMERA0) && (TIME_TRACKING_TIMER_DIVIDER != 8)
+ #error "wiring.c and timers.h want to set millis timer TCA0 to different divider"
+ #endif
+ #define TIMERA_PRESCALER_bm (TCA_SPLIT_CLKSEL_DIV8_gc)
+#endif
+
+
+#ifndef MILLIS_USE_TIMERNONE
+
+ // volatile uint16_t microseconds_per_timer_overflow;
+ // volatile uint16_t microseconds_per_timer_tick;
+ // overflow count is tracked for all timer options, even the RTC
+ struct sTimer {
+ uint8_t intClear;
+ volatile uint8_t *intStatusReg;
+ };
+
+ #if defined(MILLIS_USE_TIMERRTC)
+ #define MILLIS_TIMER_VECTOR (RTC_CNT_vect)
+ const struct sTimer _timerS = {RTC_OVF_bm, &RTC.INTCTRL};
+ #else
+ // when TCD0 is used as millis source, this will be different from above, but 99 times out of 10, when a piece of code asks for clockCyclesPerMicrosecond(), they're asking about CLK_PER/CLK_MAIN/etc, not the unprescaled TCD0!
+
+
+
+ #if defined (MILLIS_USE_TIMERA0)
+ #ifndef TCA0
+ #error "Selected millis timer, TCA0 does not exist on this part."
+ #endif
+ #if defined(TCA_BUFFERED_3PIN)
+ #define MILLIS_TIMER_VECTOR (TCA0_OVF_vect)
+ const struct sTimer _timerS = {TCA_SINGLE_OVF_bm, &TCA0.SINGLE.INTFLAGS};
+ #else
+ #define MILLIS_TIMER_VECTOR (TCA0_HUNF_vect)
+ const struct sTimer _timerS = {TCA_SPLIT_HUNF_bm, &TCA0.SPLIT.INTFLAGS};
+ #endif
+
+ #elif defined (MILLIS_USE_TIMERA1)
+ #ifndef TCA1
+ #error "Selected millis timer, TCA1 does not exist on this part."
+ #endif
+ #define MILLIS_TIMER_VECTOR (TCA1_HUNF_vect)
+ const struct sTimer _timerS = {TCA_SPLIT_HUNF_bm, &TCA1.SPLIT.INTFLAGS};
+
+ #elif defined(MILLIS_USE_TIMERB0)
+ #ifndef TCB0
+ #error "Selected millis timer, TCB0 does not exist on this part."
+ #endif
+ #define MILLIS_TIMER_VECTOR (TCB0_INT_vect)
+ static volatile TCB_t *_timer = &TCB0;
+ const struct sTimer _timerS = {TCB_CAPT_bm, &TCB0.INTFLAGS};
+
+ #elif defined(MILLIS_USE_TIMERB1)
+ #ifndef TCB1
+ #error "Selected millis timer, TCB1 does not exist on this part."
+ #endif
+ #define MILLIS_TIMER_VECTOR (TCB1_INT_vect)
+ static volatile TCB_t *_timer = &TCB1;
+ const struct sTimer _timerS = {TCB_CAPT_bm, &TCB1.INTFLAGS};
+
+ #elif defined(MILLIS_USE_TIMERB2)
+ #ifndef TCB2
+ #error "Selected millis timer, TCB2 does not exist on this part."
+ #endif
+ #define MILLIS_TIMER_VECTOR (TCB2_INT_vect)
+ static volatile TCB_t *_timer = &TCB2;
+ const struct sTimer _timerS = {TCB_CAPT_bm, &TCB2.INTFLAGS};
+
+ #elif defined(MILLIS_USE_TIMERB3)
+ #ifndef TCB3
+ #error "Selected millis timer, TCB3 does not exist on this part."
+ #endif
+ #define MILLIS_TIMER_VECTOR (TCB3_INT_vect)
+ static volatile TCB_t *_timer = &TCB3;
+ const struct sTimer _timerS = {TCB_CAPT_bm, &TCB3.INTFLAGS};
+
+ #elif defined(MILLIS_USE_TIMERB4)
+ #ifndef TCB4
+ #error "Selected millis timer, TCB4 does not exist on this part."
+ #endif
+ #define MILLIS_TIMER_VECTOR (TCB4_INT_vect)
+ static volatile TCB_t *_timer = &TCB4;
+ const struct sTimer _timerS = {TCB_CAPT_bm, &TCB4.INTFLAGS};
+
+ #elif defined(MILLIS_USE_TIMERD0)
+ #ifndef TCD0
+ #error "Selected millis timer, TCD0, is only valid for 1-series tinyAVR"
+ #endif
+ #define MILLIS_TIMER_VECTOR (TCD0_OVF_vect)
+ const struct sTimer _timerS = {TCD_OVF_bm, &TCD0.INTFLAGS};
+
+ #else
+ #error "No millis timer selected, but not disabled - can't happen!".
+ #endif /* defined(MILLIS_USE_TIMER__) */
+ #endif /* defined(MILLIS_USE_TIMERRTC) */
+
+ #define ClockCyclesToMicroseconds(__a__) ((__a__) / (F_CPU / 1000000L))
+ #define FRACT_MAX (1000)
+ #define FRACT_INC (ClockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF)%1000)
+ #define MILLIS_INC (ClockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF)/1000)
+
+ struct sTimeMillis {
+ #if (defined(MILLIS_USE_TIMERRTC) || defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4)) // Now TCB as millis source does not need fraction
+ volatile uint32_t timer_millis; // That's all we need to track here
+ #else // TCAx or TCD0
+ //volatile uint16_t timer_fract;
+ //volatile uint32_t timer_millis;
+ //volatile uint32_t timer_overflow_count;
+ volatile uint32_t timer_overflow_count;
+ volatile uint32_t timer_millis;
+ volatile uint16_t timer_fract;
+
+ #endif
+ } timingStruct;
+
+ // Now for the ISRs. This gets a little bit more interesting now...
+ #if defined (MILLIS_USE_TIMERRTC)
+ ISR(MILLIS_TIMER_VECTOR) {
+ if (RTC.INTFLAGS & RTC_OVF_bm) {
+ timingStruct.timer_millis += 64000;
+ }
+ RTC.INTFLAGS = RTC_OVF_bm | RTC_CMP_bm; // clear flag
+ }
+ #else
+ ISR(MILLIS_TIMER_VECTOR, ISR_NAKED) {
+ // Common Interrupt header for TCB, TCA and TCD;
+ // Clears the Timer Interrupt flag and pushes the CPU Registers
+ // 7 words / 7 clocks
+ __asm__ __volatile__(
+ "push r24" "\n\t" // Free up one more register to load values into
+ "ldi r24, %[CLRFL]" "\n\t" // This is the TCB interrupt clear bitmap
+ "sts %[PTCLR], r24" "\n\t" // write to Timer interrupt status register to clear flag. 2 clocks for sts
+ "in r24, 0x3F" "\n\t" // Load SREG
+ "push r24" "\n\t" // and push it on the Stack
+ "push r30" "\n\t" // First we make room for the pointer to timingStruct by pushing the Z registers
+ "push r31" "\n\t" //
+ :: [CLRFL] "M" (_timerS.intClear),
+ [PTCLR] "m" (*_timerS.intStatusReg));
+
+ #if (defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4))
+ __asm__ __volatile__(
+ "ld r24, Z" "\n\t" // Z points to LSB of timer_millis, load the LSB
+ #if (F_CPU > 2000000) // if it's 1 or 2 MHz, millis timer overflows every 2ms, intentionally sacrificing resolution for reduced time spent in ISR
+ "subi r24, 0xFF" "\n\t" // sub immediate 0xFF is the same as to add 1. (There is no add immediate instruction, except add immediate to word)
+ #else
+ "subi r24, 0xFE" "\n\t" // sub immediate 0xFE is the same as to add 2
+ #endif
+ "st Z, r24" "\n\t" // Store incremented value back to Z
+ "ldd r24, Z+1" "\n\t" // now load the next higher byte
+ "sbci r24, 0xFF" "\n\t" // because this is sbci, it treats carry bit like subtraction, and unless we did just roll over with the last byte,
+ "std Z+1, r24" "\n\t" // carry will be cleared. Thus, sbci 0xFF after a subi pressed into service to add, is the same as adc r1 after an add
+ "ldd r24, Z+2" "\n\t" // which is what we want.
+ "sbci r24, 0xFF" "\n\t" // This gets repeated...
+ "std Z+2, r24" "\n\t" //
+ "ldd r24, Z+3" "\n\t" //
+ "sbci r24, 0xFF" "\n\t" //
+ "std Z+3, r24" "\n\t" // ... until all 4 bytes were handled, at 4 clocks and 3 words per byte -> 16 clocks
+ :: "z" (&timingStruct.timer_millis)
+ ); // grrr, sublime highlights this as invalid syntax because it gets confused by the ifdef's and odd syntax on inline asm
+
+
+ /* ISR in C:
+ ISR (TCBx_INT_vect) { // x depends on user configuration
+ #if (F_CPU > 2000000)
+ timer_millis += 1;
+ #else
+ timer_millis += 2;
+ #endif
+ _timer->INTFLAGS = TCB_CAPT_bm; // reset Interrupt flag of TCBx
+ }
+ */
+ #else // TCA0 or TCD0, also naked
+ /*
+ __asm__ __volatile__(
+ // ISR prologue (overall 10 words / 10 clocks (+ loading of Z)):
+ "push r25" "\n\t" // one extra Register needed
+ // timer_fract handling (8 words / 10 clocks):
+ "ldd r24, Z+8" "\n\t" // lo8(timingStruct.timer_fract).
+ "ldd r25, Z+9" "\n\t" // hi8(timingStruct.timer_fract)
+ "subi r24,%[LFRINC]" "\n\t" // use (0xFFFF - FRACT_INC) and use the lower and higher byte to add by subtraction
+ "sbci r25,%[HFRINC]" "\n\t" // can't use adiw since FRACT_INC might be >63
+ "std Z+8, r24" "\n\t" // lo8(timingStruct.timer_fract)
+ "std Z+9, r25" "\n\t" // hi8(timingStruct.timer_fract)
+ "subi r24,%[LFRMAX]" "\n\t" // subtract FRACT_MAX and see if it is lower
+ "sbci r25,%[HFRMAX]" "\n\t" //
+
+ #if MILLIS_INC != 0 // (6 words / 4 - 5 clocks, branches were optimize to create minimal diversion)
+ "brlo higher" "\n\t" // if FRAC_MAX was not reached,
+ "ldi r24, %[MIINC]" "\n\t" // load "normal" MILLIS_INC (0x00-MILLIS_INC)
+ "rjmp sub4" "\n\t" // avoid overwriting r24
+ "higher:"
+ #else // (4 words, 2 - 4 clocks)
+ "brlo sub_end" "\n\t" // if we know at compile time that MILLIS_INC is 0,
+ #endif // we don't have to check it at runtime, saving two insn (tst, branch)
+
+ "std Z+8, r24" "\n\t" // Overwrite the just stored value with the decremented value
+ "std Z+9, r25" "\n\t" // seems counter-intuitive, but it requires less registers
+ "ldi r24, %[MINCD]" "\n\t" // load MILLIS_INC that was decreased by 1 (0xFF-MILLIS_INC)
+
+ // timer_millis handling (12 words / 16 clocks):
+ "sub4:"
+ "ldd r25, Z+4" "\n\t" // lo16.lo8(timingStruct.timer_millis)
+ "sub r25, r24" "\n\t" //
+ "std Z+4, r25" "\n\t" //
+ "ldd r25, Z+5" "\n\t" // lo16.hi8(timingStruct.timer_millis)
+ "sbci r25, 0xFF" "\n\t" //
+ "std Z+5, r25" "\n\t" //
+ "ldd r25, Z+6" "\n\t" // hi16.lo8(timingStruct.timer_millis)
+ "sbci r25, 0xFF" "\n\t" //
+ "std Z+6, r25" "\n\t" //
+ "ldd r25, Z+7" "\n\t" // hi16.hi8(timingStruct.timer_millis)
+ "sbci r25, 0xFF" "\n\t" //
+ "std Z+7, r25" "\n\t" //
+ "sub_end:" // only used if MILLIS_INC == 0
+ // timer_overflow_count handling (12 words / 16 clocks):
+ "ldd r25, Z+0" "\n\t" // lo16.lo8(timingStruct.timer_overflow_count)
+ "subi r25, 0xFF" "\n\t" //
+ "std Z+0, r25" "\n\t" //
+ "ldd r25, Z+1" "\n\t" // lo16.hi8(timingStruct.timer_overflow_count)
+ "sbci r25, 0xFF" "\n\t" //
+ "std Z+1, r25" "\n\t" //
+ "ldd r25, Z+2" "\n\t" // hi16.lo8(timingStruct.timer_overflow_count)
+ "sbci r25, 0xFF" "\n\t" //
+ "std Z+2, r25" "\n\t" //
+ "ldd r25, Z+3" "\n\t" // hi16.hi8(timingStruct.timer_overflow_count)
+ "sbci r25, 0xFF" "\n\t" //
+ "std Z+3, r25" "\n\t" //
+ // ISR epilogue (7 words / 15/16 clocks):
+ "pop r25" "\n\t" // new: total 72 - 74 clocks, 55 words / 53 - 75 clocks and 53 words with MILLIS_INC == 0
+ :: "z" (&timingStruct), // old: total 77 - 79 clocks total, and 58 words, vs 104-112 clocks and 84 words
+ [LFRINC] "M" (((0x0000 - FRACT_INC) & 0xFF)),
+ [HFRINC] "M" (((0x0000 - FRACT_INC)>>8 & 0xFF)),
+ [LFRMAX] "M" ((FRACT_MAX & 0xFF)),
+ [HFRMAX] "M" ((FRACT_MAX>>8 & 0xFF)),
+ [MIINC] "M" ((0x0000 - MILLIS_INC) & 0xFF),
+ [MINCD] "M" ((0xFFFF - MILLIS_INC) & 0xFF)
+ );
+ */
+
+ __asm__ __volatile__(
+ // ISR prologue (overall 10 words / 10 clocks (+ loading of Z)):
+ "push r25" "\n\t" // second byte
+ // timer_overflow_count handling (4 words / 4 + (18) + 1 = 23 clocks):
+ "set" "\n\t" // remember to go back here
+ "ldi r24, 0xFF" "\n\t" // first byte to be subtracted of 4, rest will be 0xFF
+ "rjmp sub4" "\n\t" // jump down to sub/sbci
+ "ovf_end:" "\n\t" // jump back to here afterwards
+ "clt" "\n\t" // make sure to not jump back again
+
+ // timer_fract handling (8 words / 10 clocks) (Z += 4):
+ "ldd r24, Z+4" "\n\t" // lo8(timingStruct.timer_fract).
+ "ldd r25, Z+5" "\n\t" // hi8(timingStruct.timer_fract)
+ "subi r24,%[LFRINC]" "\n\t" // use (0xFFFF - FRACT_INC) and use the lower and higher byte to add by subtraction
+ "sbci r25,%[HFRINC]" "\n\t" // can't use adiw since FRACT_INC might be >63
+ "std Z+4, r24" "\n\t" // lo8(timingStruct.timer_fract)
+ "std Z+5, r25" "\n\t" // hi8(timingStruct.timer_fract)
+ "subi r24,%[LFRMAX]" "\n\t" // subtract FRACT_MAX and see if it is lower
+ "sbci r25,%[HFRMAX]" "\n\t" //
+
+ #if MILLIS_INC > 0 // (6 words / 4 - 5 clocks, branches were optimize to create minimal diversion)
+ "brlo higher" "\n\t" // if FRAC_MAX was not reached,
+ "ldi r24, %[MIINC]" "\n\t" // load "normal" MILLIS_INC (0x00-MILLIS_INC)
+ "rjmp sub4" "\n\t" // avoid overwriting r24
+ "higher:"
+ #else // (4 words, 2 - 4 clocks)
+ "brlo sub_end" "\n\t" // if we know at compile time that MILLIS_INC is 0,
+ #endif // we don't have to check it at runtime, saving two insn (tst, branch)
+
+ "std Z+4, r24" "\n\t" // Overwrite the just stored value with the decremented value
+ "std Z+5, r25" "\n\t" // seems counter-intuitive, but it requires less registers
+ "ldi r24, %[MINCD]" "\n\t" // load MILLIS_INC that was decreased by 1 (0xFF-MILLIS_INC)
+
+ // subtracting 4 bytes from a dword (13 words / 17 clocks)
+ "sub4:"
+ "ld r25, Z" "\n\t" // lo16.lo8(timingStruct.timer_millis)
+ "sub r25, r24" "\n\t" //
+ "st Z+, r25" "\n\t" //
+ "ld r25, Z" "\n\t" // lo16.hi8
+ "sbci r25, 0xFF" "\n\t" //
+ "st Z+, r25" "\n\t" //
+ "ld r25, Z" "\n\t" // hi16.lo8
+ "sbci r25, 0xFF" "\n\t" //
+ "st Z+, r25" "\n\t" //
+ "ld r25, Z" "\n\t" // hi16.hi8
+ "sbci r25, 0xFF" "\n\t" //
+ "st Z+, r25" "\n\t" //
+ "brts ovf_end" "\n\t" // If T bit is set, we need to go back up
+ "sub_end:"
+ // ISR epilogue (7 words / 15/16 clocks):
+ "pop r25" "\n\t"
+ :: "z" (&timingStruct),
+ [LFRINC] "M" (((0x0000 - FRACT_INC) & 0xFF)),
+ [HFRINC] "M" (((0x0000 - FRACT_INC)>>8 & 0xFF)),
+ [LFRMAX] "M" ((FRACT_MAX & 0xFF)),
+ [HFRMAX] "M" ((FRACT_MAX>>8 & 0xFF)),
+ [MIINC] "M" ((0x0000 - MILLIS_INC) & 0xFF),
+ [MINCD] "M" ((0xFFFF - MILLIS_INC) & 0xFF)
+ );
+ #endif /* (defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4)) */
+ // Common ISR Epilogue for TCA, TCB and TCD, popping register in reverse Order
+ // 6 words, 14 clocks
+ __asm__ __volatile__(
+ "pop r31" "\n\t"
+ "pop r30" "\n\t" // 6 more clocks popping registers in reverse order.
+ "pop r24" "\n\t" // pop r24 to get the old SREG value - 2 clock
+ "out 0x3F, r24" "\n\t" // restore SREG - 1 clock
+ "pop r24" "\n\t"
+ "reti" "\n\t" // and 4 clocks for reti
+ ::
+ );
+
+
+ }
+ #endif /* defined (MILLIS_USE_TIMERRTC)*/
+
+
+ /* Both millis and micros must take great care to prevent any kind of backward time travel.
+ *
+ * These values are unsigned, and should not decrease, except when they overflow. Hence when
+ * we compare a value with what we recorded previously and find the new value to be lower, it
+ * looks the same as it would 2^32 (4.2 billion) intervals in the future. Timeouts end prematurely
+ * and similar undesired behaviors occur.
+ *
+ * There are three hazardous things we read here:
+ * timer_millis, timer_overflow_count, and the timer count itself (TCxn.CNT).
+ * The normal variables need only be read with interrupts disabled, in case of an
+ * interrupt writing to it while we were reading it. AVRs are little-endian, so this would result
+ * in the low byte being read before the overflow and the high byte after, and hence a value
+ * higher than it should be for that call. Subsequent calls would return the right value.
+ *
+ * In the case of the timer value, it is more complicated.
+ * Here, the hardware at first glance seems to protect us (see "reading 16-bit registers" in the
+ * datasheet). But the register gets read in the interrupt, so we still need those disabled.
+ * There is an additional risk though that we get a value from after the timer has overflowed
+ * and since we disabled interrupts, the interrupt hasn't updated the overflow. We check the
+ * interrupt flag, and if it's set, we check whether the timer value we read was near overflow
+ * (the specifics vary by the timer - they're very different timers). If it isn't close to overflow
+ * but the flag is set, we must have read it after the overflow, so we compensate for the missed
+ * interrupt. If interrupts are disabled for long enough, this heuristic will be wrong, but in
+ * that case it is the user's fault, as this limitation is widely known and documentedm, as well
+ * as unavoidable. Failure to compensate looks like the inverse of the above case.
+ *
+ * (note that only micros reads the timer, and hence, only micros can experience backwards time
+ * travel due to interrupts being left disabled for too long, millis will just stop increasing.
+ *
+ * Both of these cause severe breakage everywhere. The first type is simple to avoid, but if
+ * missed can be more subtle, since it makes a big difference only if the byte where the read
+ * was interrupted rolled over. The second type is more obvious, potentially happening on every timer
+ * overflow, instead of just every 256th timer overflow, and when it does happen, anything waiting
+ * for a specific number of microseconds to pass that gets that value will do so.
+ * Though (see delay below) each incidence only short-circuits one ms of delay(), not the whole
+ * thing.
+ *
+ * All time time travel except for glitchs from disabling millis for too long should no longer
+ * be possible. If they are, that is a critical bug.
+ */
+
+
+ unsigned long millis() {
+ // return timer_overflow_count; // for debugging timekeeping issues where these variables are out of scope from the sketch
+ unsigned long m;
+ // disable interrupts while we read timer_millis or we might get an
+ // inconsistent value (e.g. in the middle of a write to timer_millis)
+ uint8_t oldSREG = SREG;
+ cli();
+ #if defined(MILLIS_USE_TIMERRTC)
+ uint16_t rtccount = RTC.CNT;
+ m = timingStruct.timer_millis;
+ if (RTC.INTFLAGS & RTC_OVF_bm) {
+ /* There has just been an overflow that hasn't been accounted for by the interrupt. Check if the high bit of counter is set.
+ * We just basically need to make sure that it didn't JUST roll over at the last couple of clocks. But this merthod is
+ * implemented very efficiently (just an sbrs) so it is more efficient than other approaches. If user code is leaving
+ * interrupts off nearly 30 seconds, they shouldn't be surprised. */
+ if (!(rtccount & 0x8000)) m += 64000;
+ }
+ SREG = oldSREG;
+ m += rtccount - (rtccount >> 5) + (rtccount >> 7);
+ #else
+ m = timingStruct.timer_millis;
+ SREG = oldSREG;
+ #endif
+ return m;
+ }
+ #if !defined(MILLIS_USE_TIMERRTC)
+ unsigned long micros() {
+ uint32_t overflows, microseconds;
+ #if (defined(MILLIS_USE_TIMERD0) || (defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4)))
+ uint16_t ticks;
+ #else /* TCA */
+ uint8_t ticks;
+ #endif
+ uint8_t flags;
+ /* Save current state and disable interrupts */
+ uint8_t oldSREG = SREG;
+ cli(); /* INTERRUPTS OFF */
+ #if defined(MILLIS_USE_TIMERA0)
+ ticks = TCA0.SPLIT.HCNT;
+ flags = TCA0.SPLIT.INTFLAGS;
+ #elif defined(MILLIS_USE_TIMERD0)
+ TCD0.CTRLE = TCD_SCAPTUREA_bm;
+ while (!(TCD0.STATUS & TCD_CMDRDY_bm)); // wait for sync - should be only one iteration of this loop
+ flags = TCD0.INTFLAGS;
+ ticks = TCD0.CAPTUREA;
+ #else
+ ticks = _timer->CNT;
+ flags = _timer->INTFLAGS;
+ #endif // end getting ticks
+ /* If the timer overflow flag is raised, and the ticks we read are low, then the timer has rolled over but
+ * ISR has not fired. If we already read a high value of ticks, either we read it just before the overflow,
+ * so we shouldn't increment overflows, or interrupts are disabled and micros isn't expected to work so it
+ * doesn't matter.
+ * Get current number of overflows and timer count */
+ #if !((defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4)))
+ overflows = timingStruct.timer_overflow_count;
+ #else
+ overflows = timingStruct.timer_millis;
+ #endif
+ /* Turn interrupts back on, assuming they were on when micros was called. */
+ SREG = oldSREG; /* INTERRUPTS ON */
+ #if defined(MILLIS_USE_TIMERD0)
+ if ((flags & TCD_OVF_bm) && (ticks < 0x07)) {
+ #elif defined(MILLIS_USE_TIMERA0)
+ ticks = (TIME_TRACKING_TIMER_PERIOD) - ticks;
+ if ((flags & TCA_SPLIT_HUNF_bm) && (ticks < 0x04)) {
+ #else // timerb
+ if ((flags & TCB_CAPT_bm) && !(ticks & 0xFF00)) {
+ #endif
+ #if ((defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4)) && !(F_CPU > 2000000UL))
+ overflows +=2;
+ #else
+ overflows++;
+ #endif
+ } // end getting ticks
+
+ #if defined(MILLIS_USE_TIMERD0)
+ #if (F_CPU == 20000000UL || F_CPU == 10000000UL || F_CPU == 5000000UL)
+ uint8_t ticks_l = ticks >> 1;
+ ticks = ticks + ticks_l + ((ticks_l >> 2) - (ticks_l >> 4) + (ticks_l >> 7));
+ // + ticks +(ticks>>1)+(ticks>>3)-(ticks>>5)+(ticks>>8))
+ // speed optimization via doing math with smaller datatypes, since we know high byte is 1 or 0.
+ microseconds = overflows * (TIME_TRACKING_CYCLES_PER_OVF / 20) + ticks; // ticks value corrected above.
+ #else
+ microseconds = ((overflows * (TIME_TRACKING_CYCLES_PER_OVF / 16))
+ + (ticks * (TIME_TRACKING_CYCLES_PER_OVF / 16 / TIME_TRACKING_TIMER_PERIOD)));
+ #endif
+ #if defined(CLOCK_TUNE_INTERNAL) && !(F_CPU == 16000000UL || F_CPU == 20000000UL || F_CPU == 8000000UL || F_CPU == 10000000UL || F_CPU == 4000000UL || F_CPU == 5000000UL)
+ #warning "TCD is not supported as a millis timing source when the oscillator is tuned to a frequency other than 16 or 20 MHz. Timing results will be wrong - use TCA0 or a TCB."
+ #endif
+ #elif (defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4))
+ /* Ersatz Division for TCBs - now with inline assembly!
+ *
+ * It's well known that division is an operator you want to avoid like the plague on AVR.
+ * Not only is it slow, the execution time isn't even easy to analyze - it depends on the
+ * two opperands, particularly the divisor... so you can't just look at the generated
+ * assembly and count clock cycles, you've got to either time it expoerimentally with
+ * a representative set of sample data, or know how many times it will pass through the
+ * loops and then count clock cycles. If the operands aren't constant (if they are, you
+ * can probably manage to get it optimized away at compile time) your best hope is likely
+ * simulation, assuming you know enough about the values it will end up having to divide.
+ *
+ * Anyway. You don't want to be doing division. But that's what you need in order to
+ * appropriately scale the ick count from the prescaler-deprived TCBs. Since many users
+ * reconfigure the TCA for advanced PWM, using the TCA-prescaled clock was a non-starter
+ * particularly since many parts have only one TCA. But division can be approximated
+ * very closely if the divisor is constant using a series of bitshifts and addition/subtraction.
+ *
+ * The series of shifts was determined numerically with a spreadsheet that calculated the results for
+ * each value that could come from the initial round of rightshifts for any combination of
+ * bitshifts and provided a number of statistics to select based on. Backwards time travel must
+ * never happenb, or if it does, it must be a shorter backward step than micros runtime - 1 us
+ * otherwise delay() will break and timeouts can instantly expire when it is hit. Similarly,
+ * one wants to avoid large jumps forward, and cases where more consecutive "actual" times
+ * than absolutely necessary return the same value (time should flow at a constant rate).
+ * Finally, the artifacts of the calculation that are unavoidable should be distributed uniformly.
+ * Undershooting or overshooting 999 endpoint at the counter's maximum value is the usual
+ * source of large jumps (at the overflow point) in either direction. Terms should, as much as
+ * possible alternate between positive and negative to minimize artifacts.
+ *
+ * The most popular/important speeds are hand-implemented in assembly because the compiler
+ * was doing a miserable job of it - wasting 20-30% of the execution time and it's one of the few
+ * Arduino API functions that users will be surprised and dismayed to find running slowiy.
+ * Not only does it run faster on "normal" boards (the 16 MHz clock eliminates the need to divide
+ * DxCore offers many speeds where the math doesn't all optimize away to nothing like it does at
+ * 1/2/4/8/16/32.
+ *
+ * Do notice that we are replacing a smaller number of terms, and it's still much faster
+ * The 10's went from 5 term ersatz-division to 6, while 12's went from 5 terms to 9, yet still
+ * got a lot faster. The terrible twelves are the frequency most difficult to do this with.
+ * Ironically, one of the the two that are is easiest is 36, which is good enough with 3 and
+ * effectively exact (That "middle 12" is closer than the other 12's get with 9!)
+ * 25 also matches it. Maybe it's something 25 and 36 being perfect squares?
+ *
+ * The three problems were that:
+ * 1. Compiler generated code stubbornly insisted doing repeated shift operation in a loop
+ * with 3 cycle per iteration (the shift itself took only 2)
+ * 2. Compiler could not be convinced to do things that we know will always be < 255 as
+ * bytes. Sure, it wouldn't know that - it's not legal for it to do that on it's own.
+ * But even when I cast everything to uint8_t, it would shift a 16-bit value around
+ * unnecessarily.
+ * 3. It would distribute the ticks >> 4. That is, it wouldn't shift the value of
+ * ticks in place, even though it wasn't referenced after this because I was assigning
+ * the result to ticks, and hence the old value was "dead"
+ * Instead, it would copy it, shift the copy 3 or 4 places. Then when it needed the
+ * ticks >> 2, it would make a copy of the ORIGINAL and shift that 6 places,
+ * instead of copying the copy and shifting just 2 places.
+ *
+ * A general trend seems to be that the compiler is not smart enough to "reuse" an
+ * existing value that has already been shifted such that it's closer to the target.
+ * at least for multi-byte variables. This is not the worst example of it I've run into
+ * but the micros() function is a little bit sensitive to the execution time.
+ * Apparently people sometimes want to *do something* in response to the value it
+ * returns - and they seem to want to do that in a timely manner, otherwise they'd
+ * have not bothered to record a time so accurately...
+ *
+ * general algorithm in the assembly implementations is:
+ * start with ticks in a register pair, copy to r0, r1.
+ * rightshift it until we have the 0th term (closest power of 2).
+ * copy it to back to original location..
+ * continue rightshifting it, adding or subtracting from the original when we reach
+ * the appropriate terms.
+ * As soon as we've rightshifted the original enough times that we know it's < 256,
+ * we switch from lsr r1 ror r0 to just lsr r0. At the next term that we want to add
+ * we copy it to r1. Subsequent subtractions or additions are single-byte until we've got the last term.
+ * this time, we add r1 to r0 instead of the other way around.
+ * we will need to clear r1 anyway, but we do it now, since we need a known 0 to do the carry.
+ * we addthat to the ticks intermediate value to get the final ticks value, and drop back into C
+ * where we calculate overflows * 1000, the (now 0-999) ticks to it, and return it.
+ *
+ */
+ // Oddball clock speeds
+ #if (F_CPU == 44000000UL) // Extreme overclocking
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks - /* (ticks >> 1) + */ (ticks >> 2) - (ticks >> 5) + /* (ticks >> 6) - */ (ticks >> 7)); // + (ticks >> 10)
+ #elif (F_CPU == 36000000UL) // 50% overclock!
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks - (ticks >> 3) + (ticks >> 6)); // - (ticks >> 9) + (ticks >> 10) // with 5 terms it is DEAD ON
+ #elif (F_CPU == 28000000UL) // Not supported by DxCore - nobody wants it.
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks + (ticks >> 2) - (ticks >> 3) + (ticks >> 5) - (ticks >> 6)); // + (ticks >> 8) - (ticks >> 9)
+ #elif (F_CPU == 14000000UL) // Not supported by DxCore - nobody wants it.
+ ticks = ticks >> 3;
+ microseconds = overflows * 1000 + (ticks + (ticks >> 2) - (ticks >> 3) + (ticks >> 5) - (ticks >> 6)); // + (ticks >> 8) - (ticks >> 9)
+ #elif (F_CPU == 30000000UL) // Easy overclock
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks + (ticks >> 3) - (ticks >> 4) + (ticks >> 7) - (ticks >> 8)); // 5 terms is the optimal. Good but not as close as we get for most.
+ #elif (F_CPU == 27000000UL) // You'd think this one would be a flaming bitch right?
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks + (ticks >> 2) - (ticks >> 4) - (ticks >> 9)); // +0.1 average error with only 4 terms, minimal scatter... that's just not supposed to happen!
+ #elif (F_CPU == 25000000UL) // Barely overclocked.
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks + /* (ticks >> 1) -*/ (ticks >> 2) + /* (ticks >> 4) -*/ (ticks >> 5)); // DEAD ON with 5 terms
+
+ /* The Terrible Twelves (or threes) - Twelve may be a great number in a lot of ways... but here, it's actually 3 in disguise.
+ * NINE TERMS in the damned bitshift division expansion. And the result isn't even amazing. - it's worse than what can be done
+ * with just 5 terms for dividing by 36 or 25, or a mere 3 terms with 27... where you're dividing by 9, 12.5, and 13.5 respectively,
+ * or after the initial shifts, by 0.78125, 1.25 or 1.18, and comparable to the best series for division by 1.375 (44 MHz) or 0.9375 (30 MHz) which each have 7 terms,
+ * though it's better than the best possible for the division by 0.875 associated with 28 MHs clocks which is also a 7 term one.
+ * This is division by 0.75, which sounds like it should be the easiest out of the lot.
+ *
+ * This does the following:
+ * ticks = ticks >> (1, 2, 3, 4, or 6 for 3 MHz, 6 MHz, 12 MHz, 24 MHz, or 48 MHz)
+ * ticks = ticks + (ticks >> 1) - (ticks >> 2) + (ticks >> 3) - (ticks >> 4) + (ticks >> 5) - (ticks >> 6) + (ticks >> 7) - (ticks >> 9)
+ *
+ * Equivalent to :
+ * ticks = ticks / (1.5, 3, 6, 12, or 24)
+ *
+ * Division is way too slow, but we need to convert current timer ticks, which
+ * are are 0-2999, 0-5999, 0-11999, or 0-23999 into the 3 least significant digits
+ * of the number of microseconds so that it can be added to overflows * 1000.
+ *
+ * Runtime of the assembly is 28, 30, 32, or 34 clocks
+ * 3 and 6 MHz not a supported speed.
+ * 57 replaced with 30 save 27 clocks @ 12 = 2 us saved
+ * 67 replaced with 32 save 35 clocks @ 24 = 1.5us saved
+ * 77 replaced with 34 save 43 clocks @ 48 = 1 us saved
+ */
+ #elif (F_CPU == 48000000UL || F_CPU == 24000000UL || F_CPU == 12000000UL || F_CPU == 6000000UL || F_CPU == 3000000UL)
+ __asm__ __volatile__(
+ "movw r0,%A0" "\n\t" // we copy ticks to r0 (temp_reg) and r1 (zero_reg) so we don't need to allocate more registers.
+ "lsr r1" "\n\t" // notice how at first, each shift takes insns. Compiler wants to use an upper register, ldi number of shifts
+ "ror r0" "\n\t" // into it, then lsr, ror, dec, breq (4 insn + 5 clocks per shift, and including the ldi, it's 5 insns + 5*shiftcount clocks)
+ #if (F_CPU != 3000000UL)
+ "lsr r1" "\n\t"
+ "ror r0" "\n\t"
+ #endif
+ #if (F_CPU == 12000000UL || F_CPU == 24000000UL || F_CPU == 48000000UL)
+ "lsr r1" "\n\t" // sacrifice 1 word for 9 clocks on the 12 MHz configuration
+ "ror r0" "\n\t"
+ #endif
+ #if (F_CPU == 24000000UL || F_CPU == 48000000UL)
+ "lsr r1" "\n\t" // sacrifice 3 words for 12 clocks on the 24 MHz configuration
+ "ror r0" "\n\t"
+ #endif
+ #if (F_CPU == 48000000UL)
+ "lsr r1" "\n\t" // sacrifice 5 words for 15 clocks on the 48 MHz configuration.
+ "ror r0" "\n\t"
+ #endif
+ "movw %A0,r0" "\n\t" // This is the value we call ticks, because that's what it was in old code.
+ "lsr r1" "\n\t" // we just copied the now shifted value back to original location.
+ "ror r0" "\n\t" // 2 words per shift still
+ "add %A0, r0" "\n\t" // we now have ticks >> 1, add it to original.
+ "adc %B0, r1" "\n\t" //
+ "lsr r1" "\n\t" //
+ "ror r0" "\n\t" // we now have ticks >> 2. Now it's under 250, and r1 is 0
+ "mov r1,r0" "\n\t" // so we copy the remaining value into r1.
+ "lsr r1 " "\n\t" // now it's only 1 insn/shift!
+ "sub r0,r1" "\n\t" // - ticks >> 3
+ "lsr r1" "\n\t"
+ "add r0,r1" "\n\t" // + ticks >> 4
+ "lsr r1" "\n\t"
+ "sub r0,r1" "\n\t" // - ticks >> 5
+ "lsr r1" "\n\t"
+ "add r0,r1" "\n\t" // + ticks >> 6
+ "lsr r1" "\n\t"
+ "sub r0,r1" "\n\t" // - ticks >> 7
+ "lsr r1" "\n\t"
+ "lsr r1" "\n\t"
+ "add r0,r1" "\n\t" // + ticks >> 9
+ "eor r1,r1" "\n\t" // clear out r1
+ "sub %A0,r0" "\n\t" // Add the sum of terms that fit in a byte to what was ticks in old code.
+ "sbc %B0,r1" "\n" // carry - see,this is why AVR needs a known zero.
+ : "+r" (ticks)); // Do the rest in C. ticks is a read/write operand.
+ microseconds = overflows * 1000 + ticks; // nice and clean.
+
+ /* The Troublesome Tens - I initially fumbled this after the **now** r1 is 0 line
+ * I did several dumb things - at first I thought it was my pointless moving and
+ * adding. But the real problem was that on that line, I'd just deleted the
+ * now unnecessary lsr r1, leaving the next as ror instead of lsr. So instead of pushing
+ * that bit into the void, it came back as the new high bit, causing the device to travel
+ * back in time. Unfortunately, a few hundred milliseconds isn't far back enough to
+ * snag a winning ticket for todays lotto, but more than than the execution time
+ * of micros is far enough back to thoroughly break delay() Even if I could just go back
+ * just far enough to tell myself where the bug was, I'd take it...
+ *
+ * This does the following:
+ * ticks = ticks >> (1, 2, 3, or 4 for 5 MHz, 10 MHz, 20 MHz, or 40 MHz)
+ * ticks = ticks - (ticks >> 2) + (ticks >> 4) - (ticks >> 6) + (ticks >> 8)
+ *
+ * Equivalent to:
+ * ticks = tick / (2.5, 5, 10, or 20)
+ * Division is way too slow, but we need to convert current timer ticks, which
+ * are 0-2499, 0-4999, 0-9999, or 0-19999, into the 3 least significant digits
+ * of the number of microseconds so that it can be added to overflows * 1000.
+ *
+ * Runtime is 23,25,27, or 29 clocks, savings vs the best I could do in C
+ *
+ * 33 replaced with 23 save 10 clocks @ 5 = 2 us saved
+ * 46 replaced with 25 save 21 clocks @ 10 = 2.5 us saved
+ * 56 replaced with 27 save 29 clocks @ 20 = 1.5 us saved
+ * 66 replaced with 29 save 37 clocks @ 40 = 1 us saved
+ */
+ #elif (F_CPU == 40000000UL || F_CPU == 20000000UL || F_CPU == 10000000UL || F_CPU == 5000000UL)
+ __asm__ __volatile__(
+ "movw r0,%A0" "\n\t" // no savings until after the initial rightshifts at 5 MHz
+ "lsr r1" "\n\t"
+ "ror r0" "\n\t"
+ #if (F_CPU == 10000000UL || F_CPU == 20000000UL || F_CPU == 40000000UL)
+ "lsr r1" "\n\t" // sacrifice 1 word for 9 clocks at 10 MHz
+ "ror r0" "\n\t"
+ #endif
+ #if (F_CPU == 20000000UL || F_CPU == 40000000UL)
+ "lsr r1" "\n\t" // sacrifice 3 words for 12 clocks at 20 MHz
+ "ror r0" "\n\t"
+ #endif
+ #if (F_CPU == 40000000UL)
+ "lsr r1" "\n\t" // sacrifice 5 words for 15 clocks at 40 MHz
+ "ror r0" "\n\t"
+ #endif
+ "movw %A0,r0" "\n\t" // ticks
+ "lsr r1" "\n\t"
+ "ror r0" "\n\t"
+ "lsr r1" "\n\t"
+ "ror r0" "\n\t" // ticks >> 2.
+ "sub %A0, r0" "\n\t" // - ticks >> 2
+ "sbc %B0, r1" "\n\t" // It could be 312 so we can't do what we did for the 12's
+ "lsr r1" "\n\t"
+ "ror r0" "\n\t" // **now** r1 is 0.
+ "lsr r0" "\n\t"
+ "mov r1,r0" "\n\t" // + ticks >> 4
+ "lsr r1" "\n\t"
+ "lsr r1" "\n\t"
+ "sub r0,r1" "\n\t" // - ticks >> 6
+ "lsr r1" "\n\t"
+ "lsr r1" "\n\t"
+ "add r0,r1" "\n\t" // + ticks >> 8
+ "eor r1,r1" "\n\t" // restore zero_reg
+ "add %A0,r0" "\n\t" // add to the shifted ticks
+ "adc %B0,r1" "\n" // carry
+ : "+r" (ticks)); // Do the rest in C. ticks is a read/write operand.
+ microseconds = overflows * 1000 + ticks;
+ /* replaces:
+ #elif (F_CPU == 48000000UL) // Extreme overclocking
+ ticks = ticks >> 5;
+ microseconds = overflows * 1000 + (ticks + (ticks >> 2) + (ticks >> 3) - (ticks >> 5)); // - (ticks >> 7)
+ #elif (F_CPU == 24000000UL) // max rated speed
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks + (ticks >> 2) + (ticks >> 3) - (ticks >> 5)); // - (ticks >> 7)
+ #elif (F_CPU == 12000000UL)
+ ticks = ticks >> 3;
+ microseconds = overflows * 1000 + (ticks + (ticks >> 2) + (ticks >> 3) - (ticks >> 5)); // - (ticks >> 7)
+ // Never was an implementation for 3 or 6, but it's obvious what the old style implementation would be,
+ #elif (F_CPU == 40000000UL) // overclocked aggressively
+ ticks = ticks >> 4;
+ microseconds = overflows * 1000 + (ticks - (ticks >> 2) + (ticks >> 4) - (ticks >> 6)); // + (ticks >> 8)
+ #elif (F_CPU == 20000000UL)
+ ticks = ticks >> 3;
+ microseconds = overflows * 1000 + (ticks - (ticks >> 2) + (ticks >> 4) - (ticks >> 6)); // + (ticks >> 8)
+ #elif (F_CPU == 10000000UL)
+ ticks = ticks >> 2;
+ microseconds = overflows * 1000 + (ticks - (ticks >> 2) + (ticks >> 4) - (ticks >> 6)); // + (ticks >> 8)
+ #elif (F_CPU == 5000000UL)
+ ticks = ticks >> 1;
+ microseconds = overflows * 1000 + (ticks - (ticks >> 2) + (ticks >> 4) - (ticks >> 6)); // + (ticks >> 8)
+ */
+
+ // powers of 2 - and a catchall for parts without dedicated implementations. It gives wrong results, but
+ // it also doesn't take forever like doing division would.
+ #elif (F_CPU == 32000000UL || F_CPU > 24000000UL)
+ microseconds = overflows * 1000 + (ticks >> 4);
+ #elif (F_CPU == 16000000UL || F_CPU > 12000000UL)
+ microseconds = overflows * 1000 + (ticks >> 3);
+ #elif (F_CPU == 8000000UL || F_CPU > 6000000UL)
+ microseconds = overflows * 1000 + (ticks >> 2);
+ #elif (F_CPU == 4000000UL || F_CPU >= 3000000UL)
+ microseconds = overflows * 1000 + (ticks >> 1);
+ #else //(F_CPU == 1000000UL || F_CPU == 2000000UL) - here clock is running at system clock instead of half system clock.
+ // and hence overflows only once per 2ms. On 2 MHz
+ // also works at 2MHz, since we use CLKPER for 1MHz vs CLKPER/2 for all others.
+ microseconds = overflows * 1000 + ticks;
+ #endif
+ #if !((F_CPU == 48000000UL || F_CPU == 36000000UL || F_CPU == 24000000UL || F_CPU == 12000000UL || /* multiples of 12 */ \
+ F_CPU == 40000000UL || F_CPU == 30000000UL || F_CPU == 20000000UL || F_CPU == 10000000UL || /* multiples of 10 */ \
+ F_CPU == 32000000UL || F_CPU == 16000000UL || F_CPU == 8000000UL || F_CPU == 4000000UL || /* powers of 2 */ \
+ F_CPU == 2000000UL || F_CPU == 1000000UL || F_CPU == 25000000UL || F_CPU == 5000000UL || /* powers of 2 cont, 25, 5 */ \
+ F_CPU == 44000000UL || F_CPU == 28000000UL || F_CPU == 14000000UL || F_CPU == 3000000UL || /* oddball frequencies */ \
+ F_CPU == 27000000UL)&& /* warn fools who messed with the timers.h file too and expected that the core would sort out how */ \
+ ((TIME_TRACKING_TIMER_DIVIDER == 2 && TIME_TRACKING_TICKS_PER_OVF == F_CPU/2000) || /*how to make the timer work correctly*/ \
+ (TIME_TRACKING_TIMER_DIVIDER == 1 && (TIME_TRACKING_TICKS_PER_OVF == F_CPU/500 && F_CPU == 1000000) || (TIME_TRACKING_TICKS_PER_OVF == F_CPU/1000 && F_CPU == 2000000))))
+ /* without them implementing it. No such luck */
+ #warning "Millis timer (TCBn) at this frequency and/or configuration unsupported, micros() will return totally bogus values."
+ #endif
+ #else // Done with TCB
+ #if (F_CPU == 30000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + ((ticks * 2) + ((uint16_t)(ticks >> 3)));
+ #elif (F_CPU == 28000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + ((ticks * 2) + ((uint16_t)(ticks >> 2) + (ticks >> 5)));
+ #elif (F_CPU == 25000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + (ticks * 2 + ((uint16_t)(ticks >> 1) + (ticks >> 4)));
+ #elif (F_CPU == 24000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + (ticks * 3 - ((uint16_t)(ticks >> 2) - (ticks >> 4) - (ticks >> 5)));
+ #elif (F_CPU == 20000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + (ticks * 3 + ((uint16_t)(ticks >> 2) - (ticks >> 4)));
+ #elif (F_CPU == 28000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + (ticks * 4 + ((uint16_t)(ticks >> 1) + (ticks >> 4) + (ticks >> 5)));
+ #elif (F_CPU == 12000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + (ticks * 5 + ((uint16_t)(ticks >> 2) + (ticks >> 4) + (ticks >> 5)));
+ #elif (F_CPU == 10000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 64)
+ microseconds = (overflows * clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + ((ticks << 3) - ((uint16_t)(ticks << 1) + (ticks >> 1) - (ticks >> 3)));
+ #elif (F_CPU == 5000000UL && TIME_TRACKING_TICKS_PER_OVF == 255 && TIME_TRACKING_TIMER_DIVIDER == 16)
+ microseconds = (overflows * millisClockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + (ticks * 3 + ((uint16_t)(ticks >> 2) - (ticks >> 4)));
+ #else
+ #if (TIME_TRACKING_TIMER_DIVIDER%(F_CPU/1000000))
+ #warning "Millis timer (TCA0) at this frequency unsupported, micros() will return bogus values."
+ #endif
+ microseconds = ((overflows * millisClockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF))
+ + (ticks * (millisClockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF) / TIME_TRACKING_TIMER_PERIOD)));
+ #endif
+ #endif // end of timer-specific part of micros calculations
+ return microseconds;
+ }
+ #else // MILLIS_USE_TIMERRTC is defined, so we don't have micros
+ /* We do not have a timebase sufficiently accurate to give microsecond timing. In fact, we barely have millisecond timing available
+ * The microsecond delay counts clock cycles, and so it does still work. It is planned that a future library will switch the millis
+ * pause millis before sleeping and turn on the RTC, tracking the passage of time to a much coarser resolution with that, and turn
+ * it back on when waking from sleep, so people can keep time while sleeping without sacrificing micros().
+ * In any event, as of 2.4.3 we now provide the stub below, which we hope is more useful than being told that micros() isn't defined.
+ */
+ unsigned long micros() {
+ badCall("microsecond timekeeping is not supported when the RTC is used as the sole timekeeping timer (though delayMicroseconds() is)");
+ return -1;
+ }
+ #endif
+#else // MILLIS_USE_TIMERNONE defined - we have neither of these functions.
+ /* Uses should not call millis() or micros() if the core timekeeping has been disabled. Usually, encountering this error either means
+ * that they disabled millis earlier for some other sketch, and the preferences were saved with that - or that they are using a library
+ * with a dependence on the timekeeping facilities. Sometimes these are meaningful, other times it is only for a feature that isn't
+ * being used, or to catch a particular corner case (see: tinyNeoPixel, very end of show() for an example).
+ * As of 2.4.3 we provide the stubs below, which we hope is more useful than being told that millis or micros isn't defined.
+ */
+ unsigned long micros() {
+ badCall("micros() is not available because it has been disabled through the tools -> millis()/micros() menu");
+ return -1;
+ }
+ unsigned long millis() {
+ badCall("millis() is not available because it has been disabled through the tools -> millis()/micros() menu");
+ return -1;
+ }
+#endif // MILLIS_USE_TIMERNONE code
+
+
+/* delay()
+ * So what do you WANT in a good delay function?
+ * First, obviously you want it to delay things. You do not want it to block interrupts (then a long one would throw off
+ * timekeeping, miss inputs, and so on). And you want the compiled size to not be prohibitive for the part.
+ * The reason it's so important wrt. interrupts is that in Arduino standard delay(), if an interrupt fires in the middle,
+ * will still end at the same time - it is "interrupt insensitive". Whenever a delay is using the builtin _delay_ms()
+ * if that is interrupted it has no way of knowing time has passed. Now hopefully you're not spending so much time in
+ * an ISR that this is significant, but it is still undesirable.
+ *
+ * For the unfortunate souls using small-flash parts, the flash usage becomes a major problem - why is it such a space-hog?
+ * Because it has to pull in micros(), which is bulky even with the division turned into bitshifts... RTC has same problem
+ * with millis(), the conversion of 1024ths of a second to 1000ths is a killer, even with the bitshift tricks,
+ * and the compiler seems really stupid about how it handles it; I can't keep it from making an extra copy of the 32-bit
+ * value, which ALSO requires 4 more push and pop operations to get registers it can use.
+ *
+ * Now we will use one of three delay() implementations:
+ * If you have 16k+ your delay is the standard one, it pulls in micros(), yes, but you may well already have grabbed
+ * that for your sketch already, and the delay is more accurate and fully interrupt insensitive, and you can afford
+ * the memory. For RTC users they will get the analogous implementation that is based on millis.
+ * Users with millis disabled, or with less than 16k flash and using RTC will get the implementation based on _delay_ms().
+ * Everyone else (flash under 16k but millis enabled via non-RTC timer) will get the light version which calls _delay_ms()
+ * if the delay is under 16 ms to get less flash usage, and calculates the delay using **millis** not micros otherwise,
+ * saving over 100b of flash. The reason for the split is that the limited granularity of millis introduces an error in
+ * the delay duration of up to 1ms. That doesn't matter much when you call delay(1000) on an internal clock that's within
+ * 1% on a good day. It matters greatly when you call delay(1); */
+
+#if defined(MILLIS_USE_TIMERNONE) || (PROGMEM_SIZE < 16384 && defined(MILLIS_USE_TIMERRTC))
+ void delay(uint32_t ms) { /* Interrupts will prolong this delay */
+ if (__builtin_constant_p(ms)) {
+ _delay_ms(ms);
+ } else {
+ while (ms--) {
+ _delay_ms(1);
+ }
+ }
+ }
+#elif (PROGMEM_SIZE >= 16384 && !defined(MILLIS_USE_TIMERRTC))
+ void delay(uint32_t ms) { /* Interrupts will not prolong this less flash-efficient delay */
+ uint16_t start = (uint16_t) micros();
+ while (ms > 0) {
+ while (((uint16_t) micros() - start) >= 1000 && ms) {
+ ms-- ;
+ start += 1000;
+ }
+ }
+ }
+#else
+ void delay(uint32_t ms) {
+ if (__builtin_constant_p(ms) && ms < 16) {
+ _delay_ms(ms);
+ } else if (ms < 16) {
+ while(ms--) {
+ _delay_ms(1);
+ }
+ } else {
+ uint32_t start = millis();
+ while (millis() - start < ms);
+ }
+ }
+#endif
+
+inline __attribute__((always_inline)) void delayMicroseconds(unsigned int us) {
+ // This function gets optimized away, but to what depends on whether us is constant.
+ if (__builtin_constant_p(us)) {
+ _delay_us(us); // Constant microseconds use the avr-libc _delay_us() which is highly accurate for all values and efficient!
+ } else { // If it is not, we have to use the Arduino style implementation.
+ _delayMicroseconds(us);
+ }
+}
+
+/* delayMicroseconds() when delay is not a compile-time known constant.
+ * Delay for the given number of microseconds. This is UGLY AS SIN and explicitly depends on function call
+ * overhead for very short delays.
+ * High clock speeds shouldn't return immediately for a 1us delay - we can instead only drop a fraction of a us
+ * 48, 44, 40, and 32 drop 1/2 us, and 36 drops 2/3rds.
+ * Note that us ceases to be in units of microseconds as soon as the function is entered; it gets turned into the loop counter.
+ * Then we use a minimal number of bitshifts to calculate the number of passes through the delay loop
+ * and subtract the number of loop-cycles of time we burned doing so. But need to be careful that sane values
+ * don't get so much bigger that they overflow the unsigned int we're storing it in. To that end, we use
+ * a longer loop at faster clock speeds.
+ * In the inline assembly, when a delay of 8 clocks or longer is required, we save flash with a clever trick:
+ * "rjmp .+2" "\n\t" // 2 cycles - jump over the return.
+ * "ret" "\n\t" // 4 cycles - rjmped over initially...
+ * "rcall .-4" "\n\t" // 2 cycles - ... but then called here...
+ * This exploits the fact that return is a 4-clock instruction (even on AVRxt) by first hopping over a return
+ * then immediately calling that return instruction - 8 clocks in 3 words. Once the ret is there, additional
+ * rcall instructions can get 6 clocks in a single word, though we only get to take advantage of that once for
+ * the 30 MHz case and any longer delays do better with a loop.
+ */
+
+#if F_CPU >= 48000000L
+ // 16 MHz math, 12-cycle loop, 1us burns and passes through loop twice.
+ #define DELAYMICROS_TWELVE
+#elif F_CPU >= 44000000L
+ // 16 MHz math, 11-cycle loop, 1us burns and passes through loop twice.
+ #define DELAYMICROS_ELEVEN
+#elif F_CPU >= 40000000L
+ // 20 MHz math, 10-cycle loop, 1us burns and passes through loop twice.
+ #define DELAYMICROS_TEN
+#elif F_CPU >= 36000000L
+ // 12 MHz math, 12-cycle loop, 1us burns and passes through loop once.
+ #define DELAYMICROS_TWELVE
+#elif F_CPU >= 32000000L
+ // 16 MHz math, 8-cycle loop, 1us passes through loop twice.
+ #define DELAYMICROS_EIGHT
+#elif F_CPU >= 30000000L
+ // 12 MHz math, 10-cycle loop, 1us burns and returns.
+ #define DELAYMICROS_TEN
+#elif F_CPU >= 28000000L
+ // 16 MHz math, 7-cycle loop, 1us burns and returns.
+ #define DELAYMICROS_SEVEN
+#elif F_CPU >= 27000000L
+ // 12 MHz math, 9 cycle loop, 1us burns and returns
+ #define DELAYMICROS_NINE
+#elif F_CPU >= 24000000L
+ // 12 MHz math, 8-cycle loop, 1us burns and returns.
+ #define DELAYMICROS_EIGHT
+#elif F_CPU >= 20000000L
+ // 20 MHz math, 10-cycle loop, 1us burns and returns.
+ #define DELAYMICROS_TEN
+#elif F_CPU >= 16000000L
+ // 16 MHz math, 4-cycle loop, 1us returns immediately.
+#elif F_CPU >= 12000000L
+ // 16 MHz math, 4-cycle loop, 1us returns immediately.
+#elif F_CPU >= 10000000L || (F_CPU >= 5000000L && F_CPU < 8000000L)
+ // 10 MHz: 5-cycle loop, 1us returns immediately
+ // 5 MHz: 5-cycle loop, 1-3 us returns immediately.
+ #define DELAYMICROS_FIVE
+#else
+ // 8 MHz: 16 MHz math, 4-cycle loop, 1-2 us returns immediately.
+ // 4 MHz: 16 MHz math, 4-cycle loop, 1-4 us returns immediately.
+ // 2 MHz: 16 MHz math, 4-cycle loop, 1-8 us returns immediately.
+ // 1 MHz: 16 MHz math, 4-cycle loop, < 16 us returns immediately, < 25 burns and returns.
+ // Anything not listed uses the fastest one that is and which is slower than F_CPU
+#endif
+
+__attribute__ ((noinline)) void _delayMicroseconds(unsigned int us) {
+ /* Must be noinline because we rely on function-call overhead */
+#if F_CPU == 48000000L
+ // make the initial delay 24 cycles
+ __asm__ __volatile__ (
+ "rjmp .+2" "\n\t" // 2 cycles - jump over next instruction.
+ "ret" "\n\t" // 4 cycles - rjmped over initially....
+ "rcall .-4"); // 2 cycles - ... but then called here);
+ // wait 8 cycles with 3 words
+ // the loop takes 1/4 of a microsecond (12 cycles) per iteration
+ // so execute it four times for each microsecond of delay requested.
+ us <<= 2; // x4 us, = 4 cycles
+ // we only burned ~22 cycles above, subtraction takes another 2 - so we've lost
+ // half a us and only need to drop 2 rounds through the loop!
+ us -= 2; // = 2 cycles,
+
+#elif F_CPU >= 44000000L
+ // Again, we can do all this in half of 1 us, so we
+ // just pass through the loop 2 times for 1 us delay.
+ __asm__ __volatile__(
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "nop"); // 1 cycles
+ // Wait 5 cycles in 3 words.
+ // the loop takes 1/4 of a microsecond (11 cycles) per iteration
+ // so execute it four times for each microsecond of delay requested.
+ us <<= 2; // x4 us, = 4 cycles
+ // we just burned 19 (21) cycles above, remove 2
+ // us is at least 8 so we can subtract 2
+ us -= 2;
+
+#elif F_CPU >= 40000000L
+ // Again, we can do all this in half of 1 us, so we
+ // just pass through the loop 2 times for 1 us delay.
+ __asm__ __volatile__(
+ "rjmp .+0" "\n\t" // 2 cycles
+ "nop"); // 1 cycles
+ // Wait 3 cycles in 2 words.
+ // the loop takes 1/4 of a microsecond (10 cycles) per iteration
+ // so execute it four times for each microsecond of delay requested.
+ us <<= 2; // x4 us, = 4 cycles
+ // we just burned 17 (19) cycles above, remove 2.
+ // us is at least 8 so we can subtract 2
+ us -= 2;
+
+#elif F_CPU >= 36000000L
+ // Here we get the initial delay is about 24 cycles, so we pass through
+ // the loop once for 1us delay.
+ __asm__ __volatile__ (
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+2" "\n\t" // 2 cycles - jump over next instruction.
+ "ret" "\n\t" // 4 cycles - rjmped over initially....
+ "rcall .-4"); // 2 cycles - ... but then called here);
+ // wait 10 cycles in 4 words
+ // the loop takes 1/3 of a microsecond (12 cycles) per iteration
+ // so execute it three times for each microsecond of delay requested.
+ us = (us << 1) + us; // x3 us, = 5 cycles
+ // we just burned 23 (25) cycles above, remove 2
+ us -= 2; // 2 cycles
+
+#elif F_CPU >= 32000000L
+ // here, we only take half a us at the start
+ __asm__ __volatile__ ("rjmp .+0");
+ // wait 2 cycles
+ // in by the end of this section.
+ // the loop takes 1/4 of a microsecond (8 cycles) per iteration
+ // so execute it four times for each microsecond of delay requested.
+ us <<= 2; // x4 us, = 4 cycles
+ // we only burned ~14 cycles above, subtraction takes another 2 - so we've lost half a us,
+ // and only need to drop 2 rounds through the loop!
+ us -= 2; // = 2 cycles
+
+#elif F_CPU >= 30000000L
+ // for a one-microsecond delay, burn 14 cycles and return
+ __asm__ __volatile__ (
+ "rjmp .+2" "\n\t" // 2 cycles - jump over the return.
+ "ret" "\n\t" // 4 cycles - rjmped over initially...
+ "rcall .-4" "\n\t" // 2 cycles - ... but then called here...
+ "rcall .-6"); // 2+4 cycles - ... and here again!
+ // Waiting 14 cycles in only 4 words
+ if (us <= 1) return; // = 3 cycles, (4 when true)
+ // the loop takes 1/3 of a microsecond (10 cycles) per iteration
+ // so execute it three times for each microsecond of delay requested.
+ us = (us << 1) + us; // x3 us, = 5 cycles
+ // we just burned 28 (30) cycles above, remove 3
+ us -= 3; // 2 cycles
+
+#elif F_CPU >= 28000000L
+ // for a one-microsecond delay, burn 12 cycles and return
+ __asm__ __volatile__ (
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+2" "\n\t" // 2 cycles - jump over next instruction.
+ "ret" "\n\t" // 4 cycles - rjmped over initially....
+ "rcall .-4"); // 2 cycles - ... but then called here);
+ // wait 12 cycles in 5 words
+ if (us <= 1) return; // = 3 cycles, (4 when true)
+
+ // the loop takes 1/4 of a microsecond (7 cycles) per iteration
+ // so execute it four times for each microsecond of delay requested.
+ us <<= 2; // x4 us, = 4 cycles=
+ // we just burned 27 (29) cycles above, remove 4, (7*4=28)
+ // us is at least 8 so we can subtract 5
+ us -= 4; // = 2 cycles,
+
+#elif F_CPU >= 27000000L
+ // for a one-microsecond delay, burn 11 cycles and return
+ __asm__ __volatile__ ( // wait 8 cycles with 3 words
+ "rjmp .+2" "\n\t" // 2 cycles - jump over next instruction.
+ "ret" "\n\t" // 4 cycles - rjmped over initially....
+ "rcall .-4" "\n\t" // 2 cycles - ... but then called here);
+ "rjmp .+0" "\n\t" // 2 cycles
+ "nop"); // 1 more == 11 total
+ if (us <= 1) return; // = 3 cycles, (4 when true)
+
+ // the loop takes 1/3 of a microsecond (8 cycles) per iteration
+ // so execute it three times for each microsecond of delay requested.
+ us = (us << 1) + us; // x3 us, = 5 cycles
+ // we just burned 27 (24) cycles above, remove 3
+ us -= 3; // 2 cycles
+
+
+#elif F_CPU >= 24000000L
+ // for a one-microsecond delay, burn 8 cycles and return
+ __asm__ __volatile__ (
+ "rjmp .+2" "\n\t" // 2 cycles - jump over next instruction.
+ "ret" "\n\t" // 4 cycles - rjmped over initially....
+ "rcall .-4"); // 2 cycles - ... but then called here);
+ // wait 8 cycles with 3 words
+ if (us <= 1) return; // = 3 cycles, (4 when true)
+
+ // the loop takes 1/3 of a microsecond (8 cycles) per iteration
+ // so execute it three times for each microsecond of delay requested.
+ us = (us << 1) + us; // x3 us, = 5 cycles
+ // we just burned 24 (22) cycles above, remove 3
+ us -= 3; // 2 cycles
+
+#elif F_CPU >= 20000000L
+ // for a one-microsecond delay, burn 4 clocks and then return
+ __asm__ __volatile__ (
+ "rjmp .+0" "\n\t" // 2 cycles
+ "nop" ); // 1 cycle
+ // wait 3 cycles with 2 words
+ if (us <= 1) return; // = 3 cycles, (4 when true)
+ // the loop takes a 1/2 of a microsecond (10 cycles) per iteration
+ // so execute it twice for each microsecond of delay requested.
+ us = us << 1; // x2 us, = 2 cycles
+ // we just burned 21 (23) cycles above, remove 2
+ // us is at least 4 so we can subtract 2.
+ us -= 2; // 2 cycles
+
+#elif F_CPU >= 16000000L
+ // for a one-microsecond delay, simply return. the overhead
+ // of the function call takes 14 (16) cycles, which is 1us
+ if (us <= 1) return; // = 3 cycles, (4 when true)
+ // the loop takes 1/4 of a microsecond (4 cycles) per iteration
+ // so execute it four times for each microsecond of delay requested.
+ us <<= 2; // x4 us, = 4 cycles
+ // we just burned 19 (21) cycles above, remove 5, (5*4=20)
+ // us is at least 8 so we can subtract 5
+ us -= 5; // = 2 cycles
+
+#elif F_CPU >= 12000000L
+ // for a 1 microsecond delay, simply return. the overhead
+ // of the function call takes 14 (16) cycles, which is 1.5us
+ if (us <= 1) return; // = 3 cycles, (4 when true)
+ // the loop takes 1/3 of a microsecond (4 cycles) per iteration
+ // so execute it three times for each microsecond of delay requested.
+ us = (us << 1) + us; // x3 us, = 5 cycles
+ // we just burned 20 (22) cycles above, remove 5, (5*4=20)
+ // us is at least 6 so we can subtract 5
+ us -= 5; // 2 cycles
+
+#elif F_CPU >= 10000000L
+ // for a 1 microsecond delay, simply return. the overhead
+ // of the function call takes 14 (16) cycles, which is 1.5us
+ if (us <= 2) return; // = 3 cycles, (4 when true)
+ // the loop takes 1/2 of a microsecond (5 cycles) per iteration
+ // so execute it 2 times for each microsecond of delay requested.
+ us = us << 1; // x2 us, = 2 cycles
+ // we just burned 20 (22) cycles above, remove 4, (5*4=20)
+ // us is at least 6 so we can subtract 4
+ us -= 4; // 2 cycles
+
+#elif F_CPU >= 8000000L
+ // for a 1 and 2 microsecond delay, simply return. the overhead
+ // of the function call takes 14 (16) cycles, which is 2us
+ if (us <= 2) return; // = 3 cycles, (4 when true)
+ // the loop takes 1/2 of a microsecond (4 cycles) per iteration
+ // so execute it twice for each microsecond of delay requested.
+ us <<= 1; // x2 us, = 2 cycles
+ // we just burned 17 (19) cycles above, remove 5, (4*5=20)
+ // us is at least 6 so we can subtract 4
+ us -= 5; // = 2 cycles
+
+#elif F_CPU >= 5000000L
+ // for a 1 ~ 3 microsecond delay, simply return. the overhead
+ // of the function call takes 14 (16) cycles, which is 3us
+ if (us <= 3) return; // 3 cycles, (4 when true)
+ // the loop takes 1 microsecond (5 cycles) per iteration
+ // so just remove 3 loops for overhead
+ us -= 3; // = 2 cycles
+
+#elif F_CPU >= 4000000L
+ // for a 1 ~ 4 microsecond delay, simply return. the overhead
+ // of the function call takes 14 (16) cycles, which is 4us
+ if (us <= 4) return; // 3 cycles, (4 when true)
+ // the loop takes 1 microsecond (4 cycles) per iteration,
+ // just remove 4 loops for overhead
+ us -= 4; // = 2 cycles for the time taken up with call overhead and test above
+
+#elif F_CPU >= 2000000L
+ // for a 1 ~ 4 microsecond delay, simply return. the overhead
+ // of the function call takes 14 (16) cycles, which is 8us
+ if (us <= 8) return; // 3 cycles, (4 when true)
+ // the loop takes 2 microsecond (4 cycles) per iteration,
+ // just remove 4 loops for overhead
+ us >>= 1; // divide by 2.
+ us -= 4; // = 2 cycles for the time taken up with call overhead and test above
+
+#else // F_CPU >= 1000000
+ // for the 1 MHz internal clock (default settings for common AVR microcontrollers)
+ // the overhead of the function calls is 14 (16) cycles
+ if (us <= 16) return; // 3 cycles, (4 when true)
+ if (us <= 25) return; // 3 cycles, (4 when true), (must be at least 26 if we want to subtract 22 and rightshift twice.)
+ // compensate for the time taken by the preceding and following commands (about 22 cycles)
+ us -= 22; // = 2 cycles
+ // the loop takes 4 microseconds (4 cycles)
+ // per iteration, so execute it us/4 times
+ // us is at least 4, divided by 4 gives us 1 (no zero delay bug)
+ us >>= 2; // us div 4, = 4 cycles
+#endif
+/* Implementation of the delay loop of 4, 5, 7, 8, 10, 11, or 12 clocks. */
+#if defined(DELAYMICROS_TWELVE)
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "rjmp .+2" "\n\t" // 2 cycles - jump over next instruction.
+ "ret" "\n\t" // 4 cycles - rjmped over initially....
+ "rcall .-4" "\n\t" // 2 cycles - ... but then called here
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#elif defined(DELAYMICROS_ELEVEN)
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "nop" "\n\t" // 1 cycle
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#elif defined(DELAYMICROS_TEN)
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#elif defined(DELAYMICROS_NINE)
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "nop" "\n\t"
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#elif defined(DELAYMICROS_EIGHT)
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#elif defined(DELAYMICROS_SEVEN)
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "rjmp .+0" "\n\t" // 2 cycles
+ "nop" "\n\t" // 1 cycle
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#elif defined(DELAYMICROS_FIVE)
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "nop" "\n\t" // 1 cycle
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#else // the classic 4 cycle delay loop...
+ __asm__ __volatile__ (
+ "1: sbiw %0, 1" "\n\t" // 2 cycles
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+#endif
+ // return = 4 cycles
+}
+
+void stop_millis()
+{ // Disable the interrupt:
+ #if defined(MILLIS_USE_TIMERNONE)
+ badCall("stop_millis() is only valid with millis time keeping enabled.");
+ #else
+ #if defined(MILLIS_USE_TIMERA0)
+ TCA0.SPLIT.INTCTRL &= (~TCA_SPLIT_HUNF_bm);
+ #elif defined(MILLIS_USE_TIMERA1)
+ TCA1.SPLIT.INTCTRL &= (~TCA_SPLIT_HUNF_bm);
+ #elif defined(MILLIS_USE_TIMERD0)
+ TCD0.INTCTRL &= 0xFE;
+ #elif defined(MILLIS_USE_TIMERRTC)
+ RTC.INTCTRL &= 0xFE;
+ RTC.CTRLA &= 0xFE;
+ #else
+ _timer->INTCTRL &= ~TCB_CAPT_bm;
+ #endif
+ #endif
+}
+
+
+
+void restart_millis()
+{
+ // Call this to restart millis after it has been stopped and/or millis timer has been molested by other routines.
+ // This resets key registers to their expected states.
+ #if defined(MILLIS_USE_TIMERNONE)
+ badCall("restart_millis() is only valid with millis time keeping enabled.");
+ #else
+ #if defined(MILLIS_USE_TIMERA0)
+ /* The type A timers need to be restored to the state they were in at the start of restore */
+ TCA0.SPLIT.CTRLA = 0; // timer off (might need that for next steps)
+ TCA0.SPLIT.CTRLD = TCA_SPLIT_SPLITM_bm; // because this will not work if it's enabled.
+ TCA0.SPLIT.HPER = PWM_TIMER_PERIOD; // What was left behind
+ #if (F_CPU > 25000000) // use 256 divider when clocked over 25 MHz
+ TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV256_gc) | (TCA_SPLIT_ENABLE_bm);
+ #elif (F_CPU > 5000000) // use 64 divider for everything in the middle
+ TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV64_gc) | (TCA_SPLIT_ENABLE_bm);
+ #elif (F_CPU > 1000000) // and use 16...
+ TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV16_gc) | (TCA_SPLIT_ENABLE_bm);
+ #else // or even 8 otherwise for really slow system clocks.
+ TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV8_gc) | (TCA_SPLIT_ENABLE_bm);
+ #endif
+ /* No TCA1 on tinyAVRs */
+ #elif defined(MILLIS_USE_TIMERD0)
+ TCD0.CTRLA = 0x00;
+ while (TCD0.STATUS & 0x01);
+ #elif (defined(MILLIS_USE_TIMERB0) || defined(MILLIS_USE_TIMERB1) || defined(MILLIS_USE_TIMERB2) || defined(MILLIS_USE_TIMERB3) || defined(MILLIS_USE_TIMERB4)) // It's a type b timer
+ _timer->CTRLB = 0;
+ #endif
+ init_millis();
+ #endif
+}
+
+
+
+
+void __attribute__((weak)) init_millis()
+{
+ #if defined(MILLIS_USE_TIMERNONE)
+ badCall("init_millis() is only valid with millis time keeping enabled.");
+ #else
+ #if defined(MILLIS_USE_TIMERA0)
+ #if !defined(TCA_BUFFERED_3PIN)
+ TCA0.SPLIT.INTCTRL = TCA_SPLIT_HUNF_bm;
+ #else
+ TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
+ #endif
+ #elif defined(MILLIS_USE_TIMERA1)
+ TCA1.SPLIT.INTCTRL |= TCA_SPLIT_HUNF_bm;
+ #elif defined(MILLIS_USE_TIMERD0)
+ TCD_t* pTCD;
+ _fastPtr_d(pTCD, &TCD0);
+ pTCD->CMPBCLR = TIME_TRACKING_TIMER_PERIOD; // essentially, this is TOP
+ pTCD->CTRLB = 0x00; // oneramp mode
+ pTCD->CTRLC = 0x80;
+ pTCD->INTCTRL = 0x01; // enable interrupt
+ pTCD->CTRLA = TIMERD0_PRESCALER | 0x01; // set clock source and enable!
+ #elif defined(MILLIS_USE_TIMERRTC)
+ while(RTC.STATUS); // if RTC is currently busy, spin until it's not.
+ // to do: add support for RTC timer initialization
+ RTC.PER = 0xFFFF;
+ #ifdef MILLIS_USE_TIMERRTC_XTAL
+ _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA,0x03);
+ RTC.CLKSEL = 2; // external crystal
+ #else
+ _PROTECTED_WRITE(CLKCTRL.OSC32KCTRLA,0x02);
+ // RTC.CLKSEL=0; this is the power on value
+ #endif
+ RTC.INTCTRL = 0x01; // enable overflow interrupt
+ RTC.CTRLA = (RTC_RUNSTDBY_bm|RTC_RTCEN_bm|RTC_PRESCALER_DIV32_gc);//fire it up, prescale by 32.
+ #else // It's a type b timer - we have already errored out if that wasn't defined
+ _timer->CCMP = TIME_TRACKING_TIMER_PERIOD;
+ // Enable timer interrupt, but clear the rest of register
+ _timer->INTCTRL = TCB_CAPT_bm;
+ // Clear timer mode (since it will have been set as PWM by init())
+ _timer->CTRLB = 0;
+ // CLK_PER/1 is 0b00, . CLK_PER/2 is 0b01, so bitwise OR of valid divider with enable works
+ _timer->CTRLA = TIME_TRACKING_TIMER_DIVIDER|TCB_ENABLE_bm; // Keep this last before enabling interrupts to ensure tracking as accurate as possible
+ #endif
+ #endif
+}
+
+void set_millis(__attribute__((unused))uint32_t newmillis)
+{
+ #if defined(MILLIS_USE_TIMERNONE)
+ badCall("set_millis() is only valid with millis timekeeping enabled.");
+ (void)newmillis; // unused parameter
+ #else
+ #if defined(MILLIS_USE_TIMERRTC)
+ uint8_t oldSREG = SREG; // save SREG
+ cli(); // interrupts off
+ timingStruct.timer_millis = newmillis;
+ while(RTC.STATUS&RTC_CNTBUSY_bm); // wait if RTC busy
+ RTC.CNT = 0;
+ SREG = oldSREG; // re-enable interrupts if we killed them,
+ #else
+ /* farting around with micros via overflow count was ugly and buggy.
+ * may implement again, better, in the future - but millis and micros
+ * will get out of sync when you use set_millis
+ * I think the way to do it is to make this implementation (but not big one)
+ * inline, so if newmillis is constant, we can calculate the (compile-time known)
+ * number of overflows using all the floating point math we want, and otherwise,
+ * document that it will zero out micros.*/
+ timingStruct.timer_millis = newmillis;
+ #endif
+ #endif
+}
+
+void nudge_millis(__attribute__((unused)) uint16_t nudgesize) {
+ #if !defined(MILLIS_USE_TIMERNONE)
+ uint8_t oldSREG=SREG;
+ cli();
+ timingStruct.timer_millis += nudgesize;
+ SREG=oldSREG;
+ #else
+ (void)nudgesize; // unused parameter
+ #endif
+}
+
+void init() {
+ // Initializes hardware: First we configure the main clock, then fire up the other peripherals
+ init_clock();
+ init_ADC0();
+ init_timers();
+ #ifndef MILLIS_USE_TIMERNONE
+ init_millis();
+ #endif
+ /*************************** ENABLE GLOBAL INTERRUPTS *************************/
+ // Finally, after everything is initialized, we go ahead and enable interrupts.
+ if (onAfterInit()) {
+ sei();
+ }
+}
+
+ /******************************** CLOCK STUFF *********************************/
+#if defined(CLOCK_TUNE_INTERNAL)
+ void tune_internal(void);
+#endif
+
+void __attribute__((weak)) init_clock() {
+ #ifndef CLOCK_SOURCE
+ #error "CLOCK_SOURCE not defined. CLOCK_SOURCE must be either 0 (internal) or 2 (external clock)"
+ #endif
+ #if (CLOCK_SOURCE == 0)
+ #if (defined(CLOCK_TUNE_INTERNAL))
+ tune_internal(); // Will be inlined as only called once. Just too long and ugly to put two implementations in middle of this.
+ #else
+ #if (F_CPU == 20000000)
+ /* No division on clock */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
+ #elif (F_CPU == 16000000)
+ /* No division on clock */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
+ #elif (F_CPU == 10000000) // 20MHz prescaled by 2
+ /* Clock DIV2 */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc));
+ #elif (F_CPU == 8000000) // 16MHz prescaled by 2
+ /* Clock DIV2 */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc));
+ #elif (F_CPU == 5000000) // 20MHz prescaled by 4
+ /* Clock DIV4 */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc));
+ #elif (F_CPU == 4000000) // 16MHz prescaled by 4
+ /* Clock DIV4 */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc));
+ #elif (F_CPU == 2000000) // 16MHz prescaled by 8
+ /* Clock DIV8 */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_8X_gc));
+ #elif (F_CPU == 1000000) // 16MHz prescaled by 16
+ /* Clock DIV16 */
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_16X_gc));
+ #else
+ #ifndef F_CPU
+ #error "F_CPU not defined"
+ #else
+ #error "F_CPU defined as an unsupported value for untuned internal oscillator"
+ #endif
+ #endif
+ #endif
+ #elif (CLOCK_SOURCE == 2)
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLA, CLKCTRL_CLKSEL_EXTCLK_gc);
+ // while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm); // This either works, or hangs the chip - EXTS is pretty much useless here.
+ // w/out CFD, easier to determine what happened if we don't just hang here.
+ uint8_t count = 10;
+ while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm && count--);
+ if (CLKCTRL.MCLKSTATUS & CLKCTRL_EXTS_bm) {
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00);
+ }
+ #else
+ #error "CLOCK_SOURCE is defined, but it isn't 0 (internal) or 2 (external clock), and those are the only clock sources supported by this part."
+ #endif
+}
+
+
+
+
+#if defined(CLOCK_TUNE_INTERNAL)
+ void tune_internal() {
+ #define _CLOCKSPERUS (F_CPU/1000000)
+ uint8_t _osccfg; // magic name - do not change
+ #if defined(USING_BOOTLOADER) && USING_BOOTLOADER == 1
+ // If using Optiboot, then we do not know what value OSCFG was set to when it was bootloaded, so we have to determine it at runtime.
+ uint8_t _osccfg = FUSE.OSCCFG - 1; /****** "_osccfg" IS A MAGIC NAME - DO NOT CHANGE IT ******/
+ #else
+ // if not we set this when the
+ #if MEGATINYCORE_SERIES == 2 && (_CLOCKSPERUS > 20 || _CLOCKSPERUS== 12 || _CLOCKSPERUS == 10 || _CLOCKSPERUS == 6 || _CLOCKSPERUS == 5 || _CLOCKSPERUS == 3)
+ _osccfg = 1;
+ #elif MEGATINYCORE_SERIES < 2 && (_CLOCKSPERUS > 20 || _CLOCKSPERUS== 12 || _CLOCKSPERUS == 10 || _CLOCKSPERUS == 7 || _CLOCKSPERUS == 6 || _CLOCKSPERUS == 5 || _CLOCKSPERUS == 3)
+ _osccfg = 1;
+ #else
+ _osccfg = 0;
+ #endif
+ #endif
+ #include "tune_guesses.h"
+ // The GUESSCAL, MAX_TUNING, TUNED_CALIBRATION_OFFSET and TUNE_PRESCALE symbols, which look like constants, aren't.
+ // They're macros from tune_guesses.h and get replaced with (ternary operators and math involving osccfg), so what looks very simple here... actually isn't.
+ // Evertthing hard is done in tune_guesses.h
+ if (__builtin_constant_p(TUNED_CALIBRATION_OFFSET)) {
+ if (TUNED_CALIBRATION_OFFSET == 255) {
+ badCall("It appears that you are attempting to set a 0/1-series part to 32 MHz via tuning or otherwise set a bogus clock speed.");
+ }
+ }
+ if (TUNED_CALIBRATION_OFFSET == 255) {
+
+ GPIOR0 |= 0x80;
+ GPIOR0 |= 0x40;
+ return; // we can't do that speed at all with this part and oscillator setting! Hopefully users notice their sketch is running
+ // way too slow, and will read the docs which contain further instructions for diagnosis of these sort of problems.
+ } else {
+ uint8_t istuned =(_SFR_MEM8((_osccfg ? 0x1306 : 0x1300) + CLOCK_TUNE_START + HOME_TUNING_OFFSET)) != 255;
+ uint8_t tunedval=_SFR_MEM8(((_osccfg ? 0x1306 : 0x1300) + CLOCK_TUNE_START + TUNED_CALIBRATION_OFFSET));
+ if (!istuned) {
+ GPIOR0 |= 0x40;
+ int temp = GUESSCAL;
+ if (temp > MAX_TUNING) { // uhoh, if we apply the default guess, we'd be setting it higher than it's maximum value!
+ if (MAX_TUNING - temp > 5) {
+ GPIOR0 |= 0x80;
+ return; // How far away are we? If it's more than 5, give up - better to be obviously broken than non-obviously broken
+ }
+ tunedval = MAX_TUNING;
+ } else if (temp < 0) { // uhoh, if we apply the default guess, we'd be setting it to a negative value (which would wrap around, resulting in the value being too high..
+ if (temp < -5) return; // How far away are we? If it's more than 5, give up - better to be obviously broken than non-obviously broken
+ tunedval = 0;
+ } else {
+ tunedval = temp;
+ }
+ } else if (tunedval == 0x80) {
+ GPIOR0 |= 0x80;
+ return; // this chip was tuned and it's oscillator found to be unable to reach target and/or the chip ceased to be opprate before reaching that speed
+ // such that either the tuning sketch crashed or the incredilbly crude sanity checks found that arithmetic produced incorrect results.
+ }
+ // Udf
+ _PROTECTED_WRITE(CLKCTRL_OSC20MCALIBA,tunedval);
+ _NOP();
+ _NOP();
+ }
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, TUNE_PRESCALE);
+ }
+#endif
+
+
+/********************************* ADC ****************************************/
+void __attribute__((weak)) init_ADC0() {
+ ADC_t* pADC;
+ _fastPtr_d(pADC, &ADC0);
+ #if MEGATINYCORE_SERIES < 2
+ /* ADC clock 1 MHz to 1.25 MHz at frequencies supported by megaTinyCore
+ * Unlike the classic AVRs, which demand 50~200 kHz, for these, the datasheet
+ * spec's 50 kHz to 1.5 MHz. Slower clocks provide better response to high
+ * impedance signals, since the sample and hold circuit will be connected
+ * to the pin for longer However, we can use the SAMPLEN register to
+ * compensate for this!
+ * We target a sampling time of 12us, which is a little shorter than the
+ * classic AVRs, but the sampling cap is is 5pf instead of 14
+ * At clock speeds of 12, 24, and 25 MHz when we are forced to use an divider
+ * that leaves us with a markedly slower ADC clock (~750 kHz), we instead use
+ * a value of 7, giving us 8 ADC clocks or... around 12us. .
+ * As of 2.3.0, this setting is exposed by analogReadDuration()
+ * Note that on 0/1-series, the prescale settings are placed powers-of-two
+ * apart. On the 2-series and Dx-series, they are MUCH closer together.
+ **************************************************************************/
+ // 30 MHz / 32 = 937 kHz, 32 MHz / 32 = 1 MHz.
+ #if F_CPU > 24000000 // 24 MHz / 16 = 1.5 MHz, 25 MHz / 32 = 780 kHz
+ pADC->CTRLC = ADC_PRESC_DIV32_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #elif F_CPU >= 12000000 // 16 MHz / 16 = 1.0 MHz, 20 MHz / 16 = 1.25 MHz
+ pADC->CTRLC = ADC_PRESC_DIV16_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #elif F_CPU >= 6000000 // 8 MHz / 8 = 1.0 MHz, 10 MHz / 8 = 1.25 MHz
+ pADC->CTRLC = ADC_PRESC_DIV8_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #elif F_CPU >= 3000000 // 4 MHz / 4 = 1.0 MHz, 5 MHz / 4 = 1.25 MHz
+ pADC->CTRLC = ADC_PRESC_DIV4_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #else // 1 MHz / 2 = 500 kHz - the lowest setting
+ pADC->CTRLC = ADC_PRESC_DIV2_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #endif
+ #if (F_CPU == 6000000 || F_CPU == 12000000 || F_CPU == 24000000 || F_CPU ==25000000)
+ pADC->SAMPCTRL = (7); // 9 ADC clocks, 12 us
+ #elif (F_CPU == 5000000 || F_CPU == 10000000 || F_CPU == 20000000)
+ pADC->SAMPCTRL = (13); // 15 ADC clock,s 12 us
+ #else
+ pADC->SAMPCTRL = (10); // 12 ADC clocks, 12 us
+ #endif
+ pADC->CTRLD = ADC_INITDLY_DLY16_gc;
+ pADC->CTRLA = ADC_ENABLE_bm;
+ #else
+ /* On the 2-series maximum with internal reference is 3 MHz, so we will
+ * target highest speed that doesn't exceed that and 16 ADC clocks sample
+ * duration. */
+ #if F_CPU > 32000000 // 36 MHz /14 = 2.57 MHz
+ pADC->CTRLB = ADC_PRESC_DIV10_gc; // 33 MHz /14 = 2.35 MHz
+ #elif F_CPU >= 30000000 // 32 MHz /12 = 2.67 MHz
+ pADC->CTRLB = ADC_PRESC_DIV12_gc; // 30 MHz /12 = 2.50 MHz
+ #elif F_CPU >= 24000000 // 25 MHz /10 = 2.50 MHz
+ pADC->CTRLB = ADC_PRESC_DIV10_gc; // 24 MHz /10 = 2.40 MHz
+ #elif F_CPU >= 20000000
+ pADC->CTRLB = ADC_PRESC_DIV8_gc; // 20 MHz / 8 = 2.50 MHz
+ #elif F_CPU >= 16000000
+ pADC->CTRLB = ADC_PRESC_DIV6_gc; // 16 MHz / 6 = 2.67 MHz
+ #elif F_CPU >= 12000000
+ pADC->CTRLB = ADC_PRESC_DIV4_gc; // 12 MHz / 4 = 3.00 MHz
+ #elif F_CPU >= 6000000 // 10 MHz / 4 = 2.50 MHz
+ pADC->CTRLB = ADC_PRESC_DIV4_gc; // 8 MHz / 4 = 2.00 MHz
+ #else // 5 MHz / 2 = 2.50 MHz
+ pADC->CTRLB = ADC_PRESC_DIV2_gc; // 4 MHz / 2 = 2.00 MHz
+ #endif // 1 MHz / 2 = 500 kHz
+ pADC->CTRLE = 15; // 15.5 without PGA, 16 with PGA, corresponding to 7.75 or 8 us.
+ pADC->CTRLA = ADC_ENABLE_bm | ADC_LOWLAT_bm;
+ /* Default low latency mode on
+ * Users can turn it off if they care about power consumption while ADC is on
+ * and chip is awake, since these parts don't have the perverse ADC-left-on
+ * behavior of classic AVRs. */
+ pADC->CTRLC = TIMEBASE_1US; // defined in Arduino.h.
+ pADC->PGACTRL = ADC_PGABIASSEL_3_4X_gc | ADC_ADCPGASAMPDUR_15CLK_gc;
+ /* Note that we don't *enable* it automatically in init().
+ * 3/4th bias is good up to 4 MHz CLK_ADC, 15 ADC Clocks to sample the PGA
+ * up to 5 MHz, so within the regime of speeds that have to be compatible
+ * with internal references, we are in the clear there. */
+ #endif
+}
+
+// Must be called manually.
+#ifdef ADC1
+ __attribute__((weak)) void init_ADC1() {
+ ADC_t* pADC;
+ _fastPtr_d(pADC, &ADC1);
+ // 30 MHz / 32 = 937 kHz, 32 MHz / 32 = 1 MHz.
+ #if F_CPU > 24000000 // 24 MHz / 16 = 1.5 MHz, 25 MHz / 32 = 780 kHz
+ pADC->CTRLC = ADC_PRESC_DIV32_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #elif F_CPU >= 12000000 // 16 MHz / 16 = 1.0 MHz, 20 MHz / 16 = 1.25 MHz
+ pADC->CTRLC = ADC_PRESC_DIV16_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #elif F_CPU >= 6000000 // 8 MHz / 8 = 1.0 MHz, 10 MHz / 8 = 1.25 MHz
+ pADC->CTRLC = ADC_PRESC_DIV8_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #elif F_CPU >= 3000000 // 4 MHz / 4 = 1.0 MHz, 5 MHz / 4 = 1.25 MHz
+ pADC->CTRLC = ADC_PRESC_DIV4_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #else // 1 MHz / 2 = 500 kHz - the lowest setting
+ pADC->CTRLC = ADC_PRESC_DIV2_gc | ADC_REFSEL_VDDREF_gc | ADC_SAMPCAP_bm;
+ #endif
+ #if (F_CPU == 6000000 || F_CPU == 12000000 || F_CPU == 24000000 || F_CPU ==25000000)
+ pADC->SAMPCTRL = (7); // 9 ADC clocks, 12 us
+ #elif (F_CPU == 5000000 || F_CPU == 10000000 || F_CPU == 20000000)
+ pADC->SAMPCTRL = (13); // 15 ADC clock,s 12 us
+ #else
+ pADC->SAMPCTRL = (10); // 12 ADC clocks, 12 us
+ #endif
+ pADC->CTRLD = ADC_INITDLY_DLY16_gc;
+ pADC->CTRLA = ADC_ENABLE_bm;
+ }
+#endif
+
+void init_timers() {
+ init_TCA0();
+ #if (defined(TCD0) && defined(USE_TIMERD0_PWM) && !defined(MILLIS_USE_TIMERD0))
+ init_TCD0();
+ #endif
+}
+
+
+#if (defined(TCD0) && defined(USE_TIMERD0_PWM) && !defined(MILLIS_USE_TIMERD0))
+void __attribute__((weak)) init_TCD0() {
+ TCD_t* pTCD;
+ _fastPtr_d(pTCD, &TCD0);
+ pTCD->CMPBCLR = 509; // 510 counts, starts at 0, not 1!
+ pTCD->CMPACLR = 509;
+ pTCD->CTRLC = 0x80; // WOD outputs PWM B, WOC outputs PWM A
+ pTCD->CTRLB = TCD_WGMODE_ONERAMP_gc; // One Slope
+ pTCD->CTRLA = TIMERD0_PRESCALER; // OSC20M prescaled by 32, gives ~1.2 khz PWM at 20MHz.
+}
+#endif
+
+void __attribute__((weak)) init_TCA0() {
+ /* TYPE A TIMER */
+ #if !defined(TCA_BUFFERED_3PIN)
+ #if defined(PORTMUX_CTRLC)
+ PORTMUX.CTRLC = TCA_PORTMUX;
+ #else
+ PORTMUX.TCAROUTEA = TCA_PORTMUX;
+ #endif
+ TCA0.SPLIT.CTRLD = TCA_SPLIT_SPLITM_bm;
+ TCA0.SPLIT.LPER = PWM_TIMER_PERIOD;
+ TCA0.SPLIT.HPER = PWM_TIMER_PERIOD;
+ TCA0.SPLIT.CTRLA = (TIMERA_PRESCALER_bm | TCA_SPLIT_ENABLE_bm);
+ #else
+ #if defined(PORTMUX_CTRLC)
+ PORTMUX.CTRLC = TCA_PORTMUX;
+ #else
+ PORTMUX.TCAROUTEA = TCA_PORTMUX;
+ #endif
+ TCA0.SINGLE.PER = PWM_TIMER_PERIOD;
+ TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
+ TCA0.SINGLE.CTRLA = (TIMERA_PRESCALER_bm | TCA_SINGLE_ENABLE_bm);
+ #endif
+
+}
+
+
+__attribute__((weak)) void onPreMain() {;}
+__attribute__((weak)) void onBeforeInit() {;}
+__attribute__((weak)) uint8_t onAfterInit() {return 1;}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_analog.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_analog.c
new file mode 100644
index 0000000..55cb7ba
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_analog.c
@@ -0,0 +1,1375 @@
+/*
+ wiring_analog.c - analog input and output
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 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
+
+ Modified 28 September 2010 by Mark Sproul
+*/
+
+#include "wiring_private.h"
+#include "pins_arduino.h"
+#include "Arduino.h"
+#include
+
+/* magic value passed as the negative pin to tell the _analogReadEnh() (which implements both th new ADC
+ * functions) to tell them what kind of mode it's to be used in. This also helps with providing useful and accurate
+ * error messages and codes at runtime, since we have no other way to report such. */
+
+#define SINGLE_ENDED 254
+
+inline __attribute__((always_inline)) void check_valid_analog_pin(pin_size_t pin) {
+ if (__builtin_constant_p(pin)) {
+ #if MEGATINYCORE_SERIES == 2
+ if (pin != ADC_TEMPERATURE && pin != ADC_GROUND && pin != ADC_DACREF0 && pin != ADC_VDDDIV10)
+ #elif defined(ADC_DAC0) // 1-series
+ if (pin != ADC_DAC0 && pin != ADC_INTREF && pin != ADC_TEMPERATURE && pin != ADC_GROUND)
+ #else // 0-series.
+ if (pin != ADC_INTREF && pin != ADC_TEMPERATURE && pin != ADC_GROUND)
+ #endif
+ { // above cases cover valid internal sources.
+ if (pin & 0x80) {
+ #if MEGATINYCORE_SERIES == 2
+ if ((pin & 0x7F) >= NUM_ANALOG_INPUTS /* || pin != 0x80 */) // channel 0 is not connected to PA0 - but let's not block it just yet, if it's actually tied to ground, could it be helpful for offset cal?
+ #else
+ if ((pin & 0x7F) >= NUM_ANALOG_INPUTS)
+ #endif
+ {
+ badArg("analogRead called with constant channel that is neither valid analog channel nor valid pin");
+ }
+ } else {
+ pin = digitalPinToAnalogInput(pin);
+ if (pin == NOT_A_PIN) {
+ badArg("analogRead called with constant pin that is not a valid analog pin");
+ }
+ }
+ }
+ }
+}
+
+inline __attribute__((always_inline)) void check_valid_analog_ref(uint8_t mode) {
+ if (__builtin_constant_p(mode)) {
+ #if MEGATINYCORE_SERIES == 2
+ if (!(mode == EXTERNAL || mode == VDD || mode== INTERNAL1V024 || mode== INTERNAL2V048 || mode== INTERNAL4V1 || mode== INTERNAL2V5))
+ #elif defined(EXTERNAL)
+ if (!(mode == EXTERNAL || mode == VDD || mode== INTERNAL0V55 || mode== INTERNAL1V1 || mode== INTERNAL1V5 || mode== INTERNAL2V5 || mode== INTERNAL4V34))
+ #else
+ if (!(mode == VDD || mode== INTERNAL0V55 || mode== INTERNAL1V1 || mode== INTERNAL1V5 || mode== INTERNAL2V5 || mode== INTERNAL4V34))
+ #endif
+ badArg("analogReference called with argument that is not a valid analog reference");
+ }
+}
+
+inline __attribute__((always_inline)) void check_valid_enh_res(uint8_t res) {
+ if (__builtin_constant_p(res)) {
+ if (res < 0x80) {
+ if (res < ADC_NATIVE_RESOLUTION_LOW) {
+ badArg("When a resolution is passed to analogReadEnh, it must be at least the minimum native resolution (8 bits)");
+ } else if (res > ADC_MAX_OVERSAMPLED_RESOLUTION) {
+ badArg("The highest resolution obtainable on these parts through oversampling and decimation with a single ADC operation 13 bits on 0/1-series or 17 on 2-series");
+ }
+ #if MEGATINYCORE_SERIES == 2
+ } else if ((res & 0x7F) > 0x0A) {
+ #else
+ } else if ((res & 0x7F) > 0x06) {
+ #endif
+ badArg("Accumulation number invalid - use one of the ADC_ACC_# constants for raw (undecimated) accumulated readings");
+ }
+ }
+}
+
+
+inline __attribute__((always_inline)) void check_valid_dac_ref(uint8_t mode) {
+ if (__builtin_constant_p(mode)) {
+ if (mode >= 5)
+ badArg("DACReference called with argument that is not a valid DAC reference - VDD is not a valid reference tinyAVR parts!");
+ }
+}
+
+inline __attribute__((always_inline)) void check_valid_duty_cycle(int16_t val) {
+ if (__builtin_constant_p(val)) {
+ if (val < 0 || val >255)
+ badArg("analogWrite cannot produice duty cycle higher 100% or below 0%");
+ }
+}
+
+inline __attribute__((always_inline)) void check_valid_resolution(uint8_t res) {
+ if (__builtin_constant_p(res))
+ #if MEGATINYCORE_SERIES == 2
+ if (res !=8 && res != 10 && res != 12)
+ badArg("analogReadResolution called with invalid argument - valid options are 8, 12, or 10 (compatibility mode).");
+ #else
+ if (res !=8 && res != 10)
+ badArg("analogReadResolution called with invalid argument - valid options are 8 or 10.");
+ #endif
+}
+
+
+#if MEGATINYCORE_SERIES == 2
+ // need a variable to store the resolution selected for analogRead - 8, 10, or 12,
+ // as well as other options, such as whether to autodisable the PGA or leave it running.
+ // Default resolution 10 bits, turn off PGA enabled
+ static uint8_t _analog_options= 0x80 | 10;
+#endif
+
+inline bool analogReadResolution(uint8_t res) {
+ check_valid_resolution(res);
+ #if MEGATINYCORE_SERIES == 2
+ bool temp = (res == 8 || res == 10 || res == 12);
+ _analog_options = (_analog_options & 0xF0) | (temp ? res : 10); // just set that variable, setting the bit is awkward.
+ return temp;
+ #else
+ if (res == 8) {
+ ADC0.CTRLA |= ADC_RESSEL_bm;
+ return true;
+ }
+ ADC0.CTRLA &= ~ADC_RESSEL_bm;
+ return (res == 10);
+ #endif
+}
+
+
+#ifdef DAC0
+void DACReference(uint8_t mode) {
+ check_valid_dac_ref(mode);
+ if (mode < 5) {
+ VREF.CTRLA = mode | (VREF.CTRLA & (~VREF_DAC0REFSEL_gm));
+ }
+}
+#else
+void DACReference(__attribute__ ((unused))uint8_t mode) {
+ badCall("DACreference is not available - this part does not have a DAC");
+}
+#endif
+/*----------------------------------------------------------------------------
+ * Core ADC functionality implementations
+ *----------------------------------------------------------------------------
+ * Because the 2-series ADC is so radically different from the 0/1-series
+ * (and, for that matter, just about everything else), it was most efficient
+ * to separate out the core of the ADC stuff, where the viable shared code was
+ * virtually nothing, and put it all in one part of the file, rather than the
+ * normal practice of having the function defined in one place but with the
+ * parts that are different controlled by #if's. Here, almost every line is
+ * different!
+ *
+ * The only other time this has happened in the history of the AVR instruction
+ * set, with any perpheral, is when the modern/AVRxt parts were introduced...
+ * I hope we're not heading for total rewrites being required every few years.
+ * I think this is just a transitional state; I couldn't see how to scale the
+ * ADC like the AVR Dx-series has to something with this level of capability
+ * either.
+ *
+ * ----------------------------------------------------------------------------
+ * Functions:
+ *
+ * int16_t analogRead(uint8_t pin)
+ * The standard analogRead(). Single-ended, and resolution set by
+ * analogReadResolution(), default 10.
+ * large negative values are returned in the event of an error condition.
+
+ * bool analogReadResolution(uint8_t resolution)
+ * Sets resolution for the analogRead() function. Unlike stock version,
+ * this returns true/false. If it returns false, the value passed was
+ * invalid, and resolution is set to the default, 10 bits.
+ * ONLY 8, 10 and 12 (for 2-series only) are valid. To use
+ * any other value, you must use analogReadEnh(). The way iut is done on
+ * the Zero/Due/Etc is 1) wasteful of limited resources, and 2) dishonest
+ * because when you ask for a resolution it can't provide, it will lie and
+ * pad the value with zeros.
+ * bool analogSampleDuration(uint8_t dur)
+ * Sets sampling duration (SAMPLEN on 0/1 or SAMPDUR on 2-series)
+ * For high impedance voltage sources, use a longer sample length.
+ * For faster reads, use a shorter sample length. Passing 0 will
+ * approximately double analogRead() speed.
+ * Returns true if value is valid; on 0/1-series maximum is 31 (33 ADC clock
+ * sampling duration); on 2-series any 8-bit value is valid, and duration is
+ * this many plus 0.5 (without PGA) or 1 (with PGA) ADC clocks.
+ * ADC clock targeted by default at startup is 1~1.25 MHz on 0/1, and ~2 MHz on 2-series.
+ * uint8_t getAnalogSampleDuration()
+ * Trivial macro (located in Arduino.h). Returns the argument that you would pass to
+ * analogSampleDuration to get the current setting back (useful before
+ * changing it to something exotic)
+ * void ADCPowerOptions(uint8_t options)
+ * 0 - disable PGA, turned on and off in future as above.
+ * 1 - enable PGA ahead of time for the next measurement after which it will be turned off as above.
+ * 2 - disable PGA, and in future turn if off immediately after use.
+ * 3 - enable PGA, leave it on until explicitly turned off. This is a power hog.
+ * int32_t analogReadEnh(uint8_t pin, int8_t res=ADC_NATIVE_RESOLUTION,
+ * uint8_t gain=0)
+ * Enhanced analogRead(). Still single-ended, res is resolution in bits,
+ * which range from 8 to the largest value that can be obtained from using
+ * the accumulation feature and a single "start" command to oversample x4
+ * per extra bit, followed by decimation/2 per extra bit (the math is
+ * described in Microchip/Atmel app notes). This maximum is 13 bits for
+ * 0/1-series parts, and 17 bits for 2-series parts.
+ * Alternately, to get the raw accumulated ADC readings, pass one of the
+ * ADC_ACC_n constants for the second argument where n is a power of 2 up
+ * to 64 (0/1-series) 128 (Dx-series) or 1024 (2-series).
+ * On 2-series (but not Dx-series parts, which don't have a PGA) the PGA
+ * can be used. I was shocked when I saw that the PGA could be used with
+ * single-ended reads too, but they explicitly state that. Valid options
+ * for gain are 0 (PGA disabled), 1 (unity gain, but can improve performance
+ * of burst reads under some circumstances, and powers of 2 up to 16)
+ * int32_t analogReadDiff(uint8_t pos, uint8_t neg,
+ * int8_t res=ADC_NATIVE_RESOLUTION, uint8_t gain=0)
+ * Uses the differential ADC functionality to take a differential ADC
+ * measurement between the specified positive and negative pins. Only pins
+ * on PORTA (tinyAVR 2-series) or on PORTD/PORTE (AVR Dx-series) can be the
+ * negative input to the ADC
+ * res works the same as for analogReadEnh.
+ * gain specifies that the programmable gain amplifier should be used.
+ * If gain = 0, the PGA will not be used. Valid options are 1, 2, 4, 8
+ * or 16 to configure the PGA to amplify by that factor.
+ *
+ *----------------------------------------------------------------------------
+ * Errors:
+ * analogReadEnh() or analogReadDiff() can return:
+ * ADC_ENH_ERROR_BAD_PIN_OR_CHANNEL (-2100000000)
+ * The selected pin has no analog input capability, does not exist,
+ * or, if it's a channel number (from ADC_CH(channel number), it
+ * does not exist or is otherwise invalid.
+ * ADC_ENH_ERROR_BUSY (-2100000001)
+ * Not yet enabled - will be an optional error in future update, maybe.
+ * The ADC is already taking a reading - either in free-running mode
+ * or through some user-implemented interrupt driven ADC routine.
+ * ADC_ENH_ERROR_INVALID_SAMPLE_LENGTH (-2100000002)
+ * Not yet enabled - will be an optional error in future update, maybe.
+ * On the 0/1-series parts, if sample length is specified, it must be
+ * below 0x1F (only 5 bits are used). That corresponds to 33 ACD clocks
+ * On the 2-series parts, this error is never returned, because all
+ * values between 0 and 255, inclusive, are valid.
+ * Currently, instead of returning an error, this will just set sample
+ * length to the maximum supported value.
+ * ADC_ENH_ERROR_RES_TOO_LOW (-2100000003)
+ * Resolution must not be lower than the lowest native resolution that
+ * the part supports (Core presents this as ADC_NATIVE_RESOLUTION_LOW)
+ * Get 8-bits and divide it if this is required; this is a rare
+ * use-case, and it is not appropriate to force the overhead on
+ * everyone else.
+ * ADC_ENH_ERROR_RES_TOO_HIGH (-2100000004)
+ * The 0/1-series can get 3 extra bits by oversampling 64x and right-
+ * shifting 3 times. The 2-series can get 5 by oversampling by a whopping
+ * 1024x (taking 13-160 ms depending on options) and then right-shifting
+ * 5 times. Thus, maximums are 13 and 17. Alternately, one of the
+ * ADC_ACC_n constants may be used, where n is 2, 4, 8, 16, 32, 64, or
+ * on 2-series only, 128, 256, 512, or 1024 - in this case, that many
+ * samples will be taken through burst/accumulation mode and returned
+ * without decimation.
+ * analogReadDiff() can also return:
+ * ADC_ENH_ERROR_BAD_NEG_PIN (-2100000005)
+ * Returned by analogReadDiff when the requested pin for the negative
+ * input is not valid. Negative pins can only be on PORTA (for tinyAVR)
+ * or PORTD/PORTE (for Dx-series), and the selection of available
+ * channels is more limited.
+ *
+ * printADCRuntimeError(uint32_t error, &HardwareSerial DebugSerial)
+ * Prints a text description of an error returnedby analogRead,
+ * analogReasdEnh(),or analogReadDiff() to the specified serial device
+ * Ex:
+ * printADCRuntimeError(-2100000003, &Serial);
+ * will print "ADC_ENH_ERROR_RES_TOO_LOW"
+ * Will print nothing and return false if the result wasn't an error
+ * This function is not an efficient user of flash space, it is meant as a
+ * debugging aid.
+ * analogIsError(int16_t from analogRead or int32_t from analogReadEnh)
+ * Returns 1 (true) if the value, assuming it came from an analogRead/Enh
+ * function call, is not an analog reading but instead an error code.
+ ****************************************************************************/
+
+
+#if MEGATINYCORE_SERIES == 2
+
+ /*****************************************************
+ START 2-series analogRead/analogReadXxxx functions
+ *****************************************************/
+ #define SINGLE_ENDED 254
+
+ void analogReference(uint8_t mode) {
+ check_valid_analog_ref(mode);
+ #if defined(STRICT_ERROR_CHECKING)
+ if (mode > 7) return;
+ #else
+ mode &= 7;
+ #endif
+ if (mode != 1 && mode != 3) {
+ ADC0.CTRLC = TIMEBASE_1US | mode;
+ }
+ // Uh? Is that it? That was, ah, a tiny bit simpler.
+ }
+ uint8_t getAnalogReference() {
+ return ADC0.CTRLC & ADC_REFSEL_gm;
+ }
+ int8_t getAnalogReadResolution() {
+ return _analog_options & 0x0F;
+ }
+ int16_t analogRead(uint8_t pin) {
+ check_valid_analog_pin(pin);
+ if (pin < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ pin = digitalPinToAnalogInput(pin);
+ } else {
+ pin &= 0x3F;
+ }
+ #if PROGMEM_SIZE < 8096
+ if (pin > 0x33) { // covers most ways a bad channel could come about
+ #else
+ if (pin > NUM_ANALOG_INPUTS && ((pin < 0x30) || (pin > 0x33))) {
+ #endif
+ return ADC_ERROR_BAD_PIN_OR_CHANNEL;
+ }
+ if (!ADC0.CTRLA & 0x01) return ADC_ERROR_DISABLED;
+
+ if (ADC0.COMMAND & ADC_START_gm) return ADC_ERROR_BUSY;
+ // gotta be careful here - don't want to shit ongoing conversion - unlikle classic AVRs
+ // they say there is no buffering here!
+ /* Select channel */
+ ADC0.MUXPOS = pin; // VIA bit = 0;
+ uint8_t command = (_analog_options & 0x0F) > 8 ? 0x11 : 0x01;
+ /* Start conversion */
+ ADC0.COMMAND = command;
+
+ /* Wait for result ready */
+ while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
+ // if it's 10 bit compatibility mode, have to rightshift twice.
+ if ((_analog_options & 0x0F) == 10) {
+ int16_t temp = ADC0.RESULT;
+ temp >>= 2;
+ return temp;
+ }
+ return ADC0.RESULT;
+ }
+
+
+ inline __attribute__((always_inline)) void check_valid_negative_pin(uint8_t pin) {
+ if (__builtin_constant_p(pin)) {
+ if (pin < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ pin = digitalPinToAnalogInput(pin);
+ }
+ pin &= 0x3F;
+ if (pin != 0x33 && pin != 0x31 && pin != 0x30 && pin > 0x07) {
+ badArg("Invalid negative pin - valid options are ADC_GROUND, ADC_VDDDIV10, ADC_DACREF0, or any pin on PORTA.");
+ }
+ }
+ }
+ bool analogSampleDuration(uint8_t sampdur) {
+ // any uint8_t is a legal value...
+ ADC0.CTRLE = sampdur;
+ return true;
+ }
+
+
+ void ADCPowerOptions(uint8_t options) {
+ // 0b SSEEPPLL
+ // SS = run standby
+ // 00 = no change to run standby
+ // 01 = no change to run standby
+ // 10 = turn off run standby
+ // 11 = turn on run standby
+ // EE = ENABLE
+ // 00 = Do not enable or disable ADC.
+ // 01 = Do not enable or disable ADC.
+ // 10 = Disable the ADC.
+ // 11 = Enable the ADC.
+ // LL = LOWLAT
+ // 00 = Do nothing. No change to whether ADC enabled or LOWLAT bit.
+ // 01 = Do nothing. No change to whether ADC enabled or LOWLAT bit.
+ // 10 = LOWLAT on. No change to whether ADC enabled.
+ // 11 = LOWLAT off. No change to whether ADC enabled.
+ // 00 = Do nothing,
+ // 01 = Do nothing,
+ // 10 = LOWLAT on.
+ // 11 = LOWLAT off.
+ // PP = PGA stay-on
+ // 00 = No action
+ // 01 = Turn off PGA, settings unchanged. It will be enabled next time is requested, but will not automatically turn off.
+ // 10 = Turn on PGA, and don't turn it off automatically.
+ // 11 = turn off PGA now and automatically after each use
+ //
+ // (set rstby)(to this value)(set enable)(to this value),
+
+
+ uint8_t temp = ADC0.CTRLA; //performance.
+ if (options & _ADC_LOWLAT_CTRL) {
+ ADC0.CTRLA = 0; // hopwfully workaround lowlat errata by ensuring that everything is turned off.
+ // and configuring lowlat mode.
+ if (options & _ADC_LOWLAT_VAL) {
+ ADC0.CTRLA |= ADC_LOWLAT_bm;
+ temp |= ADC_LOWLAT_bm;
+ } else {
+ ADC0.CTRLA &= ~ADC_LOWLAT_bm;
+ temp &= ~ADC_LOWLAT_bm;
+ }
+ }
+ if (options & _ADC_ENABLE_CTRL) {
+ if (options & _ADC_ENABLE_VAL) {
+ temp |= 1; // ADC on
+ } else {
+ temp &= 0xFE; // ADC off
+ }
+ }
+ if (options & _ADC_STANDBY_CTRL) {
+ if (options & _ADC_STANDBY_VAL) {
+ temp |= 0x80; // run standby
+ } else {
+ temp &= 0x7F; // no run standby
+ }
+ }
+ ADC0.CTRLA = temp; //now we apply enable and standby, and lowlat has been turned on, hopefully that's good enough for the errata.
+ options &= _PGA_CFG_MASK;
+ if (options & 0x01) { // turn off PGA.
+ ADC0.PGACTRL &= ~ADC_PGAEN_bm;
+ if (options & 0x02) {
+ _analog_options &= 0x7F;
+ } else {
+ _analog_options |= 0x80;
+ }
+ } else { // not instruction to turn off PGA
+ if (options & 0x08) { // is it in fact an instruction to turn on the PGA and leave it on?
+ ADC0.PGACTRL |= ADC_PGAEN_bm; // turn on the PGA
+ _analog_options &= 0x7F; // turn off the auto-shutoff. If they told us to turn it on explicitly, surely they don't want us to turn it off of our own accord.
+ }
+ }
+ // What a mess!
+ }
+
+
+ int32_t _analogReadEnh(uint8_t pin, uint8_t neg, uint8_t res, uint8_t gain) {
+ if (!(ADC0.CTRLA & 0x01)) return ADC_ENH_ERROR_DISABLED;
+ uint8_t sampnum;
+ if (res > 0x80) { // raw accumulation
+ sampnum = res & 0x7F;
+ if (sampnum > 10) return ADC_ENH_ERROR_RES_TOO_HIGH;
+ } else {
+ if (res < ADC_NATIVE_RESOLUTION_LOW) return ADC_ENH_ERROR_RES_TOO_LOW;
+ if (res > 17) return ADC_ENH_ERROR_RES_TOO_HIGH;
+ sampnum = (res > ADC_NATIVE_RESOLUTION ? ((res - ADC_NATIVE_RESOLUTION) << 1) : 0);
+ }
+
+ if (pin < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ pin = digitalPinToAnalogInput(pin);
+ } else {
+ pin &= 0x3F;
+ }
+ #if PROGMEM_SIZE < 8096
+ if (pin > 0x33) { // covers most ways a bad channel could come about
+ #else
+ if (pin > NUM_ANALOG_INPUTS && ((pin < 0x30) || (pin > 0x33))) {
+ #endif
+ return ADC_ENH_ERROR_BAD_PIN_OR_CHANNEL;
+ }
+ if (neg != SINGLE_ENDED) {
+ if (neg < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ neg = digitalPinToAnalogInput(neg);
+ } else {
+ neg &= 0x3F;
+ }
+
+ #if PROGMEM_SIZE < 8096
+ if (neg > 0x33) // covers most ways a bad channel could come about
+ #else
+ if (neg > NUM_ANALOG_INPUTS && ((neg != 0x30) && (neg != 0x33) && (neg != 0x31)))
+ #endif
+ {
+ return ADC_DIFF_ERROR_BAD_NEG_PIN;
+ }
+ neg &= 0x3F;
+
+ }
+ pin &= 0x3F;
+
+ if (ADC0.COMMAND & ADC_START_gm) return ADC_ENH_ERROR_BUSY;
+ if (gain !=0) {
+ uint8_t gainbits =0;
+ while (gain > 1) {
+ gain >>= 1;
+ gainbits+=32;
+ }
+ ADC0.PGACTRL = (ADC0.PGACTRL & ~ADC_GAIN_gm) | gainbits | ADC_PGAEN_bm;
+ }
+
+ ADC0.MUXPOS = (gain ? ADC_VIA_PGA_gc:0) | pin;
+ if (neg != SINGLE_ENDED) {
+ ADC0.MUXNEG = (gain ? ADC_VIA_PGA_gc:0) | neg;
+ }
+ ADC0.CTRLF = sampnum;
+ uint8_t command = ((neg != SINGLE_ENDED)?0x80:0) | ((res == 8) ? ADC_MODE_SINGLE_8BIT_gc : (res > ADC_NATIVE_RESOLUTION ? ADC_MODE_BURST_gc : ADC_MODE_SINGLE_12BIT_gc)) | 1;
+ ADC0.COMMAND = command;
+ while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
+ int32_t result = ADC0.RESULT;
+
+ if (res < 0x80 && res > ADC_NATIVE_RESOLUTION) {
+ uint8_t shift = res - ADC_NATIVE_RESOLUTION ; // - 1;
+ while (shift) {
+ result >>= 1;
+ shift--;
+ }
+ // Sanity checks
+ // uint8_t roundup=result&0x01;
+ // result >>= 1;
+ // result += roundup;
+ } else if (res == 8) {
+ ; // do nothing
+ } else if (res < ADC_NATIVE_RESOLUTION) {
+ uint8_t shift = ADC_NATIVE_RESOLUTION - res;
+ result >>= shift;
+ }
+
+ // res > 0x80 (raw accumulate) or res == 8, res == 12 need no adjustment.
+ if (_analog_options & 0x80) { // this bit controls autoshutoff of PGA.
+ ADC0.PGACTRL &= ~ADC_PGAEN_bm;
+ }
+ return result;
+ }
+
+ int32_t analogReadEnh(uint8_t pin, uint8_t res, uint8_t gain) {
+ check_valid_enh_res(res);
+ check_valid_analog_pin(pin);
+ if (__builtin_constant_p(gain)) {
+ if (gain != 0 && gain != 1 && gain != 2 && gain != 4 && gain != 8 && gain != 16)
+ badArg("The requested gain is not available on this part, accepted values are 0, 1, 2, 4, 8 and 16.");
+ }
+ return _analogReadEnh(pin, SINGLE_ENDED, res, gain);
+ }
+
+ int32_t analogReadDiff(uint8_t pos, uint8_t neg, uint8_t res, uint8_t gain) {
+ check_valid_enh_res(res);
+ check_valid_analog_pin(pos);
+ check_valid_negative_pin(neg);
+ if (__builtin_constant_p(gain)) {
+ if (gain != 0 && gain != 1 && gain != 2 && gain != 4 && gain != 8 && gain != 16)
+ badArg("The requested gain is not available on this part, accepted values are 0, 1, 2, 4, 8 and 16.");
+ }
+ return _analogReadEnh(pos, neg, res, gain);
+ }
+
+ static const int16_t adc_prescale_to_clkadc[0x11] = {(F_CPU / 2000L),(F_CPU / 4000L),(F_CPU / 6000L),(F_CPU / 8000L),
+ /* Doesn't get copied to ram because these all */ (F_CPU / 10000L),(F_CPU / 12000L),(F_CPU / 14000L),(F_CPU / 16000L),
+ /* have fully memory mapped flash. Calculated */ (F_CPU / 20000L),(F_CPU / 24000L),(F_CPU / 28000L),(F_CPU / 32000L),
+ /* at compile time (we get to use division!) */ (F_CPU / 40000L),(F_CPU / 48000L),(F_CPU / 56000L),(F_CPU / 64000L),1};
+
+
+ /*
+ Frequency in kHz.
+ If options & 1 == 1, will set frequencies outside of safe operating range
+ Otherwise, will be constrained to between 300 and 3000 (if internal reference used) or 300 and 6000 if not.
+ Note: analogReference does NOT check this! So set the clock speed after reference if you want that guardrail.
+ 0 takes action, and -1 sets to default.
+ */
+ int16_t analogClockSpeed(int16_t frequency, uint8_t options) {
+ if (frequency == -1) {
+ frequency = 2750;
+ }
+ if (frequency > 0) {
+ if ((options & 0x01) == 0) {
+ frequency = constrain(frequency, 300, ((ADC0.CTRLC & 0x04) ? 3000 : 6000));
+ }
+ uint8_t prescale = 0;
+ for (uint8_t i =0; i < 16; i++) {
+ int16_t clkadc = adc_prescale_to_clkadc[i];
+ prescale = i;
+ if ((frequency >= clkadc) || (adc_prescale_to_clkadc[i+1] < ((options & 0x01) ? 2 : 300))) {
+ ADC0.CTRLB = prescale;
+ break;
+ }
+ }
+ }
+ if (frequency < 0) {
+ return ADC_ERROR_INVALID_CLOCK;
+ }
+ int16_t ret = adc_prescale_to_clkadc[ADC0.CTRLB];
+ if (ret > 1500) {
+
+ }
+ return adc_prescale_to_clkadc[ADC0.CTRLB];
+ }
+
+
+/*---------------------------------------------------
+ * END 2-series analogRead/analogReadXxxx functions
+ *--------------------------------------------------*/
+#else
+ /*****************************************************
+ START 0/1-series analogRead/analogReadXxxx functions
+ *****************************************************/
+
+ inline __attribute__((always_inline)) void check_valid_duration(uint8_t samplen) {
+ if (__builtin_constant_p(samplen)) {
+ if (samplen > 31)
+ badArg("Maximum SAMPLEN = 31 on these parts (33 ADC clocks)");
+ }
+ }
+
+ bool analogSampleDuration(uint8_t dur) {
+ check_valid_duration(dur);
+ if (dur > 0x1F) {
+ ADC0.SAMPCTRL = 0x1F;
+ return false;
+ } else {
+ ADC0.SAMPCTRL = dur;
+ return true;
+ }
+ }
+
+ void ADCPowerOptions(uint8_t options) {
+ if (__builtin_constant_p(options)) {
+ if (options & 0x0F) {
+ badArg("Only runstandby and enable/disable are supported - the hardware doesn't have LOWLAT nor the PGA");
+ }
+ } // 0b SEE xxxx
+ // SS = run standby
+ // 00 = no change to run standby
+ // 01 = no change to run standby
+ // 10 = turn off run standby
+ // 11 = turn on run standby
+ // EE = ENABLE
+ // 00 = Do not enable or disable ADC.
+ // 01 = Do not enable or disable ADC.
+ // 10 = Disable the ADC.
+ // 11 = Enable the ADC.
+
+ uint8_t temp = ADC0.CTRLA; //performance.
+ if (options & 0x20) {
+ if (options & 0x10) {
+ temp |= 1; // ADC on
+ } else {
+ temp &= 0xFE; // ADC off
+ }
+ }
+ if (options & 0x80) {
+ if (options & 0x40) {
+ temp |= 0x80; // run standby
+ } else {
+ temp &= 0x7F; // no run standby
+ }
+ }
+ ADC0.CTRLA = temp; //now we apply enable and standby,
+ }
+ void analogReference(uint8_t mode) {
+ check_valid_analog_ref(mode);
+ switch (mode) {
+ #if defined(EXTERNAL)
+ case EXTERNAL:
+ #endif
+ case VDD:
+ VREF.CTRLB &= ~VREF_ADC0REFEN_bm; // Turn off force-adc-reference-enable
+ ADC0.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm)) | mode | ADC_SAMPCAP_bm; // per datasheet, recommended SAMPCAP=1 at ref > 1v - we don't *KNOW* the external reference will be >1v, but it's probably more likely...
+ // VREF.CTRLA does not need to be reconfigured, as the voltage references only supply their specified voltage when requested to do so by the ADC.
+ break;
+ case INTERNAL0V55:
+ VREF.CTRLA = VREF.CTRLA & ~(VREF_ADC0REFSEL_gm); // These bits are all 0 for 0.55v reference, so no need to do the mode << VREF_ADC0REFSEL_gp here;
+ ADC0.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm | ADC_SAMPCAP_bm)) | INTERNAL; // per datasheet, recommended SAMPCAP=0 at ref < 1v
+ VREF.CTRLB |= VREF_ADC0REFEN_bm; // Turn off force-adc-reference-enable
+ break;
+ case INTERNAL1V1:
+ case INTERNAL2V5:
+ case INTERNAL4V34:
+ case INTERNAL1V5:
+ VREF.CTRLA = (VREF.CTRLA & ~(VREF_ADC0REFSEL_gm)) | (mode << VREF_ADC0REFSEL_gp);
+ ADC0.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm)) | INTERNAL | ADC_SAMPCAP_bm; // per datasheet, recommended SAMPCAP=1 at ref > 1v
+ break;
+ }
+ }
+
+ uint8_t getAnalogReference() {
+ uint8_t t = ADC0.CTRLC & ADC_REFSEL_gm;
+ if (t) {
+ return t;
+ } else {
+ return(VREF.CTRLA & (VREF_ADC0REFSEL_gm));
+ }
+ }
+
+ int8_t getAnalogReadResolution() {
+ return ((ADC0.CTRLA & (ADC_RESSEL_bm)) == 1) ? 8 : 10;
+ }
+ int analogRead(uint8_t pin) {
+ check_valid_analog_pin(pin);
+
+ if (pin < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ pin = digitalPinToAnalogInput(pin);
+ }
+ #if (PROGMEM_SIZE > 4096)
+ // don't waste flash on smallest parts.
+ if ((pin & 0x7F) > 0x1F) { // highest valid mux value for any 0 or 1-series part.
+ return ADC_ERROR_BAD_PIN_OR_CHANNEL;
+ }
+ #endif
+ if (!ADC0.CTRLA & 0x01) return ADC_ERROR_DISABLED;
+ pin &= 0x1F;
+ /* Reference should be already set up */
+ /* Select channel */
+ ADC0.MUXPOS = (pin << ADC_MUXPOS_gp);
+
+ #if defined(STRICT_ERROR_CHECKING)
+ if (ADC0.COMMAND) return ADC_ERROR_BUSY;
+ #endif
+
+ /* Start conversion */
+ ADC0.COMMAND = ADC_STCONV_bm;
+
+ /* Wait for result ready */
+ while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
+
+ /* Combine two bytes */
+ return ADC0.RES;
+ }
+
+
+
+
+
+int32_t analogReadEnh(uint8_t pin, uint8_t res, uint8_t gain) {
+ if (!(ADC0.CTRLA & 0x01)) return ADC_ENH_ERROR_DISABLED;
+ check_valid_enh_res(res);
+ check_valid_analog_pin(pin);
+ if (__builtin_constant_p(gain)) {
+ if (gain != 0)
+ badArg("This part does not have an amplifier, gain argument must be omitted or given as 0");
+ }
+ uint8_t sampnum;
+ if (res & 0x80) { // raw accumulation
+ sampnum = res & 0x7F;
+ if (sampnum > 6) return ADC_ENH_ERROR_RES_TOO_HIGH;
+ } else {
+ if (res < ADC_NATIVE_RESOLUTION_LOW) return ADC_ENH_ERROR_RES_TOO_LOW;
+ if (res > 13) return ADC_ENH_ERROR_RES_TOO_HIGH;
+ sampnum = (res > ADC_NATIVE_RESOLUTION ? ((res - ADC_NATIVE_RESOLUTION) << 1) : 0);
+ }
+ if (pin < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ pin = digitalPinToAnalogInput(pin);
+ }
+ #if (PROGMEM_SIZE > 4096)
+ // don't waste flash on smallest parts.
+ if ((pin & 0x7F) > 0x1F) { // highest valid mux value for any 0 or 1-series part.
+ return ADC_ERROR_BAD_PIN_OR_CHANNEL;
+ }
+ #endif
+ pin &= 0x1F;
+ ADC0.MUXPOS = pin;
+ #if defined(STRICT_ERROR_CHECKING) /* Strict error checking not yet implemented */
+ if (ADC0.COMMAND) return ADC_ENH_ERROR_BUSY;
+ #endif
+
+ uint8_t _ctrla = ADC0.CTRLA;
+ ADC0.CTRLA = ADC_ENABLE_bm | (res == ADC_NATIVE_RESOLUTION_LOW ? ADC_RESSEL_bm : 0);
+ // if (res > 0x80) {
+ ADC0.CTRLB = sampnum;
+ /*} else
+ if (res > ADC_NATIVE_RESOLUTION) {
+ ADC0.CTRLB = 2 * (res - ADC_NATIVE_RESOLUTION);
+ } else {
+ ADC0.CTRLB = 0;
+ }*/
+
+ ADC0.COMMAND = ADC_STCONV_bm;
+ while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
+ int32_t result = ADC0.RES;
+ if (res < 0x80 && res > ADC_NATIVE_RESOLUTION) {
+ uint8_t shift = res - ADC_NATIVE_RESOLUTION - 1;
+ while (shift) {
+ result >>= 1;
+ shift--;
+ }
+ uint8_t roundup = result & 0x01;
+ result >>= 1;
+ result += roundup;
+ } else if (res == ADC_NATIVE_RESOLUTION - 1) { // 9 bit res?!
+ result >>= 1;
+ } // res > 0x80 (raw accumulate) or res == 8, res == 10 need no adjustment;
+ ADC0.CTRLA = _ctrla;
+ ADC0.CTRLB = 0;
+ return result;
+}
+
+int32_t analogReadDiff(__attribute__ ((unused)) uint8_t pos, __attribute__ ((unused))uint8_t neg, __attribute__ ((unused))uint8_t res, __attribute__ ((unused))uint8_t gain) {
+ badCall("This part does not have a differential ADC");
+ return ADC_ENH_ERROR_NOT_DIFF_ADC;
+}
+int32_t analogReadDiff1(__attribute__ ((unused)) uint8_t pos, __attribute__ ((unused))uint8_t neg, __attribute__ ((unused))uint8_t res, __attribute__ ((unused))uint8_t gain) {
+ badCall("This part does not have a differential ADC - and certainly not TWO OF THEM");
+ return ADC_ENH_ERROR_NOT_DIFF_ADC;
+}
+static const int16_t adc_prescale_to_clkadc[0x09] = {(F_CPU / 2000UL),(F_CPU / 4000UL),(F_CPU / 8000UL),(F_CPU / 16000UL),
+/* Doesn't get copied to ram because these all */ (F_CPU / 32000UL),(F_CPU / 64000UL),(F_CPU /128000UL),(F_CPU /256000UL),1};
+
+/*
+Frequency in kHz.
+If (options & 1) == 1, will set frequencies outside of safe operating range
+Otherwise, will be constrained to between 300 and 3000 (if internal reference used) or 300 and 6000 if not.
+Note: analogReference does NOT check this! So set the clock speed after reference if you want that guardrail.
+0 takes action, and -1 sets to default.
+*/
+
+
+int16_t analogClockSpeed(int16_t frequency, uint8_t options) {
+ uint8_t prescale = 0;
+ if (frequency == -1) {
+ frequency = 1450;
+ }
+ if (frequency > 0) {
+ bool using_0v55 = !(VREF.CTRLA & VREF_ADC0REFSEL_gm || ADC0.CTRLC & ADC_REFSEL_gm);
+ if ((options & 0x01) == 0) {
+ int16_t maxadc = 1500;
+ if ((ADC0.CTRLA & ADC_RESSEL_bm)) {
+ maxadc = 2000;
+ }
+ frequency = constrain(frequency, (using_0v55 ? 100: 200), (using_0v55 ? 260 : maxadc));
+ }
+ for (uint8_t i =0; i < 8; i++) {
+ int16_t clkadc = adc_prescale_to_clkadc[i];
+ prescale = i;
+ if ((frequency >= clkadc) || (adc_prescale_to_clkadc[i + 1] < ((options & 0x01) ? 2 : (using_0v55 ? 100 : 200)))) {
+
+ ADC0.CTRLC = (ADC0.CTRLC & ~ADC_PRESC_gm) | prescale;
+ break;
+ }
+ }
+ }
+ if (frequency < 0) {
+ return ADC_ERROR_INVALID_CLOCK;
+ }
+ int16_t newadcclk = adc_prescale_to_clkadc[prescale];
+ if (newadcclk > 1500) {
+ ADC0.CALIB = 1;
+ } else {
+ ADC0.CALIB = 0;
+ }
+ return newadcclk;
+}
+
+#if defined(ADC1)
+/****************************************************/
+ // If we have two ADCs, while advise using only one, or controlling the second manually if advanced functionality is needed
+ // if you insist, you can treat it identically by appending '1' to the names of the analog functions.
+ void ADCPowerOptions1(uint8_t options) {
+ if (__builtin_constant_p(options)) {
+ if (options & 0x0F) {
+ badArg("Only runstandby and enable/disable are supported - the hardware doesn't have LOWLAT nor the PGA");
+ }
+ }
+ // 0b SSEExxxx
+ // SS = run standby
+ // 00 = no change to run standby
+ // 01 = no change to run standby
+ // 10 = turn off run standby
+ // 11 = turn on run standby
+ // EE = ENABLE
+ // 00 = Do not enable or disable ADC.
+ // 01 = Do not enable or disable ADC.
+ // 10 = Disable the ADC.
+ // 11 = Enable the ADC
+ //
+ // 0b10100000 = 0xA0 = stop and disable fully
+ // 0b00110000 - 0x30 = Enable ADC and don't change standby setting
+ // 0b11110000 - 0xF0 = Enable ADC and run in standby
+ //
+
+ uint8_t temp = ADC1.CTRLA; //performance.
+ if (options & 0x20) {
+ if (options & 0x10) {
+ temp |= 1; // ADC on
+ } else {
+ temp &= 0xFE; // ADC off
+ }
+ }
+ if (options & 0x80) {
+ if (options & 0x40) {
+ temp |= 0x80; // run standby
+ } else {
+ temp &= 0x7F; // no run standby
+ }
+ }
+ ADC1.CTRLA = temp; //now we apply enable and standby
+ }
+ inline __attribute__((always_inline)) void check_valid_analog_pin1(pin_size_t pin) {
+ if (__builtin_constant_p(pin)) {
+ if (pin != ADC1_DAC1 && pin != ADC_INTREF && pin != ADC1_DAC2 && pin != ADC_GROUND) {
+ // above cases cover valid internal sources.
+ if (pin & 0x80) {
+ if ((pin & 0x3F) >= NUM_ANALOG_INPUTS)
+ {
+ badArg("analogRead1 called with constant channel that is neither valid analog channel nor valid pin");
+ }
+ } else {
+ pin = digitalPinToAnalogInput_ADC1(pin);
+ if (pin == NOT_A_PIN) {
+ badArg("analogRead1 called with constant pin that is not a valid analog pin");
+ }
+ }
+ }
+ }
+ }
+
+ void analogReference1(uint8_t mode) {
+ check_valid_analog_ref(mode);
+ switch (mode) {
+ #if defined(EXTERNAL)
+ case EXTERNAL:
+ #endif
+ case VDD:
+ VREF.CTRLB &= ~VREF_ADC1REFEN_bm; // Turn off force-adc-reference-enable
+ ADC1.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm)) | mode | ADC_SAMPCAP_bm; // per datasheet, recommended SAMPCAP=1 at ref > 1v - we don't *KNOW* the external reference will be >1v, but it's probably more likely...
+ // VREF.CTRLA does not need to be reconfigured, as the voltage references only supply their specified voltage when requested to do so by the ADC.
+ break;
+ case INTERNAL0V55:
+ VREF.CTRLC = VREF.CTRLC & ~(VREF_ADC0REFSEL_gm); // These bits are all 0 for 0.55v reference, so no need to do the mode << VREF_ADC0REFSEL_gp here;
+ ADC1.CTRLC = (ADC1.CTRLC & ~(ADC_REFSEL_gm | ADC_SAMPCAP_bm)) | INTERNAL; // per datasheet, recommended SAMPCAP=0 at ref < 1v
+ VREF.CTRLB |= VREF_ADC1REFEN_bm; // Turn off force-adc-reference-enable
+ break;
+ case INTERNAL1V1:
+ case INTERNAL2V5:
+ case INTERNAL4V34:
+ case INTERNAL1V5:
+ VREF.CTRLC = (VREF.CTRLC & ~(VREF_ADC0REFSEL_gm)) | (mode << VREF_ADC0REFSEL_gp);
+ ADC1.CTRLC = (ADC1.CTRLC & ~(ADC_REFSEL_gm)) | INTERNAL | ADC_SAMPCAP_bm; // per datasheet, recommended SAMPCAP=1 at ref > 1v
+ break;
+ }
+ }
+ // requires a bit of explanation - basically, the groupcodes are the same for ADC0 and ADC1, just different register.
+ // VREF_ADC0REFSEL_gm == VREF_ADC1REFSEL_gm
+ uint8_t getAnalogReference1() {
+ uint8_t t = ADC1.CTRLC & ADC_REFSEL_gm;
+ if (t) {
+ return t;
+ } else {
+ return(VREF.CTRLC & (VREF_ADC0REFSEL_gm));
+ }
+ }
+ int16_t analogClockSpeed1(int16_t frequency, uint8_t options) {
+ uint8_t prescale = 0;
+ if (frequency == -1) {
+ frequency = 1450;
+ }
+ if (frequency > 0) {
+ bool using_0v55 = !(VREF.CTRLA & VREF_ADC1REFSEL_gm || ADC0.CTRLC & ADC_REFSEL_gm);
+ if ((options & 0x01) == 0) {
+ int16_t maxadc = 1500;
+ if ((ADC1.CTRLA & ADC_RESSEL_bm)) {
+ maxadc = 2000;
+ }
+ frequency = constrain(frequency, (using_0v55 ? 100: 200), (using_0v55 ? 260 : maxadc));
+ // 'cause, ya see, if you only want 8-bit resolution, and aren't using the 11/20ths of a volt reference, you can run the ADC clock faster and hope to get meaningful numbers .
+ }
+ for (uint8_t i =0; i < 8; i++) {
+ int16_t clkadc = adc_prescale_to_clkadc[i];
+ prescale = i;
+ if ((frequency >= clkadc) || (adc_prescale_to_clkadc[i + 1] < ((options & 0x01) ? 2 : (using_0v55 ? 100 : 200)))) {
+
+ ADC1.CTRLC = (ADC1.CTRLC & ~ADC_PRESC_gm) | prescale;
+ break;
+ }
+ }
+ }
+ if (frequency < 0) {
+ return ADC_ERROR_INVALID_CLOCK;
+ }
+ int16_t newadcclk = adc_prescale_to_clkadc[prescale];
+ if (newadcclk > 1500) {
+ ADC1.CALIB = 1;
+ } else {
+ ADC1.CALIB = 0;
+ }
+ return newadcclk;
+ }
+
+
+ int16_t analogRead1(uint8_t pin) {
+ check_valid_analog_pin1(pin);
+
+ if (pin < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ pin = digitalPinToAnalogInput_ADC1(pin);
+ }
+ #if (PROGMEM_SIZE > 4096)
+ // don't waste flash on smallest parts.
+ if ((pin & 0x3F) > 0x1F) { // highest valid mux value for any 0 or 1-series part.
+ return ADC_ERROR_BAD_PIN_OR_CHANNEL;
+ }
+ #endif
+ if (!ADC1.CTRLA & 0x01) return ADC_ERROR_DISABLED;
+ pin &= 0x1F;
+ /* Reference should be already set up */
+ /* Select channel */
+ ADC1.MUXPOS = (pin << ADC_MUXPOS_gp);
+
+ #if defined(STRICT_ERROR_CHECKING)
+ if (ADC1.COMMAND) return ADC_ERROR_BUSY;
+ #endif
+
+ /* Start conversion */
+ ADC1.COMMAND = ADC_STCONV_bm;
+
+ /* Wait for result ready */
+ while (!(ADC1.INTFLAGS & ADC_RESRDY_bm));
+
+ /* Combine two bytes */
+ return ADC1.RES;
+ }
+
+
+ bool analogSampleDuration1(uint8_t dur) {
+ check_valid_duration(dur);
+ if (dur > 0x1F) {
+ ADC1.SAMPCTRL = 0x1F;
+ return false;
+ } else {
+ ADC1.SAMPCTRL = dur;
+ return true;
+ }
+ }
+
+ int32_t analogReadEnh1(uint8_t pin, uint8_t res, uint8_t gain) {
+ if (!(ADC1.CTRLA & 0x01)) return ADC_ENH_ERROR_DISABLED;
+ check_valid_enh_res(res);
+ check_valid_analog_pin(pin);
+ if (__builtin_constant_p(gain)) {
+ if (gain != 0)
+ badArg("This part does not have an amplifier, gain argument must be omitted or given as 0");
+ }
+ uint8_t sampnum;
+ if (res & 0x80) { // raw accumulation
+ sampnum = res & 0x7F;
+ if (sampnum > 6) return ADC_ENH_ERROR_RES_TOO_HIGH;
+ } else {
+ if (res < ADC_NATIVE_RESOLUTION_LOW) return ADC_ENH_ERROR_RES_TOO_LOW;
+ if (res > 13) return ADC_ENH_ERROR_RES_TOO_HIGH;
+ sampnum = (res > ADC_NATIVE_RESOLUTION ? ((res - ADC_NATIVE_RESOLUTION) << 1) : 0);
+ }
+ if (pin < 0x80) {
+ // If high bit set, it's a channel, otherwise it's a digital pin so we look it up..
+ pin = digitalPinToAnalogInput_ADC1(pin);
+ }
+ #if (PROGMEM_SIZE > 4096)
+ // don't waste flash on smallest parts.
+ if ((pin & 0x7F) > 0x1F) { // highest valid mux value for any 0 or 1-series part.
+ return ADC_ERROR_BAD_PIN_OR_CHANNEL;
+ }
+ #endif
+ pin &= 0x1F;
+ ADC1.MUXPOS = pin;
+ #if defined(STRICT_ERROR_CHECKING) /* Strict error checking not yet implemented */
+ if (ADC1.COMMAND) return ADC_ENH_ERROR_BUSY;
+ #endif
+
+ uint8_t _ctrla = ADC1.CTRLA;
+ ADC1.CTRLA = ADC_ENABLE_bm | (res == ADC_NATIVE_RESOLUTION_LOW ? ADC_RESSEL_bm : 0);
+ // if (res > 0x80) {
+ ADC1.CTRLB = sampnum;
+ /*} else
+ if (res > ADC_NATIVE_RESOLUTION) {
+ ADC1.CTRLB = 2 * (res - ADC_NATIVE_RESOLUTION);
+ } else {
+ ADC1.CTRLB = 0;
+ }*/
+
+ ADC1.COMMAND = ADC_STCONV_bm;
+ while (!(ADC1.INTFLAGS & ADC_RESRDY_bm));
+ int32_t result = ADC1.RES;
+ if (res < 0x80 && res > ADC_NATIVE_RESOLUTION) {
+ uint8_t shift = res - ADC_NATIVE_RESOLUTION - 1;
+ while (shift) {
+ result >>= 1;
+ shift--;
+ }
+ uint8_t roundup = result & 0x01;
+ result >>= 1;
+ result += roundup;
+ } else if (res == ADC_NATIVE_RESOLUTION - 1) { // 9 bit res?!
+ result >>= 1;
+ } // res > 0x80 (raw accumulate) or res == 8, res == 10 need no adjustment;
+ ADC1.CTRLA = _ctrla;
+ ADC1.CTRLB = 0;
+ return result;
+ }
+ #endif
+ /*****************************************************
+ END 0/1-series analogRead/analogReadXxxx functions
+ *****************************************************/
+#endif
+
+void analogWrite(uint8_t pin, int val) {
+ check_valid_digital_pin(pin);
+ check_valid_duty_cycle(val);
+ uint8_t bit_mask = digitalPinToBitMask(pin);
+ if (bit_mask == NOT_A_PIN) {
+ return;
+ }
+ #if defined(TCD0) && defined(USE_TIMERD0_PWM) && defined(NO_GLITCH_TIMERD0)
+
+ uint8_t set_inven = 0;
+ #endif
+ // Set pin output because that's what Arduino does
+ // Moved this way down to the end, why enable output before we have the pin doing the right thing?
+ // pinMode(pin, OUTPUT);
+
+ /* Get timer */
+ /* megaTinyCore only - assumes only TIMERA0, TIMERD0, or DACOUT
+ * can be returned here, all have only 1 bit set, so we can use
+ * __PeripheralControl as a mask to see if they have taken over
+ * any timers with minimum overhead - critical on these parts
+ * Since nothing that will show up here can have more than one
+ * one bit set, binary and will give 0x00 if that bit is cleared
+ * which is NOT_ON_TIMER.
+ */
+ uint8_t digital_pin_timer = digitalPinToTimer(pin) & __PeripheralControl;
+ /* end megaTinyCore-specific section */
+ /* Find out Port and Pin to correctly handle port mux, and timer. */
+ switch (digital_pin_timer) {
+
+/**********************************************************************
+* PART 1: TIMERA
+**********************************************************************/
+ #if defined(TCA0)
+ case TIMERA0: {
+ if (val <= 0) { /* if zero or negative drive digital low */
+ digitalWrite(pin, LOW);
+ } else if (val >= 255) { /* if max or greater drive digital high */
+ digitalWrite(pin, HIGH);
+ } else {
+ /* Calculate correct compare buffer register */
+ #if defined(TCA_BUFFERED_3PIN)
+ //If we have buffered TCA0, then we write to different registers and calculate destinations differeetly.
+ volatile uint16_t *timer_cmp16_out; // must be volatile for this to be safe.
+ uint8_t offset = 0;
+ if (bit_mask & 0x12) {
+ offset = 1;
+ bit_mask = 0x20;
+ } else if (bit_mask & 0x24) {
+ offset = 2;
+ bit_mask = 0x40;
+ } else {
+ bit_mask = 0x10;
+ }
+ timer_cmp16_out = (volatile uint16_t *)(&TCA0_SINGLE_CMP0BUF);
+ *(timer_cmp16_out + offset) = (uint16_t) val;
+ TCA0.SINGLE.CTRLB |= bit_mask;
+ #else
+ //Otherwise, we're in split mode and we use the classical method.
+ volatile uint8_t *timer_cmp_out; // must be volatile for this to be safe.
+ #ifdef __AVR_ATtinyxy2__
+ if (bit_mask == 0x80) {
+ bit_mask = 1; // on the xy2, WO0 is on PA7
+ }
+ #endif
+ uint8_t offset = 0;
+ if (bit_mask > 0x04) { //if it's above pin 3 either it's on portb and should be lowered by 3, or it's not and needs to have an offset and be leftshifted
+ bit_mask <<= 1; // either wat leftshifting is thefirst step
+
+ if (digitalPinToPort(pin) == 1) {
+ _SWAP(bit_mask);
+ } else {
+ offset = 1;
+ }
+ }
+ if (bit_mask & 0x44) {
+ offset += 4;
+ } else if (bit_mask & 0x22) {
+ offset += 2;
+ }
+ timer_cmp_out = ((volatile uint8_t *)(&TCA0.SPLIT.LCMP0)) + (offset); //finally at the very end we get the actual pointer (since volatile variables should be treated like nuclear waste due to performance impact)
+ (*timer_cmp_out) = (val); // write to it - and we're done with it.
+ TCA0.SPLIT.CTRLB |= bit_mask;
+ #endif
+ }
+ break;
+ // End of TCA case
+ }
+ #endif
+
+/**********************************************************************
+* PART 2: DAC
+**********************************************************************/
+ #if defined(DAC0)
+ case DACOUT:
+ {
+ DAC0.DATA = val;
+ DAC0.CTRLA |= 0x41; // OUTEN=1, ENABLE=1, and *don't* trash the RUNSTBY setting.
+ break;
+ }
+ #endif
+
+/**********************************************************************
+* PART 1: TIMERD
+**********************************************************************/
+ #if (defined(TCD0) && defined(USE_TIMERD0_PWM))
+ case TIMERD0:
+ {
+ #if !defined(NO_GLITCH_TIMERD0)
+ /* Glitches permitted: 0 or 255 will generate a glitch on the other channels and lose a tiny amount of time if used as millis timer. If you're doing that
+ * often enough though it adds up. */
+ if (val < 1) { /* if zero or negative drive digital low */
+ digitalWrite(pin, LOW);
+ } else if (val > 254) { /* if max or greater drive digital high */
+ digitalWrite(pin, HIGH);
+ } else {
+ #else
+ /* Now, if NO_GLITCH_TIMERD0 is defined, val can legally be 0 or 255, which is to be interpreted as an instruction to keep the output constant LOW or HIGH.
+ * 0 requires no special action - 255-0 = 255, we're counting to 254 and thus will never reach the compare matchvalue. 255 on the other hand, requires us to
+ * invert the pin and set val to 0 to get the constant output. Setting the CMPxSET register to 0 produces a sub-system-clock spike (maybe you don't care.
+ * But depending on the application, this could be catastrophic!)
+ * Values below 0 are easy just clip them to zero and we're done. Values of 255 though will produce duty cycles slightly below 100%! So in that case we change
+ * val to 0 (which would keep a constant low) but then invert the output pin.
+ */
+ if (val < 1) {
+ val = 0;
+ } else if (val > 254) {
+ val = 0;
+ set_inven = 1;
+ } else {
+ #endif
+ // Calculation of values to write to CMPxSET
+ // val is 1~254, so 255-val is 1~254.
+ uint8_t oldSREG = SREG;
+
+ cli(); // interrupts off... wouldn't due to have this mess interrupted and messed with...
+
+ while ((TCD0.STATUS & (TCD_ENRDY_bm | TCD_CMDRDY_bm)) != (TCD_ENRDY_bm | TCD_CMDRDY_bm));
+ // if previous sync/enable in progress, wait for it to finish. This is dicey for sure, because we're waiting on a peripheral
+ // with interrupts off. But an interrupt could trigger one of those bits becoming unset, so we must do it this way.
+ // set new values
+ uint8_t fc_mask;
+ #if defined(USE_TCD_WOAB) && _AVR_PINCOUNT != 8 // TCD is available on PA4 or PA5 on 14+ pin parts
+ fc_mask = bit_mask;
+ if (bit_mask == 0x20) { // PIN_PA5
+ TCD0.CMPBSET = ((255 - val) << 1) - 1;
+ } else { // PIN_PA4
+ TCD0.CMPASET = ((255 - val) << 1) - 1;
+ }
+ #elif defined(USE_TCD_WOAB) && _AVR_PINCOUNT == 8 // 8 pin parts have it on PA6, PA7 only
+ if (bit_mask == 0x80) { // PIN_PA7
+ TCD0.CMPBSET = ((255 - val) << 1) - 1;
+ fc_mask = 0x20;
+ } else { // PIN_PA6
+ TCD0.CMPASET = ((255 - val) << 1) - 1;
+ fc_mask = 0x10;
+ }
+ #else // parts with more pins can have it on PC1 or PC0.
+ if (bit_mask == 2) { // PIN_PC1
+ TCD0.CMPBSET = ((255 - val) << 1) - 1;
+ fc_mask = 0x80;
+ } else { // PIN_PC0
+ TCD0.CMPASET = ((255 - val) << 1) - 1;
+ fc_mask = 0x40;
+ }
+ #endif
+ if (!(TCD0.FAULTCTRL & fc_mask)) {
+ // if it's not active, we need to activate it... which produces a glitch in the PWM
+ TCD0.CTRLA &= ~TCD_ENABLE_bm; // stop the timer
+ _PROTECTED_WRITE(TCD0.FAULTCTRL, TCD0.FAULTCTRL | fc_mask);
+ while (!(TCD0.STATUS & TCD_ENRDY_bm)); // wait until we can re-enable it
+ TCD0.CTRLA |= TCD_ENABLE_bm; // re-enable it
+ } else {
+ TCD0.CTRLE = TCD_SYNCEOC_bm; // Synchronize at the end of the current cycle
+ }
+
+
+ /**********************************************************************
+ * PART 3.5: TIMERD noglitch
+ **********************************************************************/
+ #if defined(NO_GLITCH_TIMERD0) // This mode is always used with the stock variant.
+ #if defined(USE_TCD_WOAB) && _AVR_PINCOUNT != 8
+ // TCD is on PA4 or PA5 on 14+ pin parts
+ if (set_inven == 0) { // we are not setting invert to make the pin HIGH when not set; either was 0 (just set CMPxSET > CMPBCLR) or somewhere in between.
+ if (bit_mask == 0x10) {
+ PORTA.PIN4CTRL &= ~(PORT_INVEN_bm);
+ } else {
+ PORTA.PIN5CTRL &= ~(PORT_INVEN_bm);
+ }
+ } else { // we *are* turning off PWM while forcing pin high - analogwrite(pin, 255) was called on TCD0 PWM pin...
+ if (bit_mask == 0x10) {
+ PORTA.PIN4CTRL |= PORT_INVEN_bm;
+ } else {
+ PORTA.PIN5CTRL |= PORT_INVEN_bm;
+ }
+ }
+ #elif defined(USE_TCD_WOAB) && _AVR_PINCOUNT == 8 // 8 pin parts have it on PA6, PA7
+ if (set_inven == 0) { // we are not setting invert to make the pin HIGH when not set; either was 0 (just set CMPxSET > CMPBCLR) or somewhere in between.
+ if (bit_mask == 0x40) {
+ PORTA.PIN6CTRL &= ~(PORT_INVEN_bm);
+ } else {
+ PORTA.PIN7CTRL &= ~(PORT_INVEN_bm);
+ }
+ } else { // we *are* turning off PWM while forcing pin high - analogwrite(pin, 255) was called on TCD0 PWM pin...
+ if (bit_mask == 0x40) {
+ PORTA.PIN6CTRL |= PORT_INVEN_bm;
+ } else {
+ PORTA.PIN7CTRL |= PORT_INVEN_bm;
+ }
+ }
+ #else // TCD is on PC0 or PC1 so if we're here, we're acting on either PC0 or PC1. And NO_GLITCH mode is enabled
+ if (set_inven == 0) { // we are not setting invert to make the pin HIGH when not set; either was 0 (just set CMPxSET > CMPBCLR) or somewhere in between.
+ if (bit_mask == 1) {
+ PORTC.PIN0CTRL &= ~(PORT_INVEN_bm);
+ } else {
+ PORTC.PIN1CTRL &= ~(PORT_INVEN_bm);
+ }
+ } else { // we *are* turning off PWM while forcing pin high - analogwrite(pin, 255) was called on TCD0 PWM pin...
+ if (bit_mask == 1) {
+ PORTC.PIN0CTRL |= PORT_INVEN_bm;
+ } else {
+ PORTC.PIN1CTRL |= PORT_INVEN_bm;
+ }
+ }
+ #endif //End conditional for each set of pins
+ #endif // End conditional to handle no-glitch
+ SREG = oldSREG;
+ }
+ break;
+ }
+ #endif
+ // Now catch the cases where there's no pin.
+ case NOT_ON_TIMER:
+ // fall through
+ default:
+ {
+ if (val < 128) {
+ digitalWrite(pin, LOW);
+ } else {
+ digitalWrite(pin, HIGH);
+ }
+ break;
+ }
+ // Now that everything is said and done, we've set the pin high or low as if it's not a PWM pin, or told the timer to give it PWM if it is - this is a better timwe to finally turn on the output drivers.
+ // True, it is at most 1-2 PWM timer ticks under typical settings, it's probably at least 1 tick, maybe several at 1 MHz (haven't timed analogWrite lately)
+ } // end of switch/case
+ pinMode(pin, OUTPUT);
+} // end of analogWrite
+
+void takeOverTCA0() {
+ TCA0.SPLIT.CTRLA = 0; // Stop TCA0
+ __PeripheralControl &= ~TIMERA0; // Mark timer as user controlled
+ /* Okay, seriously? The datasheets and io headers disagree here */
+ TCA0.SPLIT.CTRLESET = TCA_SPLIT_CMD_RESET_gc | 0x03; // Reset TCA0
+}
+
+uint8_t digitalPinToTimerNow(uint8_t pin) {
+ return digitalPinToTimer(pin) & __PeripheralControl;
+}
+
+#if defined(TCD0)
+void takeOverTCD0() {
+ TCD0.CTRLA = 0; // Stop TCD0
+ _PROTECTED_WRITE(TCD0.FAULTCTRL,0); // Turn off all outputs
+ __PeripheralControl &= ~TIMERD0; // Mark timer as user controlled
+}
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_digital.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_digital.c
new file mode 100644
index 0000000..36ada72
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_digital.c
@@ -0,0 +1,464 @@
+/*
+ wiring_digital.c - digital input and output functions
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 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
+
+ Modified 28 September 2010 by Mark Sproul
+ Modified extensively 2018~2021 by Spence Konde for
+ megaTinyCore and DxCore.
+*/
+
+#define ARDUINO_MAIN
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+
+
+inline __attribute__((always_inline)) void check_valid_pin_mode(uint8_t mode) {
+ if (__builtin_constant_p(mode)) {
+ if (mode != INPUT && mode != OUTPUT && mode != INPUT_PULLUP) {
+ badArg("The mode passed to pinMode must be INPUT, OUTPUT, or INPUT_PULLUP (these have numeric values of 0, 1, or 2); it was given a constant that was not one of these.");
+ }
+ }
+}
+
+void pinMode(uint8_t pin, uint8_t mode) {
+ check_valid_digital_pin(pin); /* generate compile error if a constant that is not a valid pin is used as the pin */
+ check_valid_pin_mode(mode); /* generate compile error if a constant that is not a valid pin mode is used as the mode */
+ uint8_t bit_mask = digitalPinToBitMask(pin);
+ if ((bit_mask == NOT_A_PIN) || (mode > INPUT_PULLUP)) {
+ return; /* ignore invalid pins passed at runtime */
+ }
+ volatile uint8_t * port_base = (volatile uint8_t *) (uint16_t) ((&PORTA) + digitalPinToPort(pin));
+ if (mode & 0x01) {
+ // OUTPUT mode, so write DIRSET with the mask.
+ *(port_base + 1) = bit_mask;
+ } else { // otherwise it's input so we write DIRCLR
+ *(port_base + 2) = bit_mask;
+ /* By unanimous decision of users who spoke up, we shall not set the output register to emulate classic AVRs.
+ if (mode == INPUT_PULLUP) {
+ *(port_base + 5) = bit_mask;
+ } else if (mode == 0) {
+ *(port_base + 6) = bit_mask;
+ }
+ */
+ }
+ // Now an interesting question:
+ // Is this faster?
+ //
+ // port_base +=(uint8_t) digitalPinToBitPosition(pin)
+ // bit_mask = *port_base+0x10
+ //
+ // It ought to be slightly faster. After we have loaded the bit position, either we combine with 0x10 (1 clock)
+ // add to port base (2 clocks, even though this will never result in a carry for any valid port that exist)
+ // then ld (2 clocks).
+ // Or after loading the bit position, we can add it to port_base (2 clocks)
+ // then load with displacement 2 clocks. IFF the compiler puts this pointer into Y or Z, it is faster and smaller
+ // by 2 bytes and one clock. And let's hope it is, because the code above would suck too if it was in X.
+ // Handwritten assembly that exploited the knowledge that there will never be a carry would save 1 word and 1 clock.
+ // and could probably save at least several times that in initializing the port_base pointer. But if you're using
+ // pinMode you probably don't care.
+ port_base += (uint8_t) digitalPinToBitPosition(pin);
+ bit_mask = *(port_base + 0x10);
+ if (mode & 2) {
+ bit_mask |= 0x08;
+ } else {
+ bit_mask &= 0xF7;
+ }
+ *(port_base + 0x10) = bit_mask;
+}
+
+/* This turns off PWM, if enabled. It is called automatically on every digitalWrite();
+ * This function can end up executing a heckovalotta code for one simple
+ * Note that it only operates on the PWM source with priority - TCA > TCD > TCB/DAC
+ * the order of the cases here doesn't matter - which one has priority is determined in
+ * digitalPinToTimerNow() in wiring_analog.c. That's why it's recommended to make sure
+ * that no pin you're about to move the PWM output of a TCA onto is currently outputting
+ * PWM. It can also be used from user code (unlike on the stock core). */
+void turnOffPWM(uint8_t pin)
+{
+ /* Actually turn off compare channel, not the timer */
+
+ /* Get pin's timer
+ * megaTinyCore only - assumes only TIMERA0, TIMERD0, or DACOUT
+ * can be returned here, all have only 1 bit set, so we can use
+ * __PeripheralControl as a mask to see if they have taken over
+ * any timers with minimum overhead - critical on these parts
+ * Since nothing that will show up here can have more than one
+ * one bit set, binary and will give 0x00 if that bit is cleared
+ * which is NOT_ON_TIMER.
+ */
+ uint8_t digital_pin_timer = digitalPinToTimer(pin) & __PeripheralControl;
+ /* end megaTinyCore-specific section */
+ if (digital_pin_timer== NOT_ON_TIMER) {
+ return;
+ }
+
+ uint8_t bit_mask = digitalPinToBitMask(pin);
+ // TCB_t *timerB;
+
+ switch (digital_pin_timer) {
+
+ /* TCA0 */
+ case TIMERA0:
+ {
+ #if !defined(TCA_BUFFERED_3PIN)
+ // uint8_t *timer_cmp_out;
+ /* Bit position will give output channel */
+ #ifdef __AVR_ATtinyxy2__ //8 pin parts
+ if (bit_mask == 0x80) {
+ bit_mask = 1; // on the xy2, WO0 is on PA7
+ }
+ if (bit_mask > 0x04) { // -> bit_pos > 2 -> output channel controlled by HCMP
+ bit_mask <<= 1; // mind the gap (between LCMP and HCMP)
+ }
+ #else // Normal parts
+ if (digitalPinToPort(pin) == PB) { // WO0-WO2, Bitmask has one of these bits 1: 0b00hhhlll.
+ if (bit_mask > 0x04) { // Is it one of the three high ones? If so
+ bit_mask <<= 1; // nudge it 1 place left swap nybbles since that's 1 clock faster than 3 rightshifts.
+ _SWAP(bit_mask); // swap nybbles since that's 1 clock faster than 3 rightshifts.
+ }
+ } else {
+ // Otherwise, it's WO3-5. These will always be on 0b00hhh000,. Here since we ARE working with a high half timer, we need to just leftshift it once.
+ bit_mask <<= 1;
+ }
+ #endif // End if 8 vs normal parts
+ TCA0.SPLIT.CTRLB &= ~bit_mask;
+ #else // 3-pin mode. Means we know it's either in set A or B: 0b0AAAxBBB We get 0x00ABC
+ if(bit_mask & 0b00111000) {
+ bit_mask <<= 1; // 0b01110000
+ } else {
+ //bit_maslk <<= 3; same result, but in 3 clocks 3 words instead of 1 and 1!
+
+ _SWAP(bit_mask); // 0b0111000
+ }
+ TCA0.SINGLE.CTRLB &= ~bit_mask;
+ #endif
+ break;
+ }
+
+ /* We don't need the type b timers as this core does not use them for PWM */
+
+ // 1-series parts have a DAC that we can use...
+ #if defined(DAC0)
+ case DACOUT:
+ DAC0.CTRLA = 0x00;
+ break;
+ #endif
+ /* 1-series parts also have a wacky async Type D timer, but we only use it on the 20 and 24-pin parts, as it doesn't buy us anything on the 14-pin ones...
+ * In a future update, an option to use TCD0 for PWM on PA4 and PA5 on the 14-pin parts, with TCA0 initialized in SINGLE mode is possible, but this would
+ * open a can of worms regarding SINGLE mode. I think we are best off telling people to call takeOverTCA0(), takeOverTCD0() and configure it themselves
+ * to do what they want, because you'll never make everyone happy otherwise. My calculus would be different if they'd made 8-pin parts with more than 4k
+ * of flash to fit the overhead of supporting TCA0 and TCD0 with analogWrite() comfortably - that would give a pin mapping with PWM on all pins - AND
+ * it would be able to do buffering on the TCA pins (TCD pins can always do that).*/
+ #if (defined(TCD0) && defined(USE_TIMERD0_PWM))
+ case TIMERD0:
+ {
+ // rigmarole that produces a glitch in the PWM
+ #if defined(TCD_USE_WOAB)
+ uint8_t fc_mask = bit_mask;// Hey that works out well!
+ if (TCD0.FAULTCTRL & fc_mask) {
+ uint8_t oldSREG = SREG;
+ cli();
+ // uint8_t TCD0_prescaler=TCD0.CTRLA&(~TCD_ENABLE_bm);
+ //
+ TCD0.CTRLA &= ~TCD_ENABLE_bm;
+ _PROTECTED_WRITE(TCD0.FAULTCTRL, TCD0.FAULTCTRL & (~fc_mask));
+ while (!(TCD0.STATUS & TCD_ENRDY_bm)); // wait until it can be re-enabled
+ TCD0.CTRLA |= TCD_ENABLE_bm; // re-enable it
+ #if defined(NO_GLITCH_TIMERD0) /* This is enabled in all cases where TCD0 is used for PWM */
+ // Assuming this mode is enabled, PWM can leave the pin with INVERTED mode enabled
+ // So we need to make sure that's off - wouldn't that be fun to debug?
+ if (bit_mask == 0x10) {
+ PORTA.PIN4CTRL &= ~(PORT_INVEN_bm);
+ } else {
+ PORTA.PIN5CTRL &= ~(PORT_INVEN_bm);
+ }
+ #endif
+
+ SREG = oldSREG;
+ }
+ #else
+ uint8_t fc_mask = (bit_mask == 0x02 ? 0x80 : 0x40);
+ if (TCD0.FAULTCTRL & fc_mask) {
+ uint8_t oldSREG = SREG;
+ cli();
+ // uint8_t TCD0_prescaler=TCD0.CTRLA&(~TCD_ENABLE_bm);
+ //
+ TCD0.CTRLA &= ~TCD_ENABLE_bm;
+ _PROTECTED_WRITE(TCD0.FAULTCTRL, TCD0.FAULTCTRL & (~fc_mask));
+ while (!(TCD0.STATUS & TCD_ENRDY_bm)); // wait until it can be re-enabled
+ TCD0.CTRLA |= TCD_ENABLE_bm; // re-enable it
+ #if defined(NO_GLITCH_TIMERD0) /* This is enabled in all cases where TCD0 is used for PWM */
+ // Assuming this mode is enabled, PWM can leave the pin with INVERTED mode enabled
+ // So we need to make sure that's off - wouldn't that be fun to debug?
+ #if defined(USE_TCD_WOAB)
+ if (bit_mask == 0x01) {
+ PORTA.PIN4CTRL &= ~(PORT_INVEN_bm);
+ } else {
+ PORTA.PIN5CTRL &= ~(PORT_INVEN_bm);
+ }
+ #elif defined(__AVR_ATTinyxy2__)
+ if (bit_mask == 0x40) {
+ PORTA.PIN6CTRL &= ~(PORT_INVEN_bm);
+ } else {
+ PORTA.PIN7CTRL &= ~(PORT_INVEN_bm);
+ }
+ #else
+ if (bit_mask == 0x01) {
+ PORTC.PIN0CTRL &= ~(PORT_INVEN_bm);
+ } else {
+ PORTC.PIN1CTRL &= ~(PORT_INVEN_bm);
+ }
+ #endif
+ #endif
+ SREG = oldSREG;
+ }
+ #endif
+ break;
+ }
+ #endif
+ // END TCD0 handling
+
+ default:
+ break;
+ }
+}
+
+void digitalWrite(uint8_t pin, uint8_t val) {
+ check_valid_digital_pin(pin);
+ /* Get bit mask for pin */
+ uint8_t bit_mask = digitalPinToBitMask(pin);
+ if (bit_mask == NOT_A_PIN) {
+ return;
+ }
+
+ /* Get port */
+ PORT_t *port = digitalPinToPortStruct(pin);
+ /* Set output to value
+ This now runs even if port set INPUT in order to emulate
+ the behavior of digitalWrite() on classic AVR devices, where
+ you could digitalWrite() a pin while it's an input, to ensure
+ that the value of the port was set correctly when it was
+ changed to an output. Code in the wild relies on this behavior. */
+
+ if (val == LOW) { /* If LOW */
+ port->OUTCLR = bit_mask;
+ } else if (val == CHANGE) { /* If TOGGLE
+ * For the pullup setting part below
+ * we need to know if it's been set high or low
+ * otherwise the pullup state could get out of
+ * sync with the output bit. Annoying! But we should
+ * have to read it before writing OUTTGL, since that can
+ * have a 1 clock delay. So read first + invert */
+ val = !(port->OUT & bit_mask);
+ port->OUTTGL = bit_mask;
+ // Now, for the pullup setting part below
+ // we need to know if it's been set high or low
+ // otherwise the pullup state could get out of
+ // sync with the output bit. Annoying!
+ val = port->OUT & bit_mask;
+ // val will now be 0 (LOW) if the toggling made it LOW
+ // or bit_mask if not. And further down, we only need to
+ // know if it's
+ /* If HIGH OR > TOGGLE */
+ } else {
+ port->OUTSET = bit_mask;
+ }
+
+ /* Input direction */
+ if (!(port->DIR & bit_mask)) {
+ /* Old implementation has side effect when pin set as input -
+ pull up is enabled if this function is called.
+ Should we purposely implement this side effect?
+ */
+
+ /* Get bit position for getting pin ctrl reg */
+ uint8_t bit_pos = digitalPinToBitPosition(pin);
+
+ /* Calculate where pin control register is */
+ volatile uint8_t *pin_ctrl_reg = getPINnCTRLregister(port, bit_pos);
+
+ /* Save system status and disable interrupts */
+ uint8_t status = SREG;
+ cli();
+
+ if (val == LOW) {
+ /* Disable pullup */
+ *pin_ctrl_reg &= ~PORT_PULLUPEN_bm;
+ } else {
+ /* Enable pull-up */
+ *pin_ctrl_reg |= PORT_PULLUPEN_bm;
+ }
+
+ /* Restore system status */
+ SREG = status;
+ }
+ /* Turn off PWM if applicable
+ * If the pin supports PWM output, we need to turn it off.
+ * Better to do so AFTER we have set PORTx.OUT to what we
+ * want it to be when we're done. The glitch would be short
+ * (though non-negligible since all these functions are, of
+ * course, slow - the worst case being a TCD pin currently
+ * analogWritten() 255, then digitallyWritten() to HIGH, which
+ * would turn it off for the time between turnOffPWM() and
+ * PORT->OUTCLR)
+ * Since there's no penalty, why make a glitch we don't have to? */
+ turnOffPWM(pin);
+}
+
+inline __attribute__((always_inline)) void digitalWriteFast(uint8_t pin, uint8_t val) {
+ check_constant_pin(pin);
+ check_valid_digital_pin(pin);
+ if (pin == NOT_A_PIN) return; // sigh... I wish I didn't have to catch this... but it's all compile time known so w/e
+ // Mega-0, Tiny-1 style IOPORTs
+ // Assumes VPORTs exist starting at 0 for each PORT structure
+ uint8_t mask = 1 << digital_pin_to_bit_position[pin];
+ uint8_t port = digital_pin_to_port[pin];
+ VPORT_t *vport;
+
+ // Write pin value from VPORTx.OUT register
+ vport = (VPORT_t *)(port * 4);
+/*
+ if (val == HIGH)
+ vport->OUT |= mask;
+ else if (val == LOW)
+ vport->OUT &= ~mask;
+ else // CHANGE
+ vport->IN = mask;
+*/
+ if (val == LOW)
+ vport->OUT &= ~mask;
+ else if (val == CHANGE)
+ vport->IN |= mask;
+ else // HIGH
+ vport->OUT |= mask;
+
+}
+
+int8_t digitalRead(uint8_t pin) {
+ check_valid_digital_pin(pin);
+ /* Get bit mask and check valid pin */
+ uint8_t bit_mask = digitalPinToBitMask(pin);
+ if (bit_mask == NOT_A_PIN) {
+ return -1;
+ }
+ // Originally the Arduino core this was derived from turned off PWM on the pin
+ // I cannot fathom why, insofar as the Arduino team sees Arduino as an educational
+ // tool, and I can't think of a better way to learn about PWM...
+ //
+ // More importantkly, digitialRead() already *crawls*. Hence there is a particularly
+ // high bar for stuff that would make it even slower than it already is.
+ //
+ // turnOffPWM(pin);
+
+ /* Get port and check valid port */
+ PORT_t *port = digitalPinToPortStruct(pin);
+
+ /* Read pin value from PORTx.IN register */
+ if (port->IN & bit_mask) {
+ return HIGH;
+ } else {
+ return LOW;
+ }
+}
+
+
+inline __attribute__((always_inline)) int8_t digitalReadFast(uint8_t pin) {
+ check_constant_pin(pin);
+ check_valid_digital_pin(pin);
+ // Mega-0, Tiny-1 style IOPORTs
+ // Assumes VPORTs exist starting at 0 for each PORT structure
+ uint8_t mask = 1 << digital_pin_to_bit_position[pin];
+ uint8_t port = digital_pin_to_port[pin];
+ VPORT_t *vport;
+
+ // Old style port logic is a small integer 0 for PORTA, 1 for PORTB etc.
+ vport = (VPORT_t *)(port * 4);
+
+ // Read pin value from VPORTx.IN register
+ return !!(vport->IN & mask);
+}
+
+
+void openDrain(uint8_t pin, uint8_t state) {
+ check_valid_digital_pin(pin);
+ uint8_t bit_mask = digitalPinToBitMask(pin);
+ if (bit_mask == NOT_A_PIN) return;
+ /* Get port */
+ PORT_t *port = digitalPinToPortStruct(pin);
+ port->OUTCLR = bit_mask;
+ if (state == LOW)
+ port->DIRSET = bit_mask;
+ else if (state == CHANGE)
+ port->DIRTGL=bit_mask;
+ else // assume FLOATING
+ port->DIRCLR=bit_mask;
+ turnOffPWM(pin);
+}
+
+inline __attribute__((always_inline)) void openDrainFast(uint8_t pin, uint8_t val)
+{
+ check_constant_pin(pin);
+ check_valid_digital_pin(pin);
+ if (pin == NOT_A_PIN) return; // sigh... I wish I didn't have to catch this... but it's all compile time known so w/e
+ // Mega-0, Tiny-1 style IOPORTs
+ // Assumes VPORTs exist starting at 0 for each PORT structure
+ uint8_t mask = 1 << digital_pin_to_bit_position[pin];
+ uint8_t port = digital_pin_to_port[pin];
+ VPORT_t *vport;
+ vport = (VPORT_t *)(port * 4);
+ PORT_t *portstr;
+ portstr = (PORT_t *)(0x400 + (0x20 * port));
+
+ if (val == LOW)
+ vport->DIR |= mask;
+ else if (val == CHANGE)
+ portstr->DIRTGL = mask;
+ else// FLOAT
+ vport->DIR &= ~mask;
+}
+
+
+inline __attribute__((always_inline)) void pinModeFast(uint8_t pin, uint8_t mode) {
+ check_constant_pin(pin);
+ if (!__builtin_constant_p(mode)) {
+ badArg("mode must be constant when used with pinModeFast");
+ } else {
+ if (mode != INPUT && mode != OUTPUT && mode != INPUT_PULLUP) { //} && mode != OUTPUT_PULLUP) {
+ badArg("The mode passed to pinModeFast must be INPUT, OUTPUT, INPUT_PULLUP");// or OUTPUT_PULLUP");
+ }
+ }
+ check_valid_digital_pin(pin); // generate compile error if a constant that is not a valid pin is used as the pin
+ uint8_t mask = 1 << digital_pin_to_bit_position[pin];
+ uint8_t port = digital_pin_to_port[pin];
+ VPORT_t *vport;
+ vport = (VPORT_t *)(port * 4);
+ volatile uint8_t *pin_ctrl = (volatile uint8_t *) (0x410 + digital_pin_to_port[pin] * 0x20 + digital_pin_to_bit_position[pin]);
+ if (mode == OUTPUT)// || mode == OUTPUT_PULLUP)
+ vport->DIR |= mask;
+ else
+ vport->DIR &= ~mask;
+ // 1 clock to set direction
+ if (mode == INPUT_PULLUP)
+ *pin_ctrl |= PORT_PULLUPEN_bm;
+ else //SK 3/16/23 - we were doing something really dumb here. You need to turn off the pullup when set to output too!
+ *pin_ctrl &= ~PORT_PULLUPEN_bm;
+ // and 5 to switch the damned pullup.
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_extra.cpp b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_extra.cpp
new file mode 100644
index 0000000..8748af5
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_extra.cpp
@@ -0,0 +1,148 @@
+/* (C) Spence Konde 2022 open source (LGPL2.1 see LICENSE.md)
+ * wiring_extra.cpp contains a few functions that are the sort of thing you'd expect in wiring.c or similar
+ * but which need to be in a cpp file because they use overloading or are just not closely related to any of
+ * those files' other functions.
+ *
+ *************************************************************/
+#include "Arduino.h"
+
+#if defined(LTODISABLED)
+ void badArg(__attribute__((unused))const char* c) {
+ return;
+ }
+ void badCall(__attribute__((unused))const char* c) {
+ return;
+ }
+#endif
+void badCore(const char*) __attribute__((error("")));
+#if !defined(LTODISABLED)
+void checkCore(uint8_t a) {
+ if (!__builtin_constant_p(a)) {
+ badCore("If LTO is disabled, you *MUST* inform the core by defining DISABLELTO.");
+ }
+}
+void _checkCore() {
+ checkCore(1);
+}
+#endif
+void __pinconfigure(const uint8_t digital_pin, uint16_t pin_config) {
+
+ uint8_t bit_mask = digitalPinToBitMask(digital_pin);
+ if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero
+ return;
+
+ uint8_t bit_pos = digitalPinToBitPosition(digital_pin);
+ volatile uint8_t *portbase = (volatile uint8_t*) digitalPinToPortStruct(digital_pin);
+
+ // Write to selected pin direction register
+ uint8_t setting = pin_config & 0x03; // Mask out direction bits (DIR, DIRSET, DIRCLR, DIRTGL)
+ if(setting)
+ *(portbase + setting) = bit_mask;
+
+ // Write to selected output register
+ pin_config >>= 2;
+ setting = pin_config & 0x03;
+ if(setting)
+ *(portbase + 4 + setting) = bit_mask;
+
+ // Return if there is nothing more to configure
+ if(!(pin_config & 0x3FFC))
+ return;
+
+ /* Now it gets to the fun part: The bits of PINnCTRL!
+ * For this we need to disable interrupts
+ * (for efficiency) we only read the register once
+ * modify that value, then write it back at the end.
+ */
+
+ uint8_t oldSREG = SREG; // Store SREG
+ cli();
+ pin_config >>= 2;
+ uint8_t pinncfg = *(portbase + 0x10 + bit_pos);
+ // Input sense configuration (ISC)
+ if(pin_config & 0x08)
+ pinncfg = (pinncfg & 0xF8) | (pin_config & PORT_ISC_gm);
+ // Pullup resistor
+ uint8_t temp = pin_config & 0x30;
+ if(temp)
+ {
+ if(temp == 0x30)
+ pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup
+ else if(temp == 0x20)
+ pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup
+ else
+ pinncfg |= PORT_PULLUPEN_bm; // Set pullup
+ }
+ // Invert pin
+ pin_config >>= 8;
+ #ifdef PORT_INLVL_bm
+ /* This feature is present on the AVR DB/DD-series, and headers suggest EA-series.
+ * See Ref_digital.md in the online documentation for more information.
+ *
+ * Set or clear only - toggle not supported.
+ * I question the usefulness of the other PINnCTRL toggles./
+ * I do not question the value of INLVL toggle: I am almost certain it is nil.
+ * If you want a toggle INLVL option, you're in an X-Y problem and are going about something
+ * sufficiently wrong that giving you what you think you need does you a disservice.
+ * If you disagree with this design decision please create an issue and explain the use case that would make this
+ * a worthwhile feature.
+ */
+ temp = pin_config & 0x03;
+ if (temp) {
+ if (temp == 0x01) {
+ pinncfg |= 0x40; // set INLVL
+ } else {
+ pinncfg &= ~(0x40); // clear INLVL
+ }
+ }
+ #endif
+ temp = pin_config & 0x0C;
+ if(temp)
+ {
+ if(temp == 0x0C)
+ pinncfg ^= PORT_INVEN_bm; // Toggle INVEN
+ else if(temp == 0x08)
+ pinncfg &= ~(PORT_INVEN_bm); // Clear INVEN
+ else
+ pinncfg |= PORT_INVEN_bm; // Set INVEN
+ }
+ // Write to PINnCTRL register
+ *(portbase + 0x10 + bit_pos) = pinncfg;
+
+ // Restore SREG
+ SREG = oldSREG;
+}
+/* Error Checking */
+void _pinconfigure(uint8_t pin, uint16_t pin_config) {
+ check_valid_digital_pin(pin);
+ #if defined(HARDWIRE_INPUT_ONLY)
+ if (__builtin_constant_p(pin) && pin == HARDWIRE_INPUT_ONLY) {
+ if (__builtin_constant_p(pin_config)) {
+ if (pin_config & 0x01) {
+ badArg("This pin cannot be set as an output because of hardware constraints on the board selected and must always be INPUT only");
+ }
+ } else {
+ if (pin_config & 0x01) {
+ pin_config = pin_config & 0xFFFC;
+ }
+ }
+ } else {
+ if (__builtin_constant_p(pin_config)) {
+ if (pin_config & 0x01) {
+ if (pin == HARDWIRE_INPUT_ONLY){
+ pin_config = pin_config & 0xFFFC;
+ }
+ }
+ } else {
+ if (pin_config & 0x01 && pin == HARDWIRE_INPUT_ONLY) {
+ pin_config = pin_config & 0xFFFC;
+ }
+ }
+ }
+ #endif
+ __pinconfigure(pin,pin_config);
+}
+/* Allow calls with manually OR'ed constants */
+void pinConfigure(uint8_t digital_pin, uint16_t pin_config) {
+ _pinconfigure(digital_pin, pin_config);
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_private.h b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_private.h
new file mode 100644
index 0000000..f8006c8
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_private.h
@@ -0,0 +1,51 @@
+/*
+ wiring_private.h - Internal header file.
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 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 WiringPrivate_h
+#define WiringPrivate_h
+
+#include
+#include
+#include
+#include
+
+
+#include "Arduino.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint8_t __PeripheralControl;
+
+uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops);
+
+typedef void (*voidFuncPtr)(void);
+
+#ifndef CORE_ATTACH_OLD
+ void __attribute__((naked)) __attribute__((noreturn)) isrBody();
+#endif
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_pulse.S b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_pulse.S
new file mode 100644
index 0000000..ffdbf11
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_pulse.S
@@ -0,0 +1,189 @@
+/*
+ wiring_pulse.s - pulseInASM() function in different flavours
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2014 Martino Facchin, 2020 Spence Konde
+
+ 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
+*/
+
+/*
+ * The following routine was generated by avr-gcc 4.8.3 with the following parameters
+ * -gstabs -Wa,-ahlmsd=output.lst -dp -fverbose-asm -O2
+ * on the original C function
+ *
+ * unsigned long pulseInSimpl(volatile uint8_t *port, uint8_t bit, uint8_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;
+ * }
+ *
+ * some compiler outputs were removed but the rest of the code is untouched
+ *
+ * Spence feb 2020: not untouched anymore! The first two loops ran in 11 cycles instead
+ * of 16, so if no pulse was detected, the timeout would be reached when
+ * 11/16ths of the requested timeout had elapsed. This was fixed by the addition
+ * of 2 rjmps to the next line (a 2 cycle nop that uses only 1 word) and 1 nop
+ * to each of these loops before they decrement maxloops.
+ * Additionally, removed duplication of return sequence to save 12b flash
+ * which is conveniently exactly how much the other fix cost.
+ */
+
+#include
+
+.section .text
+
+.global countPulseASM
+
+countPulseASM:
+
+.LM0:
+.LFBB1:
+ push r12 ; ; 130 pushqi1/1 [length = 1]
+ push r13 ; ; 131 pushqi1/1 [length = 1]
+ push r14 ; ; 132 pushqi1/1 [length = 1]
+ push r15 ; ; 133 pushqi1/1 [length = 1]
+ push r16 ; ; 134 pushqi1/1 [length = 1]
+ push r17 ; ; 135 pushqi1/1 [length = 1]
+/* prologue: function */
+/* frame size = 0 */
+/* stack size = 6 */
+.L__stack_usage = 6
+ mov r30,r24 ; port, port ; 2 *movhi/1 [length = 2]
+ mov r31,r25 ; port, port
+/* unsigned long width = 0;
+*** // wait for any previous pulse to end
+*** while ((*port & bit) == stateMask)
+*/
+.LM1:
+ rjmp .L2 ; ; 181 jump [length = 1]
+.L4:
+/* if (--maxloops == 0) */
+.LM2:
+ rjmp .LM2A ; waste an extra 5 cycles
+.LM2A:
+ rjmp .LM2B ;
+.LM2B:
+ nop ;
+ subi r16,1 ; maxloops, ; 17 addsi3/2 [length = 4]
+ sbc r17, r1 ; maxloops
+ sbc r18, r1 ; maxloops
+ sbc r19, r1 ; maxloops
+ breq .L13 ; , ; 19 branch [length = 1]
+.L2:
+/* if (--maxloops == 0) */
+.LM3:
+ ld r25,Z ; D.1554, *port_7(D) ; 22 movqi_insn/4 [length = 1]
+ and r25,r22 ; D.1554, bit ; 24 andqi3/1 [length = 1]
+ cp r25,r20 ; D.1554, stateMask ; 25 *cmpqi/2 [length = 1]
+ breq .L4 ; , ; 26 branch [length = 1]
+ rjmp .L6 ; ; 184 jump [length = 1]
+.L7:
+/* return 0;
+***
+*** // wait for the pulse to start
+*** while ((*port & bit) != stateMask)
+*** if (--maxloops == 0)
+*/
+.LM4:
+ rjmp .LM4A ; waste an extra 5 cycles
+.LM4A:
+ rjmp .LM4B ;
+.LM4B:
+ nop ;
+ subi r16,1 ; maxloops, ; 31 addsi3/2 [length = 4]
+ sbc r17, r1 ; maxloops
+ sbc r18, r1 ; maxloops
+ sbc r19, r1 ; maxloops
+ breq .L13 ; , ; 33 branch [length = 1]
+.L6:
+/* if (--maxloops == 0) */
+.LM5:
+ ld r25,Z ; D.1554, *port_7(D) ; 41 movqi_insn/4 [length = 1]
+ and r25,r22 ; D.1554, bit ; 43 andqi3/1 [length = 1]
+ cpse r25,r20 ; D.1554, stateMask ; 44 enable_interrupt-3 [length = 1]
+ rjmp .L7 ;
+ mov r12, r1 ; width ; 7 *movsi/2 [length = 4]
+ mov r13, r1 ; width
+ mov r14, r1 ; width
+ mov r15, r1 ; width
+ rjmp .L9 ; ; 186 jump [length = 1]
+.L10:
+/* return 0;
+***
+*** // wait for the pulse to stop
+*** while ((*port & bit) == stateMask) {
+*** if (++width == maxloops)
+*/
+.LM6:
+ ldi r24,-1 ; , ; 50 addsi3/3 [length = 5]
+ sub r12,r24 ; width,
+ sbc r13,r24 ; width,
+ sbc r14,r24 ; width,
+ sbc r15,r24 ; width,
+ cp r16,r12 ; maxloops, width ; 51 *cmpsi/2 [length = 4]
+ cpc r17,r13 ; maxloops, width
+ cpc r18,r14 ; maxloops, width
+ cpc r19,r15 ; maxloops, width
+ breq .L13 ; , ; 52 branch [length = 1]
+.L9:
+/* if (++width == maxloops) */
+.LM7:
+ ld r24,Z ; D.1554, *port_7(D) ; 60 movqi_insn/4 [length = 1]
+ and r24,r22 ; D.1554, bit ; 62 andqi3/1 [length = 1]
+ cp r24,r20 ; D.1554, stateMask ; 63 *cmpqi/2 [length = 1]
+ breq .L10 ; , ; 64 branch [length = 1]
+/* return 0;
+*** }
+*** return width;
+*/
+.LM8:
+ mov r22,r12 ; D.1553, width ; 108 movqi_insn/1 [length = 1]
+ mov r23,r13 ; D.1553, width ; 109 movqi_insn/1 [length = 1]
+ mov r24,r14 ; D.1553, width ; 110 movqi_insn/1 [length = 1]
+ mov r25,r15 ; D.1553, width ; 111 movqi_insn/1 [length = 1]
+ rjmp .LM11 ;
+/* epilogue start */
+.L13:
+.LM10:
+ ldi r22,0 ; D.1553 ; 120 movqi_insn/1 [length = 1]
+ ldi r23,0 ; D.1553 ; 121 movqi_insn/1 [length = 1]
+ ldi r24,0 ; D.1553 ; 122 movqi_insn/1 [length = 1]
+ ldi r25,0 ; D.1553 ; 123 movqi_insn/1 [length = 1]
+/* epilogue start */
+.LM11:
+ pop r17 ; ; 138 popqi [length = 1]
+ pop r16 ; ; 139 popqi [length = 1]
+ pop r15 ; ; 140 popqi [length = 1]
+ pop r14 ; ; 141 popqi [length = 1]
+ pop r13 ; ; 142 popqi [length = 1]
+ pop r12 ; ; 143 popqi [length = 1]
+ ret ; 144 return_from_epilogue [length = 1]
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_pulse.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_pulse.c
new file mode 100644
index 0000000..9a4b94c
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_pulse.c
@@ -0,0 +1,99 @@
+/*
+ wiring_pulse.c - pulseIn() function
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 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
+*/
+
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+/* 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.
+ *
+ * This function performs better with short pulses in noInterrupt() context
+ */
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long 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.
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+ uint8_t stateMask = (state ? bit : 0);
+
+ // convert the timeout from microseconds to a number of times through
+ // the initial loop; it takes approximately 16 clock cycles per iteration
+ unsigned long maxloops = (uint32_t)microsecondsToClockCycles(timeout) / 16;
+
+ unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops);
+
+ // prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out
+ if (width) {
+ return clockCyclesToMicroseconds(width * 16 + 16);
+ } else {
+ return 0;
+ }
+}
+
+#if !(defined(DISABLEMILLIS) || defined(MILLIS_USE_TIMERRTC)|| defined(MILLIS_USE_TIMERRT_XTAL))
+/* 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.
+ *
+ * ATTENTION:
+ * this function relies on micros() so cannot be used in noInterrupt() context
+ */
+unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long 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.
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+ uint8_t stateMask = (state ? bit : 0);
+
+ unsigned long startMicros = micros();
+
+ // wait for any previous pulse to end
+ while ((*portInputRegister(port) & bit) == stateMask) {
+ if (micros() - startMicros > timeout) {
+ return 0;
+ }
+ }
+
+ // wait for the pulse to start
+ while ((*portInputRegister(port) & bit) != stateMask) {
+ if (micros() - startMicros > timeout) {
+ return 0;
+ }
+ }
+
+ unsigned long start = micros();
+ // wait for the pulse to stop
+ while ((*portInputRegister(port) & bit) == stateMask) {
+ if (micros() - startMicros > timeout) {
+ return 0;
+ }
+ }
+ return micros() - start;
+}
+#endif
diff --git a/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_shift.c b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_shift.c
new file mode 100644
index 0000000..04c2c71
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/megatinycore/wiring_shift.c
@@ -0,0 +1,84 @@
+/*
+ wiring_shift.c - shiftOut() function
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 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
+*/
+
+#include
+/*
+ These turn out to be slower and less flash efficient than this imlpementation.
+ Note that faster implementations are possible (MUCH faster, such that they might
+ cause compatibility problems because they're too fast) See #197
+
+ uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
+ uint8_t value = 0;
+ uint8_t i;
+
+ for (i = 0; i < 8; ++i) {
+ digitalWrite(clockPin, HIGH);
+ if (bitOrder == LSBFIRST)
+ value |= digitalRead(dataPin) << i;
+ else
+ value |= digitalRead(dataPin) << (7 - i);
+ digitalWrite(clockPin, LOW);
+ }
+ return value;
+ }
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
+{
+ uint8_t i;
+
+ for (i = 0; i < 8; i++) {
+ if (bitOrder == LSBFIRST)
+ digitalWrite(dataPin, !!(val & (1 << i)));
+ else
+ digitalWrite(dataPin, !!(val & (1 << (7 - i))));
+
+ digitalWrite(clockPin, HIGH);
+ digitalWrite(clockPin, LOW);
+ }
+ }
+*/
+uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
+ uint8_t val = 0;
+ for (uint8_t i = 0; i != 8; i++) {
+ digitalWrite(clockPin, HIGH);
+ if (bitOrder == LSBFIRST) {
+ val = (val >> 1) | (digitalRead(dataPin) << 7);
+ } else {
+ val = (val << 1) | digitalRead(dataPin);
+ }
+ digitalWrite(clockPin, LOW);
+ }
+ return val;
+}
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) {
+ for (uint8_t i = 0; i != 8; i++) {
+ if (bitOrder == LSBFIRST) {
+ digitalWrite(dataPin, val & 0x01), val >>= 1;
+ } else {
+ digitalWrite(dataPin, !!(val & 0x80)), val <<= 1;
+ }
+
+ digitalWrite(clockPin, HIGH);
+ digitalWrite(clockPin, LOW);
+ }
+}
diff --git a/fw/HackSpaceCon_AS7/Arduino/variants/txy2/pins_arduino.h b/fw/HackSpaceCon_AS7/Arduino/variants/txy2/pins_arduino.h
new file mode 100644
index 0000000..7a9a478
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/Arduino/variants/txy2/pins_arduino.h
@@ -0,0 +1,222 @@
+/*
+ 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
+#include "timers.h"
+
+#define NUM_DIGITAL_PINS (6) //
+#define NUM_ANALOG_INPUTS (9)
+#define NUM_I2C_PINS (2) // (SDA / SCL)
+#define NUM_SPI_PINS (3) // (MISO / MOSI / SCK)
+#define NUM_TOTAL_FREE_PINS (NUM_DIGITAL_PINS)
+#define NUM_TOTAL_PINS (6)
+#define EXTERNAL_NUM_INTERRUPTS (8)
+#define PINS_COUNT (6)
+
+#define PIN_PA6 (0)
+#define PIN_PA7 (1)
+#define PIN_PA1 (2)
+#define PIN_PA2 (3)
+#define PIN_PA3 (4)
+#define PIN_PA0 (5)
+
+#define digitalPinHasPWM(p) ((p) != 0 && (p) != 5)
+
+#ifdef DAC0
+ #define DAC_PIN (PIN_PA6)
+#endif
+
+#ifndef LED_BUILTIN
+ #define LED_BUILTIN (PIN_PA3)
+#endif
+
+/*
+ #### ### #### ##### # # # # # #
+ # # # # # # # ## ## # # # #
+ #### # # #### # # # # # # #
+ # # # # # # # # # # # #
+ # ### # # # # # ### # #
+*/
+
+#ifdef PORTMUX_SPI0_bm
+ #define PIN_SPI_MISO_PINSWAP_1 (PIN_PA7)
+ #define PIN_SPI_SCK_PINSWAP_1 (PIN_PA3)
+ #define PIN_SPI_MOSI_PINSWAP_1 (PIN_PA6)
+ #define PIN_SPI_SS_PINSWAP_1 (PIN_PA6)
+#endif
+#define PIN_SPI_MISO (PIN_PA2)
+#define PIN_SPI_SCK (PIN_PA3)
+#define PIN_SPI_MOSI (PIN_PA1)
+#define PIN_SPI_SS (PIN_PA6)
+
+#define SPI_INTERFACES_COUNT (1)
+
+#define PIN_WIRE_SDA (PIN_PA1)
+#define PIN_WIRE_SCL (PIN_PA2)
+
+/* Serial pin values here are not used by the core. They don't get picked up correctly in UART.h where they're needed and I can't figure out why. */
+// Serial (USART0)
+#define HWSERIAL0_MUX_DEFAULT (0)
+#define PIN_HWSERIAL0_RX (PIN_PA7)
+#define PIN_HWSERIAL0_TX (PIN_PA6)
+#define PIN_HWSERIAL0_XCK (PIN_PA3)
+#define PIN_HWSERIAL0_XDIR (PIN_PA0)
+#define PIN_HWSERIAL0_RX_PINSWAP_1 (PIN_PA2)
+#define PIN_HWSERIAL0_TX_PINSWAP_1 (PIN_PA1)
+// Alt pins don't include the rarely used functions on 8-pin parts.
+#define PIN_HWSERIAL0_XCK_PINSWAP_1 (NOT_A_PIN)
+#define PIN_HWSERIAL0_XDIR_PINSWAP_1 (NOT_A_PIN)
+
+/*
+ ## # # ## # ### ### #### ### # # ###
+ # # ## # # # # # # # # # # ## # #
+ #### # # # #### # # # # ## #### # # # # ###
+ # # # ## # # # # # # # # # # ## #
+ # # # # # # #### ### ### # ### # # ###
+*/
+
+#define PIN_A0 (A0)
+#define PIN_A1 (A1)
+#define PIN_A2 (A2)
+#define PIN_A3 (A3)
+#define PIN_A6 (A6)
+#define PIN_A7 (A7)
+
+static const uint8_t A0 = PIN_PA0;
+static const uint8_t A1 = PIN_PA1;
+static const uint8_t A2 = PIN_PA2;
+static const uint8_t A3 = PIN_PA3;
+static const uint8_t A6 = PIN_PA6;
+static const uint8_t A7 = PIN_PA7;
+
+
+/*
+ #### ### # # ## #### #### ## # # ###
+ # # # ## # # # # # # # # # # # #
+ #### # # # # #### #### #### #### # ###
+ # # # ## # # # # # # # # # #
+ # ### # # # # # # # # # # # ###
+*/
+
+#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.
+
+// ATtiny412 / ARDUINO
+// _____
+// VDD 1|* |20 GND
+// (DAC) (AIN6) PA6 0 2| |19 4~ PA3 (AIN3)(SCK)(EXTCLK)
+// (AIN7) PA7 1 3| |18 5 PA0 (nRESET/UPDI)
+// (MOSI)(TXD*)(SDA) (AIN1) PA1 2 4|_____|17 3 PA2 (AIN2)(MISO)(RXD*)(SCL)
+//
+//
+
+/*
+ PIN# DESC Pin Name Other/Sp ADC0 ADC1 PTC AC0 AC1 AC2 DAC0 USART0 SPI0 TWI0 TCA(PWM) TCBn TCD0 CCL
+ 0 A2 or DAC PA6 AIN6 AIN2 X2/Y2 AINN0 AINP1 AINP0 OUT RxD WOA
+ 1 A3 PA7 AIN7 AIN3 X3/Y3 AINP0 AINP0 AINN0 TxD *WO0 WOB LUT1-OUT
+ 2 MOSI PA1 AIN1 *TxD MOSI SDA WO1 LUT0-IN1
+ 3 MISO PA2 EVOUT0 AIN2 *RxD MISO SCL WO2 LUT0-IN2
+ 4 SCK PA3 EXTCLK AIN3 *XCK SCK WO3 TCB1 WO
+ 5 UPDI PA0 RESET/ AIN0 LUT1-IN0
+ UPDI
+*/
+
+const uint8_t digital_pin_to_port[] = {
+ PA, // 0 PA6
+ PA, // 1 PA7
+ PA, // 2 PA1
+ PA, // 3 PA2
+ PA, // 4 PA3
+ PA // 5 PA0
+};
+
+/* Use this for accessing PINnCTRL register */
+const uint8_t digital_pin_to_bit_position[] = {
+ PIN6_bp, // 0 PA6
+ PIN7_bp, // 1 PA7
+ PIN1_bp, // 2 PA1
+ PIN2_bp, // 3 PA2
+ PIN3_bp, // 4 PA3
+ PIN0_bp // 5 PA0
+};
+
+/* Use this for accessing PINnCTRL register */
+const uint8_t digital_pin_to_bit_mask[] = {
+ PIN6_bm, // 0 PA6
+ PIN7_bm, // 1 PA7
+ PIN1_bm, // 2 PA1
+ PIN2_bm, // 3 PA2
+ PIN3_bm, // 4 PA3
+ PIN0_bm // 5 PA0
+};
+//*INDENT-OFF*
+const uint8_t digital_pin_to_timer[] = {
+ #if defined(DAC0) && !(defined(USE_TIMERD0_PWM) && defined(TCD0))
+ DACOUT, // 0 PA6
+ #elif defined(USE_TIMERD0_PWM) && defined(TCD0)
+ TIMERD0,
+ #else
+ NOT_ON_TIMER, // 0 PA6
+ #endif
+ #if defined(_TCA_ALT_WO0)
+ TIMERA0, // 1 PA7
+ #elif defined(USE_TIMERD0_PWM)
+ TIMERD0,
+ #endif
+ TIMERA0, // 2 PA1
+ TIMERA0, // 3 PA2
+ TIMERA0, // 4 PA3
+ NOT_ON_TIMER // 5 PA0
+};
+//*INDENT-ON*
+
+
+#endif
+
+#define digitalPinToAnalogInput(p) ((p<2)?(p+6):(p<5?(p-1):(p==5?0:NOT_A_PIN)))
+
+
+// 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/fw/HackSpaceCon_AS7/HSC_Wand/HSC_Wand.componentinfo.xml b/fw/HackSpaceCon_AS7/HSC_Wand/HSC_Wand.componentinfo.xml
new file mode 100644
index 0000000..2ad98d7
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/HSC_Wand.componentinfo.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ Device
+ Startup
+
+
+ Atmel
+ 1.10.0
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs
+
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\include\
+
+ include
+ C
+
+
+ include/
+
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\include\avr\iotn402.h
+
+ header
+ C
+ g0XngzH9uwBI0kp8K6DswA==
+
+ include/avr/iotn402.h
+
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\templates\main.c
+ template
+ source
+ C Exe
+ KjvOcFWd++tbnsEMfVPd/w==
+
+ templates/main.c
+ Main file (.c)
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\templates\main.cpp
+ template
+ source
+ C Exe
+ uK6xwpZG+RPPFiJUJnueCQ==
+
+ templates/main.cpp
+ Main file (.cpp)
+
+
+
+ C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402
+
+ libraryPrefix
+ GCC
+
+
+ gcc/dev/attiny402
+
+
+
+
+ ATtiny_DFP
+ C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATtiny_DFP/1.10.348/Atmel.ATtiny_DFP.pdsc
+ 1.10.348
+ true
+ ATtiny402
+
+
+
+ Resolved
+ Fixed
+ true
+
+
+
\ No newline at end of file
diff --git a/fw/HackSpaceCon_AS7/HSC_Wand/HSC_Wand.cppproj b/fw/HackSpaceCon_AS7/HSC_Wand/HSC_Wand.cppproj
new file mode 100644
index 0000000..b76eb21
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/HSC_Wand.cppproj
@@ -0,0 +1,226 @@
+
+
+
+ 2.0
+ 7.0
+ com.Atmel.AVRGCC8.CPP
+ dce6c7e3-ee26-4d79-826b-08594b9ad897
+ ATtiny402
+ none
+ Executable
+ CPP
+ $(MSBuildProjectName)
+ .elf
+ $(MSBuildProjectDirectory)\$(Configuration)
+ HackSpaceCon_AS7
+ HSC_Wand
+ HackSpaceCon_AS7
+ Native
+ true
+ false
+ true
+ true
+ 0x20000000
+
+ true
+ exception_table
+ 2
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -mmcu=attiny402 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402"
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+
+
+ NDEBUG
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+ ..\include\libraries\EEPROM\src
+ ..\include\libraries\Event\src
+ ..\include\libraries\Logic\src
+ ..\include\libraries\megaTinyCore\examples\TuningSource
+ ..\include\libraries\megaTinyCore\src
+ ..\include\libraries\SoftwareSerial\src
+ ..\include\libraries\SPI\src
+ ..\include\libraries\tinyNeoPixel
+ ..\include\libraries\tinyNeoPixel_Static
+ ..\include\libraries\Wire\src
+
+
+ Optimize for size (-Os)
+ True
+ True
+ True
+ True
+ True
+
+
+ NDEBUG
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+ ..\include\libraries\EEPROM\src
+ ..\include\libraries\Event\src
+ ..\include\libraries\Logic\src
+ ..\include\libraries\megaTinyCore\examples\TuningSource
+ ..\include\libraries\megaTinyCore\src
+ ..\include\libraries\SoftwareSerial\src
+ ..\include\libraries\SPI\src
+ ..\include\libraries\tinyNeoPixel
+ ..\include\libraries\tinyNeoPixel_Static
+ ..\include\libraries\Wire\src
+
+
+ Optimize for size (-Os)
+ True
+ True
+ True
+
+
+ libm
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+
+
+
+
+
+
+
+
+ -mmcu=attiny402 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402"
+ True
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+
+
+ DEBUG
+ ARDUINO=108019
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+ ../../Arduino/megatinycore
+ ../../Arduino/variants/txy2
+
+
+ Optimize for size (-Os)
+ True
+ True
+ Default (-g2)
+ True
+ -std=gnu11
+ True
+ True
+
+
+ DEBUG
+ ARDUINO=108019
+ ARDUINO_AVR_ATtinyxy4
+ ARDUINO_attinyxy4
+ F_CPU=8000000UL
+ MEGATINYCORE="2.6.10"
+ MEGATINYCORE_MAJOR=2UL
+ MEGATINYCORE_MINOR=6UL
+ MEGATINYCORE_PATCH=10UL
+ MEGATINYCORE_RELEASED=1
+ MILLIS_USE_TIMERA0
+ CLOCK_SOURCE=0
+ TWI_MORS
+
+
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+ ../../Arduino/megatinycore
+ ../../Arduino/variants/txy2
+ ../../Arduino/arduino_libraries/tinyNeoPixel_static
+
+
+ Optimize for size (-Os)
+ -flto -fno-threadsafe-statics
+ True
+ True
+ Default (-g2)
+ True
+ -std=gnu++17
+
+
+ libm
+
+
+ -Os -fuse-linker-plugin
+
+
+ %24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\
+
+
+ Default (-Wa,-g)
+
+
+
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+
+
+ Arduino
+ {47694d30-4990-4f03-a1f7-e94eb79783f0}
+ True
+
+
+
+
\ No newline at end of file
diff --git a/fw/HackSpaceCon_AS7/HSC_Wand/hsv2rgb.cpp b/fw/HackSpaceCon_AS7/HSC_Wand/hsv2rgb.cpp
new file mode 100644
index 0000000..15820f6
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/hsv2rgb.cpp
@@ -0,0 +1,177 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 B. Stultiens
+ * modified by true for 12-bit values
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+ #include "hsv2rgb.h"
+
+
+ /*
+ void hsv2rgb_8b(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b)
+ {
+ uint8_t sextant;
+ uint8_t bb;
+ uint16_t ww;
+ uint8_t h_fraction;
+
+ if (!(s)) {
+ *(r) = *(g) = *(b) = (v);
+ return;
+ }
+
+ sextant = h >> 8;
+ HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space
+
+ HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in
+
+ *g = v; // Top level
+
+ // Perform actual calculations
+
+ // Bottom level: v * (1.0 - s)
+ // --> (v * (255 - s) + error_corr) / 256
+
+ bb = ~s;
+ ww = v * bb;
+ ww += 1; // Error correction
+ ww += ww >> 8; // Error correction
+ *b = ww >> 8;
+
+ h_fraction = h & 0xff; // 0...255
+
+ if(!(sextant & 1)) {
+ // *r = ...slope_up...;
+
+ // Slope up: v * (1.0 - s * (1.0 - h))
+ // --> (v * (255 - (s * (256 - h) + error_corr1) / 256) + error_corr2) / 256
+
+ ww = !h_fraction ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_fraction));
+ ww += ww >> 8; // Error correction 1
+ bb = ww >> 8;
+ bb = ~bb;
+ ww = v * bb;
+ ww += v >> 1; // Error correction 2
+ *r = ww >> 8;
+ } else {
+ // *r = ...slope_down...;
+
+ // Slope down: v * (1.0 - s * h)
+ // --> (v * (255 - (s * h + error_corr1) / 256) + error_corr2) / 256
+
+ ww = s * h_fraction;
+ ww += ww >> 8; // Error correction 1
+ bb = ww >> 8;
+ bb = ~bb;
+ ww = v * bb;
+ ww += v >> 1; // Error correction 2
+ *r = ww >> 8;
+
+ // A perfect match for h_fraction == 0 implies:
+ // *r = (ww >> 8) + (h_fraction ? 0 : 1)
+ // However, this is an extra calculation that may not be required.
+ }
+ }
+ */
+
+ void hsv2rgb_32b_8(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b)
+ {
+ HSV_MONOCHROMATIC_TEST(s, v, r, g, b); // Exit with grayscale if s == 0
+
+ uint8_t sextant = h >> 8;
+
+ HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space
+
+ HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in
+
+ *g = v; // Top level
+
+ // Perform actual calculations
+
+ // Bottom level: v * (1.0 - s)
+ // --> (v * (255 - s) + error_corr + 1) / 256
+
+ uint16_t ww; // Intermediate result
+ ww = v * (255 - s); // We don't use ~s to prevent size-promotion side effects
+ ww += 1; // Error correction
+ ww += ww >> 8; // Error correction
+ *b = ww >> 8;
+
+ uint8_t h_fraction = h & 0xff; // 0...255
+ uint32_t d; // Intermediate result
+
+ if(!(sextant & 1)) {
+ // *r = ...slope_up...;
+ d = v * (uint32_t)((255 << 8) - (uint16_t)(s * (256 - h_fraction)));
+ d += d >> 8; // Error correction
+ d += v; // Error correction
+ *r = d >> 16;
+ } else {
+ // *r = ...slope_down...;
+ d = v * (uint32_t)((255 << 8) - (uint16_t)(s * h_fraction));
+ d += d >> 8; // Error correction
+ d += v; // Error correction
+ *r = d >> 16;
+ }
+ }
+
+ /*
+ void hsv2rgb_32b_16(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b)
+ {
+ HSV_MONOCHROMATIC_TEST(s, v, r, g, b); // Exit with grayscale if s == 0
+
+ uint8_t sextant = h >> 8;
+
+ HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space
+
+ HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in
+
+ *g = v; // Top level
+
+ // Bottom level: v * (1.0 - s)
+ // --> (v * (255 - s) + error_corr + 1) / 256
+
+ uint16_t ww; // Intermediate result
+ ww = v * (255 - s); // We don't use ~s to prevent size-promotion side effects
+ ww += 1; // Error correction
+ ww += ww >> 8; // Error correction
+ *b = ww >> 8;
+
+ uint8_t h_fraction = h & 0xff; // 0...255
+ uint32_t d; // Intermediate result
+
+ if(!(sextant & 1)) {
+ // *r = ...slope_up...;
+ d = v * (uint32_t)((255 << 8) - (uint16_t)(s * (256 - h_fraction)));
+ d += d >> 8; // Error correction
+ d += v; // Error correction
+ *r = d >> 16;
+ } else {
+ // *r = ...slope_down...;
+ d = v * (uint32_t)((255 << 8) - (uint16_t)(s * h_fraction));
+ d += d >> 8; // Error correction
+ d += v; // Error correction
+ *r = d >> 16;
+ }
+ }
+ */
+
\ No newline at end of file
diff --git a/fw/HackSpaceCon_AS7/HSC_Wand/hsv2rgb.h b/fw/HackSpaceCon_AS7/HSC_Wand/hsv2rgb.h
new file mode 100644
index 0000000..0ee6963
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/hsv2rgb.h
@@ -0,0 +1,132 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 B. Stultiens
+ *
+ * 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 __HSV2RGB_H__
+#define __HSV2RGB_H__
+
+#include
+
+
+typedef struct color_rgb {
+ uint16_t r;
+ uint16_t g;
+ uint16_t b;
+} color_rgb;
+
+typedef struct color_hsv {
+ uint16_t h;
+ uint16_t s;
+ uint16_t v;
+} color_hsv;
+
+
+#define HSV2RGB_BITS 8 // 10
+#define HSV2RGB_COUNT ((1 < HSV2RGB_BITS)-1)
+
+#define HSV_HUE_SEXTANT (1 << HSV2RGB_BITS)
+#define HSV_HUE_STEPS (6 * HSV_HUE_SEXTANT)
+
+#define HSV_HUE_MIN 0
+#define HSV_HUE_MAX (HSV_HUE_STEPS - 1)
+#define HSV_SAT_MIN 0
+#define HSV_SAT_MAX 255
+#define HSV_VAL_MIN 0
+#define HSV_VAL_MAX 255
+
+/* Options: */
+#define HSV_USE_SEXTANT_TEST /* Limit the hue to 0...360 degrees */
+
+#define hsv2rgb(h,s,v,r,g,b) hsv2rgb_32b_8(h,s,v,r,g,b)
+
+
+//void hsv2rgb_8b(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b);
+void hsv2rgb_32b_8(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b);
+//void hsv2rgb_32b_16(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b);
+
+
+
+/*
+ * Macros that are common to all implementations
+ */
+#ifdef HSV_USE_SEXTANT_TEST
+#define HSV_SEXTANT_TEST(sextant) \
+ if((sextant) > 5) { \
+ (sextant) = 5; \
+ }
+
+#else
+#define HSV_SEXTANT_TEST(sextant)
+#endif
+
+/*
+ * Pointer swapping:
+ * sext. r g b r<>b g<>b r <> g result
+ * 0 0 0 v u c !u v c u v c
+ * 0 0 1 d v c d v c
+ * 0 1 0 c v u u v c u v c
+ * 0 1 1 c d v v d c d v c d v c
+ * 1 0 0 u c v u v c u v c
+ * 1 0 1 v c d v d c d v c d v c
+ *
+ * if(sextant & 2)
+ * r <-> b
+ *
+ * if(sextant & 4)
+ * g <-> b
+ *
+ * if(!(sextant & 6) {
+ * if(!(sextant & 1))
+ * r <-> g
+ * } else {
+ * if(sextant & 1)
+ * r <-> g
+ * }
+ */
+#define HSV_SWAPPTR(a,b) do { uint8_t *tmp = (a); (a) = (b); (b) = tmp; } while(0)
+//#define HSV_SWAPPTR(a,b) do { uint16_t *tmp = (a); (a) = (b); (b) = tmp; } while(0)
+#define HSV_POINTER_SWAP(sextant,r,g,b) \
+ do { \
+ if((sextant) & 2) { \
+ HSV_SWAPPTR((r), (b)); \
+ } \
+ if((sextant) & 4) { \
+ HSV_SWAPPTR((g), (b)); \
+ } \
+ if(!((sextant) & 6)) { \
+ if(!((sextant) & 1)) { \
+ HSV_SWAPPTR((r), (g)); \
+ } \
+ } else { \
+ if((sextant) & 1) { \
+ HSV_SWAPPTR((r), (g)); \
+ } \
+ } \
+ } while(0)
+#define HSV_MONOCHROMATIC_TEST(s,v,r,g,b) \
+ do { \
+ if(!(s)) { \
+ *(r) = *(g) = *(b) = (v); \
+ return; \
+ } \
+ } while(0)
+#endif
diff --git a/fw/HackSpaceCon_AS7/HSC_Wand/isr.cpp b/fw/HackSpaceCon_AS7/HSC_Wand/isr.cpp
new file mode 100644
index 0000000..ec4bd66
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/isr.cpp
@@ -0,0 +1,43 @@
+/*
+ hackspacecon wand firmware
+
+ interrupt routines
+
+*/
+
+#include
+
+#include "rgbled.h"
+
+extern uint8_t run_rgbprog;
+
+
+// TCB0 general interrupt
+ISR(TCB0_INT_vect)
+{
+ uint8_t intflags = TCB0.INTFLAGS;
+
+ // in this program, this interrupt is only used for timing.
+ // we'll now return to executing loop()
+
+ // reset the INTFLAGS - necessary on this series
+ TCB0.INTFLAGS = intflags;
+}
+
+// button interrupt
+ISR(PORTA_PORT_vect)
+{
+ uint8_t intflags = PORTA.INTFLAGS;
+
+ // shitty debounce; this is bad practice
+ delay(5);
+
+ // was our pin changed?
+ if (intflags & PIN3_bm) {
+ // start or re-start running a program
+ run_rgbprog = 1; // run a new program
+ }
+
+ // reset the INTFLAGS - necessary on this series
+ PORTA.INTFLAGS = intflags;
+}
diff --git a/fw/HackSpaceCon_AS7/HSC_Wand/rgbled.cpp b/fw/HackSpaceCon_AS7/HSC_Wand/rgbled.cpp
new file mode 100644
index 0000000..05b183b
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/rgbled.cpp
@@ -0,0 +1,146 @@
+/*
+ hackspacecon wand firmware
+
+ rgb led control and programs
+*/
+
+#include
+#include "rgbled.h"
+
+#include "hsv2rgb.h"
+
+
+
+tinyNeoPixel rgb = tinyNeoPixel(RGB_COUNT, PIN_PA1, NEO_GRB, rgbled);
+
+
+
+// rgb program prototypes
+uint8_t rgbp_rainbow(uint8_t init);
+uint8_t rgbp_circlefade(uint8_t init);
+
+// rgb program function pointer array
+uint8_t (*rgb_program[PROG_COUNT])(uint8_t) = {
+ rgbp_rainbow,
+ rgbp_circlefade
+};
+
+
+
+uint8_t rgbled[3 * RGB_COUNT];
+
+
+// configures and enables the 50Hz timer interrupt that is used for RGB program updates
+void conf_rgb_timer()
+{
+ // this timer will run at half speed.
+ // so 8MHz / 2 (prescale) / 1 (CLK_PER) = 4MHz
+ // this will allow a full cycle time of ~61Hz.
+
+ _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0); // disable CLK_PER divider
+
+ disable_rgb_timer();
+
+ TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc; // prescale timer to run at half speed
+ TCB0.CCMP = 0xffff; // count to full
+ TCB0.CNT = 0;
+}
+
+
+// globals for all rgb programs
+uint16_t prog_timeout;
+uint16_t hue;
+uint8_t r, g, b;
+
+
+// rgb program 0: rainbow puke
+#define RAINBOW_HUE_INC 40 // how much to increment the hue every frame
+#define RAINBOW_OFFSET (1536/5) // offset between each LED
+#define RAINBOW_TIMEOUT 240 // how long to show this program
+#define RAINBOW_SAT 0xff // saturation
+#define RAINBOW_VAL 0x40 // value (brightness); keep low enough to keep average current down
+
+uint16_t rainbow_hue = 0;
+
+uint8_t rgbp_rainbow(uint8_t init)
+{
+ uint8_t i;
+
+ // set our timer when initializing. otherwise every call is identical
+ if (init) {
+ prog_timeout = RAINBOW_TIMEOUT;
+ }
+
+ if (--prog_timeout) {
+ // copy stored hue to working hue
+ hue = rainbow_hue;
+
+ for (i = 0; i < RGB_COUNT; i++) {
+ // each LED will increment its hue
+ hue += RAINBOW_OFFSET;
+
+ // hue wheel is 256*6 large, so bound the value
+ if (hue >= 1536) hue -= 1536;
+
+ // compute rgb from hue/sat/value
+ hsv2rgb(hue, RAINBOW_SAT, RAINBOW_VAL, &r, &g, &b);
+
+ // apply it to this LED
+ rgb.setPixelColor(i, r, g, b);
+ }
+
+ // increment stored hue wheel for the next cycle through the program
+ rainbow_hue += RAINBOW_HUE_INC;
+ if (rainbow_hue > 1536) rainbow_hue -= 1536;
+
+ return 1;
+ }
+
+ // done with program
+ return 0;
+}
+
+
+// rgb program 2: circle loops with fading
+#define CF_TIMEOUT 90 // how long to show this program (max 255, ideally (20*loopcount)+10)
+#define CF_BRIGHTNESS 64 // how bright to make the LED. don't make too bright or badge will brown out
+#define CF_FADERATE 12 // how much to fade all LEDs each frame
+
+uint8_t circlefade_idx = 0;
+
+uint8_t rgbp_circlefade(uint8_t init)
+{
+ uint8_t i;
+ uint8_t t;
+
+ // set our timer when initializing. otherwise every call is identical
+ if (init) {
+ prog_timeout = CF_TIMEOUT;
+ circlefade_idx = 4; // top LED
+ }
+
+ if (--prog_timeout) {
+ t = (uint8_t)(CF_TIMEOUT - prog_timeout); // get time elapsed
+ t &= 0x3; // light a new LED every 4th loop
+
+ // fade each LED down every frame
+ for (i = 0; i < (sizeof(rgbled) / sizeof(rgbled[0])); i++) {
+ if (rgbled[i] >= CF_FADERATE) {
+ rgbled[i] -= CF_FADERATE;
+ } else {
+ rgbled[i] = 0;
+ }
+ }
+
+ // set the next LED in sequence on to full brightness every 4 cycles
+ if (prog_timeout >= 10) { // as long as >10 loops remain,
+ if (!t) { // then on a loop boundary, light the next LED
+ rgb.setPixelColor(circlefade_idx, CF_BRIGHTNESS, CF_BRIGHTNESS, CF_BRIGHTNESS);
+
+ if (++circlefade_idx >= RGB_COUNT) { // then work on the next LED in sequence
+ circlefade_idx = 0;
+ }
+ }
+ }
+ }
+}
diff --git a/fw/HackSpaceCon_AS7/HSC_Wand/rgbled.h b/fw/HackSpaceCon_AS7/HSC_Wand/rgbled.h
new file mode 100644
index 0000000..40cd6ab
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/rgbled.h
@@ -0,0 +1,37 @@
+/*
+ hackspacecon wand firmware
+
+ rgb led control and programs
+*/
+
+#ifndef __RGBLED_H__
+#define __RGBLED_H__
+
+
+
+#include
+#include
+
+
+
+#define RGB_COUNT 5
+#define PROG_COUNT 2
+
+
+
+#define enable_rgb_timer() {TCB0.CNT = 0; TCB0.CTRLA |= 1;};
+#define disable_rgb_timer() {TCB0.CTRLA &= ~1;};
+
+
+
+extern tinyNeoPixel rgb;
+
+extern uint8_t rgbled[3 * RGB_COUNT];
+extern uint8_t (*rgb_program[PROG_COUNT])(uint8_t);
+
+
+
+void conf_rgb_timer();
+
+
+#endif
diff --git a/fw/HackSpaceCon_AS7/HSC_Wand/wand_program.cpp b/fw/HackSpaceCon_AS7/HSC_Wand/wand_program.cpp
new file mode 100644
index 0000000..400088c
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HSC_Wand/wand_program.cpp
@@ -0,0 +1,162 @@
+/*
+ hackspacecon wand firmware
+
+ initially written by true
+ rgb programs and further hacking by 000000widow
+
+ ----
+
+ this version was hacked to work with AS7.
+
+ the resulting binary at time of porting takes an additional
+ 531 bytes of flash and 8 bytes of SRAM. I do not know why.
+
+
+ operation workflow:
+
+ - at initial reset (battery inserted), set up GPIO and peripherals. this
+ includes setting up button wake interrupt. sleep MCU into standby mode.
+
+ - when button state changes, MCU will wake up and process the interrupt.
+ if button is pushed (btn gpio is low), prepare to run next RGB program.
+
+ - rgb program setup involves turning on power to the LEDs and enabling
+ TCB0 periodic timer to interrupt every ~61Hz. this timer interrupt
+ does not handle the rgb program, but will wake the CPU which resumes
+ processing in the loop() function.
+
+ - call the rgb program with the `init` parameter set to 1. idle the CPU.
+
+ - rgb prog timer will interrupt every ~61Hz. this will wake the CPU and
+ send the previously rendered LED data, then call the rgb prog function.
+ afterward, the CPU idles. process repeats until the rgb prog fn returns 0.
+
+ - every time the rgb program is run, the rgb data to send is updated.
+ the data is not actually sent until next wakeup in less than 16.4ms.
+ this allows the functions to have variable processing time, but the
+ output to have a consistent ~61Hz (~16.4ms) timing.
+
+ - once rgb program has finalized, clean up state, disable LED power, and sleep
+ the CPU in standby mode. MCU will wake again once the button is activated.
+
+
+ todo:
+ - test the code
+ - set the RGB output data in the sample rainbow puke program
+ - add more programs
+ - support incrementing or randomly selecting the next program on each button push
+ - run TCB0 in standby mode to save a little more power
+*/
+
+#include
+#include
+#include
+
+#include "rgbled.h"
+
+
+#define PIN_LED_PWRENA PIN_PA6
+
+
+
+enum {
+ RGB_IDLE,
+ RGB_INIT,
+ RGB_RUNNING
+};
+
+enum {
+ PROG_RUN = 0,
+ PROG_INIT = 1
+};
+
+uint8_t run_rgbprog = RGB_IDLE;
+uint8_t rgbprog_idx = 0;
+
+
+
+void idle_cpu()
+{
+ SLPCTRL.CTRLA = SLPCTRL_SMODE_IDLE_gc | SLPCTRL_SEN_bm;
+ __asm("sleep");
+}
+
+void sleep_cpu()
+{
+ SLPCTRL.CTRLA = SLPCTRL_SMODE_STDBY_gc | SLPCTRL_SEN_bm;
+ __asm("sleep");
+}
+
+
+// mcu init
+void setup() {
+ // configure PA2 as falling edge interrupt for button
+ // note: only PA2 and PA6 support async wakeup.
+ // since we're using PA2, we're good to wakeup from a
+ // falling edge (button pushed) event only.
+ PORTA.DIRCLR = PIN2_bm;
+ PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc;
+
+ // configure other hardware pins as appropriate
+ pinMode(PIN_PA3, INPUT_PULLUP); // unused, spare pad on board
+ pinMode(PIN_PA7, INPUT_PULLUP); // unused, voltage passthru
+
+ digitalWrite(PIN_PA6, LOW);
+ pinMode(PIN_PA6, OUTPUT); // LED boost regulator enable
+
+ digitalWrite(PIN_PA1, LOW);
+ pinMode(PIN_PA1, OUTPUT); // LED data
+
+ // set up the RGB ~61Hz periodic timer
+ conf_rgb_timer();
+
+ // enable global interrupts (though they should already be enabled?)
+ sei();
+}
+
+// mcu program loop
+void loop() {
+ switch (run_rgbprog) {
+ case RGB_INIT: { // just started running a program
+ digitalWrite(PIN_LED_PWRENA, HIGH); // enable LED power supply,
+ delay(20); // wait a moment for LEDs to stabilize,
+
+ rgbprog_idx++; // select the next program in sequence,
+ if (rgbprog_idx >= PROG_COUNT) {
+ rgbprog_idx = 0;
+ }
+
+ rgb_program[rgbprog_idx](PROG_INIT);// initialize the program,
+ run_rgbprog++; // and set to running mode.
+
+ enable_rgb_timer(); // then start the RGB program timebase.
+
+ idle_cpu(); // we can idle CPU after running the program
+
+ break;
+ }
+
+ case RGB_RUNNING: { // continuing to run a program
+ rgb.show(); // send updates to the led
+ // then process the next program frame
+ if (!rgb_program[rgbprog_idx](PROG_RUN)) {
+ run_rgbprog = RGB_IDLE; // until the program says it's done
+ break;
+ }
+
+ idle_cpu(); // we can idle CPU after running the program
+
+ break;
+ }
+
+ default: { // no longer running a program
+ disable_rgb_timer(); // disable RGB program timer,
+ digitalWrite(PIN_LED_PWRENA, LOW); // disable LED power supply,
+ run_rgbprog = RGB_IDLE; // and clear run_rgbprog.
+
+ sleep_cpu(); // finally, go to sleep in standby mode
+
+ break;
+ }
+ }
+}
diff --git a/fw/HackSpaceCon_AS7/HackSpaceCon_AS7.atsln b/fw/HackSpaceCon_AS7/HackSpaceCon_AS7.atsln
new file mode 100644
index 0000000..5d7ad3e
--- /dev/null
+++ b/fw/HackSpaceCon_AS7/HackSpaceCon_AS7.atsln
@@ -0,0 +1,28 @@
+
+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("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "Arduino", "Arduino\Arduino.cppproj", "{47694D30-4990-4F03-A1F7-E94EB79783F0}"
+EndProject
+Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "HSC_Wand", "HSC_Wand\HSC_Wand.cppproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|AVR = Debug|AVR
+ Release|AVR = Release|AVR
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {47694D30-4990-4F03-A1F7-E94EB79783F0}.Debug|AVR.ActiveCfg = Debug|AVR
+ {47694D30-4990-4F03-A1F7-E94EB79783F0}.Debug|AVR.Build.0 = Debug|AVR
+ {47694D30-4990-4F03-A1F7-E94EB79783F0}.Release|AVR.ActiveCfg = Release|AVR
+ {47694D30-4990-4F03-A1F7-E94EB79783F0}.Release|AVR.Build.0 = Release|AVR
+ {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.ActiveCfg = Debug|AVR
+ {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.Build.0 = Debug|AVR
+ {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR
+ {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal