diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2157929
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+.sconf_temp/
+.sconsign.dblite
+/build
+/dist
+/crap
+/pkg
+/mnt
+/demo
+/bbctrl-*
+node_modules
+*~
+\#*
+*.pyc
+__pycache__
+*.egg-info
+/upload
+/*.img
+*.so
+*.deb
+*.zip
+/rpi-share
+/package-lock.json
+
+*.elf
+*.hex
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..3355047
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,394 @@
+Buildbotics CNC Controller Firmware Changelog
+=============================================
+
+## v0.4.14
+ - Handle file uploads with '#' or '?' in the name.
+ - Added "step mode" to Web based jogging.
+ - Fixed touch screen Web jogging.
+
+## v0.4.13
+ - Support for OMRON MX2 VFD.
+ - Better error handling in WiFi configuration.
+ - Fix open WiFi access.
+ - Improved video camera performance.
+ - Allow up to 4 camera clients at once.
+ - Add axis bounds GCode variables ``#<_x_min>``, ``#<_x_max>``, etc.
+ - Expose ``junction-accel`` planning parameter.
+ - Fixed problem with manual firmware upload on OSX.
+ - Ignore cameras that do not support MJPEG format video.
+
+## v0.4.12
+ - Segments straddle arc in linearization.
+ - Control max-arc-error with GCode var.
+ - Implemented path modes G61, G61.1 & G64 with naive CAM and basic blending.
+ - Log GCode messages to "Messages" tab.
+ - Acknowledging a message on one browser clears it for all.
+ - Automatically reload Web view when file changes.
+ - Added ``config-screen`` script. Web based screen config to come later.
+ - Suppress message popup with (MSG,# No popup message).
+ - Show latest GCode message in ``Message`` field on CONTROL page.
+ - Marked several GCodes supported in cheat sheet.
+ - Solved planner lookahead failure for most reasonable cases.
+ - Prevent cutting off distant parts of 3D path view.
+ - Raised default ``latch-backoff`` to 100mm and ``zero-backoff`` to 5mm.
+ - Added ``max-deviation`` option.
+ - Fixed problem with GCode boolean expression parsing. #232.
+ - Ensure 2uS step pulse width.
+
+## v0.4.11
+ - Don't reset global offsets on M2.
+ - Test shunt and show error on failure.
+ - Report spindle status codes from Modbus.
+ - Save more log files in bug report.
+ - Fixed indicators low-side units.
+ - Support for YL600, YL620 & YL620-A VFDs.
+ - Move Modbus indicators to tool page.
+ - Support for Sunfar E300 VFD.
+ - Set GCODE_SCRIPT_PATH to support GCode file routines.
+ - Fix pause bug introduced in v0.4.10.
+
+## v0.4.10
+ - Fix demo password check
+ - Fix bug were fast clicks could cause jog commands to arrive out of order.
+ - Fix bug where planner position may not sync after jog.
+ - Show power shutdown on indicators page.
+ - Show all motors in shutdown when in power shutdown.
+ - Improved GCode error messages.
+ - Put controller into estop when in power shutdown.
+
+## v0.4.9
+ - Enforce 6A per motor channel peak current limit.
+ - Adjust config values above max or below min instead of resetting to default.
+
+## v0.4.8
+ - Fixed log rotating.
+ - Use systemd service instead of init.d.
+ - Fix planner terminate.
+ - Changed AVR serial interrupt priorites.
+ - Increased AVR serial and command buffers.
+ - Boost HDMI signal.
+ - Rewrote RPi serial driver.
+ - Automatically scale max CPU speed to reduce RPi temp.
+ - Disable USB camera if RPi temperature above 80°C, back on at 75°C.
+ - Respect offsets in canned cycle moves. #219
+ - Fixed G53 warning.
+ - Fixed delayed offset update after M2 or M30 end of program.
+ - Handle multiple consecutive config resets correctly.
+ - Fixed log CPU usage problem introduced in v0.4.6.
+ - Show RPi temp on indicators page.
+ - Show red thermometer if RPi temp exceeds 80°C.
+
+## v0.4.7
+ - Fix homing switch to motor channel mapping with non-standard axis order.
+ - Added ``switch-debounce`` and ``switch-lockout`` config options.
+ - Handle corrupt GCode simulation data correctly.
+ - Fixes for exception logging.
+ - Always limit motor max-velocity. #209
+ - Sync GCode and planner files to disk after write.
+ - Added warning about reliability in a noisy environment on WiFi config page.
+ - EStop on motor fault.
+ - Fixed ETA line wrapping on Web interface.
+ - Fixed zeroing with non-zero offset when unhomed. #211
+ - Handle file paths uploaded from Windows correctly. #212
+ - Don't retain estop state through reboot.
+ - Log when RPi gets hot.
+ - Support Modbus multi-write mode.
+ - Added support for Nowforever VFDs.
+
+## v0.4.6
+ - Fixed a rare ``Negative s-curve time`` error.
+ - Don't allow manual axis homing when soft limits are not set.
+ - Right click to enable camera crosshair.
+ - Demo mode.
+ - Limit idle-current to 2A.
+ - Removed dangerous ``power-mode`` in favor of simpler ``enabled`` option.
+ - Fixed bug where motor driver could fail to disabled during estop.
+ - Restored estop text.
+
+## v0.4.5
+ - Fix for random errors while running VFD.
+ - Fix bug where planner would not continue after optional pause (M1).
+ - Fix lockup on invalid no move probe G38.x. #183
+ - Fix zeroing homed axis after jog.
+ - Fix VFD communication at higher baud rates (> 9600). #184
+
+## v0.4.4
+ - Write version to log file.
+ - Write time to log file periodically.
+ - Show simulation progress with or with out 3D view.
+ - Synchronize file list between browsers.
+ - Increased max simulation time to 24hrs.
+ - Added button to download current GCode file.
+ - Blink play button to indicate pause.
+ - Many layout tweaks/improvements.
+ - Don't abort simulations when system time changes.
+ - Only allow one camera stream at a time.
+
+## v0.4.2
+ - Suppress ``Auto-creating missing tool`` warning.
+ - Prevent ``Stream is closed`` error.
+ - Suppress ``WebGL not supported`` warning.
+ - Fixed Web disconnect during simulation of large GCode.
+ - Disable outputs on estop.
+ - Improved switch debouncing for better homing.
+ - Handle zero length dwell correctly.
+ - Fixed problem with cached GCode file upload when file changed on disk.
+ - Run simulation at low process priority.
+ - Added ``Bug Report`` button to ``Admin`` -> ``General``.
+ - Only render 3D view as needed to save CPU.
+ - Prevent lockup due to browser causing out of memory condition.
+ - Show error message when too large GCode upload fails.
+ - Much faster 3D view loading.
+
+## v0.4.1
+ - Fix toolpath view axes bug.
+ - Added LASER intensity view.
+ - Fixed reverse path planner bug.
+ - Video size and path view controls persistent over browser reload.
+ - Fixed time and progress bugs.
+ - Added PWM rapid auto off feature for LASER/Plasma.
+ - Added dynamic PWM for LASER/Plasma.
+ - Added motor faults table to indicators page.
+ - Emit error and indicate FAULT on axis for motor driver faults.
+ - Display axis motor FAULT on LCD.
+ - Fixed bug with rapid repeated unpause.
+
+## v0.4.0
+ - Increased display precision of position and motor config.
+ - Added support for 256 microstepping.
+ - Smoother operation at 250k step rate by doubling clock as needed.
+ - Indicators tab improvements.
+ - Much improved camera support.
+ - Camera hotpluging.
+ - Move camera video to header.
+ - Click to switch video size.
+ - Automount/unmount USB drives.
+ - Automatically install ``buildbotics.gc`` when no other GCode exists.
+ - Preplan GCode and check for errors.
+ - Display 3D view of program tool paths in browser.
+ - Display accurate time remaining, ETA and progress during run.
+ - Automatically collapse moves in planner which are too short in time.
+ - Show IO status indicators on configuration pages.
+ - Check that axis dimensions fit path plan dimensions.
+ - Show machine working envelope in path plan viewer.
+ - Don't reload browser view on reconnect unless controller has reloaded.
+ - Increased max switch backoff search distance.
+ - Major improvements for LASER raster GCodes.
+ - Fixed major bug in command queuing.
+ - Ignore Program Number O-Codes.
+ - Improved planning of collinear line segments.
+ - Allow PWM output up to 320kHz and no slower than 8Hz.
+
+## v0.3.28
+ - Show step rate on motor configuration page.
+ - Limit motor max-velocity such that step rate cannot exceed 250k.
+ - Fixed deceleration bug at full 250k step rate.
+
+## v0.3.27
+ - Fixed homing in imperial mode.
+
+## v0.3.26
+ - Removed VFD test.
+ - Show VFD status on configuration page.
+ - Show VFD commands fail counts.
+ - Marked some VFD types as beta.
+
+## v0.3.25
+ - Error on home if max-soft-limit <= min-soft-limit + 1. #139
+ - Decrease boot time networking delay.
+ - Default to US keyboard layout. #145
+ - Added configuration option to show metric or imperial units in browser. #74
+ - Implemented fine jogging control in Web interface. #147
+
+## v0.3.24
+ - Added unhome button on axis position popup.
+ - Ignore soft limits of max <= min.
+ - Fixed problem with restarting program in imperial units mode.
+ - Handle GCode with infinite or very long loops correctly.
+ - Fixed Huanyang spindle restart after stop.
+
+## v0.3.23
+ - Fix for modbus read operation.
+ - Finalized AC-Tech VFD support.
+ - Preliminary FR-D700 VFD support.
+ - Ignore leading zeros in modbus messages.
+ - Handle older PWR firmwares.
+
+## v0.3.22
+ - Fix position loss after program pause. #130
+ - Correctly handle disabled axes.
+ - Fixed config checkbox not displaying defaulted enabled correctly.
+ - Added Custom Modbus VFD programming.
+
+## v0.3.21
+ - Implemented M70-M73 modal state save/restore.
+ - Added support for modbus VFDs.
+ - Start Huanyang spindle with out first pressing Start button on VFD.
+ - Faster switching of large GCode files in Web.
+ - Fixed reported gcode line off by one.
+ - Disable MDI input while running.
+ - Stabilized direction pin output during slow moves.
+
+## v0.3.20
+ - Eliminated drift caused by miscounting half microsteps.
+ - Fixed disappearing GCode in Web.
+ - More efficient GCode scrolling with very large files.
+ - Fully functional soft-limited jogging.
+ - Added client and access-point Wifi configuration.
+ - Fixed broken hostname Web redirect after change.
+ - Split admin page -> General & Network.
+ - Improved calculation of junction velocity limits.
+
+## v0.3.19
+ - Fixed stopping problems. #127
+ - Fixed ``Negative s-curve time`` error.
+ - Improved jogging with soft limits.
+ - Added site favicon.
+ - Fixed problems with offsets and imperial units.
+ - Fixed ``All zero s-curve times`` caused by extremely short, non-zero moves.
+ - Fixed position drift.
+
+## v0.3.18
+ - Don't enable any tool by default.
+
+## v0.3.17
+ - Fixed pausing fail near end of run bug.
+ - Show "Upgrading firmware" when upgrading.
+ - Log excessive pwr communication failures as errors.
+ - Ensure we can still get out of non-idle cycles when there are errors.
+ - Less frequent pwr variable updates.
+ - Stop cancels seek and subsequent estop.
+ - Fixed bug in AVR/Planner command synchronization.
+ - Consistently display HOMING state during homing operation.
+ - Homing zeros axis global offset.
+ - Added zero all button. #126
+ - Separate "Auto" and "MDI" play/pause & stop buttons. #126
+ - Moved home all button. #126
+ - Display "Video camera not found." instead of broken image icon.
+ - Show offset positions not absolute on LCD.
+ - Don't change gcode lines while homing.
+ - Don't change button states while homing.
+ - Adding warning about power cyclying during an upgrade.
+ - Reset planner on AVR errors.
+ - Fixed pausing with short moves.
+ - Corrected s-curve accel increasing jogging velocities.
+
+## v0.3.16
+ - Fixed switch debounce bug.
+
+## v0.3.15
+ - Suppress warning missing config.json warning after config reset.
+ - Fixed EStop reboot loop.
+ - Removed AVR unexpected reboot error.
+
+## v0.3.14
+ - Fixed: Config fails silently after web disconnect #112
+ - Always reload the page after a disconnect.
+ - Honor soft limits #111 (but not when jogging)
+ - Limit switch going active while moving causes estop. #54
+ - Added more links to help page.
+ - Fixed axis display on LCD. #122
+ - Added GCode cheat sheet.
+ - Fixed LCD boot splash screen. #121
+ - Implemented tool change procedures and pause message box. #81
+ - Implemented program start and end procedures.
+
+## v0.3.13
+ - Disable spindle and loads on stop.
+ - Fixed several state transition (stop, pause, estop, etc.) problems.
+
+## v0.3.12
+ - Updated DB25 M2 breakout diagram.
+ - Enabled AVR watchdog.
+ - Fixed problem with selecting newly uploaded file.
+ - More thorough shutdown of stepper driver in estop.
+ - Fixed spindle type specific options.
+ - No more ``Unexpected AVR firmware reboot`` errors on estop clear.
+ - Downgraded ``Machine alarmed - Command not processed`` errors to warnings.
+ - Suppress unnecessary axis homing warnings.
+ - More details for axis homing errors.
+ - Support GCode messages e.g. (MSG, Hello World!)
+ - Support programmed pauses. i.e. M0
+
+## v0.3.11
+ - Suppressed ``firmware rebooted`` warning.
+ - Error on unexpected AVR reboot.
+ - Fixed pin fault output.
+ - No longer using interrupts for switch inputs. Debouncing on clock tick.
+
+## v0.3.10
+ - Fixed "Flood" display, changed to "Load 1" and "Load 2". #108
+ - Highlight loads when on.
+ - Fixed axis zeroing.
+ - Fixed bug in home position set after successful home. #109
+ - Fixed ugly Web error dumps.
+ - Allow access to log file from Web.
+ - Rotate log so it does not grow too big.
+ - Keep same GCode file through browser reload. #20
+
+## v0.3.9
+ - Fixed bug in move exec that was causing bumping between moves.
+ - Fixed planner bug which could create negative s-curve times.
+ - Hide step and optional pause buttons until they are implemented.
+ - Fixed pausing problems.
+ - Limit number of console messages.
+ - Scrollbar on console view.
+ - Log debug messages to console in developer mode.
+ - Fixed AVR log message source.
+ - Fixed step correction.
+ - JOGGING, HOMMING and MDI states.
+ - Fixed position problem with rapid MDI entry.
+
+## v0.3.8
+ - Fixed pwr flags display
+ - Added pwr fault flags to indicators
+
+## v0.3.7
+ - Allow blocking error dialog for a period of time
+ - Show actual error message on planner errors
+ - Reset planner on serious error
+ - Fixed console clear
+ - Added helpful info to Video tab
+ - Changed "Console" tab to "Messages"
+ - Removed spin up/down velocity options, they don't do anything
+ - Allow RS485 to work when wires are swapped
+ - Allow setting VFD ID
+ - Only show relevant spindle config items
+ - More robust video camera reset
+ - Added help page
+ - Allow upgrade with out Internet
+ - Limit power fault reporting
+ - Added load over temp, load limiting and motor overload power faults
+
+## v0.3.6
+ - Set max_usb_current=1 in /boot/config.txt from installer #103
+
+## v0.3.5
+ - Fixed dwell (G4)
+ - Always show limit switch indicators regardless of motor enable
+ - Fixed feed rate display
+ - Added current GCode unit display
+ - Fixed homed axis zeroing
+ - Fixed probe pin input
+ - Added reload button to video tab
+ - Don't open error dialog on repeat messages
+ - Handle large GCode files in browser
+ - Added max lookahead limit to planner
+ - Fixed GCode stopping/pausing where ramp down needs more than is in the queue
+ - Added breakout box diagram to indicators
+ - Initialize axes offsets to zero on startup
+ - Fixed conflict between ``x`` state variable and ``x`` axis variable
+ - Don't show ipv6 addresses on LCD. They don't fit.
+
+## v0.3.4
+ - Added alternate units for motor parameters
+ - Automatic config file upgrading
+ - Fixed planner/jog sync
+ - Fixed planner limits config
+ - Accel units mm/min² -> m/min²
+ - Search and latch velocity mm/min -> m/min
+ - Fixed password update (broken in last version)
+ - Start Web server earlier in case of Python coding errors
+
+
+Changelog not maintained in previous versions. See git commit log.
diff --git a/CODE_TAG b/CODE_TAG
new file mode 100644
index 0000000..d36ffb0
--- /dev/null
+++ b/CODE_TAG
@@ -0,0 +1,22 @@
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ac86d6d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,377 @@
+The Buildbotics firmware ("the software") is free software: you can
+redistribute it and/or modify it under the terms of the GNU General
+Public License, version 2 (with out any licensing exceptions) as
+published by the Free Software Foundation. See the full license terms
+below.
+
+***********************************************************************
+
+Substantial effort was made to give credit to all authors of this
+software and of the works it was derived from and to adhere to the
+terms of the applicable license agreements. If you belive any
+mistakes have been made in this regard please contact Joseph Coffland
+.
+
+Portions of this software are copyrighted by the following entities:
+
+ Copyright (c) 2015 - 2016 Buildbotics LLC
+ Copyright (c) 2014 Thomas Nixon, Jonathan Heathcote (cpp_magic.h)
+ All rights reserved.
+
+Each source code file lists the entities which claim copyright to
+parts of those files.
+
+Much of this software was originally written by Alden S. Hart, Jr. and
+Robert Giseburt as part of the TinyG project. The TinyG project was
+in turn derived from grbl/marlin firmwares. All of the original code
+has been reformatted and cleaned up to fit our coding standards.
+Functionality in many areas has been substantially modified.
+
+The original TinyG firmware is licensed under the GPL v2 and includes
+an exception which allows use of the source code by non-GPLed
+libraires and potentially executables linked to those libraries. The
+TinyG project's license did not specify that this exception must be
+offered in derived works, therefore this software's license DOES NOT
+offer any exceptions to the GPL v2 license.
+
+***********************************************************************
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..6450ecf
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,12 @@
+recursive-include src/py/bbctrl/http *
+include package.json README.md scripts/install.sh
+include src/avr/bbctrl-avr-firmware.hex
+include src/bbserial/bbserial.ko
+include scripts/avr109-flash.py
+include scripts/buildbotics.gc
+include scripts/xinitrc
+include scripts/rc.local
+include scripts/bbctrl.service
+include scripts/11-automount.rules
+recursive-include src/py/camotics *
+global-exclude .gitignore
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0aed58e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,142 @@
+DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+
+NODE_MODS := $(DIR)/node_modules
+PUG := $(NODE_MODS)/.bin/pug
+STYLUS := $(NODE_MODS)/.bin/stylus
+
+TARGET_DIR := build/http
+HTML := index
+HTML := $(patsubst %,$(TARGET_DIR)/%.html,$(HTML))
+RESOURCES := $(shell find src/resources -type f)
+RESOURCES := $(patsubst src/resources/%,$(TARGET_DIR)/%,$(RESOURCES))
+TEMPLS := $(wildcard src/pug/templates/*.pug)
+
+AVR_FIRMWARE := src/avr/bbctrl-avr-firmware.hex
+GPLAN_MOD := rpi-share/camotics/gplan.so
+GPLAN_TARGET := src/py/camotics/gplan.so
+GPLAN_IMG := gplan-dev.img
+
+RSYNC_EXCLUDE := \*.pyc __pycache__ \*.egg-info \\\#* \*~ .\\\#\*
+RSYNC_EXCLUDE := $(patsubst %,--exclude %,$(RSYNC_EXCLUDE))
+RSYNC_OPTS := $(RSYNC_EXCLUDE) -rv --no-g --delete --force
+
+VERSION := $(shell sed -n 's/^.*"version": "\([^"]*\)",.*$$/\1/p' package.json)
+PKG_NAME := bbctrl-$(VERSION)
+PUB_PATH := root@buildbotics.com:/var/www/buildbotics.com/bbctrl
+BETA_VERSION := $(VERSION)-rc$(shell ./scripts/next-rc)
+BETA_PKG_NAME := bbctrl-$(BETA_VERSION)
+
+SUBPROJECTS := avr boot pwr jig
+WATCH := src/pug src/pug/templates src/stylus src/js src/resources Makefile
+WATCH += src/static
+
+ifndef HOST
+HOST=bbctrl.local
+endif
+
+ifndef PASSWORD
+PASSWORD=buildbotics
+endif
+
+
+all: $(HTML) $(RESOURCES)
+ @for SUB in $(SUBPROJECTS); do $(MAKE) -C src/$$SUB; done
+
+pkg: all $(AVR_FIRMWARE) bbserial
+ ./setup.py sdist
+
+beta-pkg: pkg
+ cp dist/$(PKG_NAME).tar.bz2 dist/$(BETA_PKG_NAME).tar.bz2
+
+bbserial:
+ $(MAKE) -C src/bbserial
+
+gplan: $(GPLAN_TARGET)
+
+$(GPLAN_TARGET): $(GPLAN_MOD)
+ cp $< $@
+
+$(GPLAN_MOD): $(GPLAN_IMG)
+ ./scripts/gplan-init-build.sh
+ git -C rpi-share/cbang fetch
+ git -C rpi-share/cbang reset --hard FETCH_HEAD
+ git -C rpi-share/camotics fetch
+ git -C rpi-share/camotics reset --hard FETCH_HEAD
+ cp ./scripts/gplan-build.sh rpi-share/
+ sudo ./scripts/rpi-chroot.sh $(GPLAN_IMG) /mnt/host/gplan-build.sh
+
+$(GPLAN_IMG):
+ ./scripts/gplan-init-build.sh
+
+.PHONY: $(AVR_FIRMWARE)
+$(AVR_FIRMWARE):
+ $(MAKE) -C src/avr
+
+publish: pkg
+ echo -n $(VERSION) > dist/latest.txt
+ rsync $(RSYNC_OPTS) dist/$(PKG_NAME).tar.bz2 dist/latest.txt $(PUB_PATH)/
+
+publish-beta: beta-pkg
+ echo -n $(BETA_VERSION) > dist/latest-beta.txt
+ rsync $(RSYNC_OPTS) dist/$(BETA_PKG_NAME).tar.bz2 dist/latest-beta.txt \
+ $(PUB_PATH)/
+
+update: pkg
+ http_proxy= curl -i -X PUT -H "Content-Type: multipart/form-data" \
+ -F "firmware=@dist/$(PKG_NAME).tar.bz2" -F "password=$(PASSWORD)" \
+ http://$(HOST)/api/firmware/update
+ @-tput sgr0 && echo # Fix terminal output
+
+build/templates.pug: $(TEMPLS)
+ mkdir -p build
+ cat $(TEMPLS) >$@
+
+node_modules: package.json
+ npm install && touch node_modules
+
+$(TARGET_DIR)/%: src/resources/%
+ install -D $< $@
+
+$(TARGET_DIR)/index.html: build/templates.pug
+$(TARGET_DIR)/index.html: $(wildcard src/static/js/*)
+$(TARGET_DIR)/index.html: $(wildcard src/static/css/*)
+$(TARGET_DIR)/index.html: $(wildcard src/pug/templates/*)
+$(TARGET_DIR)/index.html: $(wildcard src/js/*)
+$(TARGET_DIR)/index.html: $(wildcard src/stylus/*)
+$(TARGET_DIR)/index.html: src/resources/config-template.json
+
+$(TARGET_DIR)/%.html: src/pug/%.pug node_modules
+ @mkdir -p $(shell dirname $@)
+ $(PUG) -O pug-opts.js -P $< -o $(TARGET_DIR) || (rm -f $@; exit 1)
+
+pylint:
+ pylint3 -E $(shell find src/py -name \*.py | grep -v flycheck_)
+
+jshint:
+ ./node_modules/jshint/bin/jshint --config jshint.json src/js/*.js
+
+lint: pylint jshint
+
+watch:
+ @clear
+ $(MAKE)
+ @while sleep 1; do \
+ inotifywait -qr -e modify -e create -e delete \
+ --exclude .*~ --exclude \#.* $(WATCH); \
+ clear; \
+ $(MAKE); \
+ done
+
+tidy:
+ rm -f $(shell find "$(DIR)" -name \*~)
+
+clean: tidy
+ rm -rf build html dist
+ @for SUB in $(SUBPROJECTS); do \
+ $(MAKE) -C src/$$SUB clean; \
+ done
+
+dist-clean: clean
+ rm -rf node_modules
+
+.PHONY: all install clean tidy pkg gplan lint pylint jshint bbserial
diff --git a/README_buildbotics.md b/README_buildbotics.md
new file mode 100644
index 0000000..345ab24
--- /dev/null
+++ b/README_buildbotics.md
@@ -0,0 +1,62 @@
+# Buildbotics CNC Controller Firmware
+This repository contains the source code for the Buildbotics CNC Controller.
+See [buildbotics.com](https://buildbotics.com/) for more information.
+
+
+
+## Overview
+
+
+The main parts of the Buildbotics CNC Controller software and the technologies
+they are built with are as follows:
+
+ * Web App - Frontend user interface
+ * [Javascript](https://www.w3schools.com/js/)
+ * [HTML5](https://www.w3schools.com/html/)
+ * [Stylus](http://stylus-lang.com/)
+ * [Pug.js](https://pugjs.org/)
+ * [Vue.js](https://vuejs.org/)
+
+ * Controller OS - RaspberryPi Operating System
+ * [Raspbian](https://www.raspbian.org/)
+
+ * BBCtrl - Python App
+ * [Python 3](https://www.python.org/)
+ * [Tornado Web](https://www.tornadoweb.org/)
+
+ * GPlan - Path Planner Python Module
+ * [C++](http://www.cplusplus.com/)
+ * [CAMotics](https://camotics.org/)
+
+ * Main AVR Firmware + Bootloader - Real-time step generation, etc.
+ * [ATxmega192a3u](https://www.microchip.com/wwwproducts/ATxmega192A3U)
+ * [C](https://en.wikipedia.org/wiki/C_(programming_language))
+
+ * Pwr AVR Firmware - Power safety
+ * [ATtiny1634](https://www.microchip.com/wwwproducts/ATtiny1634)
+ * [C](https://en.wikipedia.org/wiki/C_(programming_language))
+
+## Quickstart Guide
+
+Be sure to read the [development guide](docs/development.md) for more detailed
+instructions.
+
+On a Debian Linux (9.6.0 stable) system:
+
+ # Install the required packages
+ sudo apt-get update
+ sudo apt-get install -y build-essential git wget binfmt-support qemu \
+ parted gcc-avr avr-libc avrdude pylint3 python3 python3-tornado curl \
+ unzip python3-setuptools
+ curl -sL https://deb.nodesource.com/setup_11.x | sudo -E bash -
+ sudo apt-get install -y nodejs
+
+ # Get the source
+ git clone https://github.com/buildbotics/bbctrl-firmware
+
+ # Build the Firmware
+ cd bbctrl-firmware
+ make pkg
+
+The resulting package will be a ``.tar.bz2`` file in ``dist``. See the
+[development guide](docs/development.md) for more information.
diff --git a/docs/bbdev-chroot.md b/docs/bbdev-chroot.md
new file mode 100644
index 0000000..be1e45a
--- /dev/null
+++ b/docs/bbdev-chroot.md
@@ -0,0 +1,41 @@
+This document describes how to setup a Buildbotics development environment
+on a Debian based system inside a chroot. Building in the chroot ensures that
+you have a clean and consistent build environment unaltered by other packages
+or manual changes.
+
+# Install packages required to create chroot
+
+ sudo apt-get update
+ sudo apt-get install binutils debootstrap
+
+# Create chroot environment
+
+ mkdir bbdev
+ sudo debootstrap --arch amd64 stable bbdev http://deb.debian.org/debian
+
+# Copy downloaded files (optional)
+To speed things up you can copy to large downloads, if you already have them,
+into the chroot.
+
+ sudo mkdir -p bbdev/opt/bbctrl-firmware/src/bbserial/
+ sudo cp 2017-11-29-raspbian-stretch-lite.zip bbdev/opt/bbctrl-firmware/
+ sudo cp raspberrypi-kernel_1.20171029-1.tar.gz bbdev/opt/bbctrl-firmware/src/bbserial/
+
+# Enter the chroot
+
+ sudo mount --bind /proc bbdev/proc
+ sudo mount --rbind /sys bbdev/sys
+ sudo mount --rbind /dev bbdev/dev
+ sudo chroot bbdev
+ cd /opt
+
+Now, follow the instructions in [development.md](development.md) from with in
+the chroot.
+
+# Exit the chroot
+To exit the chroot:
+
+ exit
+ sudo umount bbdev/dev
+ sudo umount bbdev/sys
+ sudo umount bbdev/proc
diff --git a/docs/buildbotics_architecture_overview.png b/docs/buildbotics_architecture_overview.png
new file mode 100644
index 0000000..960307d
Binary files /dev/null and b/docs/buildbotics_architecture_overview.png differ
diff --git a/docs/buildbotics_controller.png b/docs/buildbotics_controller.png
new file mode 100644
index 0000000..e0dd0b9
Binary files /dev/null and b/docs/buildbotics_controller.png differ
diff --git a/docs/cross_compile_rpi_kernel_module.md b/docs/cross_compile_rpi_kernel_module.md
new file mode 100644
index 0000000..2b04dd3
--- /dev/null
+++ b/docs/cross_compile_rpi_kernel_module.md
@@ -0,0 +1,68 @@
+# Install the cross compiler
+
+ sudo apt-get update
+ sudo apt-get install -y gcc-arm-linux-gnueabihf
+
+# Determine the correct kernel version on the target pi
+
+ dpkg-query -l raspberrypi-kernel
+
+# Get the kernel source for the correct kernel version
+
+ wget https://github.com/raspberrypi/linux/archive/raspberrypi-kernel_1.20171029-1.tar.gz
+ tar xf raspberrypi-kernel_1.20171029-1.tar.gz
+ cd linux-raspberrypi-kernel_1.20171029-1
+
+# Prep the kernel source
+
+ KERNEL=kernel7
+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
+ make -j 8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_prepare
+
+# Create hello.c module
+
+ #include
+ #include
+
+ MODULE_LICENSE("GPL");
+
+ static int hello_init(void) {
+ printk(KERN_ALERT "Hello world!\n");
+ return 0;
+ }
+
+ static void hello_exit(void) {
+ printk(KERN_ALERT "Goodbye cruel world!\n");
+ }
+
+ module_init(hello_init);
+ module_exit(hello_exit);
+
+# Create a Makefile
+
+ CROSS := arm-linux-gnueabihf-
+ DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+ obj-m := hello.o
+
+ all:
+ $(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS) -C kernel M=$(DIR) modules
+
+ clean:
+ $(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS) -C kernel M=$(DIR) clean
+
+# Compile the module
+
+ ln -sf path/to/rpi-kernel kernel
+ make
+
+# Copy module to rpi
+
+ scp hello.ko pi.local:
+
+# Load it on the pi
+
+ sudo insmod hello.ko
+
+# Look for message in syslog
+
+ tail /var/log/syslog
diff --git a/docs/development.md b/docs/development.md
new file mode 100644
index 0000000..6a82eb5
--- /dev/null
+++ b/docs/development.md
@@ -0,0 +1,106 @@
+# Buildbotics CNC Controller Development Guide
+
+This document describes how to setup your environment for Buildbotics CNC
+controller development on Debian Linux. Development on systems other than
+Debian Linux are not supported.
+
+## Installing the Development Prerequisites
+
+On a Debian Linux (9.6.0 stable) system install the required packages:
+
+ sudo apt-get update
+ sudo apt-get install -y build-essential git wget binfmt-support qemu \
+ parted gcc-avr avr-libc avrdude pylint3 python3 python3-tornado curl \
+ unzip python3-setuptools gcc-arm-linux-gnueabihf bc sudo
+ curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
+ sudo apt-get install -y nodejs
+
+## Getting the Source Code
+
+ git clone https://github.com/buildbotics/bbctrl-firmware
+
+## Build the Firmware
+
+ cd bbctrl-firmware
+ make
+
+## Build GPlan Module
+
+GPlan is a Python module written in C++. It must be compiled for ARM so that
+it can be used on the Raspberry Pi. This is accomplished using a chroot, qemu
+and binfmt to create an emulated ARM build environment. This is faster and
+more convenient than building on the RPi itself. All of this is automated.
+
+ make gplan
+
+The first time this is run it will take quite awhile as it setups up the build
+environment. You can run the above command again later to build the latest
+version.
+
+## Build the Firmware Package
+
+ make pkg
+
+The resulting package will be a ``.tar.bz2`` file in ``dist``.
+
+## Upload the Firmware Package to a Buildbotics CNC Controller
+If you have a Buildbotics CNC controller at ``bbctrl.local``, the default
+address, you can upgrade it with the new package like this:
+
+ make update HOST=bbctrl.local PASSWORD=
+
+Where ```` is the controller's admin password.
+
+## Updating the Pwr Firmware
+
+The Pwr firmware must be uploaded manually using an ISP programmer. With the
+programmer attached to the pwr chip ISP port on the Builbotics controller's
+main board run the following:
+
+ make -C src/pwr program
+
+## Initializing the main AVR firmware
+
+The main AVR must also be programmed manually the first time. Later it will be
+automatically programmed by the RPi as part of the firmware install. To perform
+the initial AVR programming connec the ISP programmer to the main AVR's ISP port
+on the Buildbotics controller's main board and run the following:
+
+ make -C src/avr init
+
+This will set the fuses, install the bootloader and program the firmware.
+
+## Installing the RaspberryPi base system
+
+Download the latest Buildbotics CNC controller base image and decompress it:
+
+ wget \
+ https://buildbotics.com/upload/2018-05-15-raspbian-stretch-bbctrl.img.xz
+ xz -d 2018-05-15-raspbian-stretch-bbctrl.img.xz
+
+Now copy the base system to an SD card. You need a card with at least 8GiB.
+After installing the RPi system all data on the SD card will be lost. So make
+sure you back up the SD card if there's anything important on it.
+
+In the command below, make sure you have the correct device or you can
+**destroy your Linux system** by overwriting the disk. One way to do this is
+to run ``sudo tail -f /var/log/syslog`` before inserting the SD card. After
+inserting the card look for log messages containing ``/dev/sdx`` where ``x`` is
+a letter. This should be the device name of the SD card. Hit ``CTRL-C`` to
+stop following the system log.
+
+ sudo dd bs=4M if=2015-05-05-raspbian-wheezy.img of=/dev/sde
+ sudo sync
+
+The first command takes awhile and does not produce any output until it's done.
+
+Insert the SD card into your RPi and power it on. Plug in the network
+connection, wired or wireless.
+
+## Logging into the Buildbotics Controller
+
+You can ssh in to the Buildbotics Controller like so:
+
+ ssh bbmc@bbctrl.local
+
+The default password is ``buildbotics``. It's best if you change this.
diff --git a/docs/emu_chroot.md b/docs/emu_chroot.md
new file mode 100644
index 0000000..348ed82
--- /dev/null
+++ b/docs/emu_chroot.md
@@ -0,0 +1,45 @@
+This document describes how to setup the Buildbotics firmware in a chroot
+environment for the purposes of demonstrating the user interface.
+
+On a Debian system install:
+
+ ROOT=/opt/demo
+ sudo apt-get install -y binutils debootstrap
+ sudo mkdir $ROOT
+ sudo debootstrap --arch amd64 stable $ROOT/ http://deb.debian.org/debian
+
+Then chroot:
+
+ sudo mount --bind /dev $ROOT/dev/
+ sudo mount --bind /sys $ROOT/sys/
+ sudo mount --bind /proc $ROOT/proc/
+ sudo mount --bind /dev/pts $ROOT/dev/pts
+ sudo chroot $ROOT
+
+Setup the demo system:
+
+ export LC_ALL=C
+ apt-get update
+ apt-get install -y wget git python3-tornado python3-sockjs-tornado \
+ python3-setuptools python-six build-essential scons libv8-dev
+ libpython3-dev
+
+ cd /opt
+ BASE=https://buildbotics.com/bbctrl
+ LATEST=$(wget $BASE/latest.txt -O- -q)
+ wget $BASE/bbctrl-$LATEST.tar.bz2
+ tar xf bbctrl-$LATEST.tar.bz2
+ ln -sf bbctrl-$LATEST bbctrl
+
+ git clone --depth=1 https://github.com/CauldronDevelopmentLLC/cbang
+ git clone --depth=1 https://github.com/CauldronDevelopmentLLC/camotics
+ export CBANG_HOME=/opt/cbang
+ scons -C cbang -j8 disable_local="re2 libevent"
+ scons -C camotics -j8 gplan.so with_gui=False
+
+ cd bbctrl
+ python3 setup.py install
+ cp /opt/camotics/gplan.so /usr/local/lib/python*/dist-packages/bbctrl-$VERSION-py*.egg/camotics/gplan.so
+
+ mkdir -p /var/lib/bbctrl/upload
+ useradd -u 1001 bbmc
diff --git a/jshint.json b/jshint.json
new file mode 100644
index 0000000..bb0cbb3
--- /dev/null
+++ b/jshint.json
@@ -0,0 +1,15 @@
+{
+ "asi": true,
+ "browser": true,
+ "devel": true,
+ "strict": "global",
+ "globals": {
+ "$": false,
+ "require": false,
+ "module": false,
+ "Vue": false,
+ "SockJS": false,
+ "Gauge": false,
+ "Clusterize": false
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0cd9d42
--- /dev/null
+++ b/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "bbctrl",
+ "version": "1.0.3",
+ "homepage": "https://onefinitycnc.com/",
+ "repository": "https://github.com/OneFinityCNC/onefinity",
+ "license": "GPL-3.0+",
+ "dependencies": {
+ "jshint": "",
+ "browserify": "",
+ "jstransformer-stylus": "",
+ "jstransformer-escape-html": "",
+ "pug-cli": ""
+ }
+}
diff --git a/pug-opts.js b/pug-opts.js
new file mode 100644
index 0000000..177616e
--- /dev/null
+++ b/pug-opts.js
@@ -0,0 +1,11 @@
+{
+ pretty: true,
+ filters: {
+ browserify: function (text, options) {
+ return require('child_process').execSync(
+ `./node_modules/.bin/browserify - --basedir src/js`,
+ {input: text}
+ ).toString()
+ }
+ }
+}
diff --git a/scripts/11-automount.rules b/scripts/11-automount.rules
new file mode 100644
index 0000000..96967d4
--- /dev/null
+++ b/scripts/11-automount.rules
@@ -0,0 +1,10 @@
+KERNEL!="sd[a-z]*", GOTO="automount_end"
+IMPORT{program}="/sbin/blkid -o udev -p %N"
+ENV{ID_FS_TYPE}=="", GOTO="automount_end"
+ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
+ENV{ID_FS_LABEL}=="", ENV{dir_name}="usb-%k"
+ACTION=="add", ENV{mount_options}="relatime"
+ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002,sync"
+ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}"
+ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"
+LABEL="automount_end"
diff --git a/scripts/avr109-flash.py b/scripts/avr109-flash.py
new file mode 100644
index 0000000..2fec936
--- /dev/null
+++ b/scripts/avr109-flash.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python3
+
+import sys
+import time
+import serial
+import binascii
+
+
+dev = '/dev/ttyAMA0'
+baud = 921600
+boot_id = 'bbctrl '
+verbose = False
+
+
+def crc16(data):
+ crc = 0xffff
+
+ for x in data:
+ crc = crc ^ int(x)
+ for bit in range(8):
+ if crc & 1: crc = (crc >> 1) ^ 0xa001
+ else: crc = crc >> 1
+
+ return crc
+
+
+def avr_crc32(data, length):
+ mem = [0xff] * length
+
+ for addr, chunk in data:
+ for x in chunk:
+ mem[addr] = x
+ addr += 1
+
+ return binascii.crc32(bytes(mem))
+
+
+def read_intel_hex(f):
+ base = 0
+ pos = 0
+ start = 0
+ chunk = None
+
+ for line in f:
+ line = line.strip()
+ if not line or line[0] != ':': continue
+
+ count = int(line[1:3], 16)
+ addr = int(line[3:7], 16)
+ type = int(line[7:9], 16)
+ data = line[9:-2]
+ checksum = int(line[-2:], 16)
+
+ if type == 0:
+ addr += base
+ data = binascii.unhexlify(bytes(data, 'utf8'))
+
+ if chunk is None or pos != addr:
+ if chunk is not None: yield (start, chunk)
+ start = addr
+ chunk = data
+
+ else: chunk += data
+
+ pos = addr + len(data)
+
+ if type == 2: base = int(data, 16) * 16
+
+ if chunk is not None: yield (start, chunk)
+
+
+def send(data):
+ if verbose: print('Sending:', data)
+ sp.write(bytes(data, 'utf8'))
+
+
+def send_int(x, size):
+ if verbose: print('Sending: %d', x)
+ sp.write((x).to_bytes(size, byteorder = 'big'))
+
+
+def recv(count):
+ data = sp.read(count).decode('utf8')
+ if count and verbose: print('Received:', data)
+ return data
+
+
+def recv_int(size):
+ x = int.from_bytes(sp.read(size), byteorder = 'big')
+ if verbose: print('Received:', x)
+ return x
+
+
+# Read firmware hex file
+data = list(read_intel_hex(open(sys.argv[1], 'r')))
+
+# Open serial port
+sp = serial.Serial(dev, baud, timeout = 10)
+
+# Reset AVR
+import RPi.GPIO as gpio
+gpio.setwarnings(False)
+gpio.setmode(gpio.BCM)
+gpio.setup(27, gpio.OUT)
+gpio.output(27, 0)
+gpio.output(27, 1)
+gpio.setup(27, gpio.IN, pull_up_down = gpio.PUD_UP)
+time.sleep(0.1)
+
+# Sync
+for i in range(10): send('\x1b')
+
+# Flush serial
+try:
+ recv(sp.in_waiting)
+except: pass
+
+# Get bootloader ID
+send('S')
+if boot_id != recv(len(boot_id)):
+ raise Exception('Failed to communicate with bootloader')
+
+# Get version
+send('V')
+major = int(recv(1))
+minor = int(recv(1))
+print('Bootloader version: %d.%d' % (major, minor))
+
+# If bootloader is new enough compare checksums
+if 0 < major or 1 < minor:
+ # Get flash length
+ send('n')
+ flash_len = recv_int(3)
+
+ # Get current flash CRC
+ send('X')
+ new_crc = avr_crc32(data, flash_len)
+ old_crc = recv_int(4)
+ if old_crc == new_crc:
+ print('Flash already up to date')
+ sys.exit(0)
+
+ print('CRC: old=0x%08x new=0x%08x' % (old_crc, new_crc))
+
+ # Erase
+ send('e')
+ if recv(1) != '\r': raise Exception('Flash erase failed')
+
+# Get page size
+send('b')
+if recv(1) != 'Y': raise Exception('Cannot get page size')
+page_size = recv_int(2)
+print('Page size:', page_size)
+
+
+# Program
+print('Programming', end = '')
+count = 0
+retry = 0
+for addr, chunk in data:
+ # Set address
+ send('H')
+ send_int(addr, 3)
+ if recv(1) != '\r': raise Exception('Failed to set address')
+
+ while len(chunk):
+ sys.stdout.flush()
+ page = chunk[0:512]
+
+ # Block command
+ send('B')
+
+ # Send block size
+ send_int(len(page), 2)
+
+ # Send memory type
+ send('F')
+
+ # Send block
+ sp.write(page)
+
+ if recv(1) != '\r': raise Exception('Failed to write block')
+
+ # Get and check block CRC
+ send('i')
+ crc = recv_int(2)
+ expect = crc16(page)
+ if crc != expect:
+ retry += 1
+ if retry == 5:
+ raise Exception('CRC mismatch %d != %d' % (crc, expect))
+
+ print('x', end = '')
+ continue
+
+ count += len(page)
+ chunk = chunk[512:]
+ retry = 0
+ print('.', end = '')
+
+
+print('done')
+print('Wrote %d bytes' % count)
+
+# Exit bootloader
+send('E')
diff --git a/scripts/bbctrl.service b/scripts/bbctrl.service
new file mode 100644
index 0000000..8b22cc7
--- /dev/null
+++ b/scripts/bbctrl.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Buildbotics Controller
+After=network.target
+
+[Service]
+User=root
+ExecStart=/usr/local/bin/bbctrl -l /var/log/bbctrl.log
+WorkingDirectory=/var/lib/bbctrl
+Restart=always
+StandardOutput=null
+Nice=-10
+KillMode=process
+
+[Install]
+WantedBy=multi-user.target
diff --git a/scripts/browser b/scripts/browser
new file mode 100644
index 0000000..92bd07f
--- /dev/null
+++ b/scripts/browser
@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import subprocess
+
+
+def enter_cgroup():
+ with open('/sys/fs/cgroup/memory/chrome/tasks', 'w') as f:
+ f.write(str(os.getpid()))
+
+
+# Start browser
+args = ['/usr/lib/chromium-browser/chromium-browser'] + sys.argv[1:]
+subprocess.Popen(args, preexec_fn = enter_cgroup).wait()
diff --git a/scripts/check-config-vars.py b/scripts/check-config-vars.py
new file mode 100644
index 0000000..6fd567a
--- /dev/null
+++ b/scripts/check-config-vars.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+'''Check that the configuration variable template used on the RPi matches the
+variables used in the AVR'''
+
+import sys
+import json
+
+templ = json.load(open('src/resources/config-template.json', 'r'))
+vars = json.load(open('avr/build/vars.json', 'r'))
+
+
+def check(section):
+ errors = 0
+
+ for name, entry in section.items():
+ if 'type' in entry:
+ ok = False
+
+ # TODO check that defaults are valid
+ # TODO check that types match
+
+ if 'code' in entry and not entry['code'] in vars:
+ print('"%s" with code "%s" not found' % (name, entry['code']))
+
+ else: ok = True
+
+ if not ok: errors += 1
+
+ else: errors += check(entry)
+
+ return errors
+
+
+errors = check(templ)
+print('\n%d errors' % errors)
+sys.exit(errors != 0)
diff --git a/scripts/config-screen b/scripts/config-screen
new file mode 100644
index 0000000..364c150
--- /dev/null
+++ b/scripts/config-screen
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+if [ $# != 3 ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+WIDTH="$1"
+HEIGHT="$2"
+ROTATION="$3"
+
+if [[ ! "$WIDTH" =~ ^[0-9]+$ ]]; then
+ echo "Invalid width '$WIDTH'."
+ exit 1
+fi
+
+if [[ ! "$HEIGHT" =~ ^[0-9]+$ ]]; then
+ echo "Invalid height '$HEIGHT'."
+ exit 1
+fi
+
+if [[ ! "$ROTATION" =~ ^[0-3]$ ]]; then
+ echo "Invalid rotation '$ROTATION'."
+ exit 1
+fi
+
+
+OPTIONS="framebuffer_width=$WIDTH "
+OPTIONS+="framebuffer_height=$HEIGHT "
+OPTIONS+="display_rotate=$ROTATION"
+
+edit-boot-config $OPTIONS
diff --git a/scripts/config-wifi b/scripts/config-wifi
new file mode 100644
index 0000000..018c676
--- /dev/null
+++ b/scripts/config-wifi
@@ -0,0 +1,259 @@
+#!/bin/bash -e
+
+AP=false
+DISABLE=false
+SSID=
+PASS=
+CHANNEL=7
+REBOOT=false
+
+WLAN0_CFG=/etc/network/interfaces.d/wlan0
+HOSTAPD_CFG=/etc/hostapd/hostapd.conf
+DNSMASQ_CFG=/etc/dnsmasq.conf
+DHCPCD_CFG=/etc/dhcpcd.conf
+WPA_CFG=/etc/wpa_supplicant/wpa_supplicant.conf
+
+
+function query_config() {
+ if [ -e $WLAN0_CFG ]; then
+ SSID=$(grep wpa-ssid $WLAN0_CFG |
+ sed 's/^[[:space:]]*wpa-ssid "\([^"]*\)"/\1/')
+ echo "{\"ssid\": \"$SSID\", \"mode\": \"client\"}"
+
+ else
+ if [ -e $HOSTAPD_CFG -a -e /etc/default/hostapd ]; then
+ SSID=$(grep ^ssid= $HOSTAPD_CFG | sed 's/^ssid=\(.*\)$/\1/')
+ CHANNEL=$(grep ^channel= $HOSTAPD_CFG |
+ sed 's/^channel=\(.*\)$/\1/')
+
+ echo -n "{\"ssid\": \"$SSID\", "
+ echo "\"channel\": $CHANNEL, \"mode\": \"ap\"}"
+
+ else
+ echo "{\"mode\": \"disabled\"}"
+ fi
+ fi
+
+}
+
+
+function disable_wifi() {
+ rm -f $WLAN0_CFG $HOSTAPD_CFG /etc/default/hostapd
+}
+
+
+function configure_wlan0() {
+ echo "auto wlan0"
+ echo "allow-hotplug wlan0"
+ echo "iface wlan0 inet dhcp"
+ echo " wpa-scan-ssid 1"
+ echo " wpa-ap-scan 1"
+ echo " wpa-key-mgmt WPA-PSK"
+ echo " wpa-proto RSN WPA"
+ echo " wpa-pairwise CCMP TKIP"
+ echo " wpa-group CCMP TKIP"
+ echo " wpa-ssid \"$SSID\""
+
+ if [ ${#PASS} -ne 0 ]; then
+ echo " wpa-psk \"$PASS\""
+ fi
+}
+
+
+function configure_wpa() {
+ echo "country=US"
+ echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev"
+ echo "update_config=1"
+
+ if [ ${#PASS} -eq 0 ]; then
+ echo "network={"
+ echo " ssid=\"$SSID\""
+ echo " key_mgmt=NONE"
+ echo "}"
+ fi
+}
+
+
+function configure_dhcpcd() {
+ echo "hostname"
+ echo "clientid"
+ echo "persistent"
+ echo "option rapid_commit"
+ echo "option domain_name_servers, domain_name, domain_search, host_name"
+ echo "option classless_static_routes"
+ echo "option ntp_servers"
+ echo "option interface_mtu"
+ echo "require dhcp_server_identifier"
+ echo "slaac private"
+
+ if $AP; then
+ echo
+ echo "interface wlan0"
+ echo " static ip_address=192.168.43.1/24"
+ fi
+}
+
+
+function configure_wifi() {
+ disable_wifi
+ echo "source-directory /etc/network/interfaces.d" > /etc/network/interfaces
+ configure_wlan0 > $WLAN0_CFG
+ configure_wpa > $WPA_CFG
+ configure_dhcpcd > $DHCPCD_CFG
+}
+
+
+function configure_dnsmasq() {
+ echo "interface=wlan0"
+ echo "domain-needed"
+ echo "bogus-priv"
+ echo "dhcp-range=192.168.43.2,192.168.43.20,255.255.255.0,12h"
+}
+
+
+function configure_hostapd() {
+ echo "interface=wlan0"
+ echo "driver=nl80211"
+ echo "ssid=$SSID"
+ echo "hw_mode=g"
+ echo "channel=$CHANNEL"
+ echo "wmm_enabled=0"
+ echo "macaddr_acl=0"
+ echo "auth_algs=1"
+ echo "ignore_broadcast_ssid=0"
+ echo "wpa=2"
+ echo "wpa_passphrase=$PASS"
+ echo "wpa_key_mgmt=WPA-PSK"
+ echo "wpa_pairwise=TKIP"
+ echo "rsn_pairwise=CCMP"
+}
+
+
+function is_installed() {
+ dpkg-query -W --showformat='${Status}' $1 |
+ grep "install ok installed" >/dev/null
+ if [ $? -eq 0 ]; then echo true; else echo false; fi
+}
+
+
+function configure_ap() {
+ disable_wifi
+
+ # Install packages
+ (
+ $(is_installed dnsmasq) &&
+ $(is_installed hostapd) &&
+ $(is_installed iptables-persistent)
+
+ ) || (
+ export DEBIAN_FRONTEND=noninteractive
+ apt-get update
+ apt-get install -yq dnsmasq hostapd iptables-persistent
+ )
+
+ configure_dhcpcd > $DHCPCD_CFG
+ configure_dnsmasq > $DNSMASQ_CFG
+ configure_hostapd > $HOSTAPD_CFG
+
+ echo "DAEMON_CONF=\"/etc/hostapd/hostapd.conf\"" > /etc/default/hostapd
+
+ # Enable IP forwarding
+ sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
+ echo 1 > /proc/sys/net/ipv4/ip_forward
+
+ # Enable IP masquerading
+ iptables -t nat -F
+ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+ iptables-save > /etc/iptables/rules.v4
+}
+
+
+function usage() {
+ echo "Usage: config-wifi [OPTIONS]"
+ echo
+ echo "Configure wifi as either a client or access point."
+ echo
+ echo "OPTIONS:"
+ echo
+ echo " -a Configure access point."
+ echo " -d Disable wifi."
+ echo " -r Reboot when done."
+ echo " -s Set SSID."
+ echo " -p Set password."
+ echo " -c Set wifi channel."
+ echo " -j Report wifi config as JSON data."
+ echo
+}
+
+
+# Parse args
+while [ $# -ne 0 ]; do
+ case "$1" in
+ -a) AP=true ;;
+ -d) DISABLE=true ;;
+ -r) REBOOT=true; ;;
+ -s) SSID="$2"; shift ;;
+ -p) PASS="$2"; shift ;;
+ -c) CHANNEL="$2"; shift ;;
+ -j) query_config; exit 0 ;;
+
+ -h)
+ usage
+ exit 0
+ ;;
+
+ *)
+ usage
+ echo "Unknown argument '$1'"
+ exit 1
+ esac
+
+ shift
+done
+
+
+if $DISABLE; then
+ disable_wifi
+
+else
+ # Check args
+ function clean_str() {
+ echo "$1" | tr -d '\n\r"'
+ }
+
+ SSID=$(clean_str "$SSID")
+ PASS=$(clean_str "$PASS")
+
+ LANG=C LC_ALL=C # For correct string byte length
+
+ if [ ${#SSID} -eq 0 -o 32 -lt ${#SSID} ]; then
+ echo "Invalid or missing SSID '$SSID'"
+ exit 1
+ fi
+
+ if [ ${#PASS} -ne 0 ]; then
+ if [ ${#PASS} -lt 8 -o 128 -lt ${#PASS} ]; then
+ echo "Invalid passsword"
+ exit 1
+ fi
+ fi
+
+ echo "$CHANNEL" | grep '^[0-9]\{1,2\}' > /dev/null
+ if [ $? -ne 0 ]; then
+ echo "Invalid channel '$CHANNEL'"
+ exit 1
+ fi
+
+ # Execute
+ if $AP; then
+ echo "Configuring Wifi access point"
+ configure_ap
+
+ else
+ echo "Configuring Wifi"
+ configure_wifi
+ fi
+fi
+
+
+if $REBOOT; then nohup reboot & fi
diff --git a/scripts/demo-chroot b/scripts/demo-chroot
new file mode 100644
index 0000000..75e7578
--- /dev/null
+++ b/scripts/demo-chroot
@@ -0,0 +1,17 @@
+#!/bin/bash -ex
+
+ROOT="$PWD/demo"
+
+# Clean up on EXIT
+function cleanup {
+ umount "$ROOT"/{dev/pts,dev,sys,proc} 2>/dev/null || true
+}
+trap cleanup EXIT
+
+# mount binds
+mount --bind /dev "$ROOT/dev/"
+mount --bind /sys "$ROOT/sys/"
+mount --bind /proc "$ROOT/proc/"
+mount --bind /dev/pts "$ROOT/dev/pts"
+
+chroot "$ROOT" "$@"
diff --git a/scripts/edit-boot-config b/scripts/edit-boot-config
new file mode 100644
index 0000000..d7dd4d4
--- /dev/null
+++ b/scripts/edit-boot-config
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+cp /boot/config.txt /tmp/
+
+edit-config /tmp/config.txt "$@"
+
+diff /boot/config.txt /tmp/config.txt >/dev/null
+if [ $? -eq 1 ]; then
+ mount -o remount,rw /boot
+ mv /tmp/config.txt /boot/
+ mount -o remount,ro /boot
+fi
diff --git a/scripts/edit-config b/scripts/edit-config
new file mode 100644
index 0000000..05377d6
--- /dev/null
+++ b/scripts/edit-config
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+
+import sys
+import argparse
+import re
+
+
+def option_type(s, pat = re.compile(r'\w+=.*')):
+ if not pat.match(s): raise argparse.ArgumentTypeError
+ return s
+
+
+parser = argparse.ArgumentParser(description = 'Edit config file.')
+parser.add_argument('config', help = 'The configuration file to edit.')
+parser.add_argument('options', nargs = '*', type = option_type,
+ metavar = '=', help = 'An option to set.')
+args = parser.parse_args()
+
+
+# Parse config lines and options
+lines = []
+options = {}
+optRE = re.compile(r'(\w+)\s*=\s*([^#]+)(#.*)?')
+
+
+class Line:
+ def __init__(self, text, name = None, value = None, comment = None):
+ self.text = text
+ self.name = name
+ self.value = value
+ self.comment = comment
+
+
+ def __str__(self):
+ if self.name is not None:
+ if self.value.strip():
+ text = '%s=%s' % (self.name, self.value)
+ if self.comment: text += ' # ' + self.comment
+ text += '\n'
+ return text
+
+ else: return ''
+
+ return self.text
+
+
+with open(args.config, 'r') as f:
+ for line in f:
+ m = optRE.match(line.strip())
+
+ if m: name, value, comment = m.groups()
+ else: name, value, comment = None, None, None
+
+ l = Line(line, name, value, comment)
+ lines.append(l)
+ if name is not None: options[name] = l
+
+
+# Save original config
+config = ''.join(map(str, lines))
+
+
+# Set options
+first = True
+for opt in args.options:
+ name, value = opt.split('=', 1)
+
+ if name in options: options[name].value = value
+ else:
+ if first and len(lines) and str(lines[:-1]).strip() != '':
+ first = False
+ lines.append(Line('\n'))
+
+ lines.append(Line(None, name, value, None))
+
+
+# Assemble new config
+new_config = ''.join(map(str, lines))
+
+
+if new_config != config:
+ with open(args.config, 'w') as f:
+ f.write(new_config)
diff --git a/scripts/gplan-build.sh b/scripts/gplan-build.sh
new file mode 100644
index 0000000..a21237d
--- /dev/null
+++ b/scripts/gplan-build.sh
@@ -0,0 +1,6 @@
+#!/bin/bash -ex
+
+cd /mnt/host
+scons -C cbang disable_local="re2 libevent"
+export CBANG_HOME="/mnt/host/cbang"
+scons -C camotics gplan.so with_gui=0 with_tpl=0
diff --git a/scripts/gplan-init-build.sh b/scripts/gplan-init-build.sh
new file mode 100644
index 0000000..6459f49
--- /dev/null
+++ b/scripts/gplan-init-build.sh
@@ -0,0 +1,59 @@
+#!/bin/bash -ex
+
+IMG_DATE=2017-11-29
+IMG_BASE=${IMG_DATE}-raspbian-stretch-lite
+BASE_URL=https://downloads.raspberrypi.org/raspbian_lite/images
+IMG_URL=$BASE_URL/raspbian_lite-2017-12-01/$IMG_BASE.zip
+GPLAN_IMG=gplan-dev.img
+
+# Create dev image
+if [ ! -e $GPLAN_IMG ]; then
+
+ # Get base image
+ if [ ! -e $IMG_BASE.img ]; then
+ if [ ! -e $IMG_BASE.zip ]; then
+ wget $IMG_URL
+ fi
+
+ unzip $IMG_BASE.zip
+ fi
+
+ # Copy base image
+ cp $IMG_BASE.img $GPLAN_IMG.tmp
+
+ # Init image
+ mkdir -p rpi-share
+ cp ./scripts/gplan-init-dev-img.sh rpi-share
+ sudo ./scripts/rpi-chroot.sh $GPLAN_IMG.tmp /mnt/host/gplan-init-dev-img.sh
+
+ # Move image
+ mv $GPLAN_IMG.tmp $GPLAN_IMG
+fi
+
+# Get repos
+function fetch_local_repo() {
+ mkdir -p $1
+ git -C $1 init
+ git -C $1 fetch -t "$2" $3
+ git -C $1 reset --hard FETCH_HEAD
+}
+
+mkdir -p rpi-share || true
+
+if [ ! -e rpi-share/cbang ]; then
+ if [ "$CBANG_HOME" != "" ]; then
+ fetch_local_repo rpi-share/cbang "$CBANG_HOME" master
+ else
+ git clone https://github.com/CauldronDevelopmentLLC/cbang \
+ rpi-share/cbang
+ fi
+fi
+
+if [ ! -e rpi-share/camotics ]; then
+ if [ "$CAMOTICS_HOME" != "" ]; then
+ fetch_local_repo rpi-share/camotics "$CAMOTICS_HOME" master
+ else
+ git clone https://github.com/CauldronDevelopmentLLC/camotics \
+ rpi-share/camotics
+ fi
+fi
diff --git a/scripts/gplan-init-dev-img.sh b/scripts/gplan-init-dev-img.sh
new file mode 100644
index 0000000..cfa9d4e
--- /dev/null
+++ b/scripts/gplan-init-dev-img.sh
@@ -0,0 +1,11 @@
+#!/bin/bash -e
+
+export LC_ALL=C
+cd /mnt/host
+
+# Update the system
+apt-get update
+#apt-get dist-upgrade -y
+
+# Install packages
+apt-get install -y scons build-essential libssl-dev python3-dev
diff --git a/scripts/install.sh b/scripts/install.sh
new file mode 100644
index 0000000..024b836
--- /dev/null
+++ b/scripts/install.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+UPDATE_AVR=true
+UPDATE_PY=true
+REBOOT=false
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --no-avr) UPDATE_AVR=false ;;
+ --no-py) UPDATE_PY=false ;;
+ esac
+ shift 1
+done
+
+
+if $UPDATE_PY; then
+ systemctl stop bbctrl
+
+ # Update service
+ rm -f /etc/init.d/bbctrl
+ cp scripts/bbctrl.service /etc/systemd/system/
+ systemctl daemon-reload
+ systemctl enable bbctrl
+fi
+
+if $UPDATE_AVR; then
+ ./scripts/avr109-flash.py src/avr/bbctrl-avr-firmware.hex
+fi
+
+# Update config.txt
+./scripts/edit-boot-config max_usb_current=1
+./scripts/edit-boot-config config_hdmi_boost=8
+
+# TODO Enable GPU
+#./scripts/edit-boot-config dtoverlay=vc4-kms-v3d
+#./scripts/edit-boot-config gpu_mem=16
+#chmod ug+s /usr/lib/xorg/Xorg
+
+# Fix camera
+grep dwc_otg.fiq_fsm_mask /boot/cmdline.txt >/dev/null
+if [ $? -ne 0 ]; then
+ mount -o remount,rw /boot &&
+ sed -i 's/\(.*\)/\1 dwc_otg.fiq_fsm_mask=0x3/' /boot/cmdline.txt
+ mount -o remount,ro /boot
+ REBOOT=true
+fi
+
+# Enable memory cgroups
+grep cgroup_memory /boot/cmdline.txt >/dev/null
+if [ $? -ne 0 ]; then
+ mount -o remount,rw /boot &&
+ sed -i 's/\(.*\)/\1 cgroup_memory=1/' /boot/cmdline.txt
+ mount -o remount,ro /boot
+ REBOOT=true
+fi
+
+# Remove Hawkeye
+if [ -e /etc/init.d/hawkeye ]; then
+ apt-get remove --purge -y hawkeye
+fi
+
+# Decrease boot delay
+sed -i 's/^TimeoutStartSec=.*$/TimeoutStartSec=1/' \
+ /etc/systemd/system/network-online.target.wants/networking.service
+
+# Change to US keyboard layout
+sed -i 's/^XKBLAYOUT="gb"$/XKBLAYOUT="us" # Comment stops change on upgrade/' \
+ /etc/default/keyboard
+
+# Setup USB stick automount
+diff ./scripts/11-automount.rules /etc/udev/rules.d/11-automount.rules \
+ >/dev/null
+if [ $? -ne 0 ]; then
+ cp ./scripts/11-automount.rules /etc/udev/rules.d/
+ sed -i 's/^\(MountFlags=slave\)/#\1/' \
+ /lib/systemd/system/systemd-udevd.service
+ REBOOT=true
+fi
+
+# Increase swap
+grep 'CONF_SWAPSIZE=1000' /etc/dphys-swapfile >/dev/null
+if [ $? -ne 0 ]; then
+ sed -i 's/^CONF_SWAPSIZE=.*$/CONF_SWAPSIZE=1000/' /etc/dphys-swapfile
+ REBOOT=true
+fi
+
+# Install xinitrc
+cp scripts/xinitrc ~pi/.xinitrc
+chmod +x ~pi/.xinitrc
+chown pi:pi ~pi/.xinitrc
+
+# Install bbserial
+MODSRC=src/bbserial/bbserial.ko
+MODDST=/lib/modules/$(uname -r)/kernel/drivers/tty/serial/bbserial.ko
+diff -q $MODSRC $MODDST 2>/dev/null >/dev/null
+if [ $? -ne 0 ]; then
+ cp $MODSRC $MODDST
+ depmod
+ REBOOT=true
+fi
+
+# Install rc.local
+cp scripts/rc.local /etc/
+
+# Install bbctrl
+if $UPDATE_PY; then
+ rm -rf /usr/local/lib/python*/dist-packages/bbctrl-*
+ ./setup.py install --force
+ service bbctrl restart
+ HTTP_DIR=$(find /usr/local/lib/ -type d -name "http")
+ chmod 777 $HTTP_DIR
+fi
+
+sync
+
+if $REBOOT; then
+ echo "Rebooting"
+ reboot
+fi
+
+echo "Install complete"
diff --git a/scripts/log-position-to-gcode b/scripts/log-position-to-gcode
new file mode 100644
index 0000000..7597fb4
--- /dev/null
+++ b/scripts/log-position-to-gcode
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+
+import json
+import sys
+
+p = [0, 0, 0]
+
+
+print('F400 G21')
+
+for line in sys.stdin:
+ try:
+ if not line.startswith('I:Comm:> '): continue
+ line = line[9:]
+
+ data = json.loads(line)
+
+ changed = False
+ for axis in range(3):
+ var = 'xyz'[axis] + 'p'
+ if var in data:
+ p[axis] = data[var]
+ changed = True
+
+ if changed: print('G1 X%d Y%d Z%d' % tuple(p))
+
+ except json.decoder.JSONDecodeError: pass
diff --git a/scripts/next-rc b/scripts/next-rc
new file mode 100644
index 0000000..2edc50a
--- /dev/null
+++ b/scripts/next-rc
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+
+import os
+import json
+
+if os.path.exists('dist/latest-beta.txt'):
+ with open('dist/latest-beta.txt', 'r') as f:
+ latest_beta = f.read().strip()
+
+else: latest_beta = ''
+
+with open('package.json', 'r') as f:
+ version = json.load(f)['version']
+
+if latest_beta.startswith(version + '-rc'):
+ print(int(latest_beta[len(version) + 3:]) + 1)
+
+else:
+ print(1)
diff --git a/scripts/ratpoisonrc b/scripts/ratpoisonrc
new file mode 100644
index 0000000..3337674
--- /dev/null
+++ b/scripts/ratpoisonrc
@@ -0,0 +1 @@
+startup_message off
diff --git a/scripts/rc.local b/scripts/rc.local
new file mode 100644
index 0000000..43e549a
--- /dev/null
+++ b/scripts/rc.local
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# Mount /boot read only
+mount -o remount,ro /boot
+
+# Load bbserial
+echo 3f201000.serial > /sys/bus/amba/drivers/uart-pl011/unbind
+modprobe -r bbserial
+modprobe bbserial
+
+# Set SPI GPIO mode
+gpio mode 27 alt3
+
+# Create browser memory limited cgroup
+if [ -d sys/fs/cgroup/memory ]; then
+ CGROUP=/sys/fs/cgroup/memory/chrome
+ mkdir $CGROUP
+ chown -R pi:pi $CGROUP
+ echo 650000000 > $CGROUP/memory.soft_limit_in_bytes
+ echo 750000000 > $CGROUP/memory.limit_in_bytes
+fi
+
+# Reload udev
+/etc/init.d/udev restart
+
+# Stop boot splash so it doesn't interfere with X if GPU enabled and to save CPU
+plymouth quit
+
+# Start X in /home/pi
+cd /home/pi
+sudo -u pi startx
diff --git a/scripts/reset-video b/scripts/reset-video
new file mode 100644
index 0000000..94b46cd
--- /dev/null
+++ b/scripts/reset-video
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+
+import sys
+import subprocess
+import os.path
+import time
+
+if not os.path.exists('/dev/video0'):
+ print('/dev/video0 not found')
+ sys.exit(1)
+
+p = subprocess.Popen('udevadm info -q path /dev/video0'.split(),
+ stdout = subprocess.PIPE)
+s = p.communicate()[0].decode('utf-8')
+dev = s.split('/')[7]
+
+with open('/sys/bus/usb/drivers/usb/unbind', 'w') as f:
+ f.write(dev)
+
+time.sleep(1)
+
+with open('/sys/bus/usb/drivers/usb/bind', 'w') as f:
+ f.write(dev)
diff --git a/scripts/rpi-chroot.sh b/scripts/rpi-chroot.sh
new file mode 100644
index 0000000..f7b1f0b
--- /dev/null
+++ b/scripts/rpi-chroot.sh
@@ -0,0 +1,63 @@
+#!/bin/bash -ex
+
+ROOT="$PWD/rpi-root"
+LOOP=9
+
+if [ $# -lt 1 ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+IMAGE="$1"
+LOOP_DEV=/dev/loop${LOOP}
+EXEC=
+
+if [ $# -gt 1 ]; then
+ shift
+ EXEC="$@"
+fi
+
+# install dependecies
+if [ ! -e /usr/bin/qemu-arm-static ]; then
+ apt-get update
+ apt-get install -y qemu qemu-user-static binfmt-support
+fi
+
+# Clean up on EXIT
+function cleanup {
+ umount "$ROOT"/{dev/pts,dev,sys,proc,boot,mnt/host,} 2>/dev/null || true
+ losetup -d $LOOP_DEV 2>/dev/null || true
+ rmdir "$ROOT" 2>/dev/null || true
+}
+trap cleanup EXIT
+
+# set up image as loop device
+losetup $LOOP_DEV "$IMAGE"
+partprobe $LOOP_DEV
+
+# check and fix filesystems
+fsck -f ${LOOP_DEV}p1
+fsck -f ${LOOP_DEV}p2
+
+# make dir
+mkdir -p "$ROOT"
+
+# mount partition
+mount -o rw ${LOOP_DEV}p2 -t ext4 "$ROOT"
+mount -o rw ${LOOP_DEV}p1 "$ROOT/boot"
+
+# mount binds
+mount --bind /dev "$ROOT/dev/"
+mount --bind /sys "$ROOT/sys/"
+mount --bind /proc "$ROOT/proc/"
+mount --bind /dev/pts "$ROOT/dev/pts"
+if [ -e ./rpi-share ]; then
+ mkdir -p "$ROOT/mnt/host"
+ mount --bind ./rpi-share "$ROOT/mnt/host"
+fi
+
+# copy qemu binary
+cp /usr/bin/qemu-arm-static "$ROOT/usr/bin/"
+
+# chroot to raspbian
+chroot "$ROOT" $EXEC
diff --git a/scripts/sethostname b/scripts/sethostname
new file mode 100644
index 0000000..73093b7
--- /dev/null
+++ b/scripts/sethostname
@@ -0,0 +1,26 @@
+#!/bin/bash -e
+
+HOSTNAME="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
+
+if [ "$HOSTNAME" == "" ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+if [ "$HOSTNAME" == "localhost" ]; then
+ echo "Cannot set hostname to 'localhost'"
+ exit 1
+fi
+
+if [ "$HOSTNAME" =~ ^.*\.local$ ]; then
+ echo "Hostname cannot end with '.local'"
+ exit 1
+fi
+
+if [[ ! "$HOSTNAME" =~ ^[a-zA-Z][a-zA-Z0-9-]{0,62}$ ]]; then
+ echo "Invalid hostname '$HOSTNAME'"
+ exit 1
+fi
+
+sed -i "s/^127.0.1.1\([[:space:]]*\).*$/127.0.1.1\1$HOSTNAME/" /etc/hosts
+echo "$HOSTNAME" > /etc/hostname
diff --git a/scripts/setup_rpi.sh b/scripts/setup_rpi.sh
new file mode 100644
index 0000000..89c8b28
--- /dev/null
+++ b/scripts/setup_rpi.sh
@@ -0,0 +1,110 @@
+#!/bin/bash -e
+
+export LC_ALL=C
+cd /mnt/host
+
+# Update the system
+apt-get update
+apt-get dist-upgrade -y
+
+# Install packages
+apt-get install -y avahi-daemon avrdude minicom python3-pip python3-smbus \
+ i2c-tools python3-rpi.gpio libjpeg8 wiringpi dnsmasq hostapd \
+ iptables-persistent chromium-browser xorg rpd-plym-splash samba
+pip3 install --upgrade tornado sockjs-tornado pyserial
+
+# Clean
+apt-get autoclean
+
+# Enable avahi
+update-rc.d avahi-daemon defaults
+
+# Change hostname
+sed -i "s/raspberrypi/bbctrl/" /etc/hosts /etc/hostname
+
+# Create bbmc user
+useradd -m -p $(openssl passwd -1 buildbotics) -s /bin/bash bbmc
+sed -i 's/pi$/pi,bbmc/g' /etc/group
+passwd -l pi
+
+# Disable console on serial port
+sed -i 's/console=[a-zA-Z0-9]*,115200 \?//' /boot/cmdline.txt
+
+# Disable i2c HAT ID probe
+echo -n " bcm2708.vc_i2c_override=1" >> /boot/cmdline.txt
+
+# Enable I2C
+sed -i 's/#dtparam=i2c/dtparam=i2c/' /boot/config.txt
+#echo 'dtparam=i2c_vc=on' >> /boot/config.txt
+echo i2c-bcm2708 >> /etc/modules
+echo i2c-dev >> /etc/modules
+
+# Install bbctrl w/ init.d script
+cp bbctrl.init.d /etc/init.d/bbctrl
+chmod +x /etc/init.d/bbctrl
+update-rc.d bbctrl defaults
+
+# Disable Pi 3 USART BlueTooth swap
+echo -e "\ndtoverlay=pi3-disable-bt" >> /boot/config.txt
+rm -f /etc/systemd/system/multi-user.target.wants/hciuart.service
+
+# Install hawkeye
+dpkg -i hawkeye_0.6_armhf.deb
+sed -i 's/localhost/0.0.0.0/' /etc/hawkeye/hawkeye.conf
+echo 'ACTION=="add", KERNEL=="video0", RUN+="/usr/sbin/service hawkeye restart"' > /etc/udev/rules.d/50-hawkeye.rules
+adduser hawkeye video
+
+# Disable HDMI to save power and remount /boot read-only
+sed -i 's/^exit 0$//' /etc/rc.local
+echo "mount -o remount,ro /boot" >> /etc/rc.local
+echo "gpio mode 27 alt3" >> /etc/rc.local # Enable serial CTS on pin 27
+
+# Dynamic clock to save power
+echo -e "\n# Dynamic clock\nnohz=on" >> /boot/config.txt
+
+# Shave 2 sec off of boot time
+echo -e "\n# Faster boot\ndtparam=sd_overclock=100" >> /boot/config.txt
+
+# Enable ssh
+touch /boot/ssh
+
+# Fix boot
+sed -i 's/ root=[^ ]* / root=\/dev\/mmcblk0p2/' /boot/cmdline.txt
+sed -i 's/^PARTUUID=.*\/boot/\/dev\/mmcblk0p1 \/boot/' /etc/fstab
+sed -i 's/^PARTUUID=.*\//\/dev\/mmcblk0p2 \//' /etc/fstab
+
+# Enable browser in xorg
+sed -i 's/allowed_users=console/allowed_users=anybody/' /etc/X11/Xwrapper.config
+echo "sudo -u pi startx" >> /etc/rc.local
+cp /mnt/host/xinitrc /home/pi/.xinitrc
+cp /mnt/host/ratpoisonrc /home/pi/.ratpoisonrc
+cp /mnt/host/xorg.conf /etc/X11/
+
+# Set screen resolution
+sed -i 's/^#disable_overscan/disable_overscan/' /boot/config.txt
+sed -i 's/^#framebuffer_/framebuffer_/' /boot/config.txt
+
+# Boot splash
+mkdir -p /usr/share/plymouth/themes/buildbotics/
+cp -av /mnt/host/splash/* /usr/share/plymouth/themes/buildbotics/
+echo -n " quiet splash logo.nologo plymouth.ignore-serial-consoles" >> /boot/cmdline.txt
+plymouth-set-default-theme -R buildbotics
+
+# Samba
+# TODO install custom smb.conf
+smbpasswd -a bbmc
+
+# Install bbctrl
+tar xf /mnt/host/bbctrl-*.tar.bz2
+cd $(basename bbctrl-*.tar.bz2 .tar.bz2)
+./setup.py install
+cd ..
+rm -rf $(basename bbctrl-*.tar.bz2 .tar.bz2)
+
+
+# Allow any user to shutdown
+chmod +s /sbin/{halt,reboot,shutdown,poweroff}
+
+# Clean up
+apt-get autoremove -y
+apt-get autoclean -y
diff --git a/scripts/ssh-bbctrl b/scripts/ssh-bbctrl
new file mode 100644
index 0000000..ad9ed9a
--- /dev/null
+++ b/scripts/ssh-bbctrl
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+USER=bbmc
+HOST=bbctrl.local
+
+if [ $# -eq 1 ]; then
+ if [[ "$1" = *@ ]]; then
+ LOGIN="$1"
+ else
+ LOGIN=$USER@"$1"
+ fi
+else
+ LOGIN=$USER@$HOST
+fi
+
+ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$LOGIN"
diff --git a/scripts/svg2abs.js b/scripts/svg2abs.js
new file mode 100644
index 0000000..7cfc6dd
--- /dev/null
+++ b/scripts/svg2abs.js
@@ -0,0 +1,64 @@
+function convertToAbsolute(path) {
+ var x0, y0, x1, y1, x2, y2, segs = path.pathSegList;
+
+ for (var x = 0, y = 0, i = 0, len = segs.numberOfItems; i < len; i++) {
+ var seg = segs.getItem(i), c = seg.pathSegTypeAsLetter;
+
+ if (/[MLHVCSQTA]/.test(c)){
+ if ('x' in seg) x = seg.x;
+ if ('y' in seg) y = seg.y;
+
+ } else {
+ if ('x1' in seg) x1 = x + seg.x1;
+ if ('x2' in seg) x2 = x + seg.x2;
+ if ('y1' in seg) y1 = y + seg.y1;
+ if ('y2' in seg) y2 = y + seg.y2;
+ if ('x' in seg) x += seg.x;
+ if ('y' in seg) y += seg.y;
+
+ switch(c) {
+ case 'm':
+ segs.replaceItem(path.createSVGPathSegMovetoAbs(x, y), i);
+ break;
+ case 'l':
+ segs.replaceItem(path.createSVGPathSegLinetoAbs(x, y), i);
+ break;
+ case 'h':
+ segs.replaceItem(path.createSVGPathSegLinetoHorizontalAbs(x), i);
+ break;
+ case 'v':
+ segs.replaceItem(path.createSVGPathSegLinetoVerticalAbs(y), i);
+ break;
+ case 'c':
+ segs.replaceItem(
+ path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2), i);
+ break;
+ case 's':
+ segs.replaceItem(
+ path.createSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2), i);
+ break;
+ case 'q':
+ segs.replaceItem(
+ path.createSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1), i);
+ break;
+ case 't':
+ segs.replaceItem(
+ path.createSVGPathSegCurvetoQuadraticSmoothAbs(x, y), i);
+ break;
+ case 'a':
+ segs.replaceItem(
+ path.createSVGPathSegArcAbs(x, y, seg.r1, seg.r2, seg.angle,
+ seg.largeArcFlag, seg.sweepFlag), i);
+ break;
+
+ case 'z': case 'Z':
+ x = x0;
+ y = y0;
+ break;
+ }
+ }
+
+ // Record the start of a subpath
+ if (c == 'M' || c == 'm') x0 = x, y0 = y;
+ }
+}
diff --git a/scripts/update-bbctrl b/scripts/update-bbctrl
new file mode 100644
index 0000000..ad4023b
--- /dev/null
+++ b/scripts/update-bbctrl
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+(
+ flock -n 9
+
+ UPDATE=/var/lib/bbctrl/firmware/update.tar.bz2
+
+ if [ ! -e "$UPDATE" ]; then
+ echo "Missing $UPDATE"
+ exit 1
+ fi
+
+ systemctl stop bbctrl
+
+ rm -rf /tmp/update
+ mkdir /tmp/update
+ cd /tmp/update
+
+ LOG=/var/log/bbctrl.$(date +%Y%m%d-%H%M%S).install
+ tar xf "$UPDATE"
+ cd *
+ ./scripts/install.sh "$*" 2>&1 > $LOG
+
+ cd -
+ rm -rf /tmp/update $UPDATE
+
+) 9> /var/lock/bbctrl.update.lock
diff --git a/scripts/upgrade-bbctrl b/scripts/upgrade-bbctrl
new file mode 100644
index 0000000..a26d26e
--- /dev/null
+++ b/scripts/upgrade-bbctrl
@@ -0,0 +1,25 @@
+#!/bin/bash -e
+
+(
+ flock -n 9
+
+ VERSION=$(curl -s https://raw.githubusercontent.com/OneFinityCNC/onefinity/master/latest.txt)
+ PKG_NAME=onefinity-$VERSION
+ PKG=/var/lib/bbctrl/firmware/update.tar.bz2
+ PKG_URL=https://https://raw.githubusercontent.com/OneFinityCNC/onefinity/master/release/$PKG_NAME.tar.bz2
+
+ logger Installing bbctrl firmware $VERSION
+
+ cd /var/lib/bbctrl
+ mkdir -p firmware
+
+ echo Downloading $PKG_URL
+ curl -s $PKG_URL > $PKG
+
+ /usr/local/bin/update-bbctrl
+
+ echo Success
+
+ logger bbctrl firmware $VERSION installed
+
+) 9> /var/lock/bbctrl.upgrade.lock
diff --git a/scripts/xinitrc b/scripts/xinitrc
new file mode 100644
index 0000000..048eac4
--- /dev/null
+++ b/scripts/xinitrc
@@ -0,0 +1,22 @@
+hostinfo.sh &
+ratpoison &
+
+xset -dpms
+xset s off
+xset s noblank
+
+while true; do
+ tvservice -s 2>&1 | grep "state 0x40001" >/dev/null
+ if [ $? -ne 0 ]; then
+ # Clear browser errors
+ PREFS='/home/pi/.config/chromium/Default/Preferences'
+ sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' $PREFS
+ sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' $PREFS
+
+ # Start browser
+ /usr/local/bin/browser --no-first-run --disable-infobars \
+ --noerrdialogs --disable-3d-apis http://localhost/
+ fi
+
+ sleep 1
+done
diff --git a/scripts/xorg.conf b/scripts/xorg.conf
new file mode 100644
index 0000000..acbd369
--- /dev/null
+++ b/scripts/xorg.conf
@@ -0,0 +1,3 @@
+Section "ServerFlags"
+ Option "DontVTSwitch" "on"
+EndSection
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..ba15267
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,2 @@
+[sdist]
+formats=bztar
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..cf4069d
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+from setuptools import setup
+import json
+
+pkg = json.load(open('package.json', 'r'))
+
+
+setup(
+ name = pkg['name'],
+ version = pkg['version'],
+ description = 'Buildbotics Machine Controller',
+ long_description = open('README.md', 'rt').read(),
+ author = 'Joseph Coffland',
+ author_email = 'joseph@buildbotics.org',
+ platforms = ['any'],
+ license = pkg['license'],
+ url = pkg['homepage'],
+ package_dir = {'': 'src/py'},
+ packages = ['bbctrl', 'inevent', 'lcd', 'camotics'],
+ include_package_data = True,
+ entry_points = {
+ 'console_scripts': [
+ 'bbctrl = bbctrl:run'
+ ]
+ },
+ scripts = [
+ 'scripts/update-bbctrl',
+ 'scripts/upgrade-bbctrl',
+ 'scripts/sethostname',
+ 'scripts/reset-video',
+ 'scripts/config-wifi',
+ 'scripts/config-screen',
+ 'scripts/edit-config',
+ 'scripts/edit-boot-config',
+ 'scripts/browser',
+ ],
+ install_requires = 'tornado sockjs-tornado pyserial pyudev smbus2'.split(),
+ zip_safe = False,
+ )
diff --git a/src/avr/.gitignore b/src/avr/.gitignore
new file mode 100644
index 0000000..abe2d5d
--- /dev/null
+++ b/src/avr/.gitignore
@@ -0,0 +1,14 @@
+# Backup files
+*~
+\#*
+
+build
+.dep
+
+/*.eep
+/*.hex
+/*.elf
+/*.lss
+/*.map
+
+*.o
diff --git a/src/avr/BezierMath.md b/src/avr/BezierMath.md
new file mode 100644
index 0000000..f9da75a
--- /dev/null
+++ b/src/avr/BezierMath.md
@@ -0,0 +1,56 @@
+# Cubic Bezier
+
+ f(x) = A(1 - x)^3 + 3B(1 - x)^2 x + 3C(1 - x) x^2 + Dx^3
+
+ -Ax^3 + 3Ax^2 - 3Ax + A
+ 3Bx^3 - 6Bx^2 + 3Bx
+ -3Cx^3 + 3Cx^2
+ Dx^3
+
+
+ f(x) = (-A + 3B -3C + D)x^3 + (3A - 6B + 3C)x^2 + (-3A + 3B)x + A
+
+ a = -A + 3B - 3C + D
+ b = 3A - 6B + 3C
+ c = -3A + 3B
+ d = A
+
+ f(x) = ax^3 + bx^2 + cx + d
+
+ integral f(x) dx = a/4 x^4 + b/3 x^3 + c/2 x^2 + dx + E
+
+ = (-A + 3B - 3C + D)/4 x^4 + (A - 2B + B) x^3 + 3/2 (B - A) x^2 + Ax + E
+
+# Quintic Bezier
+
+ A(1 - x)^5 + 5A(1 - x)^4 x + 10A(1 - x)^3 x^2 + 10B(1 - x)^2 x^3 +
+ 5B(1 - x)x^4 + Bx^5
+
+ (-6A + 6B)x^5 + (15A - 15B)x^4 + (-10A + 10B)x^3 + A
+
+ 6(B - A)x^5 + 15(A - B)x^4 + 10(B - A)x^3 + A
+
+ x^3 (6(B - A)x^2 + 15(A - B)x + 10(B - A)) + A
+
+ a = 6(B - A)
+ b = -15(B - A)
+ c = 10(B - A)
+ d = A
+
+ f(x) = ax^5 + bx^4 + cx^3 + d
+
+ f(x) = (ax^2 + bx + c)x^3 + d
+
+
+ integral f(x) = a/6 x^6 + b/5 x^5 + c/4 x^4 + dx + e
+
+ = (B - A)x^6 - 3(B - A)x^5 + 5/2(B - A)x^4 + Ax + e
+
+ = (B - A)x^4 (x^2 - 3x + 5/2) + Ax + e
+
+ A = 0
+ B = 1
+ e = 0
+
+ f(x) = 6x^5 -15x^4 + 10x^3
+ int f(x) dx = x^6 - 3x^5 + 5/2x^4 + C
diff --git a/src/avr/Makefile b/src/avr/Makefile
new file mode 100644
index 0000000..dc490c4
--- /dev/null
+++ b/src/avr/Makefile
@@ -0,0 +1,40 @@
+# Makefile for the project Bulidbotics firmware
+PROJECT = bbctrl-avr-firmware
+MCU = atxmega192a3u
+CLOCK = 32000000
+
+# SRC
+SRC = $(wildcard src/*.c) $(wildcard src/*.cpp) $(wildcard src/vfd/*.c)
+OBJ := $(patsubst src/%.c,build/%.o,$(SRC))
+OBJ := $(patsubst src/%.cpp,build/%.o,$(OBJ))
+OBJ := $(patsubst src/vfd/%.c,build/vfd/%.o,$(OBJ))
+JSON = vars command messages
+JSON := $(patsubst %,build/%.json,$(JSON))
+
+all: $(PROJECT).hex $(JSON) size
+
+include Makefile.common
+
+CFLAGS += -Isrc
+
+# Build
+$(PROJECT).elf: $(OBJ)
+ $(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@
+
+
+# JSON
+build/%.json: src/%.json.in src/%.def
+ cpp -Isrc $< | sed "/^#.*$$/d;s/'\(.\)'/\"\1\"/g" > $@
+
+# Program
+init:
+ $(MAKE) erase
+ -$(MAKE) fuses
+ $(MAKE) fuses
+ $(MAKE) program-boot
+ $(MAKE) program
+
+program-boot:
+ $(MAKE) -C ../boot program
+
+.PHONY: all init program-boot
diff --git a/src/avr/Makefile.common b/src/avr/Makefile.common
new file mode 100644
index 0000000..65c9480
--- /dev/null
+++ b/src/avr/Makefile.common
@@ -0,0 +1,115 @@
+# Compile flags
+CC = avr-g++
+
+COMMON = -mmcu=$(MCU) -flto -fwhole-program
+
+CFLAGS += $(COMMON)
+CFLAGS += -Wall -Werror
+CFLAGS += -Wno-error=strict-aliasing # for _invsqrt
+CFLAGS += -std=gnu++98 -DF_CPU=$(CLOCK)UL -O3
+CFLAGS += -funsigned-bitfields -fpack-struct -fshort-enums -funsigned-char
+CFLAGS += -MD -MP -MT $@ -MF build/dep/$(@F).d
+CFLAGS += -D__STDC_LIMIT_MACROS
+
+# Linker flags
+LDFLAGS += $(COMMON) -Wl,-u,vfprintf -lprintf_flt -lm
+LIBS += -lm
+
+# EEPROM flags
+EEFLAGS += -j .eeprom
+EEFLAGS += --set-section-flags=.eeprom="alloc,load"
+EEFLAGS += --change-section-lma .eeprom=0 --no-change-warnings
+
+# Programming flags
+ifndef (PROGRAMMER)
+PROGRAMMER = avrispmkII
+#PROGRAMMER = jtag3pdi
+endif
+PDEV = usb
+AVRDUDE_OPTS = -c $(PROGRAMMER) -p $(MCU) -P $(PDEV)
+
+FUSE0=0xff
+FUSE1=0x00
+FUSE2=0xbe
+FUSE4=0xff
+FUSE5=0xeb
+
+# Compile
+build/%.o: src/%.c
+ @mkdir -p $(shell dirname $@)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+build/%.o: src/%.cpp
+ @mkdir -p $(shell dirname $@)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+build/%.o: src/%.S
+ @mkdir -p $(shell dirname $@)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+# Link
+%.hex: %.elf
+ avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $< $@
+
+%.eep: %.elf
+ avr-objcopy $(EEFLAGS) -O ihex $< $@
+
+%.lss: %.elf
+ avr-objdump -h -S $< > $@
+
+size: $(PROJECT).elf
+ @for X in A B C; do\
+ echo '****************************************************************' ;\
+ avr-size -$$X --mcu=$(MCU) $(PROJECT).elf ;\
+ done
+
+data-usage: $(PROJECT).elf
+ avr-nm -CS --size-sort -t decimal $(PROJECT).elf | grep ' [BbDd] '
+
+
+prog-usage: $(PROJECT).elf
+ avr-nm -CS --size-sort -t decimal $(PROJECT).elf | grep -v ' [BbDd] '
+
+# Program
+reset:
+ avrdude $(AVRDUDE_OPTS)
+
+erase:
+ avrdude $(AVRDUDE_OPTS) -e
+
+program: $(PROJECT).hex
+ avrdude $(AVRDUDE_OPTS) -U flash:w:$(PROJECT).hex:i
+
+verify: $(PROJECT).hex
+ avrdude $(AVRDUDE_OPTS) -U flash:v:$(PROJECT).hex:i
+
+fuses:
+ avrdude $(AVRDUDE_OPTS) -U fuse0:w:$(FUSE0):m -U fuse1:w:$(FUSE1):m \
+ -U fuse2:w:$(FUSE2):m -U fuse4:w:$(FUSE4):m -U fuse5:w:$(FUSE5):m
+
+read_fuses:
+ avrdude $(AVRDUDE_OPTS) -q -q -U fuse0:r:-:h -U fuse1:r:-:h -U fuse2:r:-:h \
+ -U fuse4:r:-:h -U fuse5:r:-:h
+
+signature:
+ avrdude $(AVRDUDE_OPTS) -q -q -U signature:r:-:h
+
+prodsig:
+ avrdude $(AVRDUDE_OPTS) -q -q -U prodsig:r:-:h
+
+usersig:
+ avrdude $(AVRDUDE_OPTS) -q -q -U usersig:r:-:h
+
+# Clean
+tidy:
+ rm -f $(shell find -name \*~ -o -name \#\*)
+
+clean: tidy
+ rm -rf $(PROJECT).elf $(PROJECT).hex $(PROJECT).eep $(PROJECT).lss \
+ $(PROJECT).map build
+
+.PHONY: tidy clean size reset erase program fuses read_fuses prodsig
+.PHONY: signature usersig data-usage prog-usage
+
+# Dependencies
+-include $(shell mkdir -p build/dep) $(wildcard build/dep/*)
diff --git a/src/avr/README.md b/src/avr/README.md
new file mode 100644
index 0000000..97f5eb0
--- /dev/null
+++ b/src/avr/README.md
@@ -0,0 +1,18 @@
+The Buildbotics firmware is a 4 axis motion control system designed for
+high-performance on small to mid-sized machines. It operates in conjunction
+with the Buildbotics RaspberryPi firmware.
+
+# Build Instructions
+To build in Linux run:
+
+ make
+
+Other make commands are:
+
+ * **size** - Display program and data sizes
+ * **program** - program using AVR dude and an avrispmkII
+ * **erase** - Erase chip
+ * **fuses** - Write AVR fuses bytes
+ * **read_fuses** - Read and print AVR fuse bytes
+ * **clean** - Remove build files
+ * **tidy** - Remove backup files
diff --git a/src/avr/data_usage.py b/src/avr/data_usage.py
new file mode 100644
index 0000000..27863ec
--- /dev/null
+++ b/src/avr/data_usage.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+
+################################################################################
+# #
+# This file is part of the Buildbotics firmware. #
+# #
+# Copyright (c) 2015 - 2018, Buildbotics LLC #
+# All rights reserved. #
+# #
+# This file ("the software") is free software: you can redistribute it #
+# and/or modify it under the terms of the GNU General Public License, #
+# version 2 as published by the Free Software Foundation. You should #
+# have received a copy of the GNU General Public License, version 2 #
+# along with the software. If not, see . #
+# #
+# The software 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 the software. If not, see #
+# . #
+# #
+# For information regarding this software email: #
+# "Joseph Coffland" #
+# #
+################################################################################
+
+import os
+import re
+import shlex
+import subprocess
+
+
+lineRE = r'%(addr)s '
+command = 'avr-objdump -j .bss -t buildbotics.elf'
+
+proc = subprocess.Popen(shlex.split(command), stdout = subprocess.PIPE)
+
+out, err = proc.communicate()
+
+if proc.returncode:
+ print(out)
+ raise Exception('command failed')
+
+def get_sizes(data):
+ for line in data.decode().split('\n'):
+ if not re.match(r'^[0-9a-f]{8} .*', line): continue
+
+ size, name = int(line[22:30], 16), line[31:]
+ if not size: continue
+
+ yield (size, name)
+
+sizes = sorted(get_sizes(out))
+total = sum(x[0] for x in sizes)
+
+for size, name in sizes:
+ print('% 6d %5.2f%% %s' % (size, size / total * 100, name))
+
+print('-' * 40)
+print('% 6d Total' % total)
diff --git a/src/avr/emu/.gitignore b/src/avr/emu/.gitignore
new file mode 100644
index 0000000..0bbedea
--- /dev/null
+++ b/src/avr/emu/.gitignore
@@ -0,0 +1 @@
+bbemu
diff --git a/src/avr/emu/Makefile b/src/avr/emu/Makefile
new file mode 100644
index 0000000..7f982b2
--- /dev/null
+++ b/src/avr/emu/Makefile
@@ -0,0 +1,38 @@
+TARGET = bbemu
+
+SRC:=$(wildcard ../src/*.c) $(wildcard ../src/*.cpp)
+OBJ:=$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRC)))
+OBJ:=$(patsubst ../src/%,build/%,$(OBJ))
+SRC+=src/emu.c
+OBJ+=build/emu.o
+
+CFLAGS = -I../src -Isrc -Wall -Werror -DDEBUG -g -std=gnu++98
+CFLAGS += -MD -MP -MT $@ -MF build/$(@F).d
+CFLAGS += -DF_CPU=32000000 -Wno-class-memaccess -pthread
+LDFLAGS = -lm -pthread
+
+all: $(TARGET)
+
+$(TARGET): $(OBJ)
+ g++ -o $@ $(OBJ) $(LDFLAGS)
+
+build/%.o: ../src/%.c
+ g++ -c -o $@ $(CFLAGS) $<
+
+build/%.o: src/%.c
+ g++ -c -o $@ $(CFLAGS) $<
+
+build/%.o: ../src/%.cpp
+ g++ -c -o $@ $(CFLAGS) $<
+
+# Clean
+tidy:
+ rm -f $(shell find -name \*~ -o -name \#\*)
+
+clean: tidy
+ rm -rf $(TARGET) build
+
+.PHONY: tidy clean all
+
+# Dependencies
+-include $(shell mkdir -p build) $(wildcard build/*.d)
diff --git a/src/avr/emu/src/avr/eeprom.h b/src/avr/emu/src/avr/eeprom.h
new file mode 100644
index 0000000..bafb8b0
--- /dev/null
+++ b/src/avr/emu/src/avr/eeprom.h
@@ -0,0 +1,34 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#define EEMEM
+
+#define eeprom_update_word(PTR, VAL) *(PTR) = (VAL)
+#define eeprom_read_word(PTR) *(PTR)
+#define eeprom_is_ready() true
diff --git a/src/avr/emu/src/avr/interrupt.h b/src/avr/emu/src/avr/interrupt.h
new file mode 100644
index 0000000..10fd67b
--- /dev/null
+++ b/src/avr/emu/src/avr/interrupt.h
@@ -0,0 +1,35 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "io.h"
+
+void cli();
+void sei();
+
+#define ISR(X) void __##X()
diff --git a/src/avr/emu/src/avr/io.h b/src/avr/emu/src/avr/io.h
new file mode 100644
index 0000000..3d0e145
--- /dev/null
+++ b/src/avr/emu/src/avr/io.h
@@ -0,0 +1,7718 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+/*****************************************************************************
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of the copyright holders nor the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************************/
+
+#ifndef _AVR_ATXMEGA192A3U_H_INCLUDED
+#define _AVR_ATXMEGA192A3U_H_INCLUDED
+
+#include
+
+#define _SFR_MEM8(mem_addr) (*(volatile uint8_t *)(io_mem + (mem_addr)))
+extern volatile uint8_t io_mem[4096];
+
+/* Ungrouped common registers */
+#define GPIOR0 _SFR_MEM8(0x0000) /* General Purpose IO Register 0 */
+#define GPIOR1 _SFR_MEM8(0x0001) /* General Purpose IO Register 1 */
+#define GPIOR2 _SFR_MEM8(0x0002) /* General Purpose IO Register 2 */
+#define GPIOR3 _SFR_MEM8(0x0003) /* General Purpose IO Register 3 */
+#define GPIOR4 _SFR_MEM8(0x0004) /* General Purpose IO Register 4 */
+#define GPIOR5 _SFR_MEM8(0x0005) /* General Purpose IO Register 5 */
+#define GPIOR6 _SFR_MEM8(0x0006) /* General Purpose IO Register 6 */
+#define GPIOR7 _SFR_MEM8(0x0007) /* General Purpose IO Register 7 */
+#define GPIOR8 _SFR_MEM8(0x0008) /* General Purpose IO Register 8 */
+#define GPIOR9 _SFR_MEM8(0x0009) /* General Purpose IO Register 9 */
+#define GPIORA _SFR_MEM8(0x000A) /* General Purpose IO Register 10 */
+#define GPIORB _SFR_MEM8(0x000B) /* General Purpose IO Register 11 */
+#define GPIORC _SFR_MEM8(0x000C) /* General Purpose IO Register 12 */
+#define GPIORD _SFR_MEM8(0x000D) /* General Purpose IO Register 13 */
+#define GPIORE _SFR_MEM8(0x000E) /* General Purpose IO Register 14 */
+#define GPIORF _SFR_MEM8(0x000F) /* General Purpose IO Register 15 */
+
+/* Deprecated */
+#define GPIO0 _SFR_MEM8(0x0000) /* General Purpose IO Register 0 */
+#define GPIO1 _SFR_MEM8(0x0001) /* General Purpose IO Register 1 */
+#define GPIO2 _SFR_MEM8(0x0002) /* General Purpose IO Register 2 */
+#define GPIO3 _SFR_MEM8(0x0003) /* General Purpose IO Register 3 */
+#define GPIO4 _SFR_MEM8(0x0004) /* General Purpose IO Register 4 */
+#define GPIO5 _SFR_MEM8(0x0005) /* General Purpose IO Register 5 */
+#define GPIO6 _SFR_MEM8(0x0006) /* General Purpose IO Register 6 */
+#define GPIO7 _SFR_MEM8(0x0007) /* General Purpose IO Register 7 */
+#define GPIO8 _SFR_MEM8(0x0008) /* General Purpose IO Register 8 */
+#define GPIO9 _SFR_MEM8(0x0009) /* General Purpose IO Register 9 */
+#define GPIOA _SFR_MEM8(0x000A) /* General Purpose IO Register 10 */
+#define GPIOB _SFR_MEM8(0x000B) /* General Purpose IO Register 11 */
+#define GPIOC _SFR_MEM8(0x000C) /* General Purpose IO Register 12 */
+#define GPIOD _SFR_MEM8(0x000D) /* General Purpose IO Register 13 */
+#define GPIOE _SFR_MEM8(0x000E) /* General Purpose IO Register 14 */
+#define GPIOF _SFR_MEM8(0x000F) /* General Purpose IO Register 15 */
+
+#define CCP _SFR_MEM8(0x0034) /* Configuration Change Protection */
+#define RAMPD _SFR_MEM8(0x0038) /* Ramp D */
+#define RAMPX _SFR_MEM8(0x0039) /* Ramp X */
+#define RAMPY _SFR_MEM8(0x003A) /* Ramp Y */
+#define RAMPZ _SFR_MEM8(0x003B) /* Ramp Z */
+#define EIND _SFR_MEM8(0x003C) /* Extended Indirect Jump */
+#define SPL _SFR_MEM8(0x003D) /* Stack Pointer Low */
+#define SPH _SFR_MEM8(0x003E) /* Stack Pointer High */
+#define SREG _SFR_MEM8(0x003F) /* Status Register */
+
+/* C Language Only */
+#if !defined (__ASSEMBLER__)
+
+#include
+
+typedef volatile uint8_t register8_t;
+typedef volatile uint16_t register16_t;
+typedef volatile uint32_t register32_t;
+
+
+#ifdef _WORDREGISTER
+#undef _WORDREGISTER
+#endif
+#define _WORDREGISTER(regname) \
+ __extension__ union \
+ { \
+ register16_t regname; \
+ struct \
+ { \
+ register8_t regname ## L; \
+ register8_t regname ## H; \
+ }; \
+ }
+
+#ifdef _DWORDREGISTER
+#undef _DWORDREGISTER
+#endif
+#define _DWORDREGISTER(regname) \
+ __extension__ union \
+ { \
+ register32_t regname; \
+ struct \
+ { \
+ register8_t regname ## 0; \
+ register8_t regname ## 1; \
+ register8_t regname ## 2; \
+ register8_t regname ## 3; \
+ }; \
+ }
+
+
+/*
+==========================================================================
+IO Module Structures
+==========================================================================
+*/
+
+
+/*
+--------------------------------------------------------------------------
+VPORT - Virtual Ports
+--------------------------------------------------------------------------
+*/
+
+/* Virtual Port */
+typedef struct VPORT_struct
+{
+ register8_t DIR; /* I/O Port Data Direction */
+ register8_t OUT; /* I/O Port Output */
+ register8_t IN; /* I/O Port Input */
+ register8_t INTFLAGS; /* Interrupt Flag Register */
+} VPORT_t;
+
+
+/*
+--------------------------------------------------------------------------
+XOCD - On-Chip Debug System
+--------------------------------------------------------------------------
+*/
+
+/* On-Chip Debug System */
+typedef struct OCD_struct
+{
+ register8_t OCDR0; /* OCD Register 0 */
+ register8_t OCDR1; /* OCD Register 1 */
+} OCD_t;
+
+
+/*
+--------------------------------------------------------------------------
+CPU - CPU
+--------------------------------------------------------------------------
+*/
+
+/* CCP signatures */
+typedef enum CCP_enum
+{
+ CCP_SPM_gc = (0x9D<<0), /* SPM Instruction Protection */
+ CCP_IOREG_gc = (0xD8<<0), /* IO Register Protection */
+} CCP_t;
+
+
+/*
+--------------------------------------------------------------------------
+CLK - Clock System
+--------------------------------------------------------------------------
+*/
+
+/* Clock System */
+typedef struct CLK_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t PSCTRL; /* Prescaler Control Register */
+ register8_t LOCK; /* Lock register */
+ register8_t RTCCTRL; /* RTC Control Register */
+ register8_t USBCTRL; /* USB Control Register */
+} CLK_t;
+
+
+/* Power Reduction */
+typedef struct PR_struct
+{
+ register8_t PRGEN; /* General Power Reduction */
+ register8_t PRPA; /* Power Reduction Port A */
+ register8_t PRPB; /* Power Reduction Port B */
+ register8_t PRPC; /* Power Reduction Port C */
+ register8_t PRPD; /* Power Reduction Port D */
+ register8_t PRPE; /* Power Reduction Port E */
+ register8_t PRPF; /* Power Reduction Port F */
+} PR_t;
+
+/* System Clock Selection */
+typedef enum CLK_SCLKSEL_enum
+{
+ CLK_SCLKSEL_RC2M_gc = (0x00<<0), /* Internal 2 MHz RC Oscillator */
+ CLK_SCLKSEL_RC32M_gc = (0x01<<0), /* Internal 32 MHz RC Oscillator */
+ CLK_SCLKSEL_RC32K_gc = (0x02<<0), /* Internal 32.768 kHz RC Oscillator */
+ CLK_SCLKSEL_XOSC_gc = (0x03<<0), /* External Crystal Oscillator or Clock */
+ CLK_SCLKSEL_PLL_gc = (0x04<<0), /* Phase Locked Loop */
+} CLK_SCLKSEL_t;
+
+/* Prescaler A Division Factor */
+typedef enum CLK_PSADIV_enum
+{
+ CLK_PSADIV_1_gc = (0x00<<2), /* Divide by 1 */
+ CLK_PSADIV_2_gc = (0x01<<2), /* Divide by 2 */
+ CLK_PSADIV_4_gc = (0x03<<2), /* Divide by 4 */
+ CLK_PSADIV_8_gc = (0x05<<2), /* Divide by 8 */
+ CLK_PSADIV_16_gc = (0x07<<2), /* Divide by 16 */
+ CLK_PSADIV_32_gc = (0x09<<2), /* Divide by 32 */
+ CLK_PSADIV_64_gc = (0x0B<<2), /* Divide by 64 */
+ CLK_PSADIV_128_gc = (0x0D<<2), /* Divide by 128 */
+ CLK_PSADIV_256_gc = (0x0F<<2), /* Divide by 256 */
+ CLK_PSADIV_512_gc = (0x11<<2), /* Divide by 512 */
+} CLK_PSADIV_t;
+
+/* Prescaler B and C Division Factor */
+typedef enum CLK_PSBCDIV_enum
+{
+ CLK_PSBCDIV_1_1_gc = (0x00<<0), /* Divide B by 1 and C by 1 */
+ CLK_PSBCDIV_1_2_gc = (0x01<<0), /* Divide B by 1 and C by 2 */
+ CLK_PSBCDIV_4_1_gc = (0x02<<0), /* Divide B by 4 and C by 1 */
+ CLK_PSBCDIV_2_2_gc = (0x03<<0), /* Divide B by 2 and C by 2 */
+} CLK_PSBCDIV_t;
+
+/* RTC Clock Source */
+typedef enum CLK_RTCSRC_enum
+{
+ CLK_RTCSRC_ULP_gc = (0x00<<1), /* 1.024 kHz from internal 32kHz ULP */
+ CLK_RTCSRC_TOSC_gc = (0x01<<1), /* 1.024 kHz from 32.768 kHz crystal oscillator on TOSC */
+ CLK_RTCSRC_RCOSC_gc = (0x02<<1), /* 1.024 kHz from internal 32.768 kHz RC oscillator */
+ CLK_RTCSRC_TOSC32_gc = (0x05<<1), /* 32.768 kHz from 32.768 kHz crystal oscillator on TOSC */
+ CLK_RTCSRC_RCOSC32_gc = (0x06<<1), /* 32.768 kHz from internal 32.768 kHz RC oscillator */
+ CLK_RTCSRC_EXTCLK_gc = (0x07<<1), /* External Clock from TOSC1 */
+} CLK_RTCSRC_t;
+
+/* USB Prescaler Division Factor */
+typedef enum CLK_USBPSDIV_enum
+{
+ CLK_USBPSDIV_1_gc = (0x00<<3), /* Divide by 1 */
+ CLK_USBPSDIV_2_gc = (0x01<<3), /* Divide by 2 */
+ CLK_USBPSDIV_4_gc = (0x02<<3), /* Divide by 4 */
+ CLK_USBPSDIV_8_gc = (0x03<<3), /* Divide by 8 */
+ CLK_USBPSDIV_16_gc = (0x04<<3), /* Divide by 16 */
+ CLK_USBPSDIV_32_gc = (0x05<<3), /* Divide by 32 */
+} CLK_USBPSDIV_t;
+
+/* USB Clock Source */
+typedef enum CLK_USBSRC_enum
+{
+ CLK_USBSRC_PLL_gc = (0x00<<1), /* PLL */
+ CLK_USBSRC_RC32M_gc = (0x01<<1), /* Internal 32 MHz RC Oscillator */
+} CLK_USBSRC_t;
+
+
+/*
+--------------------------------------------------------------------------
+SLEEP - Sleep Controller
+--------------------------------------------------------------------------
+*/
+
+/* Sleep Controller */
+typedef struct SLEEP_struct
+{
+ register8_t CTRL; /* Control Register */
+} SLEEP_t;
+
+/* Sleep Mode */
+typedef enum SLEEP_SMODE_enum
+{
+ SLEEP_SMODE_IDLE_gc = (0x00<<1), /* Idle mode */
+ SLEEP_SMODE_PDOWN_gc = (0x02<<1), /* Power-down Mode */
+ SLEEP_SMODE_PSAVE_gc = (0x03<<1), /* Power-save Mode */
+ SLEEP_SMODE_STDBY_gc = (0x06<<1), /* Standby Mode */
+ SLEEP_SMODE_ESTDBY_gc = (0x07<<1), /* Extended Standby Mode */
+} SLEEP_SMODE_t;
+
+
+
+#define SLEEP_MODE_IDLE (0x00<<1)
+#define SLEEP_MODE_PWR_DOWN (0x02<<1)
+#define SLEEP_MODE_PWR_SAVE (0x03<<1)
+#define SLEEP_MODE_STANDBY (0x06<<1)
+#define SLEEP_MODE_EXT_STANDBY (0x07<<1)
+/*
+--------------------------------------------------------------------------
+OSC - Oscillator
+--------------------------------------------------------------------------
+*/
+
+/* Oscillator */
+typedef struct OSC_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t STATUS; /* Status Register */
+ register8_t XOSCCTRL; /* External Oscillator Control Register */
+ register8_t XOSCFAIL; /* Oscillator Failure Detection Register */
+ register8_t RC32KCAL; /* 32.768 kHz Internal Oscillator Calibration Register */
+ register8_t PLLCTRL; /* PLL Control Register */
+ register8_t DFLLCTRL; /* DFLL Control Register */
+} OSC_t;
+
+/* Oscillator Frequency Range */
+typedef enum OSC_FRQRANGE_enum
+{
+ OSC_FRQRANGE_04TO2_gc = (0x00<<6), /* 0.4 - 2 MHz */
+ OSC_FRQRANGE_2TO9_gc = (0x01<<6), /* 2 - 9 MHz */
+ OSC_FRQRANGE_9TO12_gc = (0x02<<6), /* 9 - 12 MHz */
+ OSC_FRQRANGE_12TO16_gc = (0x03<<6), /* 12 - 16 MHz */
+} OSC_FRQRANGE_t;
+
+/* External Oscillator Selection and Startup Time */
+typedef enum OSC_XOSCSEL_enum
+{
+ OSC_XOSCSEL_EXTCLK_gc = (0x00<<0), /* External Clock - 6 CLK */
+ OSC_XOSCSEL_32KHz_gc = (0x02<<0), /* 32.768 kHz TOSC - 32K CLK */
+ OSC_XOSCSEL_XTAL_256CLK_gc = (0x03<<0), /* 0.4-16 MHz XTAL - 256 CLK */
+ OSC_XOSCSEL_XTAL_1KCLK_gc = (0x07<<0), /* 0.4-16 MHz XTAL - 1K CLK */
+ OSC_XOSCSEL_XTAL_16KCLK_gc = (0x0B<<0), /* 0.4-16 MHz XTAL - 16K CLK */
+} OSC_XOSCSEL_t;
+
+/* PLL Clock Source */
+typedef enum OSC_PLLSRC_enum
+{
+ OSC_PLLSRC_RC2M_gc = (0x00<<6), /* Internal 2 MHz RC Oscillator */
+ OSC_PLLSRC_RC32M_gc = (0x02<<6), /* Internal 32 MHz RC Oscillator */
+ OSC_PLLSRC_XOSC_gc = (0x03<<6), /* External Oscillator */
+} OSC_PLLSRC_t;
+
+/* 2 MHz DFLL Calibration Reference */
+typedef enum OSC_RC2MCREF_enum
+{
+ OSC_RC2MCREF_RC32K_gc = (0x00<<0), /* Internal 32.768 kHz RC Oscillator */
+ OSC_RC2MCREF_XOSC32K_gc = (0x01<<0), /* External 32.768 kHz Crystal Oscillator */
+} OSC_RC2MCREF_t;
+
+/* 32 MHz DFLL Calibration Reference */
+typedef enum OSC_RC32MCREF_enum
+{
+ OSC_RC32MCREF_RC32K_gc = (0x00<<1), /* Internal 32.768 kHz RC Oscillator */
+ OSC_RC32MCREF_XOSC32K_gc = (0x01<<1), /* External 32.768 kHz Crystal Oscillator */
+ OSC_RC32MCREF_USBSOF_gc = (0x02<<1), /* USB Start of Frame */
+} OSC_RC32MCREF_t;
+
+
+/*
+--------------------------------------------------------------------------
+DFLL - DFLL
+--------------------------------------------------------------------------
+*/
+
+/* DFLL */
+typedef struct DFLL_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t reserved_0x01;
+ register8_t CALA; /* Calibration Register A */
+ register8_t CALB; /* Calibration Register B */
+ register8_t COMP0; /* Oscillator Compare Register 0 */
+ register8_t COMP1; /* Oscillator Compare Register 1 */
+ register8_t COMP2; /* Oscillator Compare Register 2 */
+ register8_t reserved_0x07;
+} DFLL_t;
+
+
+/*
+--------------------------------------------------------------------------
+RST - Reset
+--------------------------------------------------------------------------
+*/
+
+/* Reset */
+typedef struct RST_struct
+{
+ register8_t STATUS; /* Status Register */
+ register8_t CTRL; /* Control Register */
+} RST_t;
+
+
+/*
+--------------------------------------------------------------------------
+WDT - Watch-Dog Timer
+--------------------------------------------------------------------------
+*/
+
+/* Watch-Dog Timer */
+typedef struct WDT_struct
+{
+ register8_t CTRL; /* Control */
+ register8_t WINCTRL; /* Windowed Mode Control */
+ register8_t STATUS; /* Status */
+} WDT_t;
+
+/* Period setting */
+typedef enum WDT_PER_enum
+{
+ WDT_PER_8CLK_gc = (0x00<<2), /* 8 cycles (8ms @ 3.3V) */
+ WDT_PER_16CLK_gc = (0x01<<2), /* 16 cycles (16ms @ 3.3V) */
+ WDT_PER_32CLK_gc = (0x02<<2), /* 32 cycles (32ms @ 3.3V) */
+ WDT_PER_64CLK_gc = (0x03<<2), /* 64 cycles (64ms @ 3.3V) */
+ WDT_PER_128CLK_gc = (0x04<<2), /* 128 cycles (0.128s @ 3.3V) */
+ WDT_PER_256CLK_gc = (0x05<<2), /* 256 cycles (0.256s @ 3.3V) */
+ WDT_PER_512CLK_gc = (0x06<<2), /* 512 cycles (0.512s @ 3.3V) */
+ WDT_PER_1KCLK_gc = (0x07<<2), /* 1K cycles (1s @ 3.3V) */
+ WDT_PER_2KCLK_gc = (0x08<<2), /* 2K cycles (2s @ 3.3V) */
+ WDT_PER_4KCLK_gc = (0x09<<2), /* 4K cycles (4s @ 3.3V) */
+ WDT_PER_8KCLK_gc = (0x0A<<2), /* 8K cycles (8s @ 3.3V) */
+} WDT_PER_t;
+
+/* Closed window period */
+typedef enum WDT_WPER_enum
+{
+ WDT_WPER_8CLK_gc = (0x00<<2), /* 8 cycles (8ms @ 3.3V) */
+ WDT_WPER_16CLK_gc = (0x01<<2), /* 16 cycles (16ms @ 3.3V) */
+ WDT_WPER_32CLK_gc = (0x02<<2), /* 32 cycles (32ms @ 3.3V) */
+ WDT_WPER_64CLK_gc = (0x03<<2), /* 64 cycles (64ms @ 3.3V) */
+ WDT_WPER_128CLK_gc = (0x04<<2), /* 128 cycles (0.128s @ 3.3V) */
+ WDT_WPER_256CLK_gc = (0x05<<2), /* 256 cycles (0.256s @ 3.3V) */
+ WDT_WPER_512CLK_gc = (0x06<<2), /* 512 cycles (0.512s @ 3.3V) */
+ WDT_WPER_1KCLK_gc = (0x07<<2), /* 1K cycles (1s @ 3.3V) */
+ WDT_WPER_2KCLK_gc = (0x08<<2), /* 2K cycles (2s @ 3.3V) */
+ WDT_WPER_4KCLK_gc = (0x09<<2), /* 4K cycles (4s @ 3.3V) */
+ WDT_WPER_8KCLK_gc = (0x0A<<2), /* 8K cycles (8s @ 3.3V) */
+} WDT_WPER_t;
+
+
+/*
+--------------------------------------------------------------------------
+MCU - MCU Control
+--------------------------------------------------------------------------
+*/
+
+/* MCU Control */
+typedef struct MCU_struct
+{
+ register8_t DEVID0; /* Device ID byte 0 */
+ register8_t DEVID1; /* Device ID byte 1 */
+ register8_t DEVID2; /* Device ID byte 2 */
+ register8_t REVID; /* Revision ID */
+ register8_t JTAGUID; /* JTAG User ID */
+ register8_t reserved_0x05;
+ register8_t MCUCR; /* MCU Control */
+ register8_t ANAINIT; /* Analog Startup Delay */
+ register8_t EVSYSLOCK; /* Event System Lock */
+ register8_t AWEXLOCK; /* AWEX Lock */
+ register8_t reserved_0x0A;
+ register8_t reserved_0x0B;
+} MCU_t;
+
+
+/*
+--------------------------------------------------------------------------
+PMIC - Programmable Multi-level Interrupt Controller
+--------------------------------------------------------------------------
+*/
+
+/* Programmable Multi-level Interrupt Controller */
+typedef struct PMIC_struct
+{
+ register8_t STATUS; /* Status Register */
+ register8_t INTPRI; /* Interrupt Priority */
+ register8_t CTRL; /* Control Register */
+ register8_t reserved_0x03;
+ register8_t reserved_0x04;
+ register8_t reserved_0x05;
+ register8_t reserved_0x06;
+ register8_t reserved_0x07;
+ register8_t reserved_0x08;
+ register8_t reserved_0x09;
+ register8_t reserved_0x0A;
+ register8_t reserved_0x0B;
+ register8_t reserved_0x0C;
+ register8_t reserved_0x0D;
+ register8_t reserved_0x0E;
+ register8_t reserved_0x0F;
+} PMIC_t;
+
+
+/*
+--------------------------------------------------------------------------
+PORTCFG - Port Configuration
+--------------------------------------------------------------------------
+*/
+
+/* I/O port Configuration */
+typedef struct PORTCFG_struct
+{
+ register8_t MPCMASK; /* Multi-pin Configuration Mask */
+ register8_t reserved_0x01;
+ register8_t VPCTRLA; /* Virtual Port Control Register A */
+ register8_t VPCTRLB; /* Virtual Port Control Register B */
+ register8_t CLKEVOUT; /* Clock and Event Out Register */
+ register8_t EBIOUT; /* EBI Output register */
+ register8_t EVOUTSEL; /* Event Output Select */
+} PORTCFG_t;
+
+/* Virtual Port Mapping */
+typedef enum PORTCFG_VP02MAP_enum
+{
+ PORTCFG_VP02MAP_PORTA_gc = (0x00<<0), /* Mapped To PORTA */
+ PORTCFG_VP02MAP_PORTB_gc = (0x01<<0), /* Mapped To PORTB */
+ PORTCFG_VP02MAP_PORTC_gc = (0x02<<0), /* Mapped To PORTC */
+ PORTCFG_VP02MAP_PORTD_gc = (0x03<<0), /* Mapped To PORTD */
+ PORTCFG_VP02MAP_PORTE_gc = (0x04<<0), /* Mapped To PORTE */
+ PORTCFG_VP02MAP_PORTF_gc = (0x05<<0), /* Mapped To PORTF */
+ PORTCFG_VP02MAP_PORTG_gc = (0x06<<0), /* Mapped To PORTG */
+ PORTCFG_VP02MAP_PORTH_gc = (0x07<<0), /* Mapped To PORTH */
+ PORTCFG_VP02MAP_PORTJ_gc = (0x08<<0), /* Mapped To PORTJ */
+ PORTCFG_VP02MAP_PORTK_gc = (0x09<<0), /* Mapped To PORTK */
+ PORTCFG_VP02MAP_PORTL_gc = (0x0A<<0), /* Mapped To PORTL */
+ PORTCFG_VP02MAP_PORTM_gc = (0x0B<<0), /* Mapped To PORTM */
+ PORTCFG_VP02MAP_PORTN_gc = (0x0C<<0), /* Mapped To PORTN */
+ PORTCFG_VP02MAP_PORTP_gc = (0x0D<<0), /* Mapped To PORTP */
+ PORTCFG_VP02MAP_PORTQ_gc = (0x0E<<0), /* Mapped To PORTQ */
+ PORTCFG_VP02MAP_PORTR_gc = (0x0F<<0), /* Mapped To PORTR */
+} PORTCFG_VP02MAP_t;
+
+/* Virtual Port Mapping */
+typedef enum PORTCFG_VP13MAP_enum
+{
+ PORTCFG_VP13MAP_PORTA_gc = (0x00<<4), /* Mapped To PORTA */
+ PORTCFG_VP13MAP_PORTB_gc = (0x01<<4), /* Mapped To PORTB */
+ PORTCFG_VP13MAP_PORTC_gc = (0x02<<4), /* Mapped To PORTC */
+ PORTCFG_VP13MAP_PORTD_gc = (0x03<<4), /* Mapped To PORTD */
+ PORTCFG_VP13MAP_PORTE_gc = (0x04<<4), /* Mapped To PORTE */
+ PORTCFG_VP13MAP_PORTF_gc = (0x05<<4), /* Mapped To PORTF */
+ PORTCFG_VP13MAP_PORTG_gc = (0x06<<4), /* Mapped To PORTG */
+ PORTCFG_VP13MAP_PORTH_gc = (0x07<<4), /* Mapped To PORTH */
+ PORTCFG_VP13MAP_PORTJ_gc = (0x08<<4), /* Mapped To PORTJ */
+ PORTCFG_VP13MAP_PORTK_gc = (0x09<<4), /* Mapped To PORTK */
+ PORTCFG_VP13MAP_PORTL_gc = (0x0A<<4), /* Mapped To PORTL */
+ PORTCFG_VP13MAP_PORTM_gc = (0x0B<<4), /* Mapped To PORTM */
+ PORTCFG_VP13MAP_PORTN_gc = (0x0C<<4), /* Mapped To PORTN */
+ PORTCFG_VP13MAP_PORTP_gc = (0x0D<<4), /* Mapped To PORTP */
+ PORTCFG_VP13MAP_PORTQ_gc = (0x0E<<4), /* Mapped To PORTQ */
+ PORTCFG_VP13MAP_PORTR_gc = (0x0F<<4), /* Mapped To PORTR */
+} PORTCFG_VP13MAP_t;
+
+/* System Clock Output Port */
+typedef enum PORTCFG_CLKOUT_enum
+{
+ PORTCFG_CLKOUT_OFF_gc = (0x00<<0), /* System Clock Output Disabled */
+ PORTCFG_CLKOUT_PC7_gc = (0x01<<0), /* System Clock Output on Port C pin 7 */
+ PORTCFG_CLKOUT_PD7_gc = (0x02<<0), /* System Clock Output on Port D pin 7 */
+ PORTCFG_CLKOUT_PE7_gc = (0x03<<0), /* System Clock Output on Port E pin 7 */
+} PORTCFG_CLKOUT_t;
+
+/* Peripheral Clock Output Select */
+typedef enum PORTCFG_CLKOUTSEL_enum
+{
+ PORTCFG_CLKOUTSEL_CLK1X_gc = (0x00<<2), /* 1x Peripheral Clock Output to pin */
+ PORTCFG_CLKOUTSEL_CLK2X_gc = (0x01<<2), /* 2x Peripheral Clock Output to pin */
+ PORTCFG_CLKOUTSEL_CLK4X_gc = (0x02<<2), /* 4x Peripheral Clock Output to pin */
+} PORTCFG_CLKOUTSEL_t;
+
+/* Event Output Port */
+typedef enum PORTCFG_EVOUT_enum
+{
+ PORTCFG_EVOUT_OFF_gc = (0x00<<4), /* Event Output Disabled */
+ PORTCFG_EVOUT_PC7_gc = (0x01<<4), /* Event Channel 7 Output on Port C pin 7 */
+ PORTCFG_EVOUT_PD7_gc = (0x02<<4), /* Event Channel 7 Output on Port D pin 7 */
+ PORTCFG_EVOUT_PE7_gc = (0x03<<4), /* Event Channel 7 Output on Port E pin 7 */
+} PORTCFG_EVOUT_t;
+
+/* Clock and Event Output Port */
+typedef enum PORTCFG_CLKEVPIN_enum
+{
+ PORTCFG_CLKEVPIN_PIN7_gc = (0x00<<7), /* Clock and Event Ouput on PIN 7 */
+ PORTCFG_CLKEVPIN_PIN4_gc = (0x01<<7), /* Clock and Event Ouput on PIN 4 */
+} PORTCFG_CLKEVPIN_t;
+
+/* EBI Address Output Port */
+typedef enum PORTCFG_EBIADROUT_enum
+{
+ PORTCFG_EBIADROUT_PF_gc = (0x00<<2), /* EBI port 3 address output on PORTF pins 0 to 7 */
+ PORTCFG_EBIADROUT_PE_gc = (0x01<<2), /* EBI port 3 address output on PORTE pins 0 to 7 */
+ PORTCFG_EBIADROUT_PFH_gc = (0x02<<2), /* EBI port 3 address output on PORTF pins 4 to 7 */
+ PORTCFG_EBIADROUT_PEH_gc = (0x03<<2), /* EBI port 3 address output on PORTE pins 4 to 7 */
+} PORTCFG_EBIADROUT_t;
+
+/* EBI Chip Select Output Port */
+typedef enum PORTCFG_EBICSOUT_enum
+{
+ PORTCFG_EBICSOUT_PH_gc = (0x00<<0), /* EBI chip select output to PORTH pin 4 to 7 */
+ PORTCFG_EBICSOUT_PL_gc = (0x01<<0), /* EBI chip select output to PORTL pin 4 to 7 */
+ PORTCFG_EBICSOUT_PF_gc = (0x02<<0), /* EBI chip select output to PORTF pin 4 to 7 */
+ PORTCFG_EBICSOUT_PE_gc = (0x03<<0), /* EBI chip select output to PORTE pin 4 to 7 */
+} PORTCFG_EBICSOUT_t;
+
+/* Event Output Select */
+typedef enum PORTCFG_EVOUTSEL_enum
+{
+ PORTCFG_EVOUTSEL_0_gc = (0x00<<0), /* Event Channel 0 output to pin */
+ PORTCFG_EVOUTSEL_1_gc = (0x01<<0), /* Event Channel 1 output to pin */
+ PORTCFG_EVOUTSEL_2_gc = (0x02<<0), /* Event Channel 2 output to pin */
+ PORTCFG_EVOUTSEL_3_gc = (0x03<<0), /* Event Channel 3 output to pin */
+ PORTCFG_EVOUTSEL_4_gc = (0x04<<0), /* Event Channel 4 output to pin */
+ PORTCFG_EVOUTSEL_5_gc = (0x05<<0), /* Event Channel 5 output to pin */
+ PORTCFG_EVOUTSEL_6_gc = (0x06<<0), /* Event Channel 6 output to pin */
+ PORTCFG_EVOUTSEL_7_gc = (0x07<<0), /* Event Channel 7 output to pin */
+} PORTCFG_EVOUTSEL_t;
+
+
+/*
+--------------------------------------------------------------------------
+AES - AES Module
+--------------------------------------------------------------------------
+*/
+
+/* AES Module */
+typedef struct AES_struct
+{
+ register8_t CTRL; /* AES Control Register */
+ register8_t STATUS; /* AES Status Register */
+ register8_t STATE; /* AES State Register */
+ register8_t KEY; /* AES Key Register */
+ register8_t INTCTRL; /* AES Interrupt Control Register */
+} AES_t;
+
+/* Interrupt level */
+typedef enum AES_INTLVL_enum
+{
+ AES_INTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ AES_INTLVL_LO_gc = (0x01<<0), /* Low Level */
+ AES_INTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ AES_INTLVL_HI_gc = (0x03<<0), /* High Level */
+} AES_INTLVL_t;
+
+
+/*
+--------------------------------------------------------------------------
+CRC - Cyclic Redundancy Checker
+--------------------------------------------------------------------------
+*/
+
+/* Cyclic Redundancy Checker */
+typedef struct CRC_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t STATUS; /* Status Register */
+ register8_t reserved_0x02;
+ register8_t DATAIN; /* Data Input */
+ register8_t CHECKSUM0; /* Checksum byte 0 */
+ register8_t CHECKSUM1; /* Checksum byte 1 */
+ register8_t CHECKSUM2; /* Checksum byte 2 */
+ register8_t CHECKSUM3; /* Checksum byte 3 */
+} CRC_t;
+
+/* Reset */
+typedef enum CRC_RESET_enum
+{
+ CRC_RESET_NO_gc = (0x00<<6), /* No Reset */
+ CRC_RESET_RESET0_gc = (0x02<<6), /* Reset CRC with CHECKSUM to all zeros */
+ CRC_RESET_RESET1_gc = (0x03<<6), /* Reset CRC with CHECKSUM to all ones */
+} CRC_RESET_t;
+
+/* Input Source */
+typedef enum CRC_SOURCE_enum
+{
+ CRC_SOURCE_DISABLE_gc = (0x00<<0), /* Disabled */
+ CRC_SOURCE_IO_gc = (0x01<<0), /* I/O Interface */
+ CRC_SOURCE_FLASH_gc = (0x02<<0), /* Flash */
+ CRC_SOURCE_DMAC0_gc = (0x04<<0), /* DMAC Channel 0 */
+ CRC_SOURCE_DMAC1_gc = (0x05<<0), /* DMAC Channel 1 */
+ CRC_SOURCE_DMAC2_gc = (0x06<<0), /* DMAC Channel 2 */
+ CRC_SOURCE_DMAC3_gc = (0x07<<0), /* DMAC Channel 3 */
+} CRC_SOURCE_t;
+
+
+/*
+--------------------------------------------------------------------------
+DMA - DMA Controller
+--------------------------------------------------------------------------
+*/
+
+/* DMA Channel */
+typedef struct DMA_CH_struct
+{
+ register8_t CTRLA; /* Channel Control */
+ register8_t CTRLB; /* Channel Control */
+ register8_t ADDRCTRL; /* Address Control */
+ register8_t TRIGSRC; /* Channel Trigger Source */
+ _WORDREGISTER(TRFCNT); /* Channel Block Transfer Count */
+ register8_t REPCNT; /* Channel Repeat Count */
+ register8_t reserved_0x07;
+ register8_t SRCADDR0; /* Channel Source Address 0 */
+ register8_t SRCADDR1; /* Channel Source Address 1 */
+ register8_t SRCADDR2; /* Channel Source Address 2 */
+ register8_t reserved_0x0B;
+ register8_t DESTADDR0; /* Channel Destination Address 0 */
+ register8_t DESTADDR1; /* Channel Destination Address 1 */
+ register8_t DESTADDR2; /* Channel Destination Address 2 */
+ register8_t reserved_0x0F;
+} DMA_CH_t;
+
+
+/* DMA Controller */
+typedef struct DMA_struct
+{
+ register8_t CTRL; /* Control */
+ register8_t reserved_0x01;
+ register8_t reserved_0x02;
+ register8_t INTFLAGS; /* Transfer Interrupt Status */
+ register8_t STATUS; /* Status */
+ register8_t reserved_0x05;
+ _WORDREGISTER(TEMP); /* Temporary Register For 16/24-bit Access */
+ register8_t reserved_0x08;
+ register8_t reserved_0x09;
+ register8_t reserved_0x0A;
+ register8_t reserved_0x0B;
+ register8_t reserved_0x0C;
+ register8_t reserved_0x0D;
+ register8_t reserved_0x0E;
+ register8_t reserved_0x0F;
+ DMA_CH_t CH0; /* DMA Channel 0 */
+ DMA_CH_t CH1; /* DMA Channel 1 */
+ DMA_CH_t CH2; /* DMA Channel 2 */
+ DMA_CH_t CH3; /* DMA Channel 3 */
+} DMA_t;
+
+/* Burst mode */
+typedef enum DMA_CH_BURSTLEN_enum
+{
+ DMA_CH_BURSTLEN_1BYTE_gc = (0x00<<0), /* 1-byte burst mode */
+ DMA_CH_BURSTLEN_2BYTE_gc = (0x01<<0), /* 2-byte burst mode */
+ DMA_CH_BURSTLEN_4BYTE_gc = (0x02<<0), /* 4-byte burst mode */
+ DMA_CH_BURSTLEN_8BYTE_gc = (0x03<<0), /* 8-byte burst mode */
+} DMA_CH_BURSTLEN_t;
+
+/* Source address reload mode */
+typedef enum DMA_CH_SRCRELOAD_enum
+{
+ DMA_CH_SRCRELOAD_NONE_gc = (0x00<<6), /* No reload */
+ DMA_CH_SRCRELOAD_BLOCK_gc = (0x01<<6), /* Reload at end of block */
+ DMA_CH_SRCRELOAD_BURST_gc = (0x02<<6), /* Reload at end of burst */
+ DMA_CH_SRCRELOAD_TRANSACTION_gc = (0x03<<6), /* Reload at end of transaction */
+} DMA_CH_SRCRELOAD_t;
+
+/* Source addressing mode */
+typedef enum DMA_CH_SRCDIR_enum
+{
+ DMA_CH_SRCDIR_FIXED_gc = (0x00<<4), /* Fixed */
+ DMA_CH_SRCDIR_INC_gc = (0x01<<4), /* Increment */
+ DMA_CH_SRCDIR_DEC_gc = (0x02<<4), /* Decrement */
+} DMA_CH_SRCDIR_t;
+
+/* Destination adress reload mode */
+typedef enum DMA_CH_DESTRELOAD_enum
+{
+ DMA_CH_DESTRELOAD_NONE_gc = (0x00<<2), /* No reload */
+ DMA_CH_DESTRELOAD_BLOCK_gc = (0x01<<2), /* Reload at end of block */
+ DMA_CH_DESTRELOAD_BURST_gc = (0x02<<2), /* Reload at end of burst */
+ DMA_CH_DESTRELOAD_TRANSACTION_gc = (0x03<<2), /* Reload at end of transaction */
+} DMA_CH_DESTRELOAD_t;
+
+/* Destination adressing mode */
+typedef enum DMA_CH_DESTDIR_enum
+{
+ DMA_CH_DESTDIR_FIXED_gc = (0x00<<0), /* Fixed */
+ DMA_CH_DESTDIR_INC_gc = (0x01<<0), /* Increment */
+ DMA_CH_DESTDIR_DEC_gc = (0x02<<0), /* Decrement */
+} DMA_CH_DESTDIR_t;
+
+/* Transfer trigger source */
+typedef enum DMA_CH_TRIGSRC_enum
+{
+ DMA_CH_TRIGSRC_OFF_gc = (0x00<<0), /* Off software triggers only */
+ DMA_CH_TRIGSRC_EVSYS_CH0_gc = (0x01<<0), /* Event System Channel 0 */
+ DMA_CH_TRIGSRC_EVSYS_CH1_gc = (0x02<<0), /* Event System Channel 1 */
+ DMA_CH_TRIGSRC_EVSYS_CH2_gc = (0x03<<0), /* Event System Channel 2 */
+ DMA_CH_TRIGSRC_ADCA_CH0_gc = (0x10<<0), /* ADCA Channel 0 */
+ DMA_CH_TRIGSRC_ADCA_CH1_gc = (0x11<<0), /* ADCA Channel 1 */
+ DMA_CH_TRIGSRC_ADCA_CH2_gc = (0x12<<0), /* ADCA Channel 2 */
+ DMA_CH_TRIGSRC_ADCA_CH3_gc = (0x13<<0), /* ADCA Channel 3 */
+ DMA_CH_TRIGSRC_ADCA_CH4_gc = (0x14<<0), /* ADCA Channel 0,1,2,3 combined */
+ DMA_CH_TRIGSRC_DACA_CH0_gc = (0x15<<0), /* DACA Channel 0 */
+ DMA_CH_TRIGSRC_DACA_CH1_gc = (0x16<<0), /* DACA Channel 1 */
+ DMA_CH_TRIGSRC_ADCB_CH0_gc = (0x20<<0), /* ADCB Channel 0 */
+ DMA_CH_TRIGSRC_ADCB_CH1_gc = (0x21<<0), /* ADCB Channel 1 */
+ DMA_CH_TRIGSRC_ADCB_CH2_gc = (0x22<<0), /* ADCB Channel 2 */
+ DMA_CH_TRIGSRC_ADCB_CH3_gc = (0x23<<0), /* ADCB Channel 3 */
+ DMA_CH_TRIGSRC_ADCB_CH4_gc = (0x24<<0), /* ADCB Channel 0,1,2,3 combined */
+ DMA_CH_TRIGSRC_DACB_CH0_gc = (0x25<<0), /* DACB Channel 0 */
+ DMA_CH_TRIGSRC_DACB_CH1_gc = (0x26<<0), /* DACB Channel 1 */
+ DMA_CH_TRIGSRC_TCC0_OVF_gc = (0x40<<0), /* Timer/Counter C0 Overflow */
+ DMA_CH_TRIGSRC_TCC0_ERR_gc = (0x41<<0), /* Timer/Counter C0 Error */
+ DMA_CH_TRIGSRC_TCC0_CCA_gc = (0x42<<0), /* Timer/Counter C0 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCC0_CCB_gc = (0x43<<0), /* Timer/Counter C0 Compare or Capture B */
+ DMA_CH_TRIGSRC_TCC0_CCC_gc = (0x44<<0), /* Timer/Counter C0 Compare or Capture C */
+ DMA_CH_TRIGSRC_TCC0_CCD_gc = (0x45<<0), /* Timer/Counter C0 Compare or Capture D */
+ DMA_CH_TRIGSRC_TCC1_OVF_gc = (0x46<<0), /* Timer/Counter C1 Overflow */
+ DMA_CH_TRIGSRC_TCC1_ERR_gc = (0x47<<0), /* Timer/Counter C1 Error */
+ DMA_CH_TRIGSRC_TCC1_CCA_gc = (0x48<<0), /* Timer/Counter C1 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCC1_CCB_gc = (0x49<<0), /* Timer/Counter C1 Compare or Capture B */
+ DMA_CH_TRIGSRC_SPIC_gc = (0x4A<<0), /* SPI C Transfer Complete */
+ DMA_CH_TRIGSRC_USARTC0_RXC_gc = (0x4B<<0), /* USART C0 Receive Complete */
+ DMA_CH_TRIGSRC_USARTC0_DRE_gc = (0x4C<<0), /* USART C0 Data Register Empty */
+ DMA_CH_TRIGSRC_USARTC1_RXC_gc = (0x4E<<0), /* USART C1 Receive Complete */
+ DMA_CH_TRIGSRC_USARTC1_DRE_gc = (0x4F<<0), /* USART C1 Data Register Empty */
+ DMA_CH_TRIGSRC_TCD0_OVF_gc = (0x60<<0), /* Timer/Counter D0 Overflow */
+ DMA_CH_TRIGSRC_TCD0_ERR_gc = (0x61<<0), /* Timer/Counter D0 Error */
+ DMA_CH_TRIGSRC_TCD0_CCA_gc = (0x62<<0), /* Timer/Counter D0 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCD0_CCB_gc = (0x63<<0), /* Timer/Counter D0 Compare or Capture B */
+ DMA_CH_TRIGSRC_TCD0_CCC_gc = (0x64<<0), /* Timer/Counter D0 Compare or Capture C */
+ DMA_CH_TRIGSRC_TCD0_CCD_gc = (0x65<<0), /* Timer/Counter D0 Compare or Capture D */
+ DMA_CH_TRIGSRC_TCD1_OVF_gc = (0x66<<0), /* Timer/Counter D1 Overflow */
+ DMA_CH_TRIGSRC_TCD1_ERR_gc = (0x67<<0), /* Timer/Counter D1 Error */
+ DMA_CH_TRIGSRC_TCD1_CCA_gc = (0x68<<0), /* Timer/Counter D1 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCD1_CCB_gc = (0x69<<0), /* Timer/Counter D1 Compare or Capture B */
+ DMA_CH_TRIGSRC_SPID_gc = (0x6A<<0), /* SPI D Transfer Complete */
+ DMA_CH_TRIGSRC_USARTD0_RXC_gc = (0x6B<<0), /* USART D0 Receive Complete */
+ DMA_CH_TRIGSRC_USARTD0_DRE_gc = (0x6C<<0), /* USART D0 Data Register Empty */
+ DMA_CH_TRIGSRC_USARTD1_RXC_gc = (0x6E<<0), /* USART D1 Receive Complete */
+ DMA_CH_TRIGSRC_USARTD1_DRE_gc = (0x6F<<0), /* USART D1 Data Register Empty */
+ DMA_CH_TRIGSRC_TCE0_OVF_gc = (0x80<<0), /* Timer/Counter E0 Overflow */
+ DMA_CH_TRIGSRC_TCE0_ERR_gc = (0x81<<0), /* Timer/Counter E0 Error */
+ DMA_CH_TRIGSRC_TCE0_CCA_gc = (0x82<<0), /* Timer/Counter E0 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCE0_CCB_gc = (0x83<<0), /* Timer/Counter E0 Compare or Capture B */
+ DMA_CH_TRIGSRC_TCE0_CCC_gc = (0x84<<0), /* Timer/Counter E0 Compare or Capture C */
+ DMA_CH_TRIGSRC_TCE0_CCD_gc = (0x85<<0), /* Timer/Counter E0 Compare or Capture D */
+ DMA_CH_TRIGSRC_TCE1_OVF_gc = (0x86<<0), /* Timer/Counter E1 Overflow */
+ DMA_CH_TRIGSRC_TCE1_ERR_gc = (0x87<<0), /* Timer/Counter E1 Error */
+ DMA_CH_TRIGSRC_TCE1_CCA_gc = (0x88<<0), /* Timer/Counter E1 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCE1_CCB_gc = (0x89<<0), /* Timer/Counter E1 Compare or Capture B */
+ DMA_CH_TRIGSRC_SPIE_gc = (0x8A<<0), /* SPI E Transfer Complete */
+ DMA_CH_TRIGSRC_USARTE0_RXC_gc = (0x8B<<0), /* USART E0 Receive Complete */
+ DMA_CH_TRIGSRC_USARTE0_DRE_gc = (0x8C<<0), /* USART E0 Data Register Empty */
+ DMA_CH_TRIGSRC_USARTE1_RXC_gc = (0x8E<<0), /* USART E1 Receive Complete */
+ DMA_CH_TRIGSRC_USARTE1_DRE_gc = (0x8F<<0), /* USART E1 Data Register Empty */
+ DMA_CH_TRIGSRC_TCF0_OVF_gc = (0xA0<<0), /* Timer/Counter F0 Overflow */
+ DMA_CH_TRIGSRC_TCF0_ERR_gc = (0xA1<<0), /* Timer/Counter F0 Error */
+ DMA_CH_TRIGSRC_TCF0_CCA_gc = (0xA2<<0), /* Timer/Counter F0 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCF0_CCB_gc = (0xA3<<0), /* Timer/Counter F0 Compare or Capture B */
+ DMA_CH_TRIGSRC_TCF0_CCC_gc = (0xA4<<0), /* Timer/Counter F0 Compare or Capture C */
+ DMA_CH_TRIGSRC_TCF0_CCD_gc = (0xA5<<0), /* Timer/Counter F0 Compare or Capture D */
+ DMA_CH_TRIGSRC_TCF1_OVF_gc = (0xA6<<0), /* Timer/Counter F1 Overflow */
+ DMA_CH_TRIGSRC_TCF1_ERR_gc = (0xA7<<0), /* Timer/Counter F1 Error */
+ DMA_CH_TRIGSRC_TCF1_CCA_gc = (0xA8<<0), /* Timer/Counter F1 Compare or Capture A */
+ DMA_CH_TRIGSRC_TCF1_CCB_gc = (0xA9<<0), /* Timer/Counter F1 Compare or Capture B */
+ DMA_CH_TRIGSRC_SPIF_gc = (0xAA<<0), /* SPI F Transfer Complete */
+ DMA_CH_TRIGSRC_USARTF0_RXC_gc = (0xAB<<0), /* USART F0 Receive Complete */
+ DMA_CH_TRIGSRC_USARTF0_DRE_gc = (0xAC<<0), /* USART F0 Data Register Empty */
+ DMA_CH_TRIGSRC_USARTF1_RXC_gc = (0xAE<<0), /* USART F1 Receive Complete */
+ DMA_CH_TRIGSRC_USARTF1_DRE_gc = (0xAF<<0), /* USART F1 Data Register Empty */
+} DMA_CH_TRIGSRC_t;
+
+/* Double buffering mode */
+typedef enum DMA_DBUFMODE_enum
+{
+ DMA_DBUFMODE_DISABLED_gc = (0x00<<2), /* Double buffering disabled */
+ DMA_DBUFMODE_CH01_gc = (0x01<<2), /* Double buffering enabled on channel 0/1 */
+ DMA_DBUFMODE_CH23_gc = (0x02<<2), /* Double buffering enabled on channel 2/3 */
+ DMA_DBUFMODE_CH01CH23_gc = (0x03<<2), /* Double buffering enabled on ch. 0/1 and ch. 2/3 */
+} DMA_DBUFMODE_t;
+
+/* Priority mode */
+typedef enum DMA_PRIMODE_enum
+{
+ DMA_PRIMODE_RR0123_gc = (0x00<<0), /* Round Robin */
+ DMA_PRIMODE_CH0RR123_gc = (0x01<<0), /* Channel 0 > Round Robin on channel 1/2/3 */
+ DMA_PRIMODE_CH01RR23_gc = (0x02<<0), /* Channel 0 > channel 1 > Round Robin on channel 2/3 */
+ DMA_PRIMODE_CH0123_gc = (0x03<<0), /* Channel 0 > channel 1 > channel 2 > channel 3 */
+} DMA_PRIMODE_t;
+
+/* Interrupt level */
+typedef enum DMA_CH_ERRINTLVL_enum
+{
+ DMA_CH_ERRINTLVL_OFF_gc = (0x00<<2), /* Interrupt disabled */
+ DMA_CH_ERRINTLVL_LO_gc = (0x01<<2), /* Low level */
+ DMA_CH_ERRINTLVL_MED_gc = (0x02<<2), /* Medium level */
+ DMA_CH_ERRINTLVL_HI_gc = (0x03<<2), /* High level */
+} DMA_CH_ERRINTLVL_t;
+
+/* Interrupt level */
+typedef enum DMA_CH_TRNINTLVL_enum
+{
+ DMA_CH_TRNINTLVL_OFF_gc = (0x00<<0), /* Interrupt disabled */
+ DMA_CH_TRNINTLVL_LO_gc = (0x01<<0), /* Low level */
+ DMA_CH_TRNINTLVL_MED_gc = (0x02<<0), /* Medium level */
+ DMA_CH_TRNINTLVL_HI_gc = (0x03<<0), /* High level */
+} DMA_CH_TRNINTLVL_t;
+
+
+/*
+--------------------------------------------------------------------------
+EVSYS - Event System
+--------------------------------------------------------------------------
+*/
+
+/* Event System */
+typedef struct EVSYS_struct
+{
+ register8_t CH0MUX; /* Event Channel 0 Multiplexer */
+ register8_t CH1MUX; /* Event Channel 1 Multiplexer */
+ register8_t CH2MUX; /* Event Channel 2 Multiplexer */
+ register8_t CH3MUX; /* Event Channel 3 Multiplexer */
+ register8_t CH4MUX; /* Event Channel 4 Multiplexer */
+ register8_t CH5MUX; /* Event Channel 5 Multiplexer */
+ register8_t CH6MUX; /* Event Channel 6 Multiplexer */
+ register8_t CH7MUX; /* Event Channel 7 Multiplexer */
+ register8_t CH0CTRL; /* Channel 0 Control Register */
+ register8_t CH1CTRL; /* Channel 1 Control Register */
+ register8_t CH2CTRL; /* Channel 2 Control Register */
+ register8_t CH3CTRL; /* Channel 3 Control Register */
+ register8_t CH4CTRL; /* Channel 4 Control Register */
+ register8_t CH5CTRL; /* Channel 5 Control Register */
+ register8_t CH6CTRL; /* Channel 6 Control Register */
+ register8_t CH7CTRL; /* Channel 7 Control Register */
+ register8_t STROBE; /* Event Strobe */
+ register8_t DATA; /* Event Data */
+} EVSYS_t;
+
+/* Quadrature Decoder Index Recognition Mode */
+typedef enum EVSYS_QDIRM_enum
+{
+ EVSYS_QDIRM_00_gc = (0x00<<5), /* QDPH0 = 0, QDPH90 = 0 */
+ EVSYS_QDIRM_01_gc = (0x01<<5), /* QDPH0 = 0, QDPH90 = 1 */
+ EVSYS_QDIRM_10_gc = (0x02<<5), /* QDPH0 = 1, QDPH90 = 0 */
+ EVSYS_QDIRM_11_gc = (0x03<<5), /* QDPH0 = 1, QDPH90 = 1 */
+} EVSYS_QDIRM_t;
+
+/* Digital filter coefficient */
+typedef enum EVSYS_DIGFILT_enum
+{
+ EVSYS_DIGFILT_1SAMPLE_gc = (0x00<<0), /* 1 SAMPLE */
+ EVSYS_DIGFILT_2SAMPLES_gc = (0x01<<0), /* 2 SAMPLES */
+ EVSYS_DIGFILT_3SAMPLES_gc = (0x02<<0), /* 3 SAMPLES */
+ EVSYS_DIGFILT_4SAMPLES_gc = (0x03<<0), /* 4 SAMPLES */
+ EVSYS_DIGFILT_5SAMPLES_gc = (0x04<<0), /* 5 SAMPLES */
+ EVSYS_DIGFILT_6SAMPLES_gc = (0x05<<0), /* 6 SAMPLES */
+ EVSYS_DIGFILT_7SAMPLES_gc = (0x06<<0), /* 7 SAMPLES */
+ EVSYS_DIGFILT_8SAMPLES_gc = (0x07<<0), /* 8 SAMPLES */
+} EVSYS_DIGFILT_t;
+
+/* Event Channel multiplexer input selection */
+typedef enum EVSYS_CHMUX_enum
+{
+ EVSYS_CHMUX_OFF_gc = (0x00<<0), /* Off */
+ EVSYS_CHMUX_RTC_OVF_gc = (0x08<<0), /* RTC Overflow */
+ EVSYS_CHMUX_RTC_CMP_gc = (0x09<<0), /* RTC Compare Match */
+ EVSYS_CHMUX_USB_gc = (0x0A<<0), /* USB Setup, SOF, CRC error and UNF/OVF */
+ EVSYS_CHMUX_ACA_CH0_gc = (0x10<<0), /* Analog Comparator A Channel 0 */
+ EVSYS_CHMUX_ACA_CH1_gc = (0x11<<0), /* Analog Comparator A Channel 1 */
+ EVSYS_CHMUX_ACA_WIN_gc = (0x12<<0), /* Analog Comparator A Window */
+ EVSYS_CHMUX_ACB_CH0_gc = (0x13<<0), /* Analog Comparator B Channel 0 */
+ EVSYS_CHMUX_ACB_CH1_gc = (0x14<<0), /* Analog Comparator B Channel 1 */
+ EVSYS_CHMUX_ACB_WIN_gc = (0x15<<0), /* Analog Comparator B Window */
+ EVSYS_CHMUX_ADCA_CH0_gc = (0x20<<0), /* ADC A Channel 0 */
+ EVSYS_CHMUX_ADCA_CH1_gc = (0x21<<0), /* ADC A Channel 1 */
+ EVSYS_CHMUX_ADCA_CH2_gc = (0x22<<0), /* ADC A Channel 2 */
+ EVSYS_CHMUX_ADCA_CH3_gc = (0x23<<0), /* ADC A Channel 3 */
+ EVSYS_CHMUX_ADCB_CH0_gc = (0x24<<0), /* ADC B Channel 0 */
+ EVSYS_CHMUX_ADCB_CH1_gc = (0x25<<0), /* ADC B Channel 1 */
+ EVSYS_CHMUX_ADCB_CH2_gc = (0x26<<0), /* ADC B Channel 2 */
+ EVSYS_CHMUX_ADCB_CH3_gc = (0x27<<0), /* ADC B Channel 3 */
+ EVSYS_CHMUX_PORTA_PIN0_gc = (0x50<<0), /* Port A, Pin0 */
+ EVSYS_CHMUX_PORTA_PIN1_gc = (0x51<<0), /* Port A, Pin1 */
+ EVSYS_CHMUX_PORTA_PIN2_gc = (0x52<<0), /* Port A, Pin2 */
+ EVSYS_CHMUX_PORTA_PIN3_gc = (0x53<<0), /* Port A, Pin3 */
+ EVSYS_CHMUX_PORTA_PIN4_gc = (0x54<<0), /* Port A, Pin4 */
+ EVSYS_CHMUX_PORTA_PIN5_gc = (0x55<<0), /* Port A, Pin5 */
+ EVSYS_CHMUX_PORTA_PIN6_gc = (0x56<<0), /* Port A, Pin6 */
+ EVSYS_CHMUX_PORTA_PIN7_gc = (0x57<<0), /* Port A, Pin7 */
+ EVSYS_CHMUX_PORTB_PIN0_gc = (0x58<<0), /* Port B, Pin0 */
+ EVSYS_CHMUX_PORTB_PIN1_gc = (0x59<<0), /* Port B, Pin1 */
+ EVSYS_CHMUX_PORTB_PIN2_gc = (0x5A<<0), /* Port B, Pin2 */
+ EVSYS_CHMUX_PORTB_PIN3_gc = (0x5B<<0), /* Port B, Pin3 */
+ EVSYS_CHMUX_PORTB_PIN4_gc = (0x5C<<0), /* Port B, Pin4 */
+ EVSYS_CHMUX_PORTB_PIN5_gc = (0x5D<<0), /* Port B, Pin5 */
+ EVSYS_CHMUX_PORTB_PIN6_gc = (0x5E<<0), /* Port B, Pin6 */
+ EVSYS_CHMUX_PORTB_PIN7_gc = (0x5F<<0), /* Port B, Pin7 */
+ EVSYS_CHMUX_PORTC_PIN0_gc = (0x60<<0), /* Port C, Pin0 */
+ EVSYS_CHMUX_PORTC_PIN1_gc = (0x61<<0), /* Port C, Pin1 */
+ EVSYS_CHMUX_PORTC_PIN2_gc = (0x62<<0), /* Port C, Pin2 */
+ EVSYS_CHMUX_PORTC_PIN3_gc = (0x63<<0), /* Port C, Pin3 */
+ EVSYS_CHMUX_PORTC_PIN4_gc = (0x64<<0), /* Port C, Pin4 */
+ EVSYS_CHMUX_PORTC_PIN5_gc = (0x65<<0), /* Port C, Pin5 */
+ EVSYS_CHMUX_PORTC_PIN6_gc = (0x66<<0), /* Port C, Pin6 */
+ EVSYS_CHMUX_PORTC_PIN7_gc = (0x67<<0), /* Port C, Pin7 */
+ EVSYS_CHMUX_PORTD_PIN0_gc = (0x68<<0), /* Port D, Pin0 */
+ EVSYS_CHMUX_PORTD_PIN1_gc = (0x69<<0), /* Port D, Pin1 */
+ EVSYS_CHMUX_PORTD_PIN2_gc = (0x6A<<0), /* Port D, Pin2 */
+ EVSYS_CHMUX_PORTD_PIN3_gc = (0x6B<<0), /* Port D, Pin3 */
+ EVSYS_CHMUX_PORTD_PIN4_gc = (0x6C<<0), /* Port D, Pin4 */
+ EVSYS_CHMUX_PORTD_PIN5_gc = (0x6D<<0), /* Port D, Pin5 */
+ EVSYS_CHMUX_PORTD_PIN6_gc = (0x6E<<0), /* Port D, Pin6 */
+ EVSYS_CHMUX_PORTD_PIN7_gc = (0x6F<<0), /* Port D, Pin7 */
+ EVSYS_CHMUX_PORTE_PIN0_gc = (0x70<<0), /* Port E, Pin0 */
+ EVSYS_CHMUX_PORTE_PIN1_gc = (0x71<<0), /* Port E, Pin1 */
+ EVSYS_CHMUX_PORTE_PIN2_gc = (0x72<<0), /* Port E, Pin2 */
+ EVSYS_CHMUX_PORTE_PIN3_gc = (0x73<<0), /* Port E, Pin3 */
+ EVSYS_CHMUX_PORTE_PIN4_gc = (0x74<<0), /* Port E, Pin4 */
+ EVSYS_CHMUX_PORTE_PIN5_gc = (0x75<<0), /* Port E, Pin5 */
+ EVSYS_CHMUX_PORTE_PIN6_gc = (0x76<<0), /* Port E, Pin6 */
+ EVSYS_CHMUX_PORTE_PIN7_gc = (0x77<<0), /* Port E, Pin7 */
+ EVSYS_CHMUX_PORTF_PIN0_gc = (0x78<<0), /* Port F, Pin0 */
+ EVSYS_CHMUX_PORTF_PIN1_gc = (0x79<<0), /* Port F, Pin1 */
+ EVSYS_CHMUX_PORTF_PIN2_gc = (0x7A<<0), /* Port F, Pin2 */
+ EVSYS_CHMUX_PORTF_PIN3_gc = (0x7B<<0), /* Port F, Pin3 */
+ EVSYS_CHMUX_PORTF_PIN4_gc = (0x7C<<0), /* Port F, Pin4 */
+ EVSYS_CHMUX_PORTF_PIN5_gc = (0x7D<<0), /* Port F, Pin5 */
+ EVSYS_CHMUX_PORTF_PIN6_gc = (0x7E<<0), /* Port F, Pin6 */
+ EVSYS_CHMUX_PORTF_PIN7_gc = (0x7F<<0), /* Port F, Pin7 */
+ EVSYS_CHMUX_PRESCALER_1_gc = (0x80<<0), /* Prescaler, divide by 1 */
+ EVSYS_CHMUX_PRESCALER_2_gc = (0x81<<0), /* Prescaler, divide by 2 */
+ EVSYS_CHMUX_PRESCALER_4_gc = (0x82<<0), /* Prescaler, divide by 4 */
+ EVSYS_CHMUX_PRESCALER_8_gc = (0x83<<0), /* Prescaler, divide by 8 */
+ EVSYS_CHMUX_PRESCALER_16_gc = (0x84<<0), /* Prescaler, divide by 16 */
+ EVSYS_CHMUX_PRESCALER_32_gc = (0x85<<0), /* Prescaler, divide by 32 */
+ EVSYS_CHMUX_PRESCALER_64_gc = (0x86<<0), /* Prescaler, divide by 64 */
+ EVSYS_CHMUX_PRESCALER_128_gc = (0x87<<0), /* Prescaler, divide by 128 */
+ EVSYS_CHMUX_PRESCALER_256_gc = (0x88<<0), /* Prescaler, divide by 256 */
+ EVSYS_CHMUX_PRESCALER_512_gc = (0x89<<0), /* Prescaler, divide by 512 */
+ EVSYS_CHMUX_PRESCALER_1024_gc = (0x8A<<0), /* Prescaler, divide by 1024 */
+ EVSYS_CHMUX_PRESCALER_2048_gc = (0x8B<<0), /* Prescaler, divide by 2048 */
+ EVSYS_CHMUX_PRESCALER_4096_gc = (0x8C<<0), /* Prescaler, divide by 4096 */
+ EVSYS_CHMUX_PRESCALER_8192_gc = (0x8D<<0), /* Prescaler, divide by 8192 */
+ EVSYS_CHMUX_PRESCALER_16384_gc = (0x8E<<0), /* Prescaler, divide by 16384 */
+ EVSYS_CHMUX_PRESCALER_32768_gc = (0x8F<<0), /* Prescaler, divide by 32768 */
+ EVSYS_CHMUX_TCC0_OVF_gc = (0xC0<<0), /* Timer/Counter C0 Overflow */
+ EVSYS_CHMUX_TCC0_ERR_gc = (0xC1<<0), /* Timer/Counter C0 Error */
+ EVSYS_CHMUX_TCC0_CCA_gc = (0xC4<<0), /* Timer/Counter C0 Compare or Capture A */
+ EVSYS_CHMUX_TCC0_CCB_gc = (0xC5<<0), /* Timer/Counter C0 Compare or Capture B */
+ EVSYS_CHMUX_TCC0_CCC_gc = (0xC6<<0), /* Timer/Counter C0 Compare or Capture C */
+ EVSYS_CHMUX_TCC0_CCD_gc = (0xC7<<0), /* Timer/Counter C0 Compare or Capture D */
+ EVSYS_CHMUX_TCC1_OVF_gc = (0xC8<<0), /* Timer/Counter C1 Overflow */
+ EVSYS_CHMUX_TCC1_ERR_gc = (0xC9<<0), /* Timer/Counter C1 Error */
+ EVSYS_CHMUX_TCC1_CCA_gc = (0xCC<<0), /* Timer/Counter C1 Compare or Capture A */
+ EVSYS_CHMUX_TCC1_CCB_gc = (0xCD<<0), /* Timer/Counter C1 Compare or Capture B */
+ EVSYS_CHMUX_TCD0_OVF_gc = (0xD0<<0), /* Timer/Counter D0 Overflow */
+ EVSYS_CHMUX_TCD0_ERR_gc = (0xD1<<0), /* Timer/Counter D0 Error */
+ EVSYS_CHMUX_TCD0_CCA_gc = (0xD4<<0), /* Timer/Counter D0 Compare or Capture A */
+ EVSYS_CHMUX_TCD0_CCB_gc = (0xD5<<0), /* Timer/Counter D0 Compare or Capture B */
+ EVSYS_CHMUX_TCD0_CCC_gc = (0xD6<<0), /* Timer/Counter D0 Compare or Capture C */
+ EVSYS_CHMUX_TCD0_CCD_gc = (0xD7<<0), /* Timer/Counter D0 Compare or Capture D */
+ EVSYS_CHMUX_TCD1_OVF_gc = (0xD8<<0), /* Timer/Counter D1 Overflow */
+ EVSYS_CHMUX_TCD1_ERR_gc = (0xD9<<0), /* Timer/Counter D1 Error */
+ EVSYS_CHMUX_TCD1_CCA_gc = (0xDC<<0), /* Timer/Counter D1 Compare or Capture A */
+ EVSYS_CHMUX_TCD1_CCB_gc = (0xDD<<0), /* Timer/Counter D1 Compare or Capture B */
+ EVSYS_CHMUX_TCE0_OVF_gc = (0xE0<<0), /* Timer/Counter E0 Overflow */
+ EVSYS_CHMUX_TCE0_ERR_gc = (0xE1<<0), /* Timer/Counter E0 Error */
+ EVSYS_CHMUX_TCE0_CCA_gc = (0xE4<<0), /* Timer/Counter E0 Compare or Capture A */
+ EVSYS_CHMUX_TCE0_CCB_gc = (0xE5<<0), /* Timer/Counter E0 Compare or Capture B */
+ EVSYS_CHMUX_TCE0_CCC_gc = (0xE6<<0), /* Timer/Counter E0 Compare or Capture C */
+ EVSYS_CHMUX_TCE0_CCD_gc = (0xE7<<0), /* Timer/Counter E0 Compare or Capture D */
+ EVSYS_CHMUX_TCE1_OVF_gc = (0xE8<<0), /* Timer/Counter E1 Overflow */
+ EVSYS_CHMUX_TCE1_ERR_gc = (0xE9<<0), /* Timer/Counter E1 Error */
+ EVSYS_CHMUX_TCE1_CCA_gc = (0xEC<<0), /* Timer/Counter E1 Compare or Capture A */
+ EVSYS_CHMUX_TCE1_CCB_gc = (0xED<<0), /* Timer/Counter E1 Compare or Capture B */
+ EVSYS_CHMUX_TCF0_OVF_gc = (0xF0<<0), /* Timer/Counter F0 Overflow */
+ EVSYS_CHMUX_TCF0_ERR_gc = (0xF1<<0), /* Timer/Counter F0 Error */
+ EVSYS_CHMUX_TCF0_CCA_gc = (0xF4<<0), /* Timer/Counter F0 Compare or Capture A */
+ EVSYS_CHMUX_TCF0_CCB_gc = (0xF5<<0), /* Timer/Counter F0 Compare or Capture B */
+ EVSYS_CHMUX_TCF0_CCC_gc = (0xF6<<0), /* Timer/Counter F0 Compare or Capture C */
+ EVSYS_CHMUX_TCF0_CCD_gc = (0xF7<<0), /* Timer/Counter F0 Compare or Capture D */
+ EVSYS_CHMUX_TCF1_OVF_gc = (0xF8<<0), /* Timer/Counter F1 Overflow */
+ EVSYS_CHMUX_TCF1_ERR_gc = (0xF9<<0), /* Timer/Counter F1 Error */
+ EVSYS_CHMUX_TCF1_CCA_gc = (0xFC<<0), /* Timer/Counter F1 Compare or Capture A */
+ EVSYS_CHMUX_TCF1_CCB_gc = (0xFD<<0), /* Timer/Counter F1 Compare or Capture B */
+} EVSYS_CHMUX_t;
+
+
+/*
+--------------------------------------------------------------------------
+NVM - Non Volatile Memory Controller
+--------------------------------------------------------------------------
+*/
+
+/* Non-volatile Memory Controller */
+typedef struct NVM_struct
+{
+ register8_t ADDR0; /* Address Register 0 */
+ register8_t ADDR1; /* Address Register 1 */
+ register8_t ADDR2; /* Address Register 2 */
+ register8_t reserved_0x03;
+ register8_t DATA0; /* Data Register 0 */
+ register8_t DATA1; /* Data Register 1 */
+ register8_t DATA2; /* Data Register 2 */
+ register8_t reserved_0x07;
+ register8_t reserved_0x08;
+ register8_t reserved_0x09;
+ register8_t CMD; /* Command */
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t INTCTRL; /* Interrupt Control */
+ register8_t reserved_0x0E;
+ register8_t STATUS; /* Status */
+ register8_t LOCK_BITS; /* Lock Bits (Changed from LOCKBITS to avoid avr-libc collision) */
+} NVM_t;
+
+/* NVM Command */
+typedef enum NVM_CMD_enum
+{
+ NVM_CMD_NO_OPERATION_gc = (0x00<<0), /* Noop/Ordinary LPM */
+ NVM_CMD_READ_USER_SIG_ROW_gc = (0x01<<0), /* Read user signature row */
+ NVM_CMD_READ_CALIB_ROW_gc = (0x02<<0), /* Read calibration row */
+ NVM_CMD_READ_EEPROM_gc = (0x06<<0), /* Read EEPROM */
+ NVM_CMD_READ_FUSES_gc = (0x07<<0), /* Read fuse byte */
+ NVM_CMD_WRITE_LOCK_BITS_gc = (0x08<<0), /* Write lock bits */
+ NVM_CMD_ERASE_USER_SIG_ROW_gc = (0x18<<0), /* Erase user signature row */
+ NVM_CMD_WRITE_USER_SIG_ROW_gc = (0x1A<<0), /* Write user signature row */
+ NVM_CMD_ERASE_APP_gc = (0x20<<0), /* Erase Application Section */
+ NVM_CMD_ERASE_APP_PAGE_gc = (0x22<<0), /* Erase Application Section page */
+ NVM_CMD_LOAD_FLASH_BUFFER_gc = (0x23<<0), /* Load Flash page buffer */
+ NVM_CMD_WRITE_APP_PAGE_gc = (0x24<<0), /* Write Application Section page */
+ NVM_CMD_ERASE_WRITE_APP_PAGE_gc = (0x25<<0), /* Erase-and-write Application Section page */
+ NVM_CMD_ERASE_FLASH_BUFFER_gc = (0x26<<0), /* Erase/flush Flash page buffer */
+ NVM_CMD_ERASE_BOOT_PAGE_gc = (0x2A<<0), /* Erase Boot Section page */
+ NVM_CMD_ERASE_FLASH_PAGE_gc = (0x2B<<0), /* Erase Flash Page */
+ NVM_CMD_WRITE_BOOT_PAGE_gc = (0x2C<<0), /* Write Boot Section page */
+ NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc = (0x2D<<0), /* Erase-and-write Boot Section page */
+ NVM_CMD_WRITE_FLASH_PAGE_gc = (0x2E<<0), /* Write Flash Page */
+ NVM_CMD_ERASE_WRITE_FLASH_PAGE_gc = (0x2F<<0), /* Erase-and-write Flash Page */
+ NVM_CMD_ERASE_EEPROM_gc = (0x30<<0), /* Erase EEPROM */
+ NVM_CMD_ERASE_EEPROM_PAGE_gc = (0x32<<0), /* Erase EEPROM page */
+ NVM_CMD_LOAD_EEPROM_BUFFER_gc = (0x33<<0), /* Load EEPROM page buffer */
+ NVM_CMD_WRITE_EEPROM_PAGE_gc = (0x34<<0), /* Write EEPROM page */
+ NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc = (0x35<<0), /* Erase-and-write EEPROM page */
+ NVM_CMD_ERASE_EEPROM_BUFFER_gc = (0x36<<0), /* Erase/flush EEPROM page buffer */
+ NVM_CMD_APP_CRC_gc = (0x38<<0), /* Application section CRC */
+ NVM_CMD_BOOT_CRC_gc = (0x39<<0), /* Boot Section CRC */
+ NVM_CMD_FLASH_RANGE_CRC_gc = (0x3A<<0), /* Flash Range CRC */
+ NVM_CMD_CHIP_ERASE_gc = (0x40<<0), /* Erase Chip */
+ NVM_CMD_READ_NVM_gc = (0x43<<0), /* Read NVM */
+ NVM_CMD_WRITE_FUSE_gc = (0x4C<<0), /* Write Fuse byte */
+ NVM_CMD_ERASE_BOOT_gc = (0x68<<0), /* Erase Boot Section */
+ NVM_CMD_FLASH_CRC_gc = (0x78<<0), /* Flash CRC */
+} NVM_CMD_t;
+
+/* SPM ready interrupt level */
+typedef enum NVM_SPMLVL_enum
+{
+ NVM_SPMLVL_OFF_gc = (0x00<<2), /* Interrupt disabled */
+ NVM_SPMLVL_LO_gc = (0x01<<2), /* Low level */
+ NVM_SPMLVL_MED_gc = (0x02<<2), /* Medium level */
+ NVM_SPMLVL_HI_gc = (0x03<<2), /* High level */
+} NVM_SPMLVL_t;
+
+/* EEPROM ready interrupt level */
+typedef enum NVM_EELVL_enum
+{
+ NVM_EELVL_OFF_gc = (0x00<<0), /* Interrupt disabled */
+ NVM_EELVL_LO_gc = (0x01<<0), /* Low level */
+ NVM_EELVL_MED_gc = (0x02<<0), /* Medium level */
+ NVM_EELVL_HI_gc = (0x03<<0), /* High level */
+} NVM_EELVL_t;
+
+/* Boot lock bits - boot setcion */
+typedef enum NVM_BLBB_enum
+{
+ NVM_BLBB_RWLOCK_gc = (0x00<<6), /* Read and write not allowed */
+ NVM_BLBB_RLOCK_gc = (0x01<<6), /* Read not allowed */
+ NVM_BLBB_WLOCK_gc = (0x02<<6), /* Write not allowed */
+ NVM_BLBB_NOLOCK_gc = (0x03<<6), /* No locks */
+} NVM_BLBB_t;
+
+/* Boot lock bits - application section */
+typedef enum NVM_BLBA_enum
+{
+ NVM_BLBA_RWLOCK_gc = (0x00<<4), /* Read and write not allowed */
+ NVM_BLBA_RLOCK_gc = (0x01<<4), /* Read not allowed */
+ NVM_BLBA_WLOCK_gc = (0x02<<4), /* Write not allowed */
+ NVM_BLBA_NOLOCK_gc = (0x03<<4), /* No locks */
+} NVM_BLBA_t;
+
+/* Boot lock bits - application table section */
+typedef enum NVM_BLBAT_enum
+{
+ NVM_BLBAT_RWLOCK_gc = (0x00<<2), /* Read and write not allowed */
+ NVM_BLBAT_RLOCK_gc = (0x01<<2), /* Read not allowed */
+ NVM_BLBAT_WLOCK_gc = (0x02<<2), /* Write not allowed */
+ NVM_BLBAT_NOLOCK_gc = (0x03<<2), /* No locks */
+} NVM_BLBAT_t;
+
+/* Lock bits */
+typedef enum NVM_LB_enum
+{
+ NVM_LB_RWLOCK_gc = (0x00<<0), /* Read and write not allowed */
+ NVM_LB_WLOCK_gc = (0x02<<0), /* Write not allowed */
+ NVM_LB_NOLOCK_gc = (0x03<<0), /* No locks */
+} NVM_LB_t;
+
+
+/*
+--------------------------------------------------------------------------
+AC - Analog Comparator
+--------------------------------------------------------------------------
+*/
+
+/* Analog Comparator */
+typedef struct AC_struct
+{
+ register8_t AC0CTRL; /* Analog Comparator 0 Control */
+ register8_t AC1CTRL; /* Analog Comparator 1 Control */
+ register8_t AC0MUXCTRL; /* Analog Comparator 0 MUX Control */
+ register8_t AC1MUXCTRL; /* Analog Comparator 1 MUX Control */
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t WINCTRL; /* Window Mode Control */
+ register8_t STATUS; /* Status */
+} AC_t;
+
+/* Interrupt mode */
+typedef enum AC_INTMODE_enum
+{
+ AC_INTMODE_BOTHEDGES_gc = (0x00<<6), /* Interrupt on both edges */
+ AC_INTMODE_FALLING_gc = (0x02<<6), /* Interrupt on falling edge */
+ AC_INTMODE_RISING_gc = (0x03<<6), /* Interrupt on rising edge */
+} AC_INTMODE_t;
+
+/* Interrupt level */
+typedef enum AC_INTLVL_enum
+{
+ AC_INTLVL_OFF_gc = (0x00<<4), /* Interrupt disabled */
+ AC_INTLVL_LO_gc = (0x01<<4), /* Low level */
+ AC_INTLVL_MED_gc = (0x02<<4), /* Medium level */
+ AC_INTLVL_HI_gc = (0x03<<4), /* High level */
+} AC_INTLVL_t;
+
+/* Hysteresis mode selection */
+typedef enum AC_HYSMODE_enum
+{
+ AC_HYSMODE_NO_gc = (0x00<<1), /* No hysteresis */
+ AC_HYSMODE_SMALL_gc = (0x01<<1), /* Small hysteresis */
+ AC_HYSMODE_LARGE_gc = (0x02<<1), /* Large hysteresis */
+} AC_HYSMODE_t;
+
+/* Positive input multiplexer selection */
+typedef enum AC_MUXPOS_enum
+{
+ AC_MUXPOS_PIN0_gc = (0x00<<3), /* Pin 0 */
+ AC_MUXPOS_PIN1_gc = (0x01<<3), /* Pin 1 */
+ AC_MUXPOS_PIN2_gc = (0x02<<3), /* Pin 2 */
+ AC_MUXPOS_PIN3_gc = (0x03<<3), /* Pin 3 */
+ AC_MUXPOS_PIN4_gc = (0x04<<3), /* Pin 4 */
+ AC_MUXPOS_PIN5_gc = (0x05<<3), /* Pin 5 */
+ AC_MUXPOS_PIN6_gc = (0x06<<3), /* Pin 6 */
+ AC_MUXPOS_DAC_gc = (0x07<<3), /* DAC output */
+} AC_MUXPOS_t;
+
+/* Negative input multiplexer selection */
+typedef enum AC_MUXNEG_enum
+{
+ AC_MUXNEG_PIN0_gc = (0x00<<0), /* Pin 0 */
+ AC_MUXNEG_PIN1_gc = (0x01<<0), /* Pin 1 */
+ AC_MUXNEG_PIN3_gc = (0x02<<0), /* Pin 3 */
+ AC_MUXNEG_PIN5_gc = (0x03<<0), /* Pin 5 */
+ AC_MUXNEG_PIN7_gc = (0x04<<0), /* Pin 7 */
+ AC_MUXNEG_DAC_gc = (0x05<<0), /* DAC output */
+ AC_MUXNEG_BANDGAP_gc = (0x06<<0), /* Bandgap Reference */
+ AC_MUXNEG_SCALER_gc = (0x07<<0), /* Internal voltage scaler */
+} AC_MUXNEG_t;
+
+/* Windows interrupt mode */
+typedef enum AC_WINTMODE_enum
+{
+ AC_WINTMODE_ABOVE_gc = (0x00<<2), /* Interrupt on above window */
+ AC_WINTMODE_INSIDE_gc = (0x01<<2), /* Interrupt on inside window */
+ AC_WINTMODE_BELOW_gc = (0x02<<2), /* Interrupt on below window */
+ AC_WINTMODE_OUTSIDE_gc = (0x03<<2), /* Interrupt on outside window */
+} AC_WINTMODE_t;
+
+/* Window interrupt level */
+typedef enum AC_WINTLVL_enum
+{
+ AC_WINTLVL_OFF_gc = (0x00<<0), /* Interrupt disabled */
+ AC_WINTLVL_LO_gc = (0x01<<0), /* Low priority */
+ AC_WINTLVL_MED_gc = (0x02<<0), /* Medium priority */
+ AC_WINTLVL_HI_gc = (0x03<<0), /* High priority */
+} AC_WINTLVL_t;
+
+/* Window mode state */
+typedef enum AC_WSTATE_enum
+{
+ AC_WSTATE_ABOVE_gc = (0x00<<6), /* Signal above window */
+ AC_WSTATE_INSIDE_gc = (0x01<<6), /* Signal inside window */
+ AC_WSTATE_BELOW_gc = (0x02<<6), /* Signal below window */
+} AC_WSTATE_t;
+
+
+/*
+--------------------------------------------------------------------------
+ADC - Analog/Digital Converter
+--------------------------------------------------------------------------
+*/
+
+/* ADC Channel */
+typedef struct ADC_CH_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t MUXCTRL; /* MUX Control */
+ register8_t INTCTRL; /* Channel Interrupt Control Register */
+ register8_t INTFLAGS; /* Interrupt Flags */
+ _WORDREGISTER(RES); /* Channel Result */
+ register8_t SCAN; /* Input Channel Scan */
+ register8_t reserved_0x07;
+} ADC_CH_t;
+
+
+/* Analog-to-Digital Converter */
+typedef struct ADC_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t REFCTRL; /* Reference Control */
+ register8_t EVCTRL; /* Event Control */
+ register8_t PRESCALER; /* Clock Prescaler */
+ register8_t reserved_0x05;
+ register8_t INTFLAGS; /* Interrupt Flags */
+ register8_t TEMP; /* Temporary Register */
+ register8_t reserved_0x08;
+ register8_t reserved_0x09;
+ register8_t reserved_0x0A;
+ register8_t reserved_0x0B;
+ _WORDREGISTER(CAL); /* Calibration Value */
+ register8_t reserved_0x0E;
+ register8_t reserved_0x0F;
+ _WORDREGISTER(CH0RES); /* Channel 0 Result */
+ _WORDREGISTER(CH1RES); /* Channel 1 Result */
+ _WORDREGISTER(CH2RES); /* Channel 2 Result */
+ _WORDREGISTER(CH3RES); /* Channel 3 Result */
+ _WORDREGISTER(CMP); /* Compare Value */
+ register8_t reserved_0x1A;
+ register8_t reserved_0x1B;
+ register8_t reserved_0x1C;
+ register8_t reserved_0x1D;
+ register8_t reserved_0x1E;
+ register8_t reserved_0x1F;
+ ADC_CH_t CH0; /* ADC Channel 0 */
+ ADC_CH_t CH1; /* ADC Channel 1 */
+ ADC_CH_t CH2; /* ADC Channel 2 */
+ ADC_CH_t CH3; /* ADC Channel 3 */
+} ADC_t;
+
+/* Positive input multiplexer selection */
+typedef enum ADC_CH_MUXPOS_enum
+{
+ ADC_CH_MUXPOS_PIN0_gc = (0x00<<3), /* Input pin 0 */
+ ADC_CH_MUXPOS_PIN1_gc = (0x01<<3), /* Input pin 1 */
+ ADC_CH_MUXPOS_PIN2_gc = (0x02<<3), /* Input pin 2 */
+ ADC_CH_MUXPOS_PIN3_gc = (0x03<<3), /* Input pin 3 */
+ ADC_CH_MUXPOS_PIN4_gc = (0x04<<3), /* Input pin 4 */
+ ADC_CH_MUXPOS_PIN5_gc = (0x05<<3), /* Input pin 5 */
+ ADC_CH_MUXPOS_PIN6_gc = (0x06<<3), /* Input pin 6 */
+ ADC_CH_MUXPOS_PIN7_gc = (0x07<<3), /* Input pin 7 */
+ ADC_CH_MUXPOS_PIN8_gc = (0x08<<3), /* Input pin 8 */
+ ADC_CH_MUXPOS_PIN9_gc = (0x09<<3), /* Input pin 9 */
+ ADC_CH_MUXPOS_PIN10_gc = (0x0A<<3), /* Input pin 10 */
+ ADC_CH_MUXPOS_PIN11_gc = (0x0B<<3), /* Input pin 11 */
+ ADC_CH_MUXPOS_PIN12_gc = (0x0C<<3), /* Input pin 12 */
+ ADC_CH_MUXPOS_PIN13_gc = (0x0D<<3), /* Input pin 13 */
+ ADC_CH_MUXPOS_PIN14_gc = (0x0E<<3), /* Input pin 14 */
+ ADC_CH_MUXPOS_PIN15_gc = (0x0F<<3), /* Input pin 15 */
+} ADC_CH_MUXPOS_t;
+
+/* Internal input multiplexer selections */
+typedef enum ADC_CH_MUXINT_enum
+{
+ ADC_CH_MUXINT_TEMP_gc = (0x00<<3), /* Temperature Reference */
+ ADC_CH_MUXINT_BANDGAP_gc = (0x01<<3), /* Bandgap Reference */
+ ADC_CH_MUXINT_SCALEDVCC_gc = (0x02<<3), /* 1/10 scaled VCC */
+ ADC_CH_MUXINT_DAC_gc = (0x03<<3), /* DAC output */
+} ADC_CH_MUXINT_t;
+
+/* Negative input multiplexer selection */
+typedef enum ADC_CH_MUXNEG_enum
+{
+ ADC_CH_MUXNEG_PIN0_gc = (0x00<<0), /* Input pin 0 (Input Mode = 2) */
+ ADC_CH_MUXNEG_PIN1_gc = (0x01<<0), /* Input pin 1 (Input Mode = 2) */
+ ADC_CH_MUXNEG_PIN2_gc = (0x02<<0), /* Input pin 2 (Input Mode = 2) */
+ ADC_CH_MUXNEG_PIN3_gc = (0x03<<0), /* Input pin 3 (Input Mode = 2) */
+ ADC_CH_MUXNEG_PIN4_gc = (0x00<<0), /* Input pin 4 (Input Mode = 3) */
+ ADC_CH_MUXNEG_PIN5_gc = (0x01<<0), /* Input pin 5 (Input Mode = 3) */
+ ADC_CH_MUXNEG_PIN6_gc = (0x02<<0), /* Input pin 6 (Input Mode = 3) */
+ ADC_CH_MUXNEG_PIN7_gc = (0x03<<0), /* Input pin 7 (Input Mode = 3) */
+ ADC_CH_MUXNEG_GND_MODE3_gc = (0x05<<0), /* PAD Ground (Input Mode = 2) */
+ ADC_CH_MUXNEG_INTGND_MODE3_gc = (0x07<<0), /* Internal Ground (Input Mode = 2) */
+ ADC_CH_MUXNEG_INTGND_MODE4_gc = (0x04<<0), /* Internal Ground (Input Mode = 3) */
+ ADC_CH_MUXNEG_GND_MODE4_gc = (0x07<<0), /* PAD Ground (Input Mode = 3) */
+} ADC_CH_MUXNEG_t;
+
+/* Input mode */
+typedef enum ADC_CH_INPUTMODE_enum
+{
+ ADC_CH_INPUTMODE_INTERNAL_gc = (0x00<<0), /* Internal inputs, no gain */
+ ADC_CH_INPUTMODE_SINGLEENDED_gc = (0x01<<0), /* Single-ended input, no gain */
+ ADC_CH_INPUTMODE_DIFF_gc = (0x02<<0), /* Differential input, no gain */
+ ADC_CH_INPUTMODE_DIFFWGAIN_gc = (0x03<<0), /* Differential input, with gain */
+} ADC_CH_INPUTMODE_t;
+
+/* Gain factor */
+typedef enum ADC_CH_GAIN_enum
+{
+ ADC_CH_GAIN_1X_gc = (0x00<<2), /* 1x gain */
+ ADC_CH_GAIN_2X_gc = (0x01<<2), /* 2x gain */
+ ADC_CH_GAIN_4X_gc = (0x02<<2), /* 4x gain */
+ ADC_CH_GAIN_8X_gc = (0x03<<2), /* 8x gain */
+ ADC_CH_GAIN_16X_gc = (0x04<<2), /* 16x gain */
+ ADC_CH_GAIN_32X_gc = (0x05<<2), /* 32x gain */
+ ADC_CH_GAIN_64X_gc = (0x06<<2), /* 64x gain */
+ ADC_CH_GAIN_DIV2_gc = (0x07<<2), /* x/2 gain */
+} ADC_CH_GAIN_t;
+
+/* Conversion result resolution */
+typedef enum ADC_RESOLUTION_enum
+{
+ ADC_RESOLUTION_12BIT_gc = (0x00<<1), /* 12-bit right-adjusted result */
+ ADC_RESOLUTION_8BIT_gc = (0x02<<1), /* 8-bit right-adjusted result */
+ ADC_RESOLUTION_LEFT12BIT_gc = (0x03<<1), /* 12-bit left-adjusted result */
+} ADC_RESOLUTION_t;
+
+/* Current Limitation Mode */
+typedef enum ADC_CURRLIMIT_enum
+{
+ ADC_CURRLIMIT_NO_gc = (0x00<<5), /* No limit */
+ ADC_CURRLIMIT_LOW_gc = (0x01<<5), /* Low current limit, max. sampling rate 1.5MSPS */
+ ADC_CURRLIMIT_MED_gc = (0x02<<5), /* Medium current limit, max. sampling rate 1MSPS */
+ ADC_CURRLIMIT_HIGH_gc = (0x03<<5), /* High current limit, max. sampling rate 0.5MSPS */
+} ADC_CURRLIMIT_t;
+
+/* Voltage reference selection */
+typedef enum ADC_REFSEL_enum
+{
+ ADC_REFSEL_INT1V_gc = (0x00<<4), /* Internal 1V */
+ ADC_REFSEL_INTVCC_gc = (0x01<<4), /* Internal VCC / 1.6 */
+ ADC_REFSEL_AREFA_gc = (0x02<<4), /* External reference on PORT A */
+ ADC_REFSEL_AREFB_gc = (0x03<<4), /* External reference on PORT B */
+ ADC_REFSEL_INTVCC2_gc = (0x04<<4), /* Internal VCC / 2 */
+} ADC_REFSEL_t;
+
+/* Channel sweep selection */
+typedef enum ADC_SWEEP_enum
+{
+ ADC_SWEEP_0_gc = (0x00<<6), /* ADC Channel 0 */
+ ADC_SWEEP_01_gc = (0x01<<6), /* ADC Channel 0,1 */
+ ADC_SWEEP_012_gc = (0x02<<6), /* ADC Channel 0,1,2 */
+ ADC_SWEEP_0123_gc = (0x03<<6), /* ADC Channel 0,1,2,3 */
+} ADC_SWEEP_t;
+
+/* Event channel input selection */
+typedef enum ADC_EVSEL_enum
+{
+ ADC_EVSEL_0123_gc = (0x00<<3), /* Event Channel 0,1,2,3 */
+ ADC_EVSEL_1234_gc = (0x01<<3), /* Event Channel 1,2,3,4 */
+ ADC_EVSEL_2345_gc = (0x02<<3), /* Event Channel 2,3,4,5 */
+ ADC_EVSEL_3456_gc = (0x03<<3), /* Event Channel 3,4,5,6 */
+ ADC_EVSEL_4567_gc = (0x04<<3), /* Event Channel 4,5,6,7 */
+ ADC_EVSEL_567_gc = (0x05<<3), /* Event Channel 5,6,7 */
+ ADC_EVSEL_67_gc = (0x06<<3), /* Event Channel 6,7 */
+ ADC_EVSEL_7_gc = (0x07<<3), /* Event Channel 7 */
+} ADC_EVSEL_t;
+
+/* Event action selection */
+typedef enum ADC_EVACT_enum
+{
+ ADC_EVACT_NONE_gc = (0x00<<0), /* No event action */
+ ADC_EVACT_CH0_gc = (0x01<<0), /* First event triggers channel 0 */
+ ADC_EVACT_CH01_gc = (0x02<<0), /* First two events trigger channel 0,1 */
+ ADC_EVACT_CH012_gc = (0x03<<0), /* First three events trigger channel 0,1,2 */
+ ADC_EVACT_CH0123_gc = (0x04<<0), /* Events trigger channel 0,1,2,3 */
+ ADC_EVACT_SWEEP_gc = (0x05<<0), /* First event triggers sweep */
+ ADC_EVACT_SYNCSWEEP_gc = (0x06<<0), /* The ADC is flushed and restarted for accurate timing */
+} ADC_EVACT_t;
+
+/* Interupt mode */
+typedef enum ADC_CH_INTMODE_enum
+{
+ ADC_CH_INTMODE_COMPLETE_gc = (0x00<<2), /* Interrupt on conversion complete */
+ ADC_CH_INTMODE_BELOW_gc = (0x01<<2), /* Interrupt on result below compare value */
+ ADC_CH_INTMODE_ABOVE_gc = (0x03<<2), /* Interrupt on result above compare value */
+} ADC_CH_INTMODE_t;
+
+/* Interrupt level */
+typedef enum ADC_CH_INTLVL_enum
+{
+ ADC_CH_INTLVL_OFF_gc = (0x00<<0), /* Interrupt disabled */
+ ADC_CH_INTLVL_LO_gc = (0x01<<0), /* Low level */
+ ADC_CH_INTLVL_MED_gc = (0x02<<0), /* Medium level */
+ ADC_CH_INTLVL_HI_gc = (0x03<<0), /* High level */
+} ADC_CH_INTLVL_t;
+
+/* DMA request selection */
+typedef enum ADC_DMASEL_enum
+{
+ ADC_DMASEL_OFF_gc = (0x00<<6), /* Combined DMA request OFF */
+ ADC_DMASEL_CH01_gc = (0x01<<6), /* ADC Channel 0 or 1 */
+ ADC_DMASEL_CH012_gc = (0x02<<6), /* ADC Channel 0 or 1 or 2 */
+ ADC_DMASEL_CH0123_gc = (0x03<<6), /* ADC Channel 0 or 1 or 2 or 3 */
+} ADC_DMASEL_t;
+
+/* Clock prescaler */
+typedef enum ADC_PRESCALER_enum
+{
+ ADC_PRESCALER_DIV4_gc = (0x00<<0), /* Divide clock by 4 */
+ ADC_PRESCALER_DIV8_gc = (0x01<<0), /* Divide clock by 8 */
+ ADC_PRESCALER_DIV16_gc = (0x02<<0), /* Divide clock by 16 */
+ ADC_PRESCALER_DIV32_gc = (0x03<<0), /* Divide clock by 32 */
+ ADC_PRESCALER_DIV64_gc = (0x04<<0), /* Divide clock by 64 */
+ ADC_PRESCALER_DIV128_gc = (0x05<<0), /* Divide clock by 128 */
+ ADC_PRESCALER_DIV256_gc = (0x06<<0), /* Divide clock by 256 */
+ ADC_PRESCALER_DIV512_gc = (0x07<<0), /* Divide clock by 512 */
+} ADC_PRESCALER_t;
+
+
+/*
+--------------------------------------------------------------------------
+DAC - Digital/Analog Converter
+--------------------------------------------------------------------------
+*/
+
+/* Digital-to-Analog Converter */
+typedef struct DAC_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t CTRLC; /* Control Register C */
+ register8_t EVCTRL; /* Event Input Control */
+ register8_t reserved_0x04;
+ register8_t STATUS; /* Status */
+ register8_t reserved_0x06;
+ register8_t reserved_0x07;
+ register8_t CH0GAINCAL; /* Gain Calibration */
+ register8_t CH0OFFSETCAL; /* Offset Calibration */
+ register8_t CH1GAINCAL; /* Gain Calibration */
+ register8_t CH1OFFSETCAL; /* Offset Calibration */
+ register8_t reserved_0x0C;
+ register8_t reserved_0x0D;
+ register8_t reserved_0x0E;
+ register8_t reserved_0x0F;
+ register8_t reserved_0x10;
+ register8_t reserved_0x11;
+ register8_t reserved_0x12;
+ register8_t reserved_0x13;
+ register8_t reserved_0x14;
+ register8_t reserved_0x15;
+ register8_t reserved_0x16;
+ register8_t reserved_0x17;
+ _WORDREGISTER(CH0DATA); /* Channel 0 Data */
+ _WORDREGISTER(CH1DATA); /* Channel 1 Data */
+} DAC_t;
+
+/* Output channel selection */
+typedef enum DAC_CHSEL_enum
+{
+ DAC_CHSEL_SINGLE_gc = (0x00<<5), /* Single channel operation (Channel 0 only) */
+ DAC_CHSEL_SINGLE1_gc = (0x01<<5), /* Single channel operation (Channel 1 only) */
+ DAC_CHSEL_DUAL_gc = (0x02<<5), /* Dual channel operation (Channel 0 and channel 1) */
+} DAC_CHSEL_t;
+
+/* Reference voltage selection */
+typedef enum DAC_REFSEL_enum
+{
+ DAC_REFSEL_INT1V_gc = (0x00<<3), /* Internal 1V */
+ DAC_REFSEL_AVCC_gc = (0x01<<3), /* Analog supply voltage */
+ DAC_REFSEL_AREFA_gc = (0x02<<3), /* External reference on AREF on PORTA */
+ DAC_REFSEL_AREFB_gc = (0x03<<3), /* External reference on AREF on PORTB */
+} DAC_REFSEL_t;
+
+/* Event channel selection */
+typedef enum DAC_EVSEL_enum
+{
+ DAC_EVSEL_0_gc = (0x00<<0), /* Event Channel 0 */
+ DAC_EVSEL_1_gc = (0x01<<0), /* Event Channel 1 */
+ DAC_EVSEL_2_gc = (0x02<<0), /* Event Channel 2 */
+ DAC_EVSEL_3_gc = (0x03<<0), /* Event Channel 3 */
+ DAC_EVSEL_4_gc = (0x04<<0), /* Event Channel 4 */
+ DAC_EVSEL_5_gc = (0x05<<0), /* Event Channel 5 */
+ DAC_EVSEL_6_gc = (0x06<<0), /* Event Channel 6 */
+ DAC_EVSEL_7_gc = (0x07<<0), /* Event Channel 7 */
+} DAC_EVSEL_t;
+
+
+/*
+--------------------------------------------------------------------------
+RTC - Real-Time Counter
+--------------------------------------------------------------------------
+*/
+
+/* Real-Time Counter */
+typedef struct RTC_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t STATUS; /* Status Register */
+ register8_t INTCTRL; /* Interrupt Control Register */
+ register8_t INTFLAGS; /* Interrupt Flags */
+ register8_t TEMP; /* Temporary register */
+ register8_t reserved_0x05;
+ register8_t reserved_0x06;
+ register8_t reserved_0x07;
+ _WORDREGISTER(CNT); /* Count Register */
+ _WORDREGISTER(PER); /* Period Register */
+ _WORDREGISTER(COMP); /* Compare Register */
+} RTC_t;
+
+/* Prescaler Factor */
+typedef enum RTC_PRESCALER_enum
+{
+ RTC_PRESCALER_OFF_gc = (0x00<<0), /* RTC Off */
+ RTC_PRESCALER_DIV1_gc = (0x01<<0), /* RTC Clock */
+ RTC_PRESCALER_DIV2_gc = (0x02<<0), /* RTC Clock / 2 */
+ RTC_PRESCALER_DIV8_gc = (0x03<<0), /* RTC Clock / 8 */
+ RTC_PRESCALER_DIV16_gc = (0x04<<0), /* RTC Clock / 16 */
+ RTC_PRESCALER_DIV64_gc = (0x05<<0), /* RTC Clock / 64 */
+ RTC_PRESCALER_DIV256_gc = (0x06<<0), /* RTC Clock / 256 */
+ RTC_PRESCALER_DIV1024_gc = (0x07<<0), /* RTC Clock / 1024 */
+} RTC_PRESCALER_t;
+
+/* Compare Interrupt level */
+typedef enum RTC_COMPINTLVL_enum
+{
+ RTC_COMPINTLVL_OFF_gc = (0x00<<2), /* Interrupt Disabled */
+ RTC_COMPINTLVL_LO_gc = (0x01<<2), /* Low Level */
+ RTC_COMPINTLVL_MED_gc = (0x02<<2), /* Medium Level */
+ RTC_COMPINTLVL_HI_gc = (0x03<<2), /* High Level */
+} RTC_COMPINTLVL_t;
+
+/* Overflow Interrupt level */
+typedef enum RTC_OVFINTLVL_enum
+{
+ RTC_OVFINTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ RTC_OVFINTLVL_LO_gc = (0x01<<0), /* Low Level */
+ RTC_OVFINTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ RTC_OVFINTLVL_HI_gc = (0x03<<0), /* High Level */
+} RTC_OVFINTLVL_t;
+
+
+/*
+--------------------------------------------------------------------------
+TWI - Two-Wire Interface
+--------------------------------------------------------------------------
+*/
+
+/* */
+typedef struct TWI_MASTER_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t CTRLC; /* Control Register C */
+ register8_t STATUS; /* Status Register */
+ register8_t BAUD; /* Baurd Rate Control Register */
+ register8_t ADDR; /* Address Register */
+ register8_t DATA; /* Data Register */
+} TWI_MASTER_t;
+
+
+/* */
+typedef struct TWI_SLAVE_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t STATUS; /* Status Register */
+ register8_t ADDR; /* Address Register */
+ register8_t DATA; /* Data Register */
+ register8_t ADDRMASK; /* Address Mask Register */
+} TWI_SLAVE_t;
+
+
+/* Two-Wire Interface */
+typedef struct TWI_struct
+{
+ register8_t CTRL; /* TWI Common Control Register */
+ TWI_MASTER_t MASTER; /* TWI master module */
+ TWI_SLAVE_t SLAVE; /* TWI slave module */
+} TWI_t;
+
+/* SDA Hold Time */
+typedef enum TWI_SDAHOLD_enum
+{
+ TWI_SDAHOLD_OFF_gc = (0x00<<1), /* SDA Hold Time off */
+ TWI_SDAHOLD_50NS_gc = (0x01<<1), /* SDA Hold Time 50 ns */
+ TWI_SDAHOLD_300NS_gc = (0x02<<1), /* SDA Hold Time 300 ns */
+ TWI_SDAHOLD_400NS_gc = (0x03<<1), /* SDA Hold Time 400 ns */
+} TWI_SDAHOLD_t;
+
+/* Master Interrupt Level */
+typedef enum TWI_MASTER_INTLVL_enum
+{
+ TWI_MASTER_INTLVL_OFF_gc = (0x00<<6), /* Interrupt Disabled */
+ TWI_MASTER_INTLVL_LO_gc = (0x01<<6), /* Low Level */
+ TWI_MASTER_INTLVL_MED_gc = (0x02<<6), /* Medium Level */
+ TWI_MASTER_INTLVL_HI_gc = (0x03<<6), /* High Level */
+} TWI_MASTER_INTLVL_t;
+
+/* Inactive Timeout */
+typedef enum TWI_MASTER_TIMEOUT_enum
+{
+ TWI_MASTER_TIMEOUT_DISABLED_gc = (0x00<<2), /* Bus Timeout Disabled */
+ TWI_MASTER_TIMEOUT_50US_gc = (0x01<<2), /* 50 Microseconds */
+ TWI_MASTER_TIMEOUT_100US_gc = (0x02<<2), /* 100 Microseconds */
+ TWI_MASTER_TIMEOUT_200US_gc = (0x03<<2), /* 200 Microseconds */
+} TWI_MASTER_TIMEOUT_t;
+
+/* Master Command */
+typedef enum TWI_MASTER_CMD_enum
+{
+ TWI_MASTER_CMD_NOACT_gc = (0x00<<0), /* No Action */
+ TWI_MASTER_CMD_REPSTART_gc = (0x01<<0), /* Issue Repeated Start Condition */
+ TWI_MASTER_CMD_RECVTRANS_gc = (0x02<<0), /* Receive or Transmit Data */
+ TWI_MASTER_CMD_STOP_gc = (0x03<<0), /* Issue Stop Condition */
+} TWI_MASTER_CMD_t;
+
+/* Master Bus State */
+typedef enum TWI_MASTER_BUSSTATE_enum
+{
+ TWI_MASTER_BUSSTATE_UNKNOWN_gc = (0x00<<0), /* Unknown Bus State */
+ TWI_MASTER_BUSSTATE_IDLE_gc = (0x01<<0), /* Bus is Idle */
+ TWI_MASTER_BUSSTATE_OWNER_gc = (0x02<<0), /* This Module Controls The Bus */
+ TWI_MASTER_BUSSTATE_BUSY_gc = (0x03<<0), /* The Bus is Busy */
+} TWI_MASTER_BUSSTATE_t;
+
+/* Slave Interrupt Level */
+typedef enum TWI_SLAVE_INTLVL_enum
+{
+ TWI_SLAVE_INTLVL_OFF_gc = (0x00<<6), /* Interrupt Disabled */
+ TWI_SLAVE_INTLVL_LO_gc = (0x01<<6), /* Low Level */
+ TWI_SLAVE_INTLVL_MED_gc = (0x02<<6), /* Medium Level */
+ TWI_SLAVE_INTLVL_HI_gc = (0x03<<6), /* High Level */
+} TWI_SLAVE_INTLVL_t;
+
+/* Slave Command */
+typedef enum TWI_SLAVE_CMD_enum
+{
+ TWI_SLAVE_CMD_NOACT_gc = (0x00<<0), /* No Action */
+ TWI_SLAVE_CMD_COMPTRANS_gc = (0x02<<0), /* Used To Complete a Transaction */
+ TWI_SLAVE_CMD_RESPONSE_gc = (0x03<<0), /* Used in Response to Address/Data Interrupt */
+} TWI_SLAVE_CMD_t;
+
+
+/*
+--------------------------------------------------------------------------
+USB - USB
+--------------------------------------------------------------------------
+*/
+
+/* USB Endpoint */
+typedef struct USB_EP_struct
+{
+ register8_t STATUS; /* Endpoint Status */
+ register8_t CTRL; /* Endpoint Control */
+ _WORDREGISTER(CNT); /* USB Endpoint Counter */
+ _WORDREGISTER(DATAPTR); /* Data Pointer */
+ _WORDREGISTER(AUXDATA); /* Auxiliary Data */
+} USB_EP_t;
+
+
+/* Universal Serial Bus */
+typedef struct USB_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t STATUS; /* Status Register */
+ register8_t ADDR; /* Address Register */
+ register8_t FIFOWP; /* FIFO Write Pointer Register */
+ register8_t FIFORP; /* FIFO Read Pointer Register */
+ _WORDREGISTER(EPPTR); /* Endpoint Configuration Table Pointer */
+ register8_t INTCTRLA; /* Interrupt Control Register A */
+ register8_t INTCTRLB; /* Interrupt Control Register B */
+ register8_t INTFLAGSACLR; /* Clear Interrupt Flag Register A */
+ register8_t INTFLAGSASET; /* Set Interrupt Flag Register A */
+ register8_t INTFLAGSBCLR; /* Clear Interrupt Flag Register B */
+ register8_t INTFLAGSBSET; /* Set Interrupt Flag Register B */
+ register8_t reserved_0x0E;
+ register8_t reserved_0x0F;
+ register8_t reserved_0x10;
+ register8_t reserved_0x11;
+ register8_t reserved_0x12;
+ register8_t reserved_0x13;
+ register8_t reserved_0x14;
+ register8_t reserved_0x15;
+ register8_t reserved_0x16;
+ register8_t reserved_0x17;
+ register8_t reserved_0x18;
+ register8_t reserved_0x19;
+ register8_t reserved_0x1A;
+ register8_t reserved_0x1B;
+ register8_t reserved_0x1C;
+ register8_t reserved_0x1D;
+ register8_t reserved_0x1E;
+ register8_t reserved_0x1F;
+ register8_t reserved_0x20;
+ register8_t reserved_0x21;
+ register8_t reserved_0x22;
+ register8_t reserved_0x23;
+ register8_t reserved_0x24;
+ register8_t reserved_0x25;
+ register8_t reserved_0x26;
+ register8_t reserved_0x27;
+ register8_t reserved_0x28;
+ register8_t reserved_0x29;
+ register8_t reserved_0x2A;
+ register8_t reserved_0x2B;
+ register8_t reserved_0x2C;
+ register8_t reserved_0x2D;
+ register8_t reserved_0x2E;
+ register8_t reserved_0x2F;
+ register8_t reserved_0x30;
+ register8_t reserved_0x31;
+ register8_t reserved_0x32;
+ register8_t reserved_0x33;
+ register8_t reserved_0x34;
+ register8_t reserved_0x35;
+ register8_t reserved_0x36;
+ register8_t reserved_0x37;
+ register8_t reserved_0x38;
+ register8_t reserved_0x39;
+ register8_t CAL0; /* Calibration Byte 0 */
+ register8_t CAL1; /* Calibration Byte 1 */
+} USB_t;
+
+
+/* USB Endpoint Table */
+typedef struct USB_EP_TABLE_struct
+{
+ USB_EP_t EP0OUT; /* Endpoint 0 */
+ USB_EP_t EP0IN; /* Endpoint 0 */
+ USB_EP_t EP1OUT; /* Endpoint 1 */
+ USB_EP_t EP1IN; /* Endpoint 1 */
+ USB_EP_t EP2OUT; /* Endpoint 2 */
+ USB_EP_t EP2IN; /* Endpoint 2 */
+ USB_EP_t EP3OUT; /* Endpoint 3 */
+ USB_EP_t EP3IN; /* Endpoint 3 */
+ USB_EP_t EP4OUT; /* Endpoint 4 */
+ USB_EP_t EP4IN; /* Endpoint 4 */
+ USB_EP_t EP5OUT; /* Endpoint 5 */
+ USB_EP_t EP5IN; /* Endpoint 5 */
+ USB_EP_t EP6OUT; /* Endpoint 6 */
+ USB_EP_t EP6IN; /* Endpoint 6 */
+ USB_EP_t EP7OUT; /* Endpoint 7 */
+ USB_EP_t EP7IN; /* Endpoint 7 */
+ USB_EP_t EP8OUT; /* Endpoint 8 */
+ USB_EP_t EP8IN; /* Endpoint 8 */
+ USB_EP_t EP9OUT; /* Endpoint 9 */
+ USB_EP_t EP9IN; /* Endpoint 9 */
+ USB_EP_t EP10OUT; /* Endpoint 10 */
+ USB_EP_t EP10IN; /* Endpoint 10 */
+ USB_EP_t EP11OUT; /* Endpoint 11 */
+ USB_EP_t EP11IN; /* Endpoint 11 */
+ USB_EP_t EP12OUT; /* Endpoint 12 */
+ USB_EP_t EP12IN; /* Endpoint 12 */
+ USB_EP_t EP13OUT; /* Endpoint 13 */
+ USB_EP_t EP13IN; /* Endpoint 13 */
+ USB_EP_t EP14OUT; /* Endpoint 14 */
+ USB_EP_t EP14IN; /* Endpoint 14 */
+ USB_EP_t EP15OUT; /* Endpoint 15 */
+ USB_EP_t EP15IN; /* Endpoint 15 */
+ register8_t reserved_0x100;
+ register8_t reserved_0x101;
+ register8_t reserved_0x102;
+ register8_t reserved_0x103;
+ register8_t reserved_0x104;
+ register8_t reserved_0x105;
+ register8_t reserved_0x106;
+ register8_t reserved_0x107;
+ register8_t reserved_0x108;
+ register8_t reserved_0x109;
+ register8_t reserved_0x10A;
+ register8_t reserved_0x10B;
+ register8_t reserved_0x10C;
+ register8_t reserved_0x10D;
+ register8_t reserved_0x10E;
+ register8_t reserved_0x10F;
+ register8_t FRAMENUML; /* Frame Number Low Byte */
+ register8_t FRAMENUMH; /* Frame Number High Byte */
+} USB_EP_TABLE_t;
+
+/* Interrupt level */
+typedef enum USB_INTLVL_enum
+{
+ USB_INTLVL_OFF_gc = (0x00<<0), /* Interrupt disabled */
+ USB_INTLVL_LO_gc = (0x01<<0), /* Low level */
+ USB_INTLVL_MED_gc = (0x02<<0), /* Medium level */
+ USB_INTLVL_HI_gc = (0x03<<0), /* High level */
+} USB_INTLVL_t;
+
+/* USB Endpoint Type */
+typedef enum USB_EP_TYPE_enum
+{
+ USB_EP_TYPE_DISABLE_gc = (0x00<<6), /* Endpoint Disabled */
+ USB_EP_TYPE_CONTROL_gc = (0x01<<6), /* Control */
+ USB_EP_TYPE_BULK_gc = (0x02<<6), /* Bulk/Interrupt */
+ USB_EP_TYPE_ISOCHRONOUS_gc = (0x03<<6), /* Isochronous */
+} USB_EP_TYPE_t;
+
+/* USB Endpoint Buffersize */
+typedef enum USB_EP_BUFSIZE_enum
+{
+ USB_EP_BUFSIZE_8_gc = (0x00<<0), /* 8 bytes buffer size */
+ USB_EP_BUFSIZE_16_gc = (0x01<<0), /* 16 bytes buffer size */
+ USB_EP_BUFSIZE_32_gc = (0x02<<0), /* 32 bytes buffer size */
+ USB_EP_BUFSIZE_64_gc = (0x03<<0), /* 64 bytes buffer size */
+ USB_EP_BUFSIZE_128_gc = (0x04<<0), /* 128 bytes buffer size */
+ USB_EP_BUFSIZE_256_gc = (0x05<<0), /* 256 bytes buffer size */
+ USB_EP_BUFSIZE_512_gc = (0x06<<0), /* 512 bytes buffer size */
+ USB_EP_BUFSIZE_1023_gc = (0x07<<0), /* 1023 bytes buffer size */
+} USB_EP_BUFSIZE_t;
+
+
+/*
+--------------------------------------------------------------------------
+PORT - I/O Port Configuration
+--------------------------------------------------------------------------
+*/
+
+/* I/O Ports */
+typedef struct PORT_struct
+{
+ register8_t DIR; /* I/O Port Data Direction */
+ register8_t DIRSET; /* I/O Port Data Direction Set */
+ register8_t DIRCLR; /* I/O Port Data Direction Clear */
+ register8_t DIRTGL; /* I/O Port Data Direction Toggle */
+ register8_t OUT; /* I/O Port Output */
+ register8_t OUTSET; /* I/O Port Output Set */
+ register8_t OUTCLR; /* I/O Port Output Clear */
+ register8_t OUTTGL; /* I/O Port Output Toggle */
+ register8_t IN; /* I/O port Input */
+ register8_t INTCTRL; /* Interrupt Control Register */
+ register8_t INT0MASK; /* Port Interrupt 0 Mask */
+ register8_t INT1MASK; /* Port Interrupt 1 Mask */
+ register8_t INTFLAGS; /* Interrupt Flag Register */
+ register8_t reserved_0x0D;
+ register8_t REMAP; /* I/O Port Pin Remap Register */
+ register8_t reserved_0x0F;
+ register8_t PIN0CTRL; /* Pin 0 Control Register */
+ register8_t PIN1CTRL; /* Pin 1 Control Register */
+ register8_t PIN2CTRL; /* Pin 2 Control Register */
+ register8_t PIN3CTRL; /* Pin 3 Control Register */
+ register8_t PIN4CTRL; /* Pin 4 Control Register */
+ register8_t PIN5CTRL; /* Pin 5 Control Register */
+ register8_t PIN6CTRL; /* Pin 6 Control Register */
+ register8_t PIN7CTRL; /* Pin 7 Control Register */
+} PORT_t;
+
+/* Port Interrupt 0 Level */
+typedef enum PORT_INT0LVL_enum
+{
+ PORT_INT0LVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ PORT_INT0LVL_LO_gc = (0x01<<0), /* Low Level */
+ PORT_INT0LVL_MED_gc = (0x02<<0), /* Medium Level */
+ PORT_INT0LVL_HI_gc = (0x03<<0), /* High Level */
+} PORT_INT0LVL_t;
+
+/* Port Interrupt 1 Level */
+typedef enum PORT_INT1LVL_enum
+{
+ PORT_INT1LVL_OFF_gc = (0x00<<2), /* Interrupt Disabled */
+ PORT_INT1LVL_LO_gc = (0x01<<2), /* Low Level */
+ PORT_INT1LVL_MED_gc = (0x02<<2), /* Medium Level */
+ PORT_INT1LVL_HI_gc = (0x03<<2), /* High Level */
+} PORT_INT1LVL_t;
+
+/* Output/Pull Configuration */
+typedef enum PORT_OPC_enum
+{
+ PORT_OPC_TOTEM_gc = (0x00<<3), /* Totempole */
+ PORT_OPC_BUSKEEPER_gc = (0x01<<3), /* Totempole w/ Bus keeper on Input and Output */
+ PORT_OPC_PULLDOWN_gc = (0x02<<3), /* Totempole w/ Pull-down on Input */
+ PORT_OPC_PULLUP_gc = (0x03<<3), /* Totempole w/ Pull-up on Input */
+ PORT_OPC_WIREDOR_gc = (0x04<<3), /* Wired OR */
+ PORT_OPC_WIREDAND_gc = (0x05<<3), /* Wired AND */
+ PORT_OPC_WIREDORPULL_gc = (0x06<<3), /* Wired OR w/ Pull-down */
+ PORT_OPC_WIREDANDPULL_gc = (0x07<<3), /* Wired AND w/ Pull-up */
+} PORT_OPC_t;
+
+/* Input/Sense Configuration */
+typedef enum PORT_ISC_enum
+{
+ PORT_ISC_BOTHEDGES_gc = (0x00<<0), /* Sense Both Edges */
+ PORT_ISC_RISING_gc = (0x01<<0), /* Sense Rising Edge */
+ PORT_ISC_FALLING_gc = (0x02<<0), /* Sense Falling Edge */
+ PORT_ISC_LEVEL_gc = (0x03<<0), /* Sense Level (Transparent For Events) */
+ PORT_ISC_INPUT_DISABLE_gc = (0x07<<0), /* Disable Digital Input Buffer */
+} PORT_ISC_t;
+
+
+/*
+--------------------------------------------------------------------------
+TC - 16-bit Timer/Counter With PWM
+--------------------------------------------------------------------------
+*/
+
+/* 16-bit Timer/Counter 0 */
+typedef struct TC0_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t CTRLC; /* Control register C */
+ register8_t CTRLD; /* Control Register D */
+ register8_t CTRLE; /* Control Register E */
+ register8_t reserved_0x05;
+ register8_t INTCTRLA; /* Interrupt Control Register A */
+ register8_t INTCTRLB; /* Interrupt Control Register B */
+ register8_t CTRLFCLR; /* Control Register F Clear */
+ register8_t CTRLFSET; /* Control Register F Set */
+ register8_t CTRLGCLR; /* Control Register G Clear */
+ register8_t CTRLGSET; /* Control Register G Set */
+ register8_t INTFLAGS; /* Interrupt Flag Register */
+ register8_t reserved_0x0D;
+ register8_t reserved_0x0E;
+ register8_t TEMP; /* Temporary Register For 16-bit Access */
+ register8_t reserved_0x10;
+ register8_t reserved_0x11;
+ register8_t reserved_0x12;
+ register8_t reserved_0x13;
+ register8_t reserved_0x14;
+ register8_t reserved_0x15;
+ register8_t reserved_0x16;
+ register8_t reserved_0x17;
+ register8_t reserved_0x18;
+ register8_t reserved_0x19;
+ register8_t reserved_0x1A;
+ register8_t reserved_0x1B;
+ register8_t reserved_0x1C;
+ register8_t reserved_0x1D;
+ register8_t reserved_0x1E;
+ register8_t reserved_0x1F;
+ _WORDREGISTER(CNT); /* Count */
+ register8_t reserved_0x22;
+ register8_t reserved_0x23;
+ register8_t reserved_0x24;
+ register8_t reserved_0x25;
+ _WORDREGISTER(PER); /* Period */
+ _WORDREGISTER(CCA); /* Compare or Capture A */
+ _WORDREGISTER(CCB); /* Compare or Capture B */
+ _WORDREGISTER(CCC); /* Compare or Capture C */
+ _WORDREGISTER(CCD); /* Compare or Capture D */
+ register8_t reserved_0x30;
+ register8_t reserved_0x31;
+ register8_t reserved_0x32;
+ register8_t reserved_0x33;
+ register8_t reserved_0x34;
+ register8_t reserved_0x35;
+ _WORDREGISTER(PERBUF); /* Period Buffer */
+ _WORDREGISTER(CCABUF); /* Compare Or Capture A Buffer */
+ _WORDREGISTER(CCBBUF); /* Compare Or Capture B Buffer */
+ _WORDREGISTER(CCCBUF); /* Compare Or Capture C Buffer */
+ _WORDREGISTER(CCDBUF); /* Compare Or Capture D Buffer */
+} TC0_t;
+
+
+/* 16-bit Timer/Counter 1 */
+typedef struct TC1_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t CTRLC; /* Control register C */
+ register8_t CTRLD; /* Control Register D */
+ register8_t CTRLE; /* Control Register E */
+ register8_t reserved_0x05;
+ register8_t INTCTRLA; /* Interrupt Control Register A */
+ register8_t INTCTRLB; /* Interrupt Control Register B */
+ register8_t CTRLFCLR; /* Control Register F Clear */
+ register8_t CTRLFSET; /* Control Register F Set */
+ register8_t CTRLGCLR; /* Control Register G Clear */
+ register8_t CTRLGSET; /* Control Register G Set */
+ register8_t INTFLAGS; /* Interrupt Flag Register */
+ register8_t reserved_0x0D;
+ register8_t reserved_0x0E;
+ register8_t TEMP; /* Temporary Register For 16-bit Access */
+ register8_t reserved_0x10;
+ register8_t reserved_0x11;
+ register8_t reserved_0x12;
+ register8_t reserved_0x13;
+ register8_t reserved_0x14;
+ register8_t reserved_0x15;
+ register8_t reserved_0x16;
+ register8_t reserved_0x17;
+ register8_t reserved_0x18;
+ register8_t reserved_0x19;
+ register8_t reserved_0x1A;
+ register8_t reserved_0x1B;
+ register8_t reserved_0x1C;
+ register8_t reserved_0x1D;
+ register8_t reserved_0x1E;
+ register8_t reserved_0x1F;
+ _WORDREGISTER(CNT); /* Count */
+ register8_t reserved_0x22;
+ register8_t reserved_0x23;
+ register8_t reserved_0x24;
+ register8_t reserved_0x25;
+ _WORDREGISTER(PER); /* Period */
+ _WORDREGISTER(CCA); /* Compare or Capture A */
+ _WORDREGISTER(CCB); /* Compare or Capture B */
+ register8_t reserved_0x2C;
+ register8_t reserved_0x2D;
+ register8_t reserved_0x2E;
+ register8_t reserved_0x2F;
+ register8_t reserved_0x30;
+ register8_t reserved_0x31;
+ register8_t reserved_0x32;
+ register8_t reserved_0x33;
+ register8_t reserved_0x34;
+ register8_t reserved_0x35;
+ _WORDREGISTER(PERBUF); /* Period Buffer */
+ _WORDREGISTER(CCABUF); /* Compare Or Capture A Buffer */
+ _WORDREGISTER(CCBBUF); /* Compare Or Capture B Buffer */
+} TC1_t;
+
+/* Clock Selection */
+typedef enum TC_CLKSEL_enum
+{
+ TC_CLKSEL_OFF_gc = (0x00<<0), /* Timer Off */
+ TC_CLKSEL_DIV1_gc = (0x01<<0), /* System Clock */
+ TC_CLKSEL_DIV2_gc = (0x02<<0), /* System Clock / 2 */
+ TC_CLKSEL_DIV4_gc = (0x03<<0), /* System Clock / 4 */
+ TC_CLKSEL_DIV8_gc = (0x04<<0), /* System Clock / 8 */
+ TC_CLKSEL_DIV64_gc = (0x05<<0), /* System Clock / 64 */
+ TC_CLKSEL_DIV256_gc = (0x06<<0), /* System Clock / 256 */
+ TC_CLKSEL_DIV1024_gc = (0x07<<0), /* System Clock / 1024 */
+ TC_CLKSEL_EVCH0_gc = (0x08<<0), /* Event Channel 0 */
+ TC_CLKSEL_EVCH1_gc = (0x09<<0), /* Event Channel 1 */
+ TC_CLKSEL_EVCH2_gc = (0x0A<<0), /* Event Channel 2 */
+ TC_CLKSEL_EVCH3_gc = (0x0B<<0), /* Event Channel 3 */
+ TC_CLKSEL_EVCH4_gc = (0x0C<<0), /* Event Channel 4 */
+ TC_CLKSEL_EVCH5_gc = (0x0D<<0), /* Event Channel 5 */
+ TC_CLKSEL_EVCH6_gc = (0x0E<<0), /* Event Channel 6 */
+ TC_CLKSEL_EVCH7_gc = (0x0F<<0), /* Event Channel 7 */
+} TC_CLKSEL_t;
+
+/* Waveform Generation Mode */
+typedef enum TC_WGMODE_enum
+{
+ TC_WGMODE_NORMAL_gc = (0x00<<0), /* Normal Mode */
+ TC_WGMODE_FRQ_gc = (0x01<<0), /* Frequency Generation Mode */
+ TC_WGMODE_SINGLESLOPE_gc = (0x03<<0), /* Single Slope */
+ TC_WGMODE_SS_gc = (0x03<<0), /* Single Slope */
+ TC_WGMODE_DSTOP_gc = (0x05<<0), /* Dual Slope, Update on TOP */
+ TC_WGMODE_DS_T_gc = (0x05<<0), /* Dual Slope, Update on TOP */
+ TC_WGMODE_DSBOTH_gc = (0x06<<0), /* Dual Slope, Update on both TOP and BOTTOM */
+ TC_WGMODE_DS_TB_gc = (0x06<<0), /* Dual Slope, Update on both TOP and BOTTOM */
+ TC_WGMODE_DSBOTTOM_gc = (0x07<<0), /* Dual Slope, Update on BOTTOM */
+ TC_WGMODE_DS_B_gc = (0x07<<0), /* Dual Slope, Update on BOTTOM */
+} TC_WGMODE_t;
+
+/* Byte Mode */
+typedef enum TC_BYTEM_enum
+{
+ TC_BYTEM_NORMAL_gc = (0x00<<0), /* 16-bit mode */
+ TC_BYTEM_BYTEMODE_gc = (0x01<<0), /* Timer/Counter operating in byte mode only */
+ TC_BYTEM_SPLITMODE_gc = (0x02<<0), /* Timer/Counter split into two 8-bit Counters (TC2) */
+} TC_BYTEM_t;
+
+/* Event Action */
+typedef enum TC_EVACT_enum
+{
+ TC_EVACT_OFF_gc = (0x00<<5), /* No Event Action */
+ TC_EVACT_CAPT_gc = (0x01<<5), /* Input Capture */
+ TC_EVACT_UPDOWN_gc = (0x02<<5), /* Externally Controlled Up/Down Count */
+ TC_EVACT_QDEC_gc = (0x03<<5), /* Quadrature Decode */
+ TC_EVACT_RESTART_gc = (0x04<<5), /* Restart */
+ TC_EVACT_FRQ_gc = (0x05<<5), /* Frequency Capture */
+ TC_EVACT_PW_gc = (0x06<<5), /* Pulse-width Capture */
+} TC_EVACT_t;
+
+/* Event Selection */
+typedef enum TC_EVSEL_enum
+{
+ TC_EVSEL_OFF_gc = (0x00<<0), /* No Event Source */
+ TC_EVSEL_CH0_gc = (0x08<<0), /* Event Channel 0 */
+ TC_EVSEL_CH1_gc = (0x09<<0), /* Event Channel 1 */
+ TC_EVSEL_CH2_gc = (0x0A<<0), /* Event Channel 2 */
+ TC_EVSEL_CH3_gc = (0x0B<<0), /* Event Channel 3 */
+ TC_EVSEL_CH4_gc = (0x0C<<0), /* Event Channel 4 */
+ TC_EVSEL_CH5_gc = (0x0D<<0), /* Event Channel 5 */
+ TC_EVSEL_CH6_gc = (0x0E<<0), /* Event Channel 6 */
+ TC_EVSEL_CH7_gc = (0x0F<<0), /* Event Channel 7 */
+} TC_EVSEL_t;
+
+/* Error Interrupt Level */
+typedef enum TC_ERRINTLVL_enum
+{
+ TC_ERRINTLVL_OFF_gc = (0x00<<2), /* Interrupt Disabled */
+ TC_ERRINTLVL_LO_gc = (0x01<<2), /* Low Level */
+ TC_ERRINTLVL_MED_gc = (0x02<<2), /* Medium Level */
+ TC_ERRINTLVL_HI_gc = (0x03<<2), /* High Level */
+} TC_ERRINTLVL_t;
+
+/* Overflow Interrupt Level */
+typedef enum TC_OVFINTLVL_enum
+{
+ TC_OVFINTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ TC_OVFINTLVL_LO_gc = (0x01<<0), /* Low Level */
+ TC_OVFINTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ TC_OVFINTLVL_HI_gc = (0x03<<0), /* High Level */
+} TC_OVFINTLVL_t;
+
+/* Compare or Capture D Interrupt Level */
+typedef enum TC_CCDINTLVL_enum
+{
+ TC_CCDINTLVL_OFF_gc = (0x00<<6), /* Interrupt Disabled */
+ TC_CCDINTLVL_LO_gc = (0x01<<6), /* Low Level */
+ TC_CCDINTLVL_MED_gc = (0x02<<6), /* Medium Level */
+ TC_CCDINTLVL_HI_gc = (0x03<<6), /* High Level */
+} TC_CCDINTLVL_t;
+
+/* Compare or Capture C Interrupt Level */
+typedef enum TC_CCCINTLVL_enum
+{
+ TC_CCCINTLVL_OFF_gc = (0x00<<4), /* Interrupt Disabled */
+ TC_CCCINTLVL_LO_gc = (0x01<<4), /* Low Level */
+ TC_CCCINTLVL_MED_gc = (0x02<<4), /* Medium Level */
+ TC_CCCINTLVL_HI_gc = (0x03<<4), /* High Level */
+} TC_CCCINTLVL_t;
+
+/* Compare or Capture B Interrupt Level */
+typedef enum TC_CCBINTLVL_enum
+{
+ TC_CCBINTLVL_OFF_gc = (0x00<<2), /* Interrupt Disabled */
+ TC_CCBINTLVL_LO_gc = (0x01<<2), /* Low Level */
+ TC_CCBINTLVL_MED_gc = (0x02<<2), /* Medium Level */
+ TC_CCBINTLVL_HI_gc = (0x03<<2), /* High Level */
+} TC_CCBINTLVL_t;
+
+/* Compare or Capture A Interrupt Level */
+typedef enum TC_CCAINTLVL_enum
+{
+ TC_CCAINTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ TC_CCAINTLVL_LO_gc = (0x01<<0), /* Low Level */
+ TC_CCAINTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ TC_CCAINTLVL_HI_gc = (0x03<<0), /* High Level */
+} TC_CCAINTLVL_t;
+
+/* Timer/Counter Command */
+typedef enum TC_CMD_enum
+{
+ TC_CMD_NONE_gc = (0x00<<2), /* No Command */
+ TC_CMD_UPDATE_gc = (0x01<<2), /* Force Update */
+ TC_CMD_RESTART_gc = (0x02<<2), /* Force Restart */
+ TC_CMD_RESET_gc = (0x03<<2), /* Force Hard Reset */
+} TC_CMD_t;
+
+
+/*
+--------------------------------------------------------------------------
+TC2 - 16-bit Timer/Counter type 2
+--------------------------------------------------------------------------
+*/
+
+/* 16-bit Timer/Counter type 2 */
+typedef struct TC2_struct
+{
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t CTRLC; /* Control register C */
+ register8_t reserved_0x03;
+ register8_t CTRLE; /* Control Register E */
+ register8_t reserved_0x05;
+ register8_t INTCTRLA; /* Interrupt Control Register A */
+ register8_t INTCTRLB; /* Interrupt Control Register B */
+ register8_t reserved_0x08;
+ register8_t CTRLF; /* Control Register F */
+ register8_t reserved_0x0A;
+ register8_t reserved_0x0B;
+ register8_t INTFLAGS; /* Interrupt Flag Register */
+ register8_t reserved_0x0D;
+ register8_t reserved_0x0E;
+ register8_t reserved_0x0F;
+ register8_t reserved_0x10;
+ register8_t reserved_0x11;
+ register8_t reserved_0x12;
+ register8_t reserved_0x13;
+ register8_t reserved_0x14;
+ register8_t reserved_0x15;
+ register8_t reserved_0x16;
+ register8_t reserved_0x17;
+ register8_t reserved_0x18;
+ register8_t reserved_0x19;
+ register8_t reserved_0x1A;
+ register8_t reserved_0x1B;
+ register8_t reserved_0x1C;
+ register8_t reserved_0x1D;
+ register8_t reserved_0x1E;
+ register8_t reserved_0x1F;
+ register8_t LCNT; /* Low Byte Count */
+ register8_t HCNT; /* High Byte Count */
+ register8_t reserved_0x22;
+ register8_t reserved_0x23;
+ register8_t reserved_0x24;
+ register8_t reserved_0x25;
+ register8_t LPER; /* Low Byte Period */
+ register8_t HPER; /* High Byte Period */
+ register8_t LCMPA; /* Low Byte Compare A */
+ register8_t HCMPA; /* High Byte Compare A */
+ register8_t LCMPB; /* Low Byte Compare B */
+ register8_t HCMPB; /* High Byte Compare B */
+ register8_t LCMPC; /* Low Byte Compare C */
+ register8_t HCMPC; /* High Byte Compare C */
+ register8_t LCMPD; /* Low Byte Compare D */
+ register8_t HCMPD; /* High Byte Compare D */
+} TC2_t;
+
+/* Clock Selection */
+typedef enum TC2_CLKSEL_enum
+{
+ TC2_CLKSEL_OFF_gc = (0x00<<0), /* Timer Off */
+ TC2_CLKSEL_DIV1_gc = (0x01<<0), /* System Clock */
+ TC2_CLKSEL_DIV2_gc = (0x02<<0), /* System Clock / 2 */
+ TC2_CLKSEL_DIV4_gc = (0x03<<0), /* System Clock / 4 */
+ TC2_CLKSEL_DIV8_gc = (0x04<<0), /* System Clock / 8 */
+ TC2_CLKSEL_DIV64_gc = (0x05<<0), /* System Clock / 64 */
+ TC2_CLKSEL_DIV256_gc = (0x06<<0), /* System Clock / 256 */
+ TC2_CLKSEL_DIV1024_gc = (0x07<<0), /* System Clock / 1024 */
+ TC2_CLKSEL_EVCH0_gc = (0x08<<0), /* Event Channel 0 */
+ TC2_CLKSEL_EVCH1_gc = (0x09<<0), /* Event Channel 1 */
+ TC2_CLKSEL_EVCH2_gc = (0x0A<<0), /* Event Channel 2 */
+ TC2_CLKSEL_EVCH3_gc = (0x0B<<0), /* Event Channel 3 */
+ TC2_CLKSEL_EVCH4_gc = (0x0C<<0), /* Event Channel 4 */
+ TC2_CLKSEL_EVCH5_gc = (0x0D<<0), /* Event Channel 5 */
+ TC2_CLKSEL_EVCH6_gc = (0x0E<<0), /* Event Channel 6 */
+ TC2_CLKSEL_EVCH7_gc = (0x0F<<0), /* Event Channel 7 */
+} TC2_CLKSEL_t;
+
+/* Byte Mode */
+typedef enum TC2_BYTEM_enum
+{
+ TC2_BYTEM_NORMAL_gc = (0x00<<0), /* 16-bit mode */
+ TC2_BYTEM_BYTEMODE_gc = (0x01<<0), /* Timer/Counter operating in byte mode only (TC2) */
+ TC2_BYTEM_SPLITMODE_gc = (0x02<<0), /* Timer/Counter split into two 8-bit Counters */
+} TC2_BYTEM_t;
+
+/* High Byte Underflow Interrupt Level */
+typedef enum TC2_HUNFINTLVL_enum
+{
+ TC2_HUNFINTLVL_OFF_gc = (0x00<<2), /* Interrupt Disabled */
+ TC2_HUNFINTLVL_LO_gc = (0x01<<2), /* Low Level */
+ TC2_HUNFINTLVL_MED_gc = (0x02<<2), /* Medium Level */
+ TC2_HUNFINTLVL_HI_gc = (0x03<<2), /* High Level */
+} TC2_HUNFINTLVL_t;
+
+/* Low Byte Underflow Interrupt Level */
+typedef enum TC2_LUNFINTLVL_enum
+{
+ TC2_LUNFINTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ TC2_LUNFINTLVL_LO_gc = (0x01<<0), /* Low Level */
+ TC2_LUNFINTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ TC2_LUNFINTLVL_HI_gc = (0x03<<0), /* High Level */
+} TC2_LUNFINTLVL_t;
+
+/* Low Byte Compare D Interrupt Level */
+typedef enum TC2_LCMPDINTLVL_enum
+{
+ TC2_LCMPDINTLVL_OFF_gc = (0x00<<6), /* Interrupt Disabled */
+ TC2_LCMPDINTLVL_LO_gc = (0x01<<6), /* Low Level */
+ TC2_LCMPDINTLVL_MED_gc = (0x02<<6), /* Medium Level */
+ TC2_LCMPDINTLVL_HI_gc = (0x03<<6), /* High Level */
+} TC2_LCMPDINTLVL_t;
+
+/* Low Byte Compare C Interrupt Level */
+typedef enum TC2_LCMPCINTLVL_enum
+{
+ TC2_LCMPCINTLVL_OFF_gc = (0x00<<4), /* Interrupt Disabled */
+ TC2_LCMPCINTLVL_LO_gc = (0x01<<4), /* Low Level */
+ TC2_LCMPCINTLVL_MED_gc = (0x02<<4), /* Medium Level */
+ TC2_LCMPCINTLVL_HI_gc = (0x03<<4), /* High Level */
+} TC2_LCMPCINTLVL_t;
+
+/* Low Byte Compare B Interrupt Level */
+typedef enum TC2_LCMPBINTLVL_enum
+{
+ TC2_LCMPBINTLVL_OFF_gc = (0x00<<2), /* Interrupt Disabled */
+ TC2_LCMPBINTLVL_LO_gc = (0x01<<2), /* Low Level */
+ TC2_LCMPBINTLVL_MED_gc = (0x02<<2), /* Medium Level */
+ TC2_LCMPBINTLVL_HI_gc = (0x03<<2), /* High Level */
+} TC2_LCMPBINTLVL_t;
+
+/* Low Byte Compare A Interrupt Level */
+typedef enum TC2_LCMPAINTLVL_enum
+{
+ TC2_LCMPAINTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ TC2_LCMPAINTLVL_LO_gc = (0x01<<0), /* Low Level */
+ TC2_LCMPAINTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ TC2_LCMPAINTLVL_HI_gc = (0x03<<0), /* High Level */
+} TC2_LCMPAINTLVL_t;
+
+/* Timer/Counter Command */
+typedef enum TC2_CMD_enum
+{
+ TC2_CMD_NONE_gc = (0x00<<2), /* No Command */
+ TC2_CMD_RESTART_gc = (0x02<<2), /* Force Restart */
+ TC2_CMD_RESET_gc = (0x03<<2), /* Force Hard Reset */
+} TC2_CMD_t;
+
+/* Timer/Counter Command */
+typedef enum TC2_CMDEN_enum
+{
+ TC2_CMDEN_LOW_gc = (0x01<<0), /* Low Byte Timer/Counter */
+ TC2_CMDEN_HIGH_gc = (0x02<<0), /* High Byte Timer/Counter */
+ TC2_CMDEN_BOTH_gc = (0x03<<0), /* Both Low Byte and High Byte Timer/Counters */
+} TC2_CMDEN_t;
+
+
+/*
+--------------------------------------------------------------------------
+AWEX - Timer/Counter Advanced Waveform Extension
+--------------------------------------------------------------------------
+*/
+
+/* Advanced Waveform Extension */
+typedef struct AWEX_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t reserved_0x01;
+ register8_t FDEMASK; /* Fault Detection Event Mask */
+ register8_t FDCTRL; /* Fault Detection Control Register */
+ register8_t STATUS; /* Status Register */
+ register8_t STATUSSET; /* Status Set Register */
+ register8_t DTBOTH; /* Dead Time Both Sides */
+ register8_t DTBOTHBUF; /* Dead Time Both Sides Buffer */
+ register8_t DTLS; /* Dead Time Low Side */
+ register8_t DTHS; /* Dead Time High Side */
+ register8_t DTLSBUF; /* Dead Time Low Side Buffer */
+ register8_t DTHSBUF; /* Dead Time High Side Buffer */
+ register8_t OUTOVEN; /* Output Override Enable */
+} AWEX_t;
+
+/* Fault Detect Action */
+typedef enum AWEX_FDACT_enum
+{
+ AWEX_FDACT_NONE_gc = (0x00<<0), /* No Fault Protection */
+ AWEX_FDACT_CLEAROE_gc = (0x01<<0), /* Clear Output Enable Bits */
+ AWEX_FDACT_CLEARDIR_gc = (0x03<<0), /* Clear I/O Port Direction Bits */
+} AWEX_FDACT_t;
+
+
+/*
+--------------------------------------------------------------------------
+HIRES - Timer/Counter High-Resolution Extension
+--------------------------------------------------------------------------
+*/
+
+/* High-Resolution Extension */
+typedef struct HIRES_struct
+{
+ register8_t CTRLA; /* Control Register */
+} HIRES_t;
+
+/* High Resolution Enable */
+typedef enum HIRES_HREN_enum
+{
+ HIRES_HREN_NONE_gc = (0x00<<0), /* No Fault Protection */
+ HIRES_HREN_TC0_gc = (0x01<<0), /* Enable High Resolution on Timer/Counter 0 */
+ HIRES_HREN_TC1_gc = (0x02<<0), /* Enable High Resolution on Timer/Counter 1 */
+ HIRES_HREN_BOTH_gc = (0x03<<0), /* Enable High Resolution both Timer/Counters */
+} HIRES_HREN_t;
+
+
+/*
+--------------------------------------------------------------------------
+USART - Universal Asynchronous Receiver-Transmitter
+--------------------------------------------------------------------------
+*/
+
+/* Universal Synchronous/Asynchronous Receiver/Transmitter */
+typedef struct USART_struct
+{
+ register8_t DATA; /* Data Register */
+ register8_t STATUS; /* Status Register */
+ register8_t reserved_0x02;
+ register8_t CTRLA; /* Control Register A */
+ register8_t CTRLB; /* Control Register B */
+ register8_t CTRLC; /* Control Register C */
+ register8_t BAUDCTRLA; /* Baud Rate Control Register A */
+ register8_t BAUDCTRLB; /* Baud Rate Control Register B */
+} USART_t;
+
+/* Receive Complete Interrupt level */
+typedef enum USART_RXCINTLVL_enum
+{
+ USART_RXCINTLVL_OFF_gc = (0x00<<4), /* Interrupt Disabled */
+ USART_RXCINTLVL_LO_gc = (0x01<<4), /* Low Level */
+ USART_RXCINTLVL_MED_gc = (0x02<<4), /* Medium Level */
+ USART_RXCINTLVL_HI_gc = (0x03<<4), /* High Level */
+} USART_RXCINTLVL_t;
+
+/* Transmit Complete Interrupt level */
+typedef enum USART_TXCINTLVL_enum
+{
+ USART_TXCINTLVL_OFF_gc = (0x00<<2), /* Interrupt Disabled */
+ USART_TXCINTLVL_LO_gc = (0x01<<2), /* Low Level */
+ USART_TXCINTLVL_MED_gc = (0x02<<2), /* Medium Level */
+ USART_TXCINTLVL_HI_gc = (0x03<<2), /* High Level */
+} USART_TXCINTLVL_t;
+
+/* Data Register Empty Interrupt level */
+typedef enum USART_DREINTLVL_enum
+{
+ USART_DREINTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ USART_DREINTLVL_LO_gc = (0x01<<0), /* Low Level */
+ USART_DREINTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ USART_DREINTLVL_HI_gc = (0x03<<0), /* High Level */
+} USART_DREINTLVL_t;
+
+/* Character Size */
+typedef enum USART_CHSIZE_enum
+{
+ USART_CHSIZE_5BIT_gc = (0x00<<0), /* Character size: 5 bit */
+ USART_CHSIZE_6BIT_gc = (0x01<<0), /* Character size: 6 bit */
+ USART_CHSIZE_7BIT_gc = (0x02<<0), /* Character size: 7 bit */
+ USART_CHSIZE_8BIT_gc = (0x03<<0), /* Character size: 8 bit */
+ USART_CHSIZE_9BIT_gc = (0x07<<0), /* Character size: 9 bit */
+} USART_CHSIZE_t;
+
+/* Communication Mode */
+typedef enum USART_CMODE_enum
+{
+ USART_CMODE_ASYNCHRONOUS_gc = (0x00<<6), /* Asynchronous Mode */
+ USART_CMODE_SYNCHRONOUS_gc = (0x01<<6), /* Synchronous Mode */
+ USART_CMODE_IRDA_gc = (0x02<<6), /* IrDA Mode */
+ USART_CMODE_MSPI_gc = (0x03<<6), /* Master SPI Mode */
+} USART_CMODE_t;
+
+/* Parity Mode */
+typedef enum USART_PMODE_enum
+{
+ USART_PMODE_DISABLED_gc = (0x00<<4), /* No Parity */
+ USART_PMODE_EVEN_gc = (0x02<<4), /* Even Parity */
+ USART_PMODE_ODD_gc = (0x03<<4), /* Odd Parity */
+} USART_PMODE_t;
+
+
+/*
+--------------------------------------------------------------------------
+SPI - Serial Peripheral Interface
+--------------------------------------------------------------------------
+*/
+
+/* Serial Peripheral Interface */
+typedef struct SPI_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t INTCTRL; /* Interrupt Control Register */
+ register8_t STATUS; /* Status Register */
+ register8_t DATA; /* Data Register */
+} SPI_t;
+
+/* SPI Mode */
+typedef enum SPI_MODE_enum
+{
+ SPI_MODE_0_gc = (0x00<<2), /* SPI Mode 0 */
+ SPI_MODE_1_gc = (0x01<<2), /* SPI Mode 1 */
+ SPI_MODE_2_gc = (0x02<<2), /* SPI Mode 2 */
+ SPI_MODE_3_gc = (0x03<<2), /* SPI Mode 3 */
+} SPI_MODE_t;
+
+/* Prescaler setting */
+typedef enum SPI_PRESCALER_enum
+{
+ SPI_PRESCALER_DIV4_gc = (0x00<<0), /* System Clock / 4 */
+ SPI_PRESCALER_DIV16_gc = (0x01<<0), /* System Clock / 16 */
+ SPI_PRESCALER_DIV64_gc = (0x02<<0), /* System Clock / 64 */
+ SPI_PRESCALER_DIV128_gc = (0x03<<0), /* System Clock / 128 */
+} SPI_PRESCALER_t;
+
+/* Interrupt level */
+typedef enum SPI_INTLVL_enum
+{
+ SPI_INTLVL_OFF_gc = (0x00<<0), /* Interrupt Disabled */
+ SPI_INTLVL_LO_gc = (0x01<<0), /* Low Level */
+ SPI_INTLVL_MED_gc = (0x02<<0), /* Medium Level */
+ SPI_INTLVL_HI_gc = (0x03<<0), /* High Level */
+} SPI_INTLVL_t;
+
+
+/*
+--------------------------------------------------------------------------
+IRCOM - IR Communication Module
+--------------------------------------------------------------------------
+*/
+
+/* IR Communication Module */
+typedef struct IRCOM_struct
+{
+ register8_t CTRL; /* Control Register */
+ register8_t TXPLCTRL; /* IrDA Transmitter Pulse Length Control Register */
+ register8_t RXPLCTRL; /* IrDA Receiver Pulse Length Control Register */
+} IRCOM_t;
+
+/* Event channel selection */
+typedef enum IRDA_EVSEL_enum
+{
+ IRDA_EVSEL_OFF_gc = (0x00<<0), /* No Event Source */
+ IRDA_EVSEL_0_gc = (0x08<<0), /* Event Channel 0 */
+ IRDA_EVSEL_1_gc = (0x09<<0), /* Event Channel 1 */
+ IRDA_EVSEL_2_gc = (0x0A<<0), /* Event Channel 2 */
+ IRDA_EVSEL_3_gc = (0x0B<<0), /* Event Channel 3 */
+ IRDA_EVSEL_4_gc = (0x0C<<0), /* Event Channel 4 */
+ IRDA_EVSEL_5_gc = (0x0D<<0), /* Event Channel 5 */
+ IRDA_EVSEL_6_gc = (0x0E<<0), /* Event Channel 6 */
+ IRDA_EVSEL_7_gc = (0x0F<<0), /* Event Channel 7 */
+} IRDA_EVSEL_t;
+
+
+/*
+--------------------------------------------------------------------------
+FUSE - Fuses and Lockbits
+--------------------------------------------------------------------------
+*/
+
+/* Fuses */
+typedef struct NVM_FUSES_struct
+{
+ register8_t FUSEBYTE0; /* JTAG User ID */
+ register8_t FUSEBYTE1; /* Watchdog Configuration */
+ register8_t FUSEBYTE2; /* Reset Configuration */
+ register8_t reserved_0x03;
+ register8_t FUSEBYTE4; /* Start-up Configuration */
+ register8_t FUSEBYTE5; /* EESAVE and BOD Level */
+} NVM_FUSES_t;
+
+/* Boot Loader Section Reset Vector */
+typedef enum BOOTRST_enum
+{
+ BOOTRST_BOOTLDR_gc = (0x00<<6), /* Boot Loader Reset */
+ BOOTRST_APPLICATION_gc = (0x01<<6), /* Application Reset */
+} BOOTRST_t;
+
+/* Timer Oscillator pin location */
+typedef enum TOSCSEL_enum
+{
+ TOSCSEL_ALTERNATE_gc = (0x00<<5), /* TOSC1 / TOSC2 on separate pins */
+ TOSCSEL_XTAL_gc = (0x01<<5), /* TOSC1 / TOSC2 shared with XTAL1 / XTAL2 */
+} TOSCSEL_t;
+
+/* BOD operation */
+typedef enum BOD_enum
+{
+ BOD_SAMPLED_gc = (0x01<<0), /* BOD enabled in sampled mode */
+ BOD_CONTINUOUS_gc = (0x02<<0), /* BOD enabled continuously */
+ BOD_DISABLED_gc = (0x03<<0), /* BOD Disabled */
+} BOD_t;
+
+/* BOD operation */
+typedef enum BODACT_enum
+{
+ BODACT_SAMPLED_gc = (0x01<<4), /* BOD enabled in sampled mode */
+ BODACT_CONTINUOUS_gc = (0x02<<4), /* BOD enabled continuously */
+ BODACT_DISABLED_gc = (0x03<<4), /* BOD Disabled */
+} BODACT_t;
+
+/* Watchdog (Window) Timeout Period */
+typedef enum WD_enum
+{
+ WD_8CLK_gc = (0x00<<4), /* 8 cycles (8ms @ 3.3V) */
+ WD_16CLK_gc = (0x01<<4), /* 16 cycles (16ms @ 3.3V) */
+ WD_32CLK_gc = (0x02<<4), /* 32 cycles (32ms @ 3.3V) */
+ WD_64CLK_gc = (0x03<<4), /* 64 cycles (64ms @ 3.3V) */
+ WD_128CLK_gc = (0x04<<4), /* 128 cycles (0.125s @ 3.3V) */
+ WD_256CLK_gc = (0x05<<4), /* 256 cycles (0.25s @ 3.3V) */
+ WD_512CLK_gc = (0x06<<4), /* 512 cycles (0.5s @ 3.3V) */
+ WD_1KCLK_gc = (0x07<<4), /* 1K cycles (1s @ 3.3V) */
+ WD_2KCLK_gc = (0x08<<4), /* 2K cycles (2s @ 3.3V) */
+ WD_4KCLK_gc = (0x09<<4), /* 4K cycles (4s @ 3.3V) */
+ WD_8KCLK_gc = (0x0A<<4), /* 8K cycles (8s @ 3.3V) */
+} WD_t;
+
+/* Watchdog (Window) Timeout Period */
+typedef enum WDP_enum
+{
+ WDP_8CLK_gc = (0x00<<0), /* 8 cycles (8ms @ 3.3V) */
+ WDP_16CLK_gc = (0x01<<0), /* 16 cycles (16ms @ 3.3V) */
+ WDP_32CLK_gc = (0x02<<0), /* 32 cycles (32ms @ 3.3V) */
+ WDP_64CLK_gc = (0x03<<0), /* 64 cycles (64ms @ 3.3V) */
+ WDP_128CLK_gc = (0x04<<0), /* 128 cycles (0.125s @ 3.3V) */
+ WDP_256CLK_gc = (0x05<<0), /* 256 cycles (0.25s @ 3.3V) */
+ WDP_512CLK_gc = (0x06<<0), /* 512 cycles (0.5s @ 3.3V) */
+ WDP_1KCLK_gc = (0x07<<0), /* 1K cycles (1s @ 3.3V) */
+ WDP_2KCLK_gc = (0x08<<0), /* 2K cycles (2s @ 3.3V) */
+ WDP_4KCLK_gc = (0x09<<0), /* 4K cycles (4s @ 3.3V) */
+ WDP_8KCLK_gc = (0x0A<<0), /* 8K cycles (8s @ 3.3V) */
+} WDP_t;
+
+/* Start-up Time */
+typedef enum SUT_enum
+{
+ SUT_0MS_gc = (0x03<<2), /* 0 ms */
+ SUT_4MS_gc = (0x01<<2), /* 4 ms */
+ SUT_64MS_gc = (0x00<<2), /* 64 ms */
+} SUT_t;
+
+/* Brownout Detection Voltage Level */
+typedef enum BODLVL_enum
+{
+ BODLVL_1V6_gc = (0x07<<0), /* 1.6 V */
+ BODLVL_1V8_gc = (0x06<<0), /* 1.8 V */
+ BODLVL_2V0_gc = (0x05<<0), /* 2.0 V */
+ BODLVL_2V2_gc = (0x04<<0), /* 2.2 V */
+ BODLVL_2V4_gc = (0x03<<0), /* 2.4 V */
+ BODLVL_2V6_gc = (0x02<<0), /* 2.6 V */
+ BODLVL_2V8_gc = (0x01<<0), /* 2.8 V */
+ BODLVL_3V0_gc = (0x00<<0), /* 3.0 V */
+} BODLVL_t;
+
+
+/*
+--------------------------------------------------------------------------
+LOCKBIT - Fuses and Lockbits
+--------------------------------------------------------------------------
+*/
+
+/* Lock Bits */
+typedef struct NVM_LOCKBITS_struct
+{
+ register8_t LOCK_BITS; /* Lock Bits (Changed from LOCKBITS to avoid avr-libc collision) */
+} NVM_LOCKBITS_t;
+
+/* Boot lock bits - boot setcion */
+typedef enum FUSE_BLBB_enum
+{
+ FUSE_BLBB_RWLOCK_gc = (0x00<<6), /* Read and write not allowed */
+ FUSE_BLBB_RLOCK_gc = (0x01<<6), /* Read not allowed */
+ FUSE_BLBB_WLOCK_gc = (0x02<<6), /* Write not allowed */
+ FUSE_BLBB_NOLOCK_gc = (0x03<<6), /* No locks */
+} FUSE_BLBB_t;
+
+/* Boot lock bits - application section */
+typedef enum FUSE_BLBA_enum
+{
+ FUSE_BLBA_RWLOCK_gc = (0x00<<4), /* Read and write not allowed */
+ FUSE_BLBA_RLOCK_gc = (0x01<<4), /* Read not allowed */
+ FUSE_BLBA_WLOCK_gc = (0x02<<4), /* Write not allowed */
+ FUSE_BLBA_NOLOCK_gc = (0x03<<4), /* No locks */
+} FUSE_BLBA_t;
+
+/* Boot lock bits - application table section */
+typedef enum FUSE_BLBAT_enum
+{
+ FUSE_BLBAT_RWLOCK_gc = (0x00<<2), /* Read and write not allowed */
+ FUSE_BLBAT_RLOCK_gc = (0x01<<2), /* Read not allowed */
+ FUSE_BLBAT_WLOCK_gc = (0x02<<2), /* Write not allowed */
+ FUSE_BLBAT_NOLOCK_gc = (0x03<<2), /* No locks */
+} FUSE_BLBAT_t;
+
+/* Lock bits */
+typedef enum FUSE_LB_enum
+{
+ FUSE_LB_RWLOCK_gc = (0x00<<0), /* Read and write not allowed */
+ FUSE_LB_WLOCK_gc = (0x02<<0), /* Write not allowed */
+ FUSE_LB_NOLOCK_gc = (0x03<<0), /* No locks */
+} FUSE_LB_t;
+
+
+/*
+--------------------------------------------------------------------------
+SIGROW - Signature Row
+--------------------------------------------------------------------------
+*/
+
+/* Production Signatures */
+typedef struct NVM_PROD_SIGNATURES_struct
+{
+ register8_t RCOSC2M; /* RCOSC 2 MHz Calibration Value B */
+ register8_t RCOSC2MA; /* RCOSC 2 MHz Calibration Value A */
+ register8_t RCOSC32K; /* RCOSC 32.768 kHz Calibration Value */
+ register8_t RCOSC32M; /* RCOSC 32 MHz Calibration Value B */
+ register8_t RCOSC32MA; /* RCOSC 32 MHz Calibration Value A */
+ register8_t reserved_0x05;
+ register8_t reserved_0x06;
+ register8_t reserved_0x07;
+ register8_t LOTNUM0; /* Lot Number Byte 0, ASCII */
+ register8_t LOTNUM1; /* Lot Number Byte 1, ASCII */
+ register8_t LOTNUM2; /* Lot Number Byte 2, ASCII */
+ register8_t LOTNUM3; /* Lot Number Byte 3, ASCII */
+ register8_t LOTNUM4; /* Lot Number Byte 4, ASCII */
+ register8_t LOTNUM5; /* Lot Number Byte 5, ASCII */
+ register8_t reserved_0x0E;
+ register8_t reserved_0x0F;
+ register8_t WAFNUM; /* Wafer Number */
+ register8_t reserved_0x11;
+ register8_t COORDX0; /* Wafer Coordinate X Byte 0 */
+ register8_t COORDX1; /* Wafer Coordinate X Byte 1 */
+ register8_t COORDY0; /* Wafer Coordinate Y Byte 0 */
+ register8_t COORDY1; /* Wafer Coordinate Y Byte 1 */
+ register8_t reserved_0x16;
+ register8_t reserved_0x17;
+ register8_t reserved_0x18;
+ register8_t reserved_0x19;
+ register8_t USBCAL0; /* USB Calibration Byte 0 */
+ register8_t USBCAL1; /* USB Calibration Byte 1 */
+ register8_t USBRCOSC; /* USB RCOSC Calibration Value B */
+ register8_t USBRCOSCA; /* USB RCOSC Calibration Value A */
+ register8_t reserved_0x1E;
+ register8_t reserved_0x1F;
+ register8_t ADCACAL0; /* ADCA Calibration Byte 0 */
+ register8_t ADCACAL1; /* ADCA Calibration Byte 1 */
+ register8_t reserved_0x22;
+ register8_t reserved_0x23;
+ register8_t ADCBCAL0; /* ADCB Calibration Byte 0 */
+ register8_t ADCBCAL1; /* ADCB Calibration Byte 1 */
+ register8_t reserved_0x26;
+ register8_t reserved_0x27;
+ register8_t reserved_0x28;
+ register8_t reserved_0x29;
+ register8_t reserved_0x2A;
+ register8_t reserved_0x2B;
+ register8_t reserved_0x2C;
+ register8_t reserved_0x2D;
+ register8_t TEMPSENSE0; /* Temperature Sensor Calibration Byte 0 */
+ register8_t TEMPSENSE1; /* Temperature Sensor Calibration Byte 1 */
+ register8_t DACA0OFFCAL; /* DACA0 Calibration Byte 0 */
+ register8_t DACA0GAINCAL; /* DACA0 Calibration Byte 1 */
+ register8_t DACB0OFFCAL; /* DACB0 Calibration Byte 0 */
+ register8_t DACB0GAINCAL; /* DACB0 Calibration Byte 1 */
+ register8_t DACA1OFFCAL; /* DACA1 Calibration Byte 0 */
+ register8_t DACA1GAINCAL; /* DACA1 Calibration Byte 1 */
+ register8_t DACB1OFFCAL; /* DACB1 Calibration Byte 0 */
+ register8_t DACB1GAINCAL; /* DACB1 Calibration Byte 1 */
+ register8_t reserved_0x38;
+ register8_t reserved_0x39;
+ register8_t reserved_0x3A;
+ register8_t reserved_0x3B;
+ register8_t reserved_0x3C;
+ register8_t reserved_0x3D;
+ register8_t reserved_0x3E;
+ register8_t reserved_0x3F;
+ register8_t reserved_0x40;
+ register8_t reserved_0x41;
+ register8_t reserved_0x42;
+ register8_t reserved_0x43;
+ register8_t reserved_0x44;
+ register8_t reserved_0x45;
+ register8_t reserved_0x46;
+ register8_t reserved_0x47;
+} NVM_PROD_SIGNATURES_t;
+
+/*
+==========================================================================
+IO Module Instances. Mapped to memory.
+==========================================================================
+*/
+
+#define VPORT0 (*(VPORT_t *)(io_mem + 0x0010)) /* Virtual Port */
+#define VPORT1 (*(VPORT_t *)(io_mem + 0x0014)) /* Virtual Port */
+#define VPORT2 (*(VPORT_t *)(io_mem + 0x0018)) /* Virtual Port */
+#define VPORT3 (*(VPORT_t *)(io_mem + 0x001C)) /* Virtual Port */
+#define OCD (*(OCD_t *)(io_mem + 0x002E)) /* On-Chip Debug System */
+#define CLK (*(CLK_t *)(io_mem + 0x0040)) /* Clock System */
+#define SLEEP (*(SLEEP_t *)(io_mem + 0x0048)) /* Sleep Controller */
+#define OSC (*(OSC_t *)(io_mem + 0x0050)) /* Oscillator */
+#define DFLLRC32M (*(DFLL_t *)(io_mem + 0x0060)) /* DFLL */
+#define DFLLRC2M (*(DFLL_t *)(io_mem + 0x0068)) /* DFLL */
+#define PR (*(PR_t *)(io_mem + 0x0070)) /* Power Reduction */
+#define RST (*(RST_t *)(io_mem + 0x0078)) /* Reset */
+#define WDT (*(WDT_t *)(io_mem + 0x0080)) /* Watch-Dog Timer */
+#define MCU (*(MCU_t *)(io_mem + 0x0090)) /* MCU Control */
+#define PMIC (*(PMIC_t *)(io_mem + 0x00A0)) /* Programmable Multi-level Interrupt Controller */
+#define PORTCFG (*(PORTCFG_t *)(io_mem + 0x00B0)) /* I/O port Configuration */
+#define AES (*(AES_t *)(io_mem + 0x00C0)) /* AES Module */
+#define CRC (*(CRC_t *)(io_mem + 0x00D0)) /* Cyclic Redundancy Checker */
+#define DMA (*(DMA_t *)(io_mem + 0x0100)) /* DMA Controller */
+#define EVSYS (*(EVSYS_t *)(io_mem + 0x0180)) /* Event System */
+#define NVM (*(NVM_t *)(io_mem + 0x01C0)) /* Non-volatile Memory Controller */
+#define ADCA (*(ADC_t *)(io_mem + 0x0200)) /* Analog-to-Digital Converter */
+#define ADCB (*(ADC_t *)(io_mem + 0x0240)) /* Analog-to-Digital Converter */
+#define DACB (*(DAC_t *)(io_mem + 0x0320)) /* Digital-to-Analog Converter */
+#define ACA (*(AC_t *)(io_mem + 0x0380)) /* Analog Comparator */
+#define ACB (*(AC_t *)(io_mem + 0x0390)) /* Analog Comparator */
+#define RTC (*(RTC_t *)(io_mem + 0x0400)) /* Real-Time Counter */
+#define TWIC (*(TWI_t *)(io_mem + 0x0480)) /* Two-Wire Interface */
+#define TWIE (*(TWI_t *)(io_mem + 0x04A0)) /* Two-Wire Interface */
+#define USB (*(USB_t *)(io_mem + 0x04C0)) /* Universal Serial Bus */
+#define PORTA (*(PORT_t *)(io_mem + 0x0600)) /* I/O Ports */
+#define PORTB (*(PORT_t *)(io_mem + 0x0620)) /* I/O Ports */
+#define PORTC (*(PORT_t *)(io_mem + 0x0640)) /* I/O Ports */
+#define PORTD (*(PORT_t *)(io_mem + 0x0660)) /* I/O Ports */
+#define PORTE (*(PORT_t *)(io_mem + 0x0680)) /* I/O Ports */
+#define PORTF (*(PORT_t *)(io_mem + 0x06A0)) /* I/O Ports */
+#define PORTR (*(PORT_t *)(io_mem + 0x07E0)) /* I/O Ports */
+#define TCC0 (*(TC0_t *)(io_mem + 0x0800)) /* 16-bit Timer/Counter 0 */
+#define TCC2 (*(TC2_t *)(io_mem + 0x0800)) /* 16-bit Timer/Counter type 2 */
+#define TCC1 (*(TC1_t *)(io_mem + 0x0840)) /* 16-bit Timer/Counter 1 */
+#define AWEXC (*(AWEX_t *)(io_mem + 0x0880)) /* Advanced Waveform Extension */
+#define HIRESC (*(HIRES_t *)(io_mem + 0x0890)) /* High-Resolution Extension */
+#define USARTC0 (*(USART_t *)(io_mem + 0x08A0)) /* Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTC1 (*(USART_t *)(io_mem + 0x08B0)) /* Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define SPIC (*(SPI_t *)(io_mem + 0x08C0)) /* Serial Peripheral Interface */
+#define IRCOM (*(IRCOM_t *)(io_mem + 0x08F8)) /* IR Communication Module */
+#define TCD0 (*(TC0_t *)(io_mem + 0x0900)) /* 16-bit Timer/Counter 0 */
+#define TCD2 (*(TC2_t *)(io_mem + 0x0900)) /* 16-bit Timer/Counter type 2 */
+#define TCD1 (*(TC1_t *)(io_mem + 0x0940)) /* 16-bit Timer/Counter 1 */
+#define HIRESD (*(HIRES_t *)(io_mem + 0x0990)) /* High-Resolution Extension */
+#define USARTD0 (*(USART_t *)(io_mem + 0x09A0)) /* Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTD1 (*(USART_t *)(io_mem + 0x09B0)) /* Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define SPID (*(SPI_t *)(io_mem + 0x09C0)) /* Serial Peripheral Interface */
+#define TCE0 (*(TC0_t *)(io_mem + 0x0A00)) /* 16-bit Timer/Counter 0 */
+#define TCE2 (*(TC2_t *)(io_mem + 0x0A00)) /* 16-bit Timer/Counter type 2 */
+#define TCE1 (*(TC1_t *)(io_mem + 0x0A40)) /* 16-bit Timer/Counter 1 */
+#define AWEXE (*(AWEX_t *)(io_mem + 0x0A80)) /* Advanced Waveform Extension */
+#define HIRESE (*(HIRES_t *)(io_mem + 0x0A90)) /* High-Resolution Extension */
+#define USARTE0 (*(USART_t *)(io_mem + 0x0AA0)) /* Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTE1 (*(USART_t *)(io_mem + 0x0AB0)) /* Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define SPIE (*(SPI_t *)(io_mem + 0x0AC0)) /* Serial Peripheral Interface */
+#define TCF0 (*(TC0_t *)(io_mem + 0x0B00)) /* 16-bit Timer/Counter 0 */
+#define TCF2 (*(TC2_t *)(io_mem + 0x0B00)) /* 16-bit Timer/Counter type 2 */
+#define HIRESF (*(HIRES_t *)(io_mem + 0x0B90)) /* High-Resolution Extension */
+#define USARTF0 (*(USART_t *)(io_mem + 0x0BA0)) /* Universal Synchronous/Asynchronous Receiver/Transmitter */
+
+
+#endif /* !defined (__ASSEMBLER__) */
+
+
+/* ========== Flattened fully qualified IO register names ========== */
+
+/* GPIO - General Purpose IO Registers */
+#define GPIO_GPIOR0 _SFR_MEM8(0x0000)
+#define GPIO_GPIOR1 _SFR_MEM8(0x0001)
+#define GPIO_GPIOR2 _SFR_MEM8(0x0002)
+#define GPIO_GPIOR3 _SFR_MEM8(0x0003)
+#define GPIO_GPIOR4 _SFR_MEM8(0x0004)
+#define GPIO_GPIOR5 _SFR_MEM8(0x0005)
+#define GPIO_GPIOR6 _SFR_MEM8(0x0006)
+#define GPIO_GPIOR7 _SFR_MEM8(0x0007)
+#define GPIO_GPIOR8 _SFR_MEM8(0x0008)
+#define GPIO_GPIOR9 _SFR_MEM8(0x0009)
+#define GPIO_GPIORA _SFR_MEM8(0x000A)
+#define GPIO_GPIORB _SFR_MEM8(0x000B)
+#define GPIO_GPIORC _SFR_MEM8(0x000C)
+#define GPIO_GPIORD _SFR_MEM8(0x000D)
+#define GPIO_GPIORE _SFR_MEM8(0x000E)
+#define GPIO_GPIORF _SFR_MEM8(0x000F)
+
+/* Deprecated */
+#define GPIO_GPIO0 _SFR_MEM8(0x0000)
+#define GPIO_GPIO1 _SFR_MEM8(0x0001)
+#define GPIO_GPIO2 _SFR_MEM8(0x0002)
+#define GPIO_GPIO3 _SFR_MEM8(0x0003)
+#define GPIO_GPIO4 _SFR_MEM8(0x0004)
+#define GPIO_GPIO5 _SFR_MEM8(0x0005)
+#define GPIO_GPIO6 _SFR_MEM8(0x0006)
+#define GPIO_GPIO7 _SFR_MEM8(0x0007)
+#define GPIO_GPIO8 _SFR_MEM8(0x0008)
+#define GPIO_GPIO9 _SFR_MEM8(0x0009)
+#define GPIO_GPIOA _SFR_MEM8(0x000A)
+#define GPIO_GPIOB _SFR_MEM8(0x000B)
+#define GPIO_GPIOC _SFR_MEM8(0x000C)
+#define GPIO_GPIOD _SFR_MEM8(0x000D)
+#define GPIO_GPIOE _SFR_MEM8(0x000E)
+#define GPIO_GPIOF _SFR_MEM8(0x000F)
+
+/* NVM_FUSES - Fuses */
+#define FUSE_FUSEBYTE0 _SFR_MEM8(0x0000)
+#define FUSE_FUSEBYTE1 _SFR_MEM8(0x0001)
+#define FUSE_FUSEBYTE2 _SFR_MEM8(0x0002)
+#define FUSE_FUSEBYTE4 _SFR_MEM8(0x0004)
+#define FUSE_FUSEBYTE5 _SFR_MEM8(0x0005)
+
+/* NVM_LOCKBITS - Lock Bits */
+#define LOCKBIT_LOCKBITS _SFR_MEM8(0x0000)
+
+/* NVM_PROD_SIGNATURES - Production Signatures */
+#define PRODSIGNATURES_RCOSC2M _SFR_MEM8(0x0000)
+#define PRODSIGNATURES_RCOSC2MA _SFR_MEM8(0x0001)
+#define PRODSIGNATURES_RCOSC32K _SFR_MEM8(0x0002)
+#define PRODSIGNATURES_RCOSC32M _SFR_MEM8(0x0003)
+#define PRODSIGNATURES_RCOSC32MA _SFR_MEM8(0x0004)
+#define PRODSIGNATURES_LOTNUM0 _SFR_MEM8(0x0008)
+#define PRODSIGNATURES_LOTNUM1 _SFR_MEM8(0x0009)
+#define PRODSIGNATURES_LOTNUM2 _SFR_MEM8(0x000A)
+#define PRODSIGNATURES_LOTNUM3 _SFR_MEM8(0x000B)
+#define PRODSIGNATURES_LOTNUM4 _SFR_MEM8(0x000C)
+#define PRODSIGNATURES_LOTNUM5 _SFR_MEM8(0x000D)
+#define PRODSIGNATURES_WAFNUM _SFR_MEM8(0x0010)
+#define PRODSIGNATURES_COORDX0 _SFR_MEM8(0x0012)
+#define PRODSIGNATURES_COORDX1 _SFR_MEM8(0x0013)
+#define PRODSIGNATURES_COORDY0 _SFR_MEM8(0x0014)
+#define PRODSIGNATURES_COORDY1 _SFR_MEM8(0x0015)
+#define PRODSIGNATURES_USBCAL0 _SFR_MEM8(0x001A)
+#define PRODSIGNATURES_USBCAL1 _SFR_MEM8(0x001B)
+#define PRODSIGNATURES_USBRCOSC _SFR_MEM8(0x001C)
+#define PRODSIGNATURES_USBRCOSCA _SFR_MEM8(0x001D)
+#define PRODSIGNATURES_ADCACAL0 _SFR_MEM8(0x0020)
+#define PRODSIGNATURES_ADCACAL1 _SFR_MEM8(0x0021)
+#define PRODSIGNATURES_ADCBCAL0 _SFR_MEM8(0x0024)
+#define PRODSIGNATURES_ADCBCAL1 _SFR_MEM8(0x0025)
+#define PRODSIGNATURES_TEMPSENSE0 _SFR_MEM8(0x002E)
+#define PRODSIGNATURES_TEMPSENSE1 _SFR_MEM8(0x002F)
+#define PRODSIGNATURES_DACA0OFFCAL _SFR_MEM8(0x0030)
+#define PRODSIGNATURES_DACA0GAINCAL _SFR_MEM8(0x0031)
+#define PRODSIGNATURES_DACB0OFFCAL _SFR_MEM8(0x0032)
+#define PRODSIGNATURES_DACB0GAINCAL _SFR_MEM8(0x0033)
+#define PRODSIGNATURES_DACA1OFFCAL _SFR_MEM8(0x0034)
+#define PRODSIGNATURES_DACA1GAINCAL _SFR_MEM8(0x0035)
+#define PRODSIGNATURES_DACB1OFFCAL _SFR_MEM8(0x0036)
+#define PRODSIGNATURES_DACB1GAINCAL _SFR_MEM8(0x0037)
+
+/* VPORT - Virtual Port */
+#define VPORT0_DIR _SFR_MEM8(0x0010)
+#define VPORT0_OUT _SFR_MEM8(0x0011)
+#define VPORT0_IN _SFR_MEM8(0x0012)
+#define VPORT0_INTFLAGS _SFR_MEM8(0x0013)
+
+/* VPORT - Virtual Port */
+#define VPORT1_DIR _SFR_MEM8(0x0014)
+#define VPORT1_OUT _SFR_MEM8(0x0015)
+#define VPORT1_IN _SFR_MEM8(0x0016)
+#define VPORT1_INTFLAGS _SFR_MEM8(0x0017)
+
+/* VPORT - Virtual Port */
+#define VPORT2_DIR _SFR_MEM8(0x0018)
+#define VPORT2_OUT _SFR_MEM8(0x0019)
+#define VPORT2_IN _SFR_MEM8(0x001A)
+#define VPORT2_INTFLAGS _SFR_MEM8(0x001B)
+
+/* VPORT - Virtual Port */
+#define VPORT3_DIR _SFR_MEM8(0x001C)
+#define VPORT3_OUT _SFR_MEM8(0x001D)
+#define VPORT3_IN _SFR_MEM8(0x001E)
+#define VPORT3_INTFLAGS _SFR_MEM8(0x001F)
+
+/* OCD - On-Chip Debug System */
+#define OCD_OCDR0 _SFR_MEM8(0x002E)
+#define OCD_OCDR1 _SFR_MEM8(0x002F)
+
+/* CPU - CPU registers */
+#define CPU_CCP _SFR_MEM8(0x0034)
+#define CPU_RAMPD _SFR_MEM8(0x0038)
+#define CPU_RAMPX _SFR_MEM8(0x0039)
+#define CPU_RAMPY _SFR_MEM8(0x003A)
+#define CPU_RAMPZ _SFR_MEM8(0x003B)
+#define CPU_EIND _SFR_MEM8(0x003C)
+#define CPU_SPL _SFR_MEM8(0x003D)
+#define CPU_SPH _SFR_MEM8(0x003E)
+#define CPU_SREG _SFR_MEM8(0x003F)
+
+/* CLK - Clock System */
+#define CLK_CTRL _SFR_MEM8(0x0040)
+#define CLK_PSCTRL _SFR_MEM8(0x0041)
+#define CLK_LOCK _SFR_MEM8(0x0042)
+#define CLK_RTCCTRL _SFR_MEM8(0x0043)
+#define CLK_USBCTRL _SFR_MEM8(0x0044)
+
+/* SLEEP - Sleep Controller */
+#define SLEEP_CTRL _SFR_MEM8(0x0048)
+
+/* OSC - Oscillator */
+#define OSC_CTRL _SFR_MEM8(0x0050)
+#define OSC_STATUS _SFR_MEM8(0x0051)
+#define OSC_XOSCCTRL _SFR_MEM8(0x0052)
+#define OSC_XOSCFAIL _SFR_MEM8(0x0053)
+#define OSC_RC32KCAL _SFR_MEM8(0x0054)
+#define OSC_PLLCTRL _SFR_MEM8(0x0055)
+#define OSC_DFLLCTRL _SFR_MEM8(0x0056)
+
+/* DFLL - DFLL */
+#define DFLLRC32M_CTRL _SFR_MEM8(0x0060)
+#define DFLLRC32M_CALA _SFR_MEM8(0x0062)
+#define DFLLRC32M_CALB _SFR_MEM8(0x0063)
+#define DFLLRC32M_COMP0 _SFR_MEM8(0x0064)
+#define DFLLRC32M_COMP1 _SFR_MEM8(0x0065)
+#define DFLLRC32M_COMP2 _SFR_MEM8(0x0066)
+
+/* DFLL - DFLL */
+#define DFLLRC2M_CTRL _SFR_MEM8(0x0068)
+#define DFLLRC2M_CALA _SFR_MEM8(0x006A)
+#define DFLLRC2M_CALB _SFR_MEM8(0x006B)
+#define DFLLRC2M_COMP0 _SFR_MEM8(0x006C)
+#define DFLLRC2M_COMP1 _SFR_MEM8(0x006D)
+#define DFLLRC2M_COMP2 _SFR_MEM8(0x006E)
+
+/* PR - Power Reduction */
+#define PR_PRGEN _SFR_MEM8(0x0070)
+#define PR_PRPA _SFR_MEM8(0x0071)
+#define PR_PRPB _SFR_MEM8(0x0072)
+#define PR_PRPC _SFR_MEM8(0x0073)
+#define PR_PRPD _SFR_MEM8(0x0074)
+#define PR_PRPE _SFR_MEM8(0x0075)
+#define PR_PRPF _SFR_MEM8(0x0076)
+
+/* RST - Reset */
+#define RST_STATUS _SFR_MEM8(0x0078)
+#define RST_CTRL _SFR_MEM8(0x0079)
+
+/* WDT - Watch-Dog Timer */
+#define WDT_CTRL _SFR_MEM8(0x0080)
+#define WDT_WINCTRL _SFR_MEM8(0x0081)
+#define WDT_STATUS _SFR_MEM8(0x0082)
+
+/* MCU - MCU Control */
+#define MCU_DEVID0 _SFR_MEM8(0x0090)
+#define MCU_DEVID1 _SFR_MEM8(0x0091)
+#define MCU_DEVID2 _SFR_MEM8(0x0092)
+#define MCU_REVID _SFR_MEM8(0x0093)
+#define MCU_JTAGUID _SFR_MEM8(0x0094)
+#define MCU_MCUCR _SFR_MEM8(0x0096)
+#define MCU_ANAINIT _SFR_MEM8(0x0097)
+#define MCU_EVSYSLOCK _SFR_MEM8(0x0098)
+#define MCU_AWEXLOCK _SFR_MEM8(0x0099)
+
+/* PMIC - Programmable Multi-level Interrupt Controller */
+#define PMIC_STATUS _SFR_MEM8(0x00A0)
+#define PMIC_INTPRI _SFR_MEM8(0x00A1)
+#define PMIC_CTRL _SFR_MEM8(0x00A2)
+
+/* PORTCFG - I/O port Configuration */
+#define PORTCFG_MPCMASK _SFR_MEM8(0x00B0)
+#define PORTCFG_VPCTRLA _SFR_MEM8(0x00B2)
+#define PORTCFG_VPCTRLB _SFR_MEM8(0x00B3)
+#define PORTCFG_CLKEVOUT _SFR_MEM8(0x00B4)
+#define PORTCFG_EBIOUT _SFR_MEM8(0x00B5)
+#define PORTCFG_EVOUTSEL _SFR_MEM8(0x00B6)
+
+/* AES - AES Module */
+#define AES_CTRL _SFR_MEM8(0x00C0)
+#define AES_STATUS _SFR_MEM8(0x00C1)
+#define AES_STATE _SFR_MEM8(0x00C2)
+#define AES_KEY _SFR_MEM8(0x00C3)
+#define AES_INTCTRL _SFR_MEM8(0x00C4)
+
+/* CRC - Cyclic Redundancy Checker */
+#define CRC_CTRL _SFR_MEM8(0x00D0)
+#define CRC_STATUS _SFR_MEM8(0x00D1)
+#define CRC_DATAIN _SFR_MEM8(0x00D3)
+#define CRC_CHECKSUM0 _SFR_MEM8(0x00D4)
+#define CRC_CHECKSUM1 _SFR_MEM8(0x00D5)
+#define CRC_CHECKSUM2 _SFR_MEM8(0x00D6)
+#define CRC_CHECKSUM3 _SFR_MEM8(0x00D7)
+
+/* DMA - DMA Controller */
+#define DMA_CTRL _SFR_MEM8(0x0100)
+#define DMA_INTFLAGS _SFR_MEM8(0x0103)
+#define DMA_STATUS _SFR_MEM8(0x0104)
+#define DMA_TEMP _SFR_MEM16(0x0106)
+#define DMA_CH0_CTRLA _SFR_MEM8(0x0110)
+#define DMA_CH0_CTRLB _SFR_MEM8(0x0111)
+#define DMA_CH0_ADDRCTRL _SFR_MEM8(0x0112)
+#define DMA_CH0_TRIGSRC _SFR_MEM8(0x0113)
+#define DMA_CH0_TRFCNT _SFR_MEM16(0x0114)
+#define DMA_CH0_REPCNT _SFR_MEM8(0x0116)
+#define DMA_CH0_SRCADDR0 _SFR_MEM8(0x0118)
+#define DMA_CH0_SRCADDR1 _SFR_MEM8(0x0119)
+#define DMA_CH0_SRCADDR2 _SFR_MEM8(0x011A)
+#define DMA_CH0_DESTADDR0 _SFR_MEM8(0x011C)
+#define DMA_CH0_DESTADDR1 _SFR_MEM8(0x011D)
+#define DMA_CH0_DESTADDR2 _SFR_MEM8(0x011E)
+#define DMA_CH1_CTRLA _SFR_MEM8(0x0120)
+#define DMA_CH1_CTRLB _SFR_MEM8(0x0121)
+#define DMA_CH1_ADDRCTRL _SFR_MEM8(0x0122)
+#define DMA_CH1_TRIGSRC _SFR_MEM8(0x0123)
+#define DMA_CH1_TRFCNT _SFR_MEM16(0x0124)
+#define DMA_CH1_REPCNT _SFR_MEM8(0x0126)
+#define DMA_CH1_SRCADDR0 _SFR_MEM8(0x0128)
+#define DMA_CH1_SRCADDR1 _SFR_MEM8(0x0129)
+#define DMA_CH1_SRCADDR2 _SFR_MEM8(0x012A)
+#define DMA_CH1_DESTADDR0 _SFR_MEM8(0x012C)
+#define DMA_CH1_DESTADDR1 _SFR_MEM8(0x012D)
+#define DMA_CH1_DESTADDR2 _SFR_MEM8(0x012E)
+#define DMA_CH2_CTRLA _SFR_MEM8(0x0130)
+#define DMA_CH2_CTRLB _SFR_MEM8(0x0131)
+#define DMA_CH2_ADDRCTRL _SFR_MEM8(0x0132)
+#define DMA_CH2_TRIGSRC _SFR_MEM8(0x0133)
+#define DMA_CH2_TRFCNT _SFR_MEM16(0x0134)
+#define DMA_CH2_REPCNT _SFR_MEM8(0x0136)
+#define DMA_CH2_SRCADDR0 _SFR_MEM8(0x0138)
+#define DMA_CH2_SRCADDR1 _SFR_MEM8(0x0139)
+#define DMA_CH2_SRCADDR2 _SFR_MEM8(0x013A)
+#define DMA_CH2_DESTADDR0 _SFR_MEM8(0x013C)
+#define DMA_CH2_DESTADDR1 _SFR_MEM8(0x013D)
+#define DMA_CH2_DESTADDR2 _SFR_MEM8(0x013E)
+#define DMA_CH3_CTRLA _SFR_MEM8(0x0140)
+#define DMA_CH3_CTRLB _SFR_MEM8(0x0141)
+#define DMA_CH3_ADDRCTRL _SFR_MEM8(0x0142)
+#define DMA_CH3_TRIGSRC _SFR_MEM8(0x0143)
+#define DMA_CH3_TRFCNT _SFR_MEM16(0x0144)
+#define DMA_CH3_REPCNT _SFR_MEM8(0x0146)
+#define DMA_CH3_SRCADDR0 _SFR_MEM8(0x0148)
+#define DMA_CH3_SRCADDR1 _SFR_MEM8(0x0149)
+#define DMA_CH3_SRCADDR2 _SFR_MEM8(0x014A)
+#define DMA_CH3_DESTADDR0 _SFR_MEM8(0x014C)
+#define DMA_CH3_DESTADDR1 _SFR_MEM8(0x014D)
+#define DMA_CH3_DESTADDR2 _SFR_MEM8(0x014E)
+
+/* EVSYS - Event System */
+#define EVSYS_CH0MUX _SFR_MEM8(0x0180)
+#define EVSYS_CH1MUX _SFR_MEM8(0x0181)
+#define EVSYS_CH2MUX _SFR_MEM8(0x0182)
+#define EVSYS_CH3MUX _SFR_MEM8(0x0183)
+#define EVSYS_CH4MUX _SFR_MEM8(0x0184)
+#define EVSYS_CH5MUX _SFR_MEM8(0x0185)
+#define EVSYS_CH6MUX _SFR_MEM8(0x0186)
+#define EVSYS_CH7MUX _SFR_MEM8(0x0187)
+#define EVSYS_CH0CTRL _SFR_MEM8(0x0188)
+#define EVSYS_CH1CTRL _SFR_MEM8(0x0189)
+#define EVSYS_CH2CTRL _SFR_MEM8(0x018A)
+#define EVSYS_CH3CTRL _SFR_MEM8(0x018B)
+#define EVSYS_CH4CTRL _SFR_MEM8(0x018C)
+#define EVSYS_CH5CTRL _SFR_MEM8(0x018D)
+#define EVSYS_CH6CTRL _SFR_MEM8(0x018E)
+#define EVSYS_CH7CTRL _SFR_MEM8(0x018F)
+#define EVSYS_STROBE _SFR_MEM8(0x0190)
+#define EVSYS_DATA _SFR_MEM8(0x0191)
+
+/* NVM - Non-volatile Memory Controller */
+#define NVM_ADDR0 _SFR_MEM8(0x01C0)
+#define NVM_ADDR1 _SFR_MEM8(0x01C1)
+#define NVM_ADDR2 _SFR_MEM8(0x01C2)
+#define NVM_DATA0 _SFR_MEM8(0x01C4)
+#define NVM_DATA1 _SFR_MEM8(0x01C5)
+#define NVM_DATA2 _SFR_MEM8(0x01C6)
+#define NVM_CMD _SFR_MEM8(0x01CA)
+#define NVM_CTRLA _SFR_MEM8(0x01CB)
+#define NVM_CTRLB _SFR_MEM8(0x01CC)
+#define NVM_INTCTRL _SFR_MEM8(0x01CD)
+#define NVM_STATUS _SFR_MEM8(0x01CF)
+#define NVM_LOCKBITS _SFR_MEM8(0x01D0)
+
+/* ADC - Analog-to-Digital Converter */
+#define ADCA_CTRLA _SFR_MEM8(0x0200)
+#define ADCA_CTRLB _SFR_MEM8(0x0201)
+#define ADCA_REFCTRL _SFR_MEM8(0x0202)
+#define ADCA_EVCTRL _SFR_MEM8(0x0203)
+#define ADCA_PRESCALER _SFR_MEM8(0x0204)
+#define ADCA_INTFLAGS _SFR_MEM8(0x0206)
+#define ADCA_TEMP _SFR_MEM8(0x0207)
+#define ADCA_CAL _SFR_MEM16(0x020C)
+#define ADCA_CH0RES _SFR_MEM16(0x0210)
+#define ADCA_CH1RES _SFR_MEM16(0x0212)
+#define ADCA_CH2RES _SFR_MEM16(0x0214)
+#define ADCA_CH3RES _SFR_MEM16(0x0216)
+#define ADCA_CMP _SFR_MEM16(0x0218)
+#define ADCA_CH0_CTRL _SFR_MEM8(0x0220)
+#define ADCA_CH0_MUXCTRL _SFR_MEM8(0x0221)
+#define ADCA_CH0_INTCTRL _SFR_MEM8(0x0222)
+#define ADCA_CH0_INTFLAGS _SFR_MEM8(0x0223)
+#define ADCA_CH0_RES _SFR_MEM16(0x0224)
+#define ADCA_CH0_SCAN _SFR_MEM8(0x0226)
+#define ADCA_CH1_CTRL _SFR_MEM8(0x0228)
+#define ADCA_CH1_MUXCTRL _SFR_MEM8(0x0229)
+#define ADCA_CH1_INTCTRL _SFR_MEM8(0x022A)
+#define ADCA_CH1_INTFLAGS _SFR_MEM8(0x022B)
+#define ADCA_CH1_RES _SFR_MEM16(0x022C)
+#define ADCA_CH1_SCAN _SFR_MEM8(0x022E)
+#define ADCA_CH2_CTRL _SFR_MEM8(0x0230)
+#define ADCA_CH2_MUXCTRL _SFR_MEM8(0x0231)
+#define ADCA_CH2_INTCTRL _SFR_MEM8(0x0232)
+#define ADCA_CH2_INTFLAGS _SFR_MEM8(0x0233)
+#define ADCA_CH2_RES _SFR_MEM16(0x0234)
+#define ADCA_CH2_SCAN _SFR_MEM8(0x0236)
+#define ADCA_CH3_CTRL _SFR_MEM8(0x0238)
+#define ADCA_CH3_MUXCTRL _SFR_MEM8(0x0239)
+#define ADCA_CH3_INTCTRL _SFR_MEM8(0x023A)
+#define ADCA_CH3_INTFLAGS _SFR_MEM8(0x023B)
+#define ADCA_CH3_RES _SFR_MEM16(0x023C)
+#define ADCA_CH3_SCAN _SFR_MEM8(0x023E)
+
+/* ADC - Analog-to-Digital Converter */
+#define ADCB_CTRLA _SFR_MEM8(0x0240)
+#define ADCB_CTRLB _SFR_MEM8(0x0241)
+#define ADCB_REFCTRL _SFR_MEM8(0x0242)
+#define ADCB_EVCTRL _SFR_MEM8(0x0243)
+#define ADCB_PRESCALER _SFR_MEM8(0x0244)
+#define ADCB_INTFLAGS _SFR_MEM8(0x0246)
+#define ADCB_TEMP _SFR_MEM8(0x0247)
+#define ADCB_CAL _SFR_MEM16(0x024C)
+#define ADCB_CH0RES _SFR_MEM16(0x0250)
+#define ADCB_CH1RES _SFR_MEM16(0x0252)
+#define ADCB_CH2RES _SFR_MEM16(0x0254)
+#define ADCB_CH3RES _SFR_MEM16(0x0256)
+#define ADCB_CMP _SFR_MEM16(0x0258)
+#define ADCB_CH0_CTRL _SFR_MEM8(0x0260)
+#define ADCB_CH0_MUXCTRL _SFR_MEM8(0x0261)
+#define ADCB_CH0_INTCTRL _SFR_MEM8(0x0262)
+#define ADCB_CH0_INTFLAGS _SFR_MEM8(0x0263)
+#define ADCB_CH0_RES _SFR_MEM16(0x0264)
+#define ADCB_CH0_SCAN _SFR_MEM8(0x0266)
+#define ADCB_CH1_CTRL _SFR_MEM8(0x0268)
+#define ADCB_CH1_MUXCTRL _SFR_MEM8(0x0269)
+#define ADCB_CH1_INTCTRL _SFR_MEM8(0x026A)
+#define ADCB_CH1_INTFLAGS _SFR_MEM8(0x026B)
+#define ADCB_CH1_RES _SFR_MEM16(0x026C)
+#define ADCB_CH1_SCAN _SFR_MEM8(0x026E)
+#define ADCB_CH2_CTRL _SFR_MEM8(0x0270)
+#define ADCB_CH2_MUXCTRL _SFR_MEM8(0x0271)
+#define ADCB_CH2_INTCTRL _SFR_MEM8(0x0272)
+#define ADCB_CH2_INTFLAGS _SFR_MEM8(0x0273)
+#define ADCB_CH2_RES _SFR_MEM16(0x0274)
+#define ADCB_CH2_SCAN _SFR_MEM8(0x0276)
+#define ADCB_CH3_CTRL _SFR_MEM8(0x0278)
+#define ADCB_CH3_MUXCTRL _SFR_MEM8(0x0279)
+#define ADCB_CH3_INTCTRL _SFR_MEM8(0x027A)
+#define ADCB_CH3_INTFLAGS _SFR_MEM8(0x027B)
+#define ADCB_CH3_RES _SFR_MEM16(0x027C)
+#define ADCB_CH3_SCAN _SFR_MEM8(0x027E)
+
+/* DAC - Digital-to-Analog Converter */
+#define DACB_CTRLA _SFR_MEM8(0x0320)
+#define DACB_CTRLB _SFR_MEM8(0x0321)
+#define DACB_CTRLC _SFR_MEM8(0x0322)
+#define DACB_EVCTRL _SFR_MEM8(0x0323)
+#define DACB_STATUS _SFR_MEM8(0x0325)
+#define DACB_CH0GAINCAL _SFR_MEM8(0x0328)
+#define DACB_CH0OFFSETCAL _SFR_MEM8(0x0329)
+#define DACB_CH1GAINCAL _SFR_MEM8(0x032A)
+#define DACB_CH1OFFSETCAL _SFR_MEM8(0x032B)
+#define DACB_CH0DATA _SFR_MEM16(0x0338)
+#define DACB_CH1DATA _SFR_MEM16(0x033A)
+
+/* AC - Analog Comparator */
+#define ACA_AC0CTRL _SFR_MEM8(0x0380)
+#define ACA_AC1CTRL _SFR_MEM8(0x0381)
+#define ACA_AC0MUXCTRL _SFR_MEM8(0x0382)
+#define ACA_AC1MUXCTRL _SFR_MEM8(0x0383)
+#define ACA_CTRLA _SFR_MEM8(0x0384)
+#define ACA_CTRLB _SFR_MEM8(0x0385)
+#define ACA_WINCTRL _SFR_MEM8(0x0386)
+#define ACA_STATUS _SFR_MEM8(0x0387)
+
+/* AC - Analog Comparator */
+#define ACB_AC0CTRL _SFR_MEM8(0x0390)
+#define ACB_AC1CTRL _SFR_MEM8(0x0391)
+#define ACB_AC0MUXCTRL _SFR_MEM8(0x0392)
+#define ACB_AC1MUXCTRL _SFR_MEM8(0x0393)
+#define ACB_CTRLA _SFR_MEM8(0x0394)
+#define ACB_CTRLB _SFR_MEM8(0x0395)
+#define ACB_WINCTRL _SFR_MEM8(0x0396)
+#define ACB_STATUS _SFR_MEM8(0x0397)
+
+/* RTC - Real-Time Counter */
+#define RTC_CTRL _SFR_MEM8(0x0400)
+#define RTC_STATUS _SFR_MEM8(0x0401)
+#define RTC_INTCTRL _SFR_MEM8(0x0402)
+#define RTC_INTFLAGS _SFR_MEM8(0x0403)
+#define RTC_TEMP _SFR_MEM8(0x0404)
+#define RTC_CNT _SFR_MEM16(0x0408)
+#define RTC_PER _SFR_MEM16(0x040A)
+#define RTC_COMP _SFR_MEM16(0x040C)
+
+/* TWI - Two-Wire Interface */
+#define TWIC_CTRL _SFR_MEM8(0x0480)
+#define TWIC_MASTER_CTRLA _SFR_MEM8(0x0481)
+#define TWIC_MASTER_CTRLB _SFR_MEM8(0x0482)
+#define TWIC_MASTER_CTRLC _SFR_MEM8(0x0483)
+#define TWIC_MASTER_STATUS _SFR_MEM8(0x0484)
+#define TWIC_MASTER_BAUD _SFR_MEM8(0x0485)
+#define TWIC_MASTER_ADDR _SFR_MEM8(0x0486)
+#define TWIC_MASTER_DATA _SFR_MEM8(0x0487)
+#define TWIC_SLAVE_CTRLA _SFR_MEM8(0x0488)
+#define TWIC_SLAVE_CTRLB _SFR_MEM8(0x0489)
+#define TWIC_SLAVE_STATUS _SFR_MEM8(0x048A)
+#define TWIC_SLAVE_ADDR _SFR_MEM8(0x048B)
+#define TWIC_SLAVE_DATA _SFR_MEM8(0x048C)
+#define TWIC_SLAVE_ADDRMASK _SFR_MEM8(0x048D)
+
+/* TWI - Two-Wire Interface */
+#define TWIE_CTRL _SFR_MEM8(0x04A0)
+#define TWIE_MASTER_CTRLA _SFR_MEM8(0x04A1)
+#define TWIE_MASTER_CTRLB _SFR_MEM8(0x04A2)
+#define TWIE_MASTER_CTRLC _SFR_MEM8(0x04A3)
+#define TWIE_MASTER_STATUS _SFR_MEM8(0x04A4)
+#define TWIE_MASTER_BAUD _SFR_MEM8(0x04A5)
+#define TWIE_MASTER_ADDR _SFR_MEM8(0x04A6)
+#define TWIE_MASTER_DATA _SFR_MEM8(0x04A7)
+#define TWIE_SLAVE_CTRLA _SFR_MEM8(0x04A8)
+#define TWIE_SLAVE_CTRLB _SFR_MEM8(0x04A9)
+#define TWIE_SLAVE_STATUS _SFR_MEM8(0x04AA)
+#define TWIE_SLAVE_ADDR _SFR_MEM8(0x04AB)
+#define TWIE_SLAVE_DATA _SFR_MEM8(0x04AC)
+#define TWIE_SLAVE_ADDRMASK _SFR_MEM8(0x04AD)
+
+/* USB - Universal Serial Bus */
+#define USB_CTRLA _SFR_MEM8(0x04C0)
+#define USB_CTRLB _SFR_MEM8(0x04C1)
+#define USB_STATUS _SFR_MEM8(0x04C2)
+#define USB_ADDR _SFR_MEM8(0x04C3)
+#define USB_FIFOWP _SFR_MEM8(0x04C4)
+#define USB_FIFORP _SFR_MEM8(0x04C5)
+#define USB_EPPTR _SFR_MEM16(0x04C6)
+#define USB_INTCTRLA _SFR_MEM8(0x04C8)
+#define USB_INTCTRLB _SFR_MEM8(0x04C9)
+#define USB_INTFLAGSACLR _SFR_MEM8(0x04CA)
+#define USB_INTFLAGSASET _SFR_MEM8(0x04CB)
+#define USB_INTFLAGSBCLR _SFR_MEM8(0x04CC)
+#define USB_INTFLAGSBSET _SFR_MEM8(0x04CD)
+#define USB_CAL0 _SFR_MEM8(0x04FA)
+#define USB_CAL1 _SFR_MEM8(0x04FB)
+
+/* PORT - I/O Ports */
+#define PORTA_DIR _SFR_MEM8(0x0600)
+#define PORTA_DIRSET _SFR_MEM8(0x0601)
+#define PORTA_DIRCLR _SFR_MEM8(0x0602)
+#define PORTA_DIRTGL _SFR_MEM8(0x0603)
+#define PORTA_OUT _SFR_MEM8(0x0604)
+#define PORTA_OUTSET _SFR_MEM8(0x0605)
+#define PORTA_OUTCLR _SFR_MEM8(0x0606)
+#define PORTA_OUTTGL _SFR_MEM8(0x0607)
+#define PORTA_IN _SFR_MEM8(0x0608)
+#define PORTA_INTCTRL _SFR_MEM8(0x0609)
+#define PORTA_INT0MASK _SFR_MEM8(0x060A)
+#define PORTA_INT1MASK _SFR_MEM8(0x060B)
+#define PORTA_INTFLAGS _SFR_MEM8(0x060C)
+#define PORTA_REMAP _SFR_MEM8(0x060E)
+#define PORTA_PIN0CTRL _SFR_MEM8(0x0610)
+#define PORTA_PIN1CTRL _SFR_MEM8(0x0611)
+#define PORTA_PIN2CTRL _SFR_MEM8(0x0612)
+#define PORTA_PIN3CTRL _SFR_MEM8(0x0613)
+#define PORTA_PIN4CTRL _SFR_MEM8(0x0614)
+#define PORTA_PIN5CTRL _SFR_MEM8(0x0615)
+#define PORTA_PIN6CTRL _SFR_MEM8(0x0616)
+#define PORTA_PIN7CTRL _SFR_MEM8(0x0617)
+
+/* PORT - I/O Ports */
+#define PORTB_DIR _SFR_MEM8(0x0620)
+#define PORTB_DIRSET _SFR_MEM8(0x0621)
+#define PORTB_DIRCLR _SFR_MEM8(0x0622)
+#define PORTB_DIRTGL _SFR_MEM8(0x0623)
+#define PORTB_OUT _SFR_MEM8(0x0624)
+#define PORTB_OUTSET _SFR_MEM8(0x0625)
+#define PORTB_OUTCLR _SFR_MEM8(0x0626)
+#define PORTB_OUTTGL _SFR_MEM8(0x0627)
+#define PORTB_IN _SFR_MEM8(0x0628)
+#define PORTB_INTCTRL _SFR_MEM8(0x0629)
+#define PORTB_INT0MASK _SFR_MEM8(0x062A)
+#define PORTB_INT1MASK _SFR_MEM8(0x062B)
+#define PORTB_INTFLAGS _SFR_MEM8(0x062C)
+#define PORTB_REMAP _SFR_MEM8(0x062E)
+#define PORTB_PIN0CTRL _SFR_MEM8(0x0630)
+#define PORTB_PIN1CTRL _SFR_MEM8(0x0631)
+#define PORTB_PIN2CTRL _SFR_MEM8(0x0632)
+#define PORTB_PIN3CTRL _SFR_MEM8(0x0633)
+#define PORTB_PIN4CTRL _SFR_MEM8(0x0634)
+#define PORTB_PIN5CTRL _SFR_MEM8(0x0635)
+#define PORTB_PIN6CTRL _SFR_MEM8(0x0636)
+#define PORTB_PIN7CTRL _SFR_MEM8(0x0637)
+
+/* PORT - I/O Ports */
+#define PORTC_DIR _SFR_MEM8(0x0640)
+#define PORTC_DIRSET _SFR_MEM8(0x0641)
+#define PORTC_DIRCLR _SFR_MEM8(0x0642)
+#define PORTC_DIRTGL _SFR_MEM8(0x0643)
+#define PORTC_OUT _SFR_MEM8(0x0644)
+#define PORTC_OUTSET _SFR_MEM8(0x0645)
+#define PORTC_OUTCLR _SFR_MEM8(0x0646)
+#define PORTC_OUTTGL _SFR_MEM8(0x0647)
+#define PORTC_IN _SFR_MEM8(0x0648)
+#define PORTC_INTCTRL _SFR_MEM8(0x0649)
+#define PORTC_INT0MASK _SFR_MEM8(0x064A)
+#define PORTC_INT1MASK _SFR_MEM8(0x064B)
+#define PORTC_INTFLAGS _SFR_MEM8(0x064C)
+#define PORTC_REMAP _SFR_MEM8(0x064E)
+#define PORTC_PIN0CTRL _SFR_MEM8(0x0650)
+#define PORTC_PIN1CTRL _SFR_MEM8(0x0651)
+#define PORTC_PIN2CTRL _SFR_MEM8(0x0652)
+#define PORTC_PIN3CTRL _SFR_MEM8(0x0653)
+#define PORTC_PIN4CTRL _SFR_MEM8(0x0654)
+#define PORTC_PIN5CTRL _SFR_MEM8(0x0655)
+#define PORTC_PIN6CTRL _SFR_MEM8(0x0656)
+#define PORTC_PIN7CTRL _SFR_MEM8(0x0657)
+
+/* PORT - I/O Ports */
+#define PORTD_DIR _SFR_MEM8(0x0660)
+#define PORTD_DIRSET _SFR_MEM8(0x0661)
+#define PORTD_DIRCLR _SFR_MEM8(0x0662)
+#define PORTD_DIRTGL _SFR_MEM8(0x0663)
+#define PORTD_OUT _SFR_MEM8(0x0664)
+#define PORTD_OUTSET _SFR_MEM8(0x0665)
+#define PORTD_OUTCLR _SFR_MEM8(0x0666)
+#define PORTD_OUTTGL _SFR_MEM8(0x0667)
+#define PORTD_IN _SFR_MEM8(0x0668)
+#define PORTD_INTCTRL _SFR_MEM8(0x0669)
+#define PORTD_INT0MASK _SFR_MEM8(0x066A)
+#define PORTD_INT1MASK _SFR_MEM8(0x066B)
+#define PORTD_INTFLAGS _SFR_MEM8(0x066C)
+#define PORTD_REMAP _SFR_MEM8(0x066E)
+#define PORTD_PIN0CTRL _SFR_MEM8(0x0670)
+#define PORTD_PIN1CTRL _SFR_MEM8(0x0671)
+#define PORTD_PIN2CTRL _SFR_MEM8(0x0672)
+#define PORTD_PIN3CTRL _SFR_MEM8(0x0673)
+#define PORTD_PIN4CTRL _SFR_MEM8(0x0674)
+#define PORTD_PIN5CTRL _SFR_MEM8(0x0675)
+#define PORTD_PIN6CTRL _SFR_MEM8(0x0676)
+#define PORTD_PIN7CTRL _SFR_MEM8(0x0677)
+
+/* PORT - I/O Ports */
+#define PORTE_DIR _SFR_MEM8(0x0680)
+#define PORTE_DIRSET _SFR_MEM8(0x0681)
+#define PORTE_DIRCLR _SFR_MEM8(0x0682)
+#define PORTE_DIRTGL _SFR_MEM8(0x0683)
+#define PORTE_OUT _SFR_MEM8(0x0684)
+#define PORTE_OUTSET _SFR_MEM8(0x0685)
+#define PORTE_OUTCLR _SFR_MEM8(0x0686)
+#define PORTE_OUTTGL _SFR_MEM8(0x0687)
+#define PORTE_IN _SFR_MEM8(0x0688)
+#define PORTE_INTCTRL _SFR_MEM8(0x0689)
+#define PORTE_INT0MASK _SFR_MEM8(0x068A)
+#define PORTE_INT1MASK _SFR_MEM8(0x068B)
+#define PORTE_INTFLAGS _SFR_MEM8(0x068C)
+#define PORTE_REMAP _SFR_MEM8(0x068E)
+#define PORTE_PIN0CTRL _SFR_MEM8(0x0690)
+#define PORTE_PIN1CTRL _SFR_MEM8(0x0691)
+#define PORTE_PIN2CTRL _SFR_MEM8(0x0692)
+#define PORTE_PIN3CTRL _SFR_MEM8(0x0693)
+#define PORTE_PIN4CTRL _SFR_MEM8(0x0694)
+#define PORTE_PIN5CTRL _SFR_MEM8(0x0695)
+#define PORTE_PIN6CTRL _SFR_MEM8(0x0696)
+#define PORTE_PIN7CTRL _SFR_MEM8(0x0697)
+
+/* PORT - I/O Ports */
+#define PORTF_DIR _SFR_MEM8(0x06A0)
+#define PORTF_DIRSET _SFR_MEM8(0x06A1)
+#define PORTF_DIRCLR _SFR_MEM8(0x06A2)
+#define PORTF_DIRTGL _SFR_MEM8(0x06A3)
+#define PORTF_OUT _SFR_MEM8(0x06A4)
+#define PORTF_OUTSET _SFR_MEM8(0x06A5)
+#define PORTF_OUTCLR _SFR_MEM8(0x06A6)
+#define PORTF_OUTTGL _SFR_MEM8(0x06A7)
+#define PORTF_IN _SFR_MEM8(0x06A8)
+#define PORTF_INTCTRL _SFR_MEM8(0x06A9)
+#define PORTF_INT0MASK _SFR_MEM8(0x06AA)
+#define PORTF_INT1MASK _SFR_MEM8(0x06AB)
+#define PORTF_INTFLAGS _SFR_MEM8(0x06AC)
+#define PORTF_REMAP _SFR_MEM8(0x06AE)
+#define PORTF_PIN0CTRL _SFR_MEM8(0x06B0)
+#define PORTF_PIN1CTRL _SFR_MEM8(0x06B1)
+#define PORTF_PIN2CTRL _SFR_MEM8(0x06B2)
+#define PORTF_PIN3CTRL _SFR_MEM8(0x06B3)
+#define PORTF_PIN4CTRL _SFR_MEM8(0x06B4)
+#define PORTF_PIN5CTRL _SFR_MEM8(0x06B5)
+#define PORTF_PIN6CTRL _SFR_MEM8(0x06B6)
+#define PORTF_PIN7CTRL _SFR_MEM8(0x06B7)
+
+/* PORT - I/O Ports */
+#define PORTR_DIR _SFR_MEM8(0x07E0)
+#define PORTR_DIRSET _SFR_MEM8(0x07E1)
+#define PORTR_DIRCLR _SFR_MEM8(0x07E2)
+#define PORTR_DIRTGL _SFR_MEM8(0x07E3)
+#define PORTR_OUT _SFR_MEM8(0x07E4)
+#define PORTR_OUTSET _SFR_MEM8(0x07E5)
+#define PORTR_OUTCLR _SFR_MEM8(0x07E6)
+#define PORTR_OUTTGL _SFR_MEM8(0x07E7)
+#define PORTR_IN _SFR_MEM8(0x07E8)
+#define PORTR_INTCTRL _SFR_MEM8(0x07E9)
+#define PORTR_INT0MASK _SFR_MEM8(0x07EA)
+#define PORTR_INT1MASK _SFR_MEM8(0x07EB)
+#define PORTR_INTFLAGS _SFR_MEM8(0x07EC)
+#define PORTR_REMAP _SFR_MEM8(0x07EE)
+#define PORTR_PIN0CTRL _SFR_MEM8(0x07F0)
+#define PORTR_PIN1CTRL _SFR_MEM8(0x07F1)
+#define PORTR_PIN2CTRL _SFR_MEM8(0x07F2)
+#define PORTR_PIN3CTRL _SFR_MEM8(0x07F3)
+#define PORTR_PIN4CTRL _SFR_MEM8(0x07F4)
+#define PORTR_PIN5CTRL _SFR_MEM8(0x07F5)
+#define PORTR_PIN6CTRL _SFR_MEM8(0x07F6)
+#define PORTR_PIN7CTRL _SFR_MEM8(0x07F7)
+
+/* TC0 - 16-bit Timer/Counter 0 */
+#define TCC0_CTRLA _SFR_MEM8(0x0800)
+#define TCC0_CTRLB _SFR_MEM8(0x0801)
+#define TCC0_CTRLC _SFR_MEM8(0x0802)
+#define TCC0_CTRLD _SFR_MEM8(0x0803)
+#define TCC0_CTRLE _SFR_MEM8(0x0804)
+#define TCC0_INTCTRLA _SFR_MEM8(0x0806)
+#define TCC0_INTCTRLB _SFR_MEM8(0x0807)
+#define TCC0_CTRLFCLR _SFR_MEM8(0x0808)
+#define TCC0_CTRLFSET _SFR_MEM8(0x0809)
+#define TCC0_CTRLGCLR _SFR_MEM8(0x080A)
+#define TCC0_CTRLGSET _SFR_MEM8(0x080B)
+#define TCC0_INTFLAGS _SFR_MEM8(0x080C)
+#define TCC0_TEMP _SFR_MEM8(0x080F)
+#define TCC0_CNT _SFR_MEM16(0x0820)
+#define TCC0_PER _SFR_MEM16(0x0826)
+#define TCC0_CCA _SFR_MEM16(0x0828)
+#define TCC0_CCB _SFR_MEM16(0x082A)
+#define TCC0_CCC _SFR_MEM16(0x082C)
+#define TCC0_CCD _SFR_MEM16(0x082E)
+#define TCC0_PERBUF _SFR_MEM16(0x0836)
+#define TCC0_CCABUF _SFR_MEM16(0x0838)
+#define TCC0_CCBBUF _SFR_MEM16(0x083A)
+#define TCC0_CCCBUF _SFR_MEM16(0x083C)
+#define TCC0_CCDBUF _SFR_MEM16(0x083E)
+
+/* TC2 - 16-bit Timer/Counter type 2 */
+#define TCC2_CTRLA _SFR_MEM8(0x0800)
+#define TCC2_CTRLB _SFR_MEM8(0x0801)
+#define TCC2_CTRLC _SFR_MEM8(0x0802)
+#define TCC2_CTRLE _SFR_MEM8(0x0804)
+#define TCC2_INTCTRLA _SFR_MEM8(0x0806)
+#define TCC2_INTCTRLB _SFR_MEM8(0x0807)
+#define TCC2_CTRLF _SFR_MEM8(0x0809)
+#define TCC2_INTFLAGS _SFR_MEM8(0x080C)
+#define TCC2_LCNT _SFR_MEM8(0x0820)
+#define TCC2_HCNT _SFR_MEM8(0x0821)
+#define TCC2_LPER _SFR_MEM8(0x0826)
+#define TCC2_HPER _SFR_MEM8(0x0827)
+#define TCC2_LCMPA _SFR_MEM8(0x0828)
+#define TCC2_HCMPA _SFR_MEM8(0x0829)
+#define TCC2_LCMPB _SFR_MEM8(0x082A)
+#define TCC2_HCMPB _SFR_MEM8(0x082B)
+#define TCC2_LCMPC _SFR_MEM8(0x082C)
+#define TCC2_HCMPC _SFR_MEM8(0x082D)
+#define TCC2_LCMPD _SFR_MEM8(0x082E)
+#define TCC2_HCMPD _SFR_MEM8(0x082F)
+
+/* TC1 - 16-bit Timer/Counter 1 */
+#define TCC1_CTRLA _SFR_MEM8(0x0840)
+#define TCC1_CTRLB _SFR_MEM8(0x0841)
+#define TCC1_CTRLC _SFR_MEM8(0x0842)
+#define TCC1_CTRLD _SFR_MEM8(0x0843)
+#define TCC1_CTRLE _SFR_MEM8(0x0844)
+#define TCC1_INTCTRLA _SFR_MEM8(0x0846)
+#define TCC1_INTCTRLB _SFR_MEM8(0x0847)
+#define TCC1_CTRLFCLR _SFR_MEM8(0x0848)
+#define TCC1_CTRLFSET _SFR_MEM8(0x0849)
+#define TCC1_CTRLGCLR _SFR_MEM8(0x084A)
+#define TCC1_CTRLGSET _SFR_MEM8(0x084B)
+#define TCC1_INTFLAGS _SFR_MEM8(0x084C)
+#define TCC1_TEMP _SFR_MEM8(0x084F)
+#define TCC1_CNT _SFR_MEM16(0x0860)
+#define TCC1_PER _SFR_MEM16(0x0866)
+#define TCC1_CCA _SFR_MEM16(0x0868)
+#define TCC1_CCB _SFR_MEM16(0x086A)
+#define TCC1_PERBUF _SFR_MEM16(0x0876)
+#define TCC1_CCABUF _SFR_MEM16(0x0878)
+#define TCC1_CCBBUF _SFR_MEM16(0x087A)
+
+/* AWEX - Advanced Waveform Extension */
+#define AWEXC_CTRL _SFR_MEM8(0x0880)
+#define AWEXC_FDEMASK _SFR_MEM8(0x0882)
+#define AWEXC_FDCTRL _SFR_MEM8(0x0883)
+#define AWEXC_STATUS _SFR_MEM8(0x0884)
+#define AWEXC_STATUSSET _SFR_MEM8(0x0885)
+#define AWEXC_DTBOTH _SFR_MEM8(0x0886)
+#define AWEXC_DTBOTHBUF _SFR_MEM8(0x0887)
+#define AWEXC_DTLS _SFR_MEM8(0x0888)
+#define AWEXC_DTHS _SFR_MEM8(0x0889)
+#define AWEXC_DTLSBUF _SFR_MEM8(0x088A)
+#define AWEXC_DTHSBUF _SFR_MEM8(0x088B)
+#define AWEXC_OUTOVEN _SFR_MEM8(0x088C)
+
+/* HIRES - High-Resolution Extension */
+#define HIRESC_CTRLA _SFR_MEM8(0x0890)
+
+/* USART - Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTC0_DATA _SFR_MEM8(0x08A0)
+#define USARTC0_STATUS _SFR_MEM8(0x08A1)
+#define USARTC0_CTRLA _SFR_MEM8(0x08A3)
+#define USARTC0_CTRLB _SFR_MEM8(0x08A4)
+#define USARTC0_CTRLC _SFR_MEM8(0x08A5)
+#define USARTC0_BAUDCTRLA _SFR_MEM8(0x08A6)
+#define USARTC0_BAUDCTRLB _SFR_MEM8(0x08A7)
+
+/* USART - Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTC1_DATA _SFR_MEM8(0x08B0)
+#define USARTC1_STATUS _SFR_MEM8(0x08B1)
+#define USARTC1_CTRLA _SFR_MEM8(0x08B3)
+#define USARTC1_CTRLB _SFR_MEM8(0x08B4)
+#define USARTC1_CTRLC _SFR_MEM8(0x08B5)
+#define USARTC1_BAUDCTRLA _SFR_MEM8(0x08B6)
+#define USARTC1_BAUDCTRLB _SFR_MEM8(0x08B7)
+
+/* SPI - Serial Peripheral Interface */
+#define SPIC_CTRL _SFR_MEM8(0x08C0)
+#define SPIC_INTCTRL _SFR_MEM8(0x08C1)
+#define SPIC_STATUS _SFR_MEM8(0x08C2)
+#define SPIC_DATA _SFR_MEM8(0x08C3)
+
+/* IRCOM - IR Communication Module */
+#define IRCOM_CTRL _SFR_MEM8(0x08F8)
+#define IRCOM_TXPLCTRL _SFR_MEM8(0x08F9)
+#define IRCOM_RXPLCTRL _SFR_MEM8(0x08FA)
+
+/* TC0 - 16-bit Timer/Counter 0 */
+#define TCD0_CTRLA _SFR_MEM8(0x0900)
+#define TCD0_CTRLB _SFR_MEM8(0x0901)
+#define TCD0_CTRLC _SFR_MEM8(0x0902)
+#define TCD0_CTRLD _SFR_MEM8(0x0903)
+#define TCD0_CTRLE _SFR_MEM8(0x0904)
+#define TCD0_INTCTRLA _SFR_MEM8(0x0906)
+#define TCD0_INTCTRLB _SFR_MEM8(0x0907)
+#define TCD0_CTRLFCLR _SFR_MEM8(0x0908)
+#define TCD0_CTRLFSET _SFR_MEM8(0x0909)
+#define TCD0_CTRLGCLR _SFR_MEM8(0x090A)
+#define TCD0_CTRLGSET _SFR_MEM8(0x090B)
+#define TCD0_INTFLAGS _SFR_MEM8(0x090C)
+#define TCD0_TEMP _SFR_MEM8(0x090F)
+#define TCD0_CNT _SFR_MEM16(0x0920)
+#define TCD0_PER _SFR_MEM16(0x0926)
+#define TCD0_CCA _SFR_MEM16(0x0928)
+#define TCD0_CCB _SFR_MEM16(0x092A)
+#define TCD0_CCC _SFR_MEM16(0x092C)
+#define TCD0_CCD _SFR_MEM16(0x092E)
+#define TCD0_PERBUF _SFR_MEM16(0x0936)
+#define TCD0_CCABUF _SFR_MEM16(0x0938)
+#define TCD0_CCBBUF _SFR_MEM16(0x093A)
+#define TCD0_CCCBUF _SFR_MEM16(0x093C)
+#define TCD0_CCDBUF _SFR_MEM16(0x093E)
+
+/* TC2 - 16-bit Timer/Counter type 2 */
+#define TCD2_CTRLA _SFR_MEM8(0x0900)
+#define TCD2_CTRLB _SFR_MEM8(0x0901)
+#define TCD2_CTRLC _SFR_MEM8(0x0902)
+#define TCD2_CTRLE _SFR_MEM8(0x0904)
+#define TCD2_INTCTRLA _SFR_MEM8(0x0906)
+#define TCD2_INTCTRLB _SFR_MEM8(0x0907)
+#define TCD2_CTRLF _SFR_MEM8(0x0909)
+#define TCD2_INTFLAGS _SFR_MEM8(0x090C)
+#define TCD2_LCNT _SFR_MEM8(0x0920)
+#define TCD2_HCNT _SFR_MEM8(0x0921)
+#define TCD2_LPER _SFR_MEM8(0x0926)
+#define TCD2_HPER _SFR_MEM8(0x0927)
+#define TCD2_LCMPA _SFR_MEM8(0x0928)
+#define TCD2_HCMPA _SFR_MEM8(0x0929)
+#define TCD2_LCMPB _SFR_MEM8(0x092A)
+#define TCD2_HCMPB _SFR_MEM8(0x092B)
+#define TCD2_LCMPC _SFR_MEM8(0x092C)
+#define TCD2_HCMPC _SFR_MEM8(0x092D)
+#define TCD2_LCMPD _SFR_MEM8(0x092E)
+#define TCD2_HCMPD _SFR_MEM8(0x092F)
+
+/* TC1 - 16-bit Timer/Counter 1 */
+#define TCD1_CTRLA _SFR_MEM8(0x0940)
+#define TCD1_CTRLB _SFR_MEM8(0x0941)
+#define TCD1_CTRLC _SFR_MEM8(0x0942)
+#define TCD1_CTRLD _SFR_MEM8(0x0943)
+#define TCD1_CTRLE _SFR_MEM8(0x0944)
+#define TCD1_INTCTRLA _SFR_MEM8(0x0946)
+#define TCD1_INTCTRLB _SFR_MEM8(0x0947)
+#define TCD1_CTRLFCLR _SFR_MEM8(0x0948)
+#define TCD1_CTRLFSET _SFR_MEM8(0x0949)
+#define TCD1_CTRLGCLR _SFR_MEM8(0x094A)
+#define TCD1_CTRLGSET _SFR_MEM8(0x094B)
+#define TCD1_INTFLAGS _SFR_MEM8(0x094C)
+#define TCD1_TEMP _SFR_MEM8(0x094F)
+#define TCD1_CNT _SFR_MEM16(0x0960)
+#define TCD1_PER _SFR_MEM16(0x0966)
+#define TCD1_CCA _SFR_MEM16(0x0968)
+#define TCD1_CCB _SFR_MEM16(0x096A)
+#define TCD1_PERBUF _SFR_MEM16(0x0976)
+#define TCD1_CCABUF _SFR_MEM16(0x0978)
+#define TCD1_CCBBUF _SFR_MEM16(0x097A)
+
+/* HIRES - High-Resolution Extension */
+#define HIRESD_CTRLA _SFR_MEM8(0x0990)
+
+/* USART - Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTD0_DATA _SFR_MEM8(0x09A0)
+#define USARTD0_STATUS _SFR_MEM8(0x09A1)
+#define USARTD0_CTRLA _SFR_MEM8(0x09A3)
+#define USARTD0_CTRLB _SFR_MEM8(0x09A4)
+#define USARTD0_CTRLC _SFR_MEM8(0x09A5)
+#define USARTD0_BAUDCTRLA _SFR_MEM8(0x09A6)
+#define USARTD0_BAUDCTRLB _SFR_MEM8(0x09A7)
+
+/* USART - Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTD1_DATA _SFR_MEM8(0x09B0)
+#define USARTD1_STATUS _SFR_MEM8(0x09B1)
+#define USARTD1_CTRLA _SFR_MEM8(0x09B3)
+#define USARTD1_CTRLB _SFR_MEM8(0x09B4)
+#define USARTD1_CTRLC _SFR_MEM8(0x09B5)
+#define USARTD1_BAUDCTRLA _SFR_MEM8(0x09B6)
+#define USARTD1_BAUDCTRLB _SFR_MEM8(0x09B7)
+
+/* SPI - Serial Peripheral Interface */
+#define SPID_CTRL _SFR_MEM8(0x09C0)
+#define SPID_INTCTRL _SFR_MEM8(0x09C1)
+#define SPID_STATUS _SFR_MEM8(0x09C2)
+#define SPID_DATA _SFR_MEM8(0x09C3)
+
+/* TC0 - 16-bit Timer/Counter 0 */
+#define TCE0_CTRLA _SFR_MEM8(0x0A00)
+#define TCE0_CTRLB _SFR_MEM8(0x0A01)
+#define TCE0_CTRLC _SFR_MEM8(0x0A02)
+#define TCE0_CTRLD _SFR_MEM8(0x0A03)
+#define TCE0_CTRLE _SFR_MEM8(0x0A04)
+#define TCE0_INTCTRLA _SFR_MEM8(0x0A06)
+#define TCE0_INTCTRLB _SFR_MEM8(0x0A07)
+#define TCE0_CTRLFCLR _SFR_MEM8(0x0A08)
+#define TCE0_CTRLFSET _SFR_MEM8(0x0A09)
+#define TCE0_CTRLGCLR _SFR_MEM8(0x0A0A)
+#define TCE0_CTRLGSET _SFR_MEM8(0x0A0B)
+#define TCE0_INTFLAGS _SFR_MEM8(0x0A0C)
+#define TCE0_TEMP _SFR_MEM8(0x0A0F)
+#define TCE0_CNT _SFR_MEM16(0x0A20)
+#define TCE0_PER _SFR_MEM16(0x0A26)
+#define TCE0_CCA _SFR_MEM16(0x0A28)
+#define TCE0_CCB _SFR_MEM16(0x0A2A)
+#define TCE0_CCC _SFR_MEM16(0x0A2C)
+#define TCE0_CCD _SFR_MEM16(0x0A2E)
+#define TCE0_PERBUF _SFR_MEM16(0x0A36)
+#define TCE0_CCABUF _SFR_MEM16(0x0A38)
+#define TCE0_CCBBUF _SFR_MEM16(0x0A3A)
+#define TCE0_CCCBUF _SFR_MEM16(0x0A3C)
+#define TCE0_CCDBUF _SFR_MEM16(0x0A3E)
+
+/* TC2 - 16-bit Timer/Counter type 2 */
+#define TCE2_CTRLA _SFR_MEM8(0x0A00)
+#define TCE2_CTRLB _SFR_MEM8(0x0A01)
+#define TCE2_CTRLC _SFR_MEM8(0x0A02)
+#define TCE2_CTRLE _SFR_MEM8(0x0A04)
+#define TCE2_INTCTRLA _SFR_MEM8(0x0A06)
+#define TCE2_INTCTRLB _SFR_MEM8(0x0A07)
+#define TCE2_CTRLF _SFR_MEM8(0x0A09)
+#define TCE2_INTFLAGS _SFR_MEM8(0x0A0C)
+#define TCE2_LCNT _SFR_MEM8(0x0A20)
+#define TCE2_HCNT _SFR_MEM8(0x0A21)
+#define TCE2_LPER _SFR_MEM8(0x0A26)
+#define TCE2_HPER _SFR_MEM8(0x0A27)
+#define TCE2_LCMPA _SFR_MEM8(0x0A28)
+#define TCE2_HCMPA _SFR_MEM8(0x0A29)
+#define TCE2_LCMPB _SFR_MEM8(0x0A2A)
+#define TCE2_HCMPB _SFR_MEM8(0x0A2B)
+#define TCE2_LCMPC _SFR_MEM8(0x0A2C)
+#define TCE2_HCMPC _SFR_MEM8(0x0A2D)
+#define TCE2_LCMPD _SFR_MEM8(0x0A2E)
+#define TCE2_HCMPD _SFR_MEM8(0x0A2F)
+
+/* TC1 - 16-bit Timer/Counter 1 */
+#define TCE1_CTRLA _SFR_MEM8(0x0A40)
+#define TCE1_CTRLB _SFR_MEM8(0x0A41)
+#define TCE1_CTRLC _SFR_MEM8(0x0A42)
+#define TCE1_CTRLD _SFR_MEM8(0x0A43)
+#define TCE1_CTRLE _SFR_MEM8(0x0A44)
+#define TCE1_INTCTRLA _SFR_MEM8(0x0A46)
+#define TCE1_INTCTRLB _SFR_MEM8(0x0A47)
+#define TCE1_CTRLFCLR _SFR_MEM8(0x0A48)
+#define TCE1_CTRLFSET _SFR_MEM8(0x0A49)
+#define TCE1_CTRLGCLR _SFR_MEM8(0x0A4A)
+#define TCE1_CTRLGSET _SFR_MEM8(0x0A4B)
+#define TCE1_INTFLAGS _SFR_MEM8(0x0A4C)
+#define TCE1_TEMP _SFR_MEM8(0x0A4F)
+#define TCE1_CNT _SFR_MEM16(0x0A60)
+#define TCE1_PER _SFR_MEM16(0x0A66)
+#define TCE1_CCA _SFR_MEM16(0x0A68)
+#define TCE1_CCB _SFR_MEM16(0x0A6A)
+#define TCE1_PERBUF _SFR_MEM16(0x0A76)
+#define TCE1_CCABUF _SFR_MEM16(0x0A78)
+#define TCE1_CCBBUF _SFR_MEM16(0x0A7A)
+
+/* AWEX - Advanced Waveform Extension */
+#define AWEXE_CTRL _SFR_MEM8(0x0A80)
+#define AWEXE_FDEMASK _SFR_MEM8(0x0A82)
+#define AWEXE_FDCTRL _SFR_MEM8(0x0A83)
+#define AWEXE_STATUS _SFR_MEM8(0x0A84)
+#define AWEXE_STATUSSET _SFR_MEM8(0x0A85)
+#define AWEXE_DTBOTH _SFR_MEM8(0x0A86)
+#define AWEXE_DTBOTHBUF _SFR_MEM8(0x0A87)
+#define AWEXE_DTLS _SFR_MEM8(0x0A88)
+#define AWEXE_DTHS _SFR_MEM8(0x0A89)
+#define AWEXE_DTLSBUF _SFR_MEM8(0x0A8A)
+#define AWEXE_DTHSBUF _SFR_MEM8(0x0A8B)
+#define AWEXE_OUTOVEN _SFR_MEM8(0x0A8C)
+
+/* HIRES - High-Resolution Extension */
+#define HIRESE_CTRLA _SFR_MEM8(0x0A90)
+
+/* USART - Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTE0_DATA _SFR_MEM8(0x0AA0)
+#define USARTE0_STATUS _SFR_MEM8(0x0AA1)
+#define USARTE0_CTRLA _SFR_MEM8(0x0AA3)
+#define USARTE0_CTRLB _SFR_MEM8(0x0AA4)
+#define USARTE0_CTRLC _SFR_MEM8(0x0AA5)
+#define USARTE0_BAUDCTRLA _SFR_MEM8(0x0AA6)
+#define USARTE0_BAUDCTRLB _SFR_MEM8(0x0AA7)
+
+/* USART - Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTE1_DATA _SFR_MEM8(0x0AB0)
+#define USARTE1_STATUS _SFR_MEM8(0x0AB1)
+#define USARTE1_CTRLA _SFR_MEM8(0x0AB3)
+#define USARTE1_CTRLB _SFR_MEM8(0x0AB4)
+#define USARTE1_CTRLC _SFR_MEM8(0x0AB5)
+#define USARTE1_BAUDCTRLA _SFR_MEM8(0x0AB6)
+#define USARTE1_BAUDCTRLB _SFR_MEM8(0x0AB7)
+
+/* SPI - Serial Peripheral Interface */
+#define SPIE_CTRL _SFR_MEM8(0x0AC0)
+#define SPIE_INTCTRL _SFR_MEM8(0x0AC1)
+#define SPIE_STATUS _SFR_MEM8(0x0AC2)
+#define SPIE_DATA _SFR_MEM8(0x0AC3)
+
+/* TC0 - 16-bit Timer/Counter 0 */
+#define TCF0_CTRLA _SFR_MEM8(0x0B00)
+#define TCF0_CTRLB _SFR_MEM8(0x0B01)
+#define TCF0_CTRLC _SFR_MEM8(0x0B02)
+#define TCF0_CTRLD _SFR_MEM8(0x0B03)
+#define TCF0_CTRLE _SFR_MEM8(0x0B04)
+#define TCF0_INTCTRLA _SFR_MEM8(0x0B06)
+#define TCF0_INTCTRLB _SFR_MEM8(0x0B07)
+#define TCF0_CTRLFCLR _SFR_MEM8(0x0B08)
+#define TCF0_CTRLFSET _SFR_MEM8(0x0B09)
+#define TCF0_CTRLGCLR _SFR_MEM8(0x0B0A)
+#define TCF0_CTRLGSET _SFR_MEM8(0x0B0B)
+#define TCF0_INTFLAGS _SFR_MEM8(0x0B0C)
+#define TCF0_TEMP _SFR_MEM8(0x0B0F)
+#define TCF0_CNT _SFR_MEM16(0x0B20)
+#define TCF0_PER _SFR_MEM16(0x0B26)
+#define TCF0_CCA _SFR_MEM16(0x0B28)
+#define TCF0_CCB _SFR_MEM16(0x0B2A)
+#define TCF0_CCC _SFR_MEM16(0x0B2C)
+#define TCF0_CCD _SFR_MEM16(0x0B2E)
+#define TCF0_PERBUF _SFR_MEM16(0x0B36)
+#define TCF0_CCABUF _SFR_MEM16(0x0B38)
+#define TCF0_CCBBUF _SFR_MEM16(0x0B3A)
+#define TCF0_CCCBUF _SFR_MEM16(0x0B3C)
+#define TCF0_CCDBUF _SFR_MEM16(0x0B3E)
+
+/* TC2 - 16-bit Timer/Counter type 2 */
+#define TCF2_CTRLA _SFR_MEM8(0x0B00)
+#define TCF2_CTRLB _SFR_MEM8(0x0B01)
+#define TCF2_CTRLC _SFR_MEM8(0x0B02)
+#define TCF2_CTRLE _SFR_MEM8(0x0B04)
+#define TCF2_INTCTRLA _SFR_MEM8(0x0B06)
+#define TCF2_INTCTRLB _SFR_MEM8(0x0B07)
+#define TCF2_CTRLF _SFR_MEM8(0x0B09)
+#define TCF2_INTFLAGS _SFR_MEM8(0x0B0C)
+#define TCF2_LCNT _SFR_MEM8(0x0B20)
+#define TCF2_HCNT _SFR_MEM8(0x0B21)
+#define TCF2_LPER _SFR_MEM8(0x0B26)
+#define TCF2_HPER _SFR_MEM8(0x0B27)
+#define TCF2_LCMPA _SFR_MEM8(0x0B28)
+#define TCF2_HCMPA _SFR_MEM8(0x0B29)
+#define TCF2_LCMPB _SFR_MEM8(0x0B2A)
+#define TCF2_HCMPB _SFR_MEM8(0x0B2B)
+#define TCF2_LCMPC _SFR_MEM8(0x0B2C)
+#define TCF2_HCMPC _SFR_MEM8(0x0B2D)
+#define TCF2_LCMPD _SFR_MEM8(0x0B2E)
+#define TCF2_HCMPD _SFR_MEM8(0x0B2F)
+
+/* HIRES - High-Resolution Extension */
+#define HIRESF_CTRLA _SFR_MEM8(0x0B90)
+
+/* USART - Universal Synchronous/Asynchronous Receiver/Transmitter */
+#define USARTF0_DATA _SFR_MEM8(0x0BA0)
+#define USARTF0_STATUS _SFR_MEM8(0x0BA1)
+#define USARTF0_CTRLA _SFR_MEM8(0x0BA3)
+#define USARTF0_CTRLB _SFR_MEM8(0x0BA4)
+#define USARTF0_CTRLC _SFR_MEM8(0x0BA5)
+#define USARTF0_BAUDCTRLA _SFR_MEM8(0x0BA6)
+#define USARTF0_BAUDCTRLB _SFR_MEM8(0x0BA7)
+
+
+
+/*================== Bitfield Definitions ================== */
+
+/* VPORT - Virtual Ports */
+/* VPORT.INTFLAGS bit masks and bit positions */
+#define VPORT_INT1IF_bm 0x02 /* Port Interrupt 1 Flag bit mask. */
+#define VPORT_INT1IF_bp 1 /* Port Interrupt 1 Flag bit position. */
+
+#define VPORT_INT0IF_bm 0x01 /* Port Interrupt 0 Flag bit mask. */
+#define VPORT_INT0IF_bp 0 /* Port Interrupt 0 Flag bit position. */
+
+/* XOCD - On-Chip Debug System */
+/* OCD.OCDR0 bit masks and bit positions */
+#define OCD_OCDRD_gm 0xFF /* OCDR Dirty group mask. */
+#define OCD_OCDRD_gp 0 /* OCDR Dirty group position. */
+#define OCD_OCDRD0_bm (1<<0) /* OCDR Dirty bit 0 mask. */
+#define OCD_OCDRD0_bp 0 /* OCDR Dirty bit 0 position. */
+#define OCD_OCDRD1_bm (1<<1) /* OCDR Dirty bit 1 mask. */
+#define OCD_OCDRD1_bp 1 /* OCDR Dirty bit 1 position. */
+#define OCD_OCDRD2_bm (1<<2) /* OCDR Dirty bit 2 mask. */
+#define OCD_OCDRD2_bp 2 /* OCDR Dirty bit 2 position. */
+#define OCD_OCDRD3_bm (1<<3) /* OCDR Dirty bit 3 mask. */
+#define OCD_OCDRD3_bp 3 /* OCDR Dirty bit 3 position. */
+#define OCD_OCDRD4_bm (1<<4) /* OCDR Dirty bit 4 mask. */
+#define OCD_OCDRD4_bp 4 /* OCDR Dirty bit 4 position. */
+#define OCD_OCDRD5_bm (1<<5) /* OCDR Dirty bit 5 mask. */
+#define OCD_OCDRD5_bp 5 /* OCDR Dirty bit 5 position. */
+#define OCD_OCDRD6_bm (1<<6) /* OCDR Dirty bit 6 mask. */
+#define OCD_OCDRD6_bp 6 /* OCDR Dirty bit 6 position. */
+#define OCD_OCDRD7_bm (1<<7) /* OCDR Dirty bit 7 mask. */
+#define OCD_OCDRD7_bp 7 /* OCDR Dirty bit 7 position. */
+
+/* OCD.OCDR1 bit masks and bit positions */
+/* OCD_OCDRD Predefined. */
+/* OCD_OCDRD Predefined. */
+
+/* CPU - CPU */
+/* CPU.CCP bit masks and bit positions */
+#define CPU_CCP_gm 0xFF /* CCP signature group mask. */
+#define CPU_CCP_gp 0 /* CCP signature group position. */
+#define CPU_CCP0_bm (1<<0) /* CCP signature bit 0 mask. */
+#define CPU_CCP0_bp 0 /* CCP signature bit 0 position. */
+#define CPU_CCP1_bm (1<<1) /* CCP signature bit 1 mask. */
+#define CPU_CCP1_bp 1 /* CCP signature bit 1 position. */
+#define CPU_CCP2_bm (1<<2) /* CCP signature bit 2 mask. */
+#define CPU_CCP2_bp 2 /* CCP signature bit 2 position. */
+#define CPU_CCP3_bm (1<<3) /* CCP signature bit 3 mask. */
+#define CPU_CCP3_bp 3 /* CCP signature bit 3 position. */
+#define CPU_CCP4_bm (1<<4) /* CCP signature bit 4 mask. */
+#define CPU_CCP4_bp 4 /* CCP signature bit 4 position. */
+#define CPU_CCP5_bm (1<<5) /* CCP signature bit 5 mask. */
+#define CPU_CCP5_bp 5 /* CCP signature bit 5 position. */
+#define CPU_CCP6_bm (1<<6) /* CCP signature bit 6 mask. */
+#define CPU_CCP6_bp 6 /* CCP signature bit 6 position. */
+#define CPU_CCP7_bm (1<<7) /* CCP signature bit 7 mask. */
+#define CPU_CCP7_bp 7 /* CCP signature bit 7 position. */
+
+/* CPU.SREG bit masks and bit positions */
+#define CPU_I_bm 0x80 /* Global Interrupt Enable Flag bit mask. */
+#define CPU_I_bp 7 /* Global Interrupt Enable Flag bit position. */
+
+#define CPU_T_bm 0x40 /* Transfer Bit bit mask. */
+#define CPU_T_bp 6 /* Transfer Bit bit position. */
+
+#define CPU_H_bm 0x20 /* Half Carry Flag bit mask. */
+#define CPU_H_bp 5 /* Half Carry Flag bit position. */
+
+#define CPU_S_bm 0x10 /* N Exclusive Or V Flag bit mask. */
+#define CPU_S_bp 4 /* N Exclusive Or V Flag bit position. */
+
+#define CPU_V_bm 0x08 /* Two's Complement Overflow Flag bit mask. */
+#define CPU_V_bp 3 /* Two's Complement Overflow Flag bit position. */
+
+#define CPU_N_bm 0x04 /* Negative Flag bit mask. */
+#define CPU_N_bp 2 /* Negative Flag bit position. */
+
+#define CPU_Z_bm 0x02 /* Zero Flag bit mask. */
+#define CPU_Z_bp 1 /* Zero Flag bit position. */
+
+#define CPU_C_bm 0x01 /* Carry Flag bit mask. */
+#define CPU_C_bp 0 /* Carry Flag bit position. */
+
+/* CLK - Clock System */
+/* CLK.CTRL bit masks and bit positions */
+#define CLK_SCLKSEL_gm 0x07 /* System Clock Selection group mask. */
+#define CLK_SCLKSEL_gp 0 /* System Clock Selection group position. */
+#define CLK_SCLKSEL0_bm (1<<0) /* System Clock Selection bit 0 mask. */
+#define CLK_SCLKSEL0_bp 0 /* System Clock Selection bit 0 position. */
+#define CLK_SCLKSEL1_bm (1<<1) /* System Clock Selection bit 1 mask. */
+#define CLK_SCLKSEL1_bp 1 /* System Clock Selection bit 1 position. */
+#define CLK_SCLKSEL2_bm (1<<2) /* System Clock Selection bit 2 mask. */
+#define CLK_SCLKSEL2_bp 2 /* System Clock Selection bit 2 position. */
+
+/* CLK.PSCTRL bit masks and bit positions */
+#define CLK_PSADIV_gm 0x7C /* Prescaler A Division Factor group mask. */
+#define CLK_PSADIV_gp 2 /* Prescaler A Division Factor group position. */
+#define CLK_PSADIV0_bm (1<<2) /* Prescaler A Division Factor bit 0 mask. */
+#define CLK_PSADIV0_bp 2 /* Prescaler A Division Factor bit 0 position. */
+#define CLK_PSADIV1_bm (1<<3) /* Prescaler A Division Factor bit 1 mask. */
+#define CLK_PSADIV1_bp 3 /* Prescaler A Division Factor bit 1 position. */
+#define CLK_PSADIV2_bm (1<<4) /* Prescaler A Division Factor bit 2 mask. */
+#define CLK_PSADIV2_bp 4 /* Prescaler A Division Factor bit 2 position. */
+#define CLK_PSADIV3_bm (1<<5) /* Prescaler A Division Factor bit 3 mask. */
+#define CLK_PSADIV3_bp 5 /* Prescaler A Division Factor bit 3 position. */
+#define CLK_PSADIV4_bm (1<<6) /* Prescaler A Division Factor bit 4 mask. */
+#define CLK_PSADIV4_bp 6 /* Prescaler A Division Factor bit 4 position. */
+
+#define CLK_PSBCDIV_gm 0x03 /* Prescaler B and C Division factor group mask. */
+#define CLK_PSBCDIV_gp 0 /* Prescaler B and C Division factor group position. */
+#define CLK_PSBCDIV0_bm (1<<0) /* Prescaler B and C Division factor bit 0 mask. */
+#define CLK_PSBCDIV0_bp 0 /* Prescaler B and C Division factor bit 0 position. */
+#define CLK_PSBCDIV1_bm (1<<1) /* Prescaler B and C Division factor bit 1 mask. */
+#define CLK_PSBCDIV1_bp 1 /* Prescaler B and C Division factor bit 1 position. */
+
+/* CLK.LOCK bit masks and bit positions */
+#define CLK_LOCK_bm 0x01 /* Clock System Lock bit mask. */
+#define CLK_LOCK_bp 0 /* Clock System Lock bit position. */
+
+/* CLK.RTCCTRL bit masks and bit positions */
+#define CLK_RTCSRC_gm 0x0E /* Clock Source group mask. */
+#define CLK_RTCSRC_gp 1 /* Clock Source group position. */
+#define CLK_RTCSRC0_bm (1<<1) /* Clock Source bit 0 mask. */
+#define CLK_RTCSRC0_bp 1 /* Clock Source bit 0 position. */
+#define CLK_RTCSRC1_bm (1<<2) /* Clock Source bit 1 mask. */
+#define CLK_RTCSRC1_bp 2 /* Clock Source bit 1 position. */
+#define CLK_RTCSRC2_bm (1<<3) /* Clock Source bit 2 mask. */
+#define CLK_RTCSRC2_bp 3 /* Clock Source bit 2 position. */
+
+#define CLK_RTCEN_bm 0x01 /* Clock Source Enable bit mask. */
+#define CLK_RTCEN_bp 0 /* Clock Source Enable bit position. */
+
+/* CLK.USBCTRL bit masks and bit positions */
+#define CLK_USBPSDIV_gm 0x38 /* Prescaler Division Factor group mask. */
+#define CLK_USBPSDIV_gp 3 /* Prescaler Division Factor group position. */
+#define CLK_USBPSDIV0_bm (1<<3) /* Prescaler Division Factor bit 0 mask. */
+#define CLK_USBPSDIV0_bp 3 /* Prescaler Division Factor bit 0 position. */
+#define CLK_USBPSDIV1_bm (1<<4) /* Prescaler Division Factor bit 1 mask. */
+#define CLK_USBPSDIV1_bp 4 /* Prescaler Division Factor bit 1 position. */
+#define CLK_USBPSDIV2_bm (1<<5) /* Prescaler Division Factor bit 2 mask. */
+#define CLK_USBPSDIV2_bp 5 /* Prescaler Division Factor bit 2 position. */
+
+#define CLK_USBSRC_gm 0x06 /* Clock Source group mask. */
+#define CLK_USBSRC_gp 1 /* Clock Source group position. */
+#define CLK_USBSRC0_bm (1<<1) /* Clock Source bit 0 mask. */
+#define CLK_USBSRC0_bp 1 /* Clock Source bit 0 position. */
+#define CLK_USBSRC1_bm (1<<2) /* Clock Source bit 1 mask. */
+#define CLK_USBSRC1_bp 2 /* Clock Source bit 1 position. */
+
+#define CLK_USBSEN_bm 0x01 /* Clock Source Enable bit mask. */
+#define CLK_USBSEN_bp 0 /* Clock Source Enable bit position. */
+
+/* PR.PRGEN bit masks and bit positions */
+#define PR_USB_bm 0x40 /* USB bit mask. */
+#define PR_USB_bp 6 /* USB bit position. */
+
+#define PR_AES_bm 0x10 /* AES bit mask. */
+#define PR_AES_bp 4 /* AES bit position. */
+
+#define PR_EBI_bm 0x08 /* External Bus Interface bit mask. */
+#define PR_EBI_bp 3 /* External Bus Interface bit position. */
+
+#define PR_RTC_bm 0x04 /* Real-time Counter bit mask. */
+#define PR_RTC_bp 2 /* Real-time Counter bit position. */
+
+#define PR_EVSYS_bm 0x02 /* Event System bit mask. */
+#define PR_EVSYS_bp 1 /* Event System bit position. */
+
+#define PR_DMA_bm 0x01 /* DMA-Controller bit mask. */
+#define PR_DMA_bp 0 /* DMA-Controller bit position. */
+
+/* PR.PRPA bit masks and bit positions */
+#define PR_DAC_bm 0x04 /* Port A DAC bit mask. */
+#define PR_DAC_bp 2 /* Port A DAC bit position. */
+
+#define PR_ADC_bm 0x02 /* Port A ADC bit mask. */
+#define PR_ADC_bp 1 /* Port A ADC bit position. */
+
+#define PR_AC_bm 0x01 /* Port A Analog Comparator bit mask. */
+#define PR_AC_bp 0 /* Port A Analog Comparator bit position. */
+
+/* PR.PRPB bit masks and bit positions */
+/* PR_DAC Predefined. */
+/* PR_DAC Predefined. */
+
+/* PR_ADC Predefined. */
+/* PR_ADC Predefined. */
+
+/* PR_AC Predefined. */
+/* PR_AC Predefined. */
+
+/* PR.PRPC bit masks and bit positions */
+#define PR_TWI_bm 0x40 /* Port C Two-wire Interface bit mask. */
+#define PR_TWI_bp 6 /* Port C Two-wire Interface bit position. */
+
+#define PR_USART1_bm 0x20 /* Port C USART1 bit mask. */
+#define PR_USART1_bp 5 /* Port C USART1 bit position. */
+
+#define PR_USART0_bm 0x10 /* Port C USART0 bit mask. */
+#define PR_USART0_bp 4 /* Port C USART0 bit position. */
+
+#define PR_SPI_bm 0x08 /* Port C SPI bit mask. */
+#define PR_SPI_bp 3 /* Port C SPI bit position. */
+
+#define PR_HIRES_bm 0x04 /* Port C AWEX bit mask. */
+#define PR_HIRES_bp 2 /* Port C AWEX bit position. */
+
+#define PR_TC1_bm 0x02 /* Port C Timer/Counter1 bit mask. */
+#define PR_TC1_bp 1 /* Port C Timer/Counter1 bit position. */
+
+#define PR_TC0_bm 0x01 /* Port C Timer/Counter0 bit mask. */
+#define PR_TC0_bp 0 /* Port C Timer/Counter0 bit position. */
+
+/* PR.PRPD bit masks and bit positions */
+/* PR_TWI Predefined. */
+/* PR_TWI Predefined. */
+
+/* PR_USART1 Predefined. */
+/* PR_USART1 Predefined. */
+
+/* PR_USART0 Predefined. */
+/* PR_USART0 Predefined. */
+
+/* PR_SPI Predefined. */
+/* PR_SPI Predefined. */
+
+/* PR_HIRES Predefined. */
+/* PR_HIRES Predefined. */
+
+/* PR_TC1 Predefined. */
+/* PR_TC1 Predefined. */
+
+/* PR_TC0 Predefined. */
+/* PR_TC0 Predefined. */
+
+/* PR.PRPE bit masks and bit positions */
+/* PR_TWI Predefined. */
+/* PR_TWI Predefined. */
+
+/* PR_USART1 Predefined. */
+/* PR_USART1 Predefined. */
+
+/* PR_USART0 Predefined. */
+/* PR_USART0 Predefined. */
+
+/* PR_SPI Predefined. */
+/* PR_SPI Predefined. */
+
+/* PR_HIRES Predefined. */
+/* PR_HIRES Predefined. */
+
+/* PR_TC1 Predefined. */
+/* PR_TC1 Predefined. */
+
+/* PR_TC0 Predefined. */
+/* PR_TC0 Predefined. */
+
+/* PR.PRPF bit masks and bit positions */
+/* PR_TWI Predefined. */
+/* PR_TWI Predefined. */
+
+/* PR_USART1 Predefined. */
+/* PR_USART1 Predefined. */
+
+/* PR_USART0 Predefined. */
+/* PR_USART0 Predefined. */
+
+/* PR_SPI Predefined. */
+/* PR_SPI Predefined. */
+
+/* PR_HIRES Predefined. */
+/* PR_HIRES Predefined. */
+
+/* PR_TC1 Predefined. */
+/* PR_TC1 Predefined. */
+
+/* PR_TC0 Predefined. */
+/* PR_TC0 Predefined. */
+
+/* SLEEP - Sleep Controller */
+/* SLEEP.CTRL bit masks and bit positions */
+#define SLEEP_SMODE_gm 0x0E /* Sleep Mode group mask. */
+#define SLEEP_SMODE_gp 1 /* Sleep Mode group position. */
+#define SLEEP_SMODE0_bm (1<<1) /* Sleep Mode bit 0 mask. */
+#define SLEEP_SMODE0_bp 1 /* Sleep Mode bit 0 position. */
+#define SLEEP_SMODE1_bm (1<<2) /* Sleep Mode bit 1 mask. */
+#define SLEEP_SMODE1_bp 2 /* Sleep Mode bit 1 position. */
+#define SLEEP_SMODE2_bm (1<<3) /* Sleep Mode bit 2 mask. */
+#define SLEEP_SMODE2_bp 3 /* Sleep Mode bit 2 position. */
+
+#define SLEEP_SEN_bm 0x01 /* Sleep Enable bit mask. */
+#define SLEEP_SEN_bp 0 /* Sleep Enable bit position. */
+
+/* OSC - Oscillator */
+/* OSC.CTRL bit masks and bit positions */
+#define OSC_PLLEN_bm 0x10 /* PLL Enable bit mask. */
+#define OSC_PLLEN_bp 4 /* PLL Enable bit position. */
+
+#define OSC_XOSCEN_bm 0x08 /* External Oscillator Enable bit mask. */
+#define OSC_XOSCEN_bp 3 /* External Oscillator Enable bit position. */
+
+#define OSC_RC32KEN_bm 0x04 /* Internal 32.768 kHz RC Oscillator Enable bit mask. */
+#define OSC_RC32KEN_bp 2 /* Internal 32.768 kHz RC Oscillator Enable bit position. */
+
+#define OSC_RC32MEN_bm 0x02 /* Internal 32 MHz RC Oscillator Enable bit mask. */
+#define OSC_RC32MEN_bp 1 /* Internal 32 MHz RC Oscillator Enable bit position. */
+
+#define OSC_RC2MEN_bm 0x01 /* Internal 2 MHz RC Oscillator Enable bit mask. */
+#define OSC_RC2MEN_bp 0 /* Internal 2 MHz RC Oscillator Enable bit position. */
+
+/* OSC.STATUS bit masks and bit positions */
+#define OSC_PLLRDY_bm 0x10 /* PLL Ready bit mask. */
+#define OSC_PLLRDY_bp 4 /* PLL Ready bit position. */
+
+#define OSC_XOSCRDY_bm 0x08 /* External Oscillator Ready bit mask. */
+#define OSC_XOSCRDY_bp 3 /* External Oscillator Ready bit position. */
+
+#define OSC_RC32KRDY_bm 0x04 /* Internal 32.768 kHz RC Oscillator Ready bit mask. */
+#define OSC_RC32KRDY_bp 2 /* Internal 32.768 kHz RC Oscillator Ready bit position. */
+
+#define OSC_RC32MRDY_bm 0x02 /* Internal 32 MHz RC Oscillator Ready bit mask. */
+#define OSC_RC32MRDY_bp 1 /* Internal 32 MHz RC Oscillator Ready bit position. */
+
+#define OSC_RC2MRDY_bm 0x01 /* Internal 2 MHz RC Oscillator Ready bit mask. */
+#define OSC_RC2MRDY_bp 0 /* Internal 2 MHz RC Oscillator Ready bit position. */
+
+/* OSC.XOSCCTRL bit masks and bit positions */
+#define OSC_FRQRANGE_gm 0xC0 /* Frequency Range group mask. */
+#define OSC_FRQRANGE_gp 6 /* Frequency Range group position. */
+#define OSC_FRQRANGE0_bm (1<<6) /* Frequency Range bit 0 mask. */
+#define OSC_FRQRANGE0_bp 6 /* Frequency Range bit 0 position. */
+#define OSC_FRQRANGE1_bm (1<<7) /* Frequency Range bit 1 mask. */
+#define OSC_FRQRANGE1_bp 7 /* Frequency Range bit 1 position. */
+
+#define OSC_X32KLPM_bm 0x20 /* 32.768 kHz XTAL OSC Low-power Mode bit mask. */
+#define OSC_X32KLPM_bp 5 /* 32.768 kHz XTAL OSC Low-power Mode bit position. */
+
+#define OSC_XOSCPWR_bm 0x10 /* 16 MHz Crystal Oscillator High Power mode bit mask. */
+#define OSC_XOSCPWR_bp 4 /* 16 MHz Crystal Oscillator High Power mode bit position. */
+
+#define OSC_XOSCSEL_gm 0x0F /* External Oscillator Selection and Startup Time group mask. */
+#define OSC_XOSCSEL_gp 0 /* External Oscillator Selection and Startup Time group position. */
+#define OSC_XOSCSEL0_bm (1<<0) /* External Oscillator Selection and Startup Time bit 0 mask. */
+#define OSC_XOSCSEL0_bp 0 /* External Oscillator Selection and Startup Time bit 0 position. */
+#define OSC_XOSCSEL1_bm (1<<1) /* External Oscillator Selection and Startup Time bit 1 mask. */
+#define OSC_XOSCSEL1_bp 1 /* External Oscillator Selection and Startup Time bit 1 position. */
+#define OSC_XOSCSEL2_bm (1<<2) /* External Oscillator Selection and Startup Time bit 2 mask. */
+#define OSC_XOSCSEL2_bp 2 /* External Oscillator Selection and Startup Time bit 2 position. */
+#define OSC_XOSCSEL3_bm (1<<3) /* External Oscillator Selection and Startup Time bit 3 mask. */
+#define OSC_XOSCSEL3_bp 3 /* External Oscillator Selection and Startup Time bit 3 position. */
+
+/* OSC.XOSCFAIL bit masks and bit positions */
+#define OSC_PLLFDIF_bm 0x08 /* PLL Failure Detection Interrupt Flag bit mask. */
+#define OSC_PLLFDIF_bp 3 /* PLL Failure Detection Interrupt Flag bit position. */
+
+#define OSC_PLLFDEN_bm 0x04 /* PLL Failure Detection Enable bit mask. */
+#define OSC_PLLFDEN_bp 2 /* PLL Failure Detection Enable bit position. */
+
+#define OSC_XOSCFDIF_bm 0x02 /* XOSC Failure Detection Interrupt Flag bit mask. */
+#define OSC_XOSCFDIF_bp 1 /* XOSC Failure Detection Interrupt Flag bit position. */
+
+#define OSC_XOSCFDEN_bm 0x01 /* XOSC Failure Detection Enable bit mask. */
+#define OSC_XOSCFDEN_bp 0 /* XOSC Failure Detection Enable bit position. */
+
+/* OSC.PLLCTRL bit masks and bit positions */
+#define OSC_PLLSRC_gm 0xC0 /* Clock Source group mask. */
+#define OSC_PLLSRC_gp 6 /* Clock Source group position. */
+#define OSC_PLLSRC0_bm (1<<6) /* Clock Source bit 0 mask. */
+#define OSC_PLLSRC0_bp 6 /* Clock Source bit 0 position. */
+#define OSC_PLLSRC1_bm (1<<7) /* Clock Source bit 1 mask. */
+#define OSC_PLLSRC1_bp 7 /* Clock Source bit 1 position. */
+
+#define OSC_PLLDIV_bm 0x20 /* Divide by 2 bit mask. */
+#define OSC_PLLDIV_bp 5 /* Divide by 2 bit position. */
+
+#define OSC_PLLFAC_gm 0x1F /* Multiplication Factor group mask. */
+#define OSC_PLLFAC_gp 0 /* Multiplication Factor group position. */
+#define OSC_PLLFAC0_bm (1<<0) /* Multiplication Factor bit 0 mask. */
+#define OSC_PLLFAC0_bp 0 /* Multiplication Factor bit 0 position. */
+#define OSC_PLLFAC1_bm (1<<1) /* Multiplication Factor bit 1 mask. */
+#define OSC_PLLFAC1_bp 1 /* Multiplication Factor bit 1 position. */
+#define OSC_PLLFAC2_bm (1<<2) /* Multiplication Factor bit 2 mask. */
+#define OSC_PLLFAC2_bp 2 /* Multiplication Factor bit 2 position. */
+#define OSC_PLLFAC3_bm (1<<3) /* Multiplication Factor bit 3 mask. */
+#define OSC_PLLFAC3_bp 3 /* Multiplication Factor bit 3 position. */
+#define OSC_PLLFAC4_bm (1<<4) /* Multiplication Factor bit 4 mask. */
+#define OSC_PLLFAC4_bp 4 /* Multiplication Factor bit 4 position. */
+
+/* OSC.DFLLCTRL bit masks and bit positions */
+#define OSC_RC32MCREF_gm 0x06 /* 32 MHz DFLL Calibration Reference group mask. */
+#define OSC_RC32MCREF_gp 1 /* 32 MHz DFLL Calibration Reference group position. */
+#define OSC_RC32MCREF0_bm (1<<1) /* 32 MHz DFLL Calibration Reference bit 0 mask. */
+#define OSC_RC32MCREF0_bp 1 /* 32 MHz DFLL Calibration Reference bit 0 position. */
+#define OSC_RC32MCREF1_bm (1<<2) /* 32 MHz DFLL Calibration Reference bit 1 mask. */
+#define OSC_RC32MCREF1_bp 2 /* 32 MHz DFLL Calibration Reference bit 1 position. */
+
+#define OSC_RC2MCREF_bm 0x01 /* 2 MHz DFLL Calibration Reference bit mask. */
+#define OSC_RC2MCREF_bp 0 /* 2 MHz DFLL Calibration Reference bit position. */
+
+/* DFLL - DFLL */
+/* DFLL.CTRL bit masks and bit positions */
+#define DFLL_ENABLE_bm 0x01 /* DFLL Enable bit mask. */
+#define DFLL_ENABLE_bp 0 /* DFLL Enable bit position. */
+
+/* DFLL.CALA bit masks and bit positions */
+#define DFLL_CALL_gm 0x7F /* DFLL Calibration Value A group mask. */
+#define DFLL_CALL_gp 0 /* DFLL Calibration Value A group position. */
+#define DFLL_CALL0_bm (1<<0) /* DFLL Calibration Value A bit 0 mask. */
+#define DFLL_CALL0_bp 0 /* DFLL Calibration Value A bit 0 position. */
+#define DFLL_CALL1_bm (1<<1) /* DFLL Calibration Value A bit 1 mask. */
+#define DFLL_CALL1_bp 1 /* DFLL Calibration Value A bit 1 position. */
+#define DFLL_CALL2_bm (1<<2) /* DFLL Calibration Value A bit 2 mask. */
+#define DFLL_CALL2_bp 2 /* DFLL Calibration Value A bit 2 position. */
+#define DFLL_CALL3_bm (1<<3) /* DFLL Calibration Value A bit 3 mask. */
+#define DFLL_CALL3_bp 3 /* DFLL Calibration Value A bit 3 position. */
+#define DFLL_CALL4_bm (1<<4) /* DFLL Calibration Value A bit 4 mask. */
+#define DFLL_CALL4_bp 4 /* DFLL Calibration Value A bit 4 position. */
+#define DFLL_CALL5_bm (1<<5) /* DFLL Calibration Value A bit 5 mask. */
+#define DFLL_CALL5_bp 5 /* DFLL Calibration Value A bit 5 position. */
+#define DFLL_CALL6_bm (1<<6) /* DFLL Calibration Value A bit 6 mask. */
+#define DFLL_CALL6_bp 6 /* DFLL Calibration Value A bit 6 position. */
+
+/* DFLL.CALB bit masks and bit positions */
+#define DFLL_CALH_gm 0x3F /* DFLL Calibration Value B group mask. */
+#define DFLL_CALH_gp 0 /* DFLL Calibration Value B group position. */
+#define DFLL_CALH0_bm (1<<0) /* DFLL Calibration Value B bit 0 mask. */
+#define DFLL_CALH0_bp 0 /* DFLL Calibration Value B bit 0 position. */
+#define DFLL_CALH1_bm (1<<1) /* DFLL Calibration Value B bit 1 mask. */
+#define DFLL_CALH1_bp 1 /* DFLL Calibration Value B bit 1 position. */
+#define DFLL_CALH2_bm (1<<2) /* DFLL Calibration Value B bit 2 mask. */
+#define DFLL_CALH2_bp 2 /* DFLL Calibration Value B bit 2 position. */
+#define DFLL_CALH3_bm (1<<3) /* DFLL Calibration Value B bit 3 mask. */
+#define DFLL_CALH3_bp 3 /* DFLL Calibration Value B bit 3 position. */
+#define DFLL_CALH4_bm (1<<4) /* DFLL Calibration Value B bit 4 mask. */
+#define DFLL_CALH4_bp 4 /* DFLL Calibration Value B bit 4 position. */
+#define DFLL_CALH5_bm (1<<5) /* DFLL Calibration Value B bit 5 mask. */
+#define DFLL_CALH5_bp 5 /* DFLL Calibration Value B bit 5 position. */
+
+/* RST - Reset */
+/* RST.STATUS bit masks and bit positions */
+#define RST_SDRF_bm 0x40 /* Spike Detection Reset Flag bit mask. */
+#define RST_SDRF_bp 6 /* Spike Detection Reset Flag bit position. */
+
+#define RST_SRF_bm 0x20 /* Software Reset Flag bit mask. */
+#define RST_SRF_bp 5 /* Software Reset Flag bit position. */
+
+#define RST_PDIRF_bm 0x10 /* Programming and Debug Interface Interface Reset Flag bit mask. */
+#define RST_PDIRF_bp 4 /* Programming and Debug Interface Interface Reset Flag bit position. */
+
+#define RST_WDRF_bm 0x08 /* Watchdog Reset Flag bit mask. */
+#define RST_WDRF_bp 3 /* Watchdog Reset Flag bit position. */
+
+#define RST_BORF_bm 0x04 /* Brown-out Reset Flag bit mask. */
+#define RST_BORF_bp 2 /* Brown-out Reset Flag bit position. */
+
+#define RST_EXTRF_bm 0x02 /* External Reset Flag bit mask. */
+#define RST_EXTRF_bp 1 /* External Reset Flag bit position. */
+
+#define RST_PORF_bm 0x01 /* Power-on Reset Flag bit mask. */
+#define RST_PORF_bp 0 /* Power-on Reset Flag bit position. */
+
+/* RST.CTRL bit masks and bit positions */
+#define RST_SWRST_bm 0x01 /* Software Reset bit mask. */
+#define RST_SWRST_bp 0 /* Software Reset bit position. */
+
+/* WDT - Watch-Dog Timer */
+/* WDT.CTRL bit masks and bit positions */
+#define WDT_PER_gm 0x3C /* Period group mask. */
+#define WDT_PER_gp 2 /* Period group position. */
+#define WDT_PER0_bm (1<<2) /* Period bit 0 mask. */
+#define WDT_PER0_bp 2 /* Period bit 0 position. */
+#define WDT_PER1_bm (1<<3) /* Period bit 1 mask. */
+#define WDT_PER1_bp 3 /* Period bit 1 position. */
+#define WDT_PER2_bm (1<<4) /* Period bit 2 mask. */
+#define WDT_PER2_bp 4 /* Period bit 2 position. */
+#define WDT_PER3_bm (1<<5) /* Period bit 3 mask. */
+#define WDT_PER3_bp 5 /* Period bit 3 position. */
+
+#define WDT_ENABLE_bm 0x02 /* Enable bit mask. */
+#define WDT_ENABLE_bp 1 /* Enable bit position. */
+
+#define WDT_CEN_bm 0x01 /* Change Enable bit mask. */
+#define WDT_CEN_bp 0 /* Change Enable bit position. */
+
+/* WDT.WINCTRL bit masks and bit positions */
+#define WDT_WPER_gm 0x3C /* Windowed Mode Period group mask. */
+#define WDT_WPER_gp 2 /* Windowed Mode Period group position. */
+#define WDT_WPER0_bm (1<<2) /* Windowed Mode Period bit 0 mask. */
+#define WDT_WPER0_bp 2 /* Windowed Mode Period bit 0 position. */
+#define WDT_WPER1_bm (1<<3) /* Windowed Mode Period bit 1 mask. */
+#define WDT_WPER1_bp 3 /* Windowed Mode Period bit 1 position. */
+#define WDT_WPER2_bm (1<<4) /* Windowed Mode Period bit 2 mask. */
+#define WDT_WPER2_bp 4 /* Windowed Mode Period bit 2 position. */
+#define WDT_WPER3_bm (1<<5) /* Windowed Mode Period bit 3 mask. */
+#define WDT_WPER3_bp 5 /* Windowed Mode Period bit 3 position. */
+
+#define WDT_WEN_bm 0x02 /* Windowed Mode Enable bit mask. */
+#define WDT_WEN_bp 1 /* Windowed Mode Enable bit position. */
+
+#define WDT_WCEN_bm 0x01 /* Windowed Mode Change Enable bit mask. */
+#define WDT_WCEN_bp 0 /* Windowed Mode Change Enable bit position. */
+
+/* WDT.STATUS bit masks and bit positions */
+#define WDT_SYNCBUSY_bm 0x01 /* Syncronization busy bit mask. */
+#define WDT_SYNCBUSY_bp 0 /* Syncronization busy bit position. */
+
+/* MCU - MCU Control */
+/* MCU.MCUCR bit masks and bit positions */
+#define MCU_JTAGD_bm 0x01 /* JTAG Disable bit mask. */
+#define MCU_JTAGD_bp 0 /* JTAG Disable bit position. */
+
+/* MCU.ANAINIT bit masks and bit positions */
+#define MCU_STARTUPDLYB_gm 0x0C /* Analog startup delay Port B group mask. */
+#define MCU_STARTUPDLYB_gp 2 /* Analog startup delay Port B group position. */
+#define MCU_STARTUPDLYB0_bm (1<<2) /* Analog startup delay Port B bit 0 mask. */
+#define MCU_STARTUPDLYB0_bp 2 /* Analog startup delay Port B bit 0 position. */
+#define MCU_STARTUPDLYB1_bm (1<<3) /* Analog startup delay Port B bit 1 mask. */
+#define MCU_STARTUPDLYB1_bp 3 /* Analog startup delay Port B bit 1 position. */
+
+#define MCU_STARTUPDLYA_gm 0x03 /* Analog startup delay Port A group mask. */
+#define MCU_STARTUPDLYA_gp 0 /* Analog startup delay Port A group position. */
+#define MCU_STARTUPDLYA0_bm (1<<0) /* Analog startup delay Port A bit 0 mask. */
+#define MCU_STARTUPDLYA0_bp 0 /* Analog startup delay Port A bit 0 position. */
+#define MCU_STARTUPDLYA1_bm (1<<1) /* Analog startup delay Port A bit 1 mask. */
+#define MCU_STARTUPDLYA1_bp 1 /* Analog startup delay Port A bit 1 position. */
+
+/* MCU.EVSYSLOCK bit masks and bit positions */
+#define MCU_EVSYS1LOCK_bm 0x10 /* Event Channel 4-7 Lock bit mask. */
+#define MCU_EVSYS1LOCK_bp 4 /* Event Channel 4-7 Lock bit position. */
+
+#define MCU_EVSYS0LOCK_bm 0x01 /* Event Channel 0-3 Lock bit mask. */
+#define MCU_EVSYS0LOCK_bp 0 /* Event Channel 0-3 Lock bit position. */
+
+/* MCU.AWEXLOCK bit masks and bit positions */
+#define MCU_AWEXFLOCK_bm 0x08 /* AWeX on T/C F0 Lock bit mask. */
+#define MCU_AWEXFLOCK_bp 3 /* AWeX on T/C F0 Lock bit position. */
+
+#define MCU_AWEXELOCK_bm 0x04 /* AWeX on T/C E0 Lock bit mask. */
+#define MCU_AWEXELOCK_bp 2 /* AWeX on T/C E0 Lock bit position. */
+
+#define MCU_AWEXDLOCK_bm 0x02 /* AWeX on T/C D0 Lock bit mask. */
+#define MCU_AWEXDLOCK_bp 1 /* AWeX on T/C D0 Lock bit position. */
+
+#define MCU_AWEXCLOCK_bm 0x01 /* AWeX on T/C C0 Lock bit mask. */
+#define MCU_AWEXCLOCK_bp 0 /* AWeX on T/C C0 Lock bit position. */
+
+/* PMIC - Programmable Multi-level Interrupt Controller */
+/* PMIC.STATUS bit masks and bit positions */
+#define PMIC_NMIEX_bm 0x80 /* Non-maskable Interrupt Executing bit mask. */
+#define PMIC_NMIEX_bp 7 /* Non-maskable Interrupt Executing bit position. */
+
+#define PMIC_HILVLEX_bm 0x04 /* High Level Interrupt Executing bit mask. */
+#define PMIC_HILVLEX_bp 2 /* High Level Interrupt Executing bit position. */
+
+#define PMIC_MEDLVLEX_bm 0x02 /* Medium Level Interrupt Executing bit mask. */
+#define PMIC_MEDLVLEX_bp 1 /* Medium Level Interrupt Executing bit position. */
+
+#define PMIC_LOLVLEX_bm 0x01 /* Low Level Interrupt Executing bit mask. */
+#define PMIC_LOLVLEX_bp 0 /* Low Level Interrupt Executing bit position. */
+
+/* PMIC.INTPRI bit masks and bit positions */
+#define PMIC_INTPRI_gm 0xFF /* Interrupt Priority group mask. */
+#define PMIC_INTPRI_gp 0 /* Interrupt Priority group position. */
+#define PMIC_INTPRI0_bm (1<<0) /* Interrupt Priority bit 0 mask. */
+#define PMIC_INTPRI0_bp 0 /* Interrupt Priority bit 0 position. */
+#define PMIC_INTPRI1_bm (1<<1) /* Interrupt Priority bit 1 mask. */
+#define PMIC_INTPRI1_bp 1 /* Interrupt Priority bit 1 position. */
+#define PMIC_INTPRI2_bm (1<<2) /* Interrupt Priority bit 2 mask. */
+#define PMIC_INTPRI2_bp 2 /* Interrupt Priority bit 2 position. */
+#define PMIC_INTPRI3_bm (1<<3) /* Interrupt Priority bit 3 mask. */
+#define PMIC_INTPRI3_bp 3 /* Interrupt Priority bit 3 position. */
+#define PMIC_INTPRI4_bm (1<<4) /* Interrupt Priority bit 4 mask. */
+#define PMIC_INTPRI4_bp 4 /* Interrupt Priority bit 4 position. */
+#define PMIC_INTPRI5_bm (1<<5) /* Interrupt Priority bit 5 mask. */
+#define PMIC_INTPRI5_bp 5 /* Interrupt Priority bit 5 position. */
+#define PMIC_INTPRI6_bm (1<<6) /* Interrupt Priority bit 6 mask. */
+#define PMIC_INTPRI6_bp 6 /* Interrupt Priority bit 6 position. */
+#define PMIC_INTPRI7_bm (1<<7) /* Interrupt Priority bit 7 mask. */
+#define PMIC_INTPRI7_bp 7 /* Interrupt Priority bit 7 position. */
+
+/* PMIC.CTRL bit masks and bit positions */
+#define PMIC_RREN_bm 0x80 /* Round-Robin Priority Enable bit mask. */
+#define PMIC_RREN_bp 7 /* Round-Robin Priority Enable bit position. */
+
+#define PMIC_IVSEL_bm 0x40 /* Interrupt Vector Select bit mask. */
+#define PMIC_IVSEL_bp 6 /* Interrupt Vector Select bit position. */
+
+#define PMIC_HILVLEN_bm 0x04 /* High Level Enable bit mask. */
+#define PMIC_HILVLEN_bp 2 /* High Level Enable bit position. */
+
+#define PMIC_MEDLVLEN_bm 0x02 /* Medium Level Enable bit mask. */
+#define PMIC_MEDLVLEN_bp 1 /* Medium Level Enable bit position. */
+
+#define PMIC_LOLVLEN_bm 0x01 /* Low Level Enable bit mask. */
+#define PMIC_LOLVLEN_bp 0 /* Low Level Enable bit position. */
+
+/* PORTCFG - Port Configuration */
+/* PORTCFG.VPCTRLA bit masks and bit positions */
+#define PORTCFG_VP1MAP_gm 0xF0 /* Virtual Port 1 Mapping group mask. */
+#define PORTCFG_VP1MAP_gp 4 /* Virtual Port 1 Mapping group position. */
+#define PORTCFG_VP1MAP0_bm (1<<4) /* Virtual Port 1 Mapping bit 0 mask. */
+#define PORTCFG_VP1MAP0_bp 4 /* Virtual Port 1 Mapping bit 0 position. */
+#define PORTCFG_VP1MAP1_bm (1<<5) /* Virtual Port 1 Mapping bit 1 mask. */
+#define PORTCFG_VP1MAP1_bp 5 /* Virtual Port 1 Mapping bit 1 position. */
+#define PORTCFG_VP1MAP2_bm (1<<6) /* Virtual Port 1 Mapping bit 2 mask. */
+#define PORTCFG_VP1MAP2_bp 6 /* Virtual Port 1 Mapping bit 2 position. */
+#define PORTCFG_VP1MAP3_bm (1<<7) /* Virtual Port 1 Mapping bit 3 mask. */
+#define PORTCFG_VP1MAP3_bp 7 /* Virtual Port 1 Mapping bit 3 position. */
+
+#define PORTCFG_VP0MAP_gm 0x0F /* Virtual Port 0 Mapping group mask. */
+#define PORTCFG_VP0MAP_gp 0 /* Virtual Port 0 Mapping group position. */
+#define PORTCFG_VP0MAP0_bm (1<<0) /* Virtual Port 0 Mapping bit 0 mask. */
+#define PORTCFG_VP0MAP0_bp 0 /* Virtual Port 0 Mapping bit 0 position. */
+#define PORTCFG_VP0MAP1_bm (1<<1) /* Virtual Port 0 Mapping bit 1 mask. */
+#define PORTCFG_VP0MAP1_bp 1 /* Virtual Port 0 Mapping bit 1 position. */
+#define PORTCFG_VP0MAP2_bm (1<<2) /* Virtual Port 0 Mapping bit 2 mask. */
+#define PORTCFG_VP0MAP2_bp 2 /* Virtual Port 0 Mapping bit 2 position. */
+#define PORTCFG_VP0MAP3_bm (1<<3) /* Virtual Port 0 Mapping bit 3 mask. */
+#define PORTCFG_VP0MAP3_bp 3 /* Virtual Port 0 Mapping bit 3 position. */
+
+/* PORTCFG.VPCTRLB bit masks and bit positions */
+#define PORTCFG_VP3MAP_gm 0xF0 /* Virtual Port 3 Mapping group mask. */
+#define PORTCFG_VP3MAP_gp 4 /* Virtual Port 3 Mapping group position. */
+#define PORTCFG_VP3MAP0_bm (1<<4) /* Virtual Port 3 Mapping bit 0 mask. */
+#define PORTCFG_VP3MAP0_bp 4 /* Virtual Port 3 Mapping bit 0 position. */
+#define PORTCFG_VP3MAP1_bm (1<<5) /* Virtual Port 3 Mapping bit 1 mask. */
+#define PORTCFG_VP3MAP1_bp 5 /* Virtual Port 3 Mapping bit 1 position. */
+#define PORTCFG_VP3MAP2_bm (1<<6) /* Virtual Port 3 Mapping bit 2 mask. */
+#define PORTCFG_VP3MAP2_bp 6 /* Virtual Port 3 Mapping bit 2 position. */
+#define PORTCFG_VP3MAP3_bm (1<<7) /* Virtual Port 3 Mapping bit 3 mask. */
+#define PORTCFG_VP3MAP3_bp 7 /* Virtual Port 3 Mapping bit 3 position. */
+
+#define PORTCFG_VP2MAP_gm 0x0F /* Virtual Port 2 Mapping group mask. */
+#define PORTCFG_VP2MAP_gp 0 /* Virtual Port 2 Mapping group position. */
+#define PORTCFG_VP2MAP0_bm (1<<0) /* Virtual Port 2 Mapping bit 0 mask. */
+#define PORTCFG_VP2MAP0_bp 0 /* Virtual Port 2 Mapping bit 0 position. */
+#define PORTCFG_VP2MAP1_bm (1<<1) /* Virtual Port 2 Mapping bit 1 mask. */
+#define PORTCFG_VP2MAP1_bp 1 /* Virtual Port 2 Mapping bit 1 position. */
+#define PORTCFG_VP2MAP2_bm (1<<2) /* Virtual Port 2 Mapping bit 2 mask. */
+#define PORTCFG_VP2MAP2_bp 2 /* Virtual Port 2 Mapping bit 2 position. */
+#define PORTCFG_VP2MAP3_bm (1<<3) /* Virtual Port 2 Mapping bit 3 mask. */
+#define PORTCFG_VP2MAP3_bp 3 /* Virtual Port 2 Mapping bit 3 position. */
+
+/* PORTCFG.CLKEVOUT bit masks and bit positions */
+#define PORTCFG_CLKOUT_gm 0x03 /* Peripheral Clock Output Port group mask. */
+#define PORTCFG_CLKOUT_gp 0 /* Peripheral Clock Output Port group position. */
+#define PORTCFG_CLKOUT0_bm (1<<0) /* Peripheral Clock Output Port bit 0 mask. */
+#define PORTCFG_CLKOUT0_bp 0 /* Peripheral Clock Output Port bit 0 position. */
+#define PORTCFG_CLKOUT1_bm (1<<1) /* Peripheral Clock Output Port bit 1 mask. */
+#define PORTCFG_CLKOUT1_bp 1 /* Peripheral Clock Output Port bit 1 position. */
+
+#define PORTCFG_CLKOUTSEL_gm 0x0C /* Peripheral Clock Output Select group mask. */
+#define PORTCFG_CLKOUTSEL_gp 2 /* Peripheral Clock Output Select group position. */
+#define PORTCFG_CLKOUTSEL0_bm (1<<2) /* Peripheral Clock Output Select bit 0 mask. */
+#define PORTCFG_CLKOUTSEL0_bp 2 /* Peripheral Clock Output Select bit 0 position. */
+#define PORTCFG_CLKOUTSEL1_bm (1<<3) /* Peripheral Clock Output Select bit 1 mask. */
+#define PORTCFG_CLKOUTSEL1_bp 3 /* Peripheral Clock Output Select bit 1 position. */
+
+#define PORTCFG_EVOUT_gm 0x30 /* Event Output Port group mask. */
+#define PORTCFG_EVOUT_gp 4 /* Event Output Port group position. */
+#define PORTCFG_EVOUT0_bm (1<<4) /* Event Output Port bit 0 mask. */
+#define PORTCFG_EVOUT0_bp 4 /* Event Output Port bit 0 position. */
+#define PORTCFG_EVOUT1_bm (1<<5) /* Event Output Port bit 1 mask. */
+#define PORTCFG_EVOUT1_bp 5 /* Event Output Port bit 1 position. */
+
+#define PORTCFG_RTCOUT_bm 0x40 /* RTC Clock Output bit mask. */
+#define PORTCFG_RTCOUT_bp 6 /* RTC Clock Output bit position. */
+
+#define PORTCFG_CLKEVPIN_bm 0x80 /* Peripheral Clock and Event Output pin Select bit mask. */
+#define PORTCFG_CLKEVPIN_bp 7 /* Peripheral Clock and Event Output pin Select bit position. */
+
+/* PORTCFG.EBIOUT bit masks and bit positions */
+#define PORTCFG_EBICSOUT_gm 0x03 /* EBI Chip Select Output group mask. */
+#define PORTCFG_EBICSOUT_gp 0 /* EBI Chip Select Output group position. */
+#define PORTCFG_EBICSOUT0_bm (1<<0) /* EBI Chip Select Output bit 0 mask. */
+#define PORTCFG_EBICSOUT0_bp 0 /* EBI Chip Select Output bit 0 position. */
+#define PORTCFG_EBICSOUT1_bm (1<<1) /* EBI Chip Select Output bit 1 mask. */
+#define PORTCFG_EBICSOUT1_bp 1 /* EBI Chip Select Output bit 1 position. */
+
+#define PORTCFG_EBIADROUT_gm 0x0C /* EBI Address Output group mask. */
+#define PORTCFG_EBIADROUT_gp 2 /* EBI Address Output group position. */
+#define PORTCFG_EBIADROUT0_bm (1<<2) /* EBI Address Output bit 0 mask. */
+#define PORTCFG_EBIADROUT0_bp 2 /* EBI Address Output bit 0 position. */
+#define PORTCFG_EBIADROUT1_bm (1<<3) /* EBI Address Output bit 1 mask. */
+#define PORTCFG_EBIADROUT1_bp 3 /* EBI Address Output bit 1 position. */
+
+/* PORTCFG.EVOUTSEL bit masks and bit positions */
+#define PORTCFG_EVOUTSEL_gm 0x07 /* Event Output Select group mask. */
+#define PORTCFG_EVOUTSEL_gp 0 /* Event Output Select group position. */
+#define PORTCFG_EVOUTSEL0_bm (1<<0) /* Event Output Select bit 0 mask. */
+#define PORTCFG_EVOUTSEL0_bp 0 /* Event Output Select bit 0 position. */
+#define PORTCFG_EVOUTSEL1_bm (1<<1) /* Event Output Select bit 1 mask. */
+#define PORTCFG_EVOUTSEL1_bp 1 /* Event Output Select bit 1 position. */
+#define PORTCFG_EVOUTSEL2_bm (1<<2) /* Event Output Select bit 2 mask. */
+#define PORTCFG_EVOUTSEL2_bp 2 /* Event Output Select bit 2 position. */
+
+/* AES - AES Module */
+/* AES.CTRL bit masks and bit positions */
+#define AES_START_bm 0x80 /* Start/Run bit mask. */
+#define AES_START_bp 7 /* Start/Run bit position. */
+
+#define AES_AUTO_bm 0x40 /* Auto Start Trigger bit mask. */
+#define AES_AUTO_bp 6 /* Auto Start Trigger bit position. */
+
+#define AES_RESET_bm 0x20 /* AES Software Reset bit mask. */
+#define AES_RESET_bp 5 /* AES Software Reset bit position. */
+
+#define AES_DECRYPT_bm 0x10 /* Decryption / Direction bit mask. */
+#define AES_DECRYPT_bp 4 /* Decryption / Direction bit position. */
+
+#define AES_XOR_bm 0x04 /* State XOR Load Enable bit mask. */
+#define AES_XOR_bp 2 /* State XOR Load Enable bit position. */
+
+/* AES.STATUS bit masks and bit positions */
+#define AES_ERROR_bm 0x80 /* AES Error bit mask. */
+#define AES_ERROR_bp 7 /* AES Error bit position. */
+
+#define AES_SRIF_bm 0x01 /* State Ready Interrupt Flag bit mask. */
+#define AES_SRIF_bp 0 /* State Ready Interrupt Flag bit position. */
+
+/* AES.INTCTRL bit masks and bit positions */
+#define AES_INTLVL_gm 0x03 /* Interrupt level group mask. */
+#define AES_INTLVL_gp 0 /* Interrupt level group position. */
+#define AES_INTLVL0_bm (1<<0) /* Interrupt level bit 0 mask. */
+#define AES_INTLVL0_bp 0 /* Interrupt level bit 0 position. */
+#define AES_INTLVL1_bm (1<<1) /* Interrupt level bit 1 mask. */
+#define AES_INTLVL1_bp 1 /* Interrupt level bit 1 position. */
+
+/* CRC - Cyclic Redundancy Checker */
+/* CRC.CTRL bit masks and bit positions */
+#define CRC_RESET_gm 0xC0 /* Reset group mask. */
+#define CRC_RESET_gp 6 /* Reset group position. */
+#define CRC_RESET0_bm (1<<6) /* Reset bit 0 mask. */
+#define CRC_RESET0_bp 6 /* Reset bit 0 position. */
+#define CRC_RESET1_bm (1<<7) /* Reset bit 1 mask. */
+#define CRC_RESET1_bp 7 /* Reset bit 1 position. */
+
+#define CRC_CRC32_bm 0x20 /* CRC Mode bit mask. */
+#define CRC_CRC32_bp 5 /* CRC Mode bit position. */
+
+#define CRC_SOURCE_gm 0x0F /* Input Source group mask. */
+#define CRC_SOURCE_gp 0 /* Input Source group position. */
+#define CRC_SOURCE0_bm (1<<0) /* Input Source bit 0 mask. */
+#define CRC_SOURCE0_bp 0 /* Input Source bit 0 position. */
+#define CRC_SOURCE1_bm (1<<1) /* Input Source bit 1 mask. */
+#define CRC_SOURCE1_bp 1 /* Input Source bit 1 position. */
+#define CRC_SOURCE2_bm (1<<2) /* Input Source bit 2 mask. */
+#define CRC_SOURCE2_bp 2 /* Input Source bit 2 position. */
+#define CRC_SOURCE3_bm (1<<3) /* Input Source bit 3 mask. */
+#define CRC_SOURCE3_bp 3 /* Input Source bit 3 position. */
+
+/* CRC.STATUS bit masks and bit positions */
+#define CRC_ZERO_bm 0x02 /* Zero detection bit mask. */
+#define CRC_ZERO_bp 1 /* Zero detection bit position. */
+
+#define CRC_BUSY_bm 0x01 /* Busy bit mask. */
+#define CRC_BUSY_bp 0 /* Busy bit position. */
+
+/* DMA - DMA Controller */
+/* DMA_CH.CTRLA bit masks and bit positions */
+#define DMA_CH_ENABLE_bm 0x80 /* Channel Enable bit mask. */
+#define DMA_CH_ENABLE_bp 7 /* Channel Enable bit position. */
+
+#define DMA_CH_RESET_bm 0x40 /* Channel Software Reset bit mask. */
+#define DMA_CH_RESET_bp 6 /* Channel Software Reset bit position. */
+
+#define DMA_CH_REPEAT_bm 0x20 /* Channel Repeat Mode bit mask. */
+#define DMA_CH_REPEAT_bp 5 /* Channel Repeat Mode bit position. */
+
+#define DMA_CH_TRFREQ_bm 0x10 /* Channel Transfer Request bit mask. */
+#define DMA_CH_TRFREQ_bp 4 /* Channel Transfer Request bit position. */
+
+#define DMA_CH_SINGLE_bm 0x04 /* Channel Single Shot Data Transfer bit mask. */
+#define DMA_CH_SINGLE_bp 2 /* Channel Single Shot Data Transfer bit position. */
+
+#define DMA_CH_BURSTLEN_gm 0x03 /* Channel Transfer Mode group mask. */
+#define DMA_CH_BURSTLEN_gp 0 /* Channel Transfer Mode group position. */
+#define DMA_CH_BURSTLEN0_bm (1<<0) /* Channel Transfer Mode bit 0 mask. */
+#define DMA_CH_BURSTLEN0_bp 0 /* Channel Transfer Mode bit 0 position. */
+#define DMA_CH_BURSTLEN1_bm (1<<1) /* Channel Transfer Mode bit 1 mask. */
+#define DMA_CH_BURSTLEN1_bp 1 /* Channel Transfer Mode bit 1 position. */
+
+/* DMA_CH.CTRLB bit masks and bit positions */
+#define DMA_CH_CHBUSY_bm 0x80 /* Block Transfer Busy bit mask. */
+#define DMA_CH_CHBUSY_bp 7 /* Block Transfer Busy bit position. */
+
+#define DMA_CH_CHPEND_bm 0x40 /* Block Transfer Pending bit mask. */
+#define DMA_CH_CHPEND_bp 6 /* Block Transfer Pending bit position. */
+
+#define DMA_CH_ERRIF_bm 0x20 /* Block Transfer Error Interrupt Flag bit mask. */
+#define DMA_CH_ERRIF_bp 5 /* Block Transfer Error Interrupt Flag bit position. */
+
+#define DMA_CH_TRNIF_bm 0x10 /* Transaction Complete Interrup Flag bit mask. */
+#define DMA_CH_TRNIF_bp 4 /* Transaction Complete Interrup Flag bit position. */
+
+#define DMA_CH_ERRINTLVL_gm 0x0C /* Transfer Error Interrupt Level group mask. */
+#define DMA_CH_ERRINTLVL_gp 2 /* Transfer Error Interrupt Level group position. */
+#define DMA_CH_ERRINTLVL0_bm (1<<2) /* Transfer Error Interrupt Level bit 0 mask. */
+#define DMA_CH_ERRINTLVL0_bp 2 /* Transfer Error Interrupt Level bit 0 position. */
+#define DMA_CH_ERRINTLVL1_bm (1<<3) /* Transfer Error Interrupt Level bit 1 mask. */
+#define DMA_CH_ERRINTLVL1_bp 3 /* Transfer Error Interrupt Level bit 1 position. */
+
+#define DMA_CH_TRNINTLVL_gm 0x03 /* Transaction Complete Interrupt Level group mask. */
+#define DMA_CH_TRNINTLVL_gp 0 /* Transaction Complete Interrupt Level group position. */
+#define DMA_CH_TRNINTLVL0_bm (1<<0) /* Transaction Complete Interrupt Level bit 0 mask. */
+#define DMA_CH_TRNINTLVL0_bp 0 /* Transaction Complete Interrupt Level bit 0 position. */
+#define DMA_CH_TRNINTLVL1_bm (1<<1) /* Transaction Complete Interrupt Level bit 1 mask. */
+#define DMA_CH_TRNINTLVL1_bp 1 /* Transaction Complete Interrupt Level bit 1 position. */
+
+/* DMA_CH.ADDRCTRL bit masks and bit positions */
+#define DMA_CH_SRCRELOAD_gm 0xC0 /* Channel Source Address Reload group mask. */
+#define DMA_CH_SRCRELOAD_gp 6 /* Channel Source Address Reload group position. */
+#define DMA_CH_SRCRELOAD0_bm (1<<6) /* Channel Source Address Reload bit 0 mask. */
+#define DMA_CH_SRCRELOAD0_bp 6 /* Channel Source Address Reload bit 0 position. */
+#define DMA_CH_SRCRELOAD1_bm (1<<7) /* Channel Source Address Reload bit 1 mask. */
+#define DMA_CH_SRCRELOAD1_bp 7 /* Channel Source Address Reload bit 1 position. */
+
+#define DMA_CH_SRCDIR_gm 0x30 /* Channel Source Address Mode group mask. */
+#define DMA_CH_SRCDIR_gp 4 /* Channel Source Address Mode group position. */
+#define DMA_CH_SRCDIR0_bm (1<<4) /* Channel Source Address Mode bit 0 mask. */
+#define DMA_CH_SRCDIR0_bp 4 /* Channel Source Address Mode bit 0 position. */
+#define DMA_CH_SRCDIR1_bm (1<<5) /* Channel Source Address Mode bit 1 mask. */
+#define DMA_CH_SRCDIR1_bp 5 /* Channel Source Address Mode bit 1 position. */
+
+#define DMA_CH_DESTRELOAD_gm 0x0C /* Channel Destination Address Reload group mask. */
+#define DMA_CH_DESTRELOAD_gp 2 /* Channel Destination Address Reload group position. */
+#define DMA_CH_DESTRELOAD0_bm (1<<2) /* Channel Destination Address Reload bit 0 mask. */
+#define DMA_CH_DESTRELOAD0_bp 2 /* Channel Destination Address Reload bit 0 position. */
+#define DMA_CH_DESTRELOAD1_bm (1<<3) /* Channel Destination Address Reload bit 1 mask. */
+#define DMA_CH_DESTRELOAD1_bp 3 /* Channel Destination Address Reload bit 1 position. */
+
+#define DMA_CH_DESTDIR_gm 0x03 /* Channel Destination Address Mode group mask. */
+#define DMA_CH_DESTDIR_gp 0 /* Channel Destination Address Mode group position. */
+#define DMA_CH_DESTDIR0_bm (1<<0) /* Channel Destination Address Mode bit 0 mask. */
+#define DMA_CH_DESTDIR0_bp 0 /* Channel Destination Address Mode bit 0 position. */
+#define DMA_CH_DESTDIR1_bm (1<<1) /* Channel Destination Address Mode bit 1 mask. */
+#define DMA_CH_DESTDIR1_bp 1 /* Channel Destination Address Mode bit 1 position. */
+
+/* DMA_CH.TRIGSRC bit masks and bit positions */
+#define DMA_CH_TRIGSRC_gm 0xFF /* Channel Trigger Source group mask. */
+#define DMA_CH_TRIGSRC_gp 0 /* Channel Trigger Source group position. */
+#define DMA_CH_TRIGSRC0_bm (1<<0) /* Channel Trigger Source bit 0 mask. */
+#define DMA_CH_TRIGSRC0_bp 0 /* Channel Trigger Source bit 0 position. */
+#define DMA_CH_TRIGSRC1_bm (1<<1) /* Channel Trigger Source bit 1 mask. */
+#define DMA_CH_TRIGSRC1_bp 1 /* Channel Trigger Source bit 1 position. */
+#define DMA_CH_TRIGSRC2_bm (1<<2) /* Channel Trigger Source bit 2 mask. */
+#define DMA_CH_TRIGSRC2_bp 2 /* Channel Trigger Source bit 2 position. */
+#define DMA_CH_TRIGSRC3_bm (1<<3) /* Channel Trigger Source bit 3 mask. */
+#define DMA_CH_TRIGSRC3_bp 3 /* Channel Trigger Source bit 3 position. */
+#define DMA_CH_TRIGSRC4_bm (1<<4) /* Channel Trigger Source bit 4 mask. */
+#define DMA_CH_TRIGSRC4_bp 4 /* Channel Trigger Source bit 4 position. */
+#define DMA_CH_TRIGSRC5_bm (1<<5) /* Channel Trigger Source bit 5 mask. */
+#define DMA_CH_TRIGSRC5_bp 5 /* Channel Trigger Source bit 5 position. */
+#define DMA_CH_TRIGSRC6_bm (1<<6) /* Channel Trigger Source bit 6 mask. */
+#define DMA_CH_TRIGSRC6_bp 6 /* Channel Trigger Source bit 6 position. */
+#define DMA_CH_TRIGSRC7_bm (1<<7) /* Channel Trigger Source bit 7 mask. */
+#define DMA_CH_TRIGSRC7_bp 7 /* Channel Trigger Source bit 7 position. */
+
+/* DMA.CTRL bit masks and bit positions */
+#define DMA_ENABLE_bm 0x80 /* Enable bit mask. */
+#define DMA_ENABLE_bp 7 /* Enable bit position. */
+
+#define DMA_RESET_bm 0x40 /* Software Reset bit mask. */
+#define DMA_RESET_bp 6 /* Software Reset bit position. */
+
+#define DMA_DBUFMODE_gm 0x0C /* Double Buffering Mode group mask. */
+#define DMA_DBUFMODE_gp 2 /* Double Buffering Mode group position. */
+#define DMA_DBUFMODE0_bm (1<<2) /* Double Buffering Mode bit 0 mask. */
+#define DMA_DBUFMODE0_bp 2 /* Double Buffering Mode bit 0 position. */
+#define DMA_DBUFMODE1_bm (1<<3) /* Double Buffering Mode bit 1 mask. */
+#define DMA_DBUFMODE1_bp 3 /* Double Buffering Mode bit 1 position. */
+
+#define DMA_PRIMODE_gm 0x03 /* Channel Priority Mode group mask. */
+#define DMA_PRIMODE_gp 0 /* Channel Priority Mode group position. */
+#define DMA_PRIMODE0_bm (1<<0) /* Channel Priority Mode bit 0 mask. */
+#define DMA_PRIMODE0_bp 0 /* Channel Priority Mode bit 0 position. */
+#define DMA_PRIMODE1_bm (1<<1) /* Channel Priority Mode bit 1 mask. */
+#define DMA_PRIMODE1_bp 1 /* Channel Priority Mode bit 1 position. */
+
+/* DMA.INTFLAGS bit masks and bit positions */
+#define DMA_CH3ERRIF_bm 0x80 /* Channel 3 Block Transfer Error Interrupt Flag bit mask. */
+#define DMA_CH3ERRIF_bp 7 /* Channel 3 Block Transfer Error Interrupt Flag bit position. */
+
+#define DMA_CH2ERRIF_bm 0x40 /* Channel 2 Block Transfer Error Interrupt Flag bit mask. */
+#define DMA_CH2ERRIF_bp 6 /* Channel 2 Block Transfer Error Interrupt Flag bit position. */
+
+#define DMA_CH1ERRIF_bm 0x20 /* Channel 1 Block Transfer Error Interrupt Flag bit mask. */
+#define DMA_CH1ERRIF_bp 5 /* Channel 1 Block Transfer Error Interrupt Flag bit position. */
+
+#define DMA_CH0ERRIF_bm 0x10 /* Channel 0 Block Transfer Error Interrupt Flag bit mask. */
+#define DMA_CH0ERRIF_bp 4 /* Channel 0 Block Transfer Error Interrupt Flag bit position. */
+
+#define DMA_CH3TRNIF_bm 0x08 /* Channel 3 Transaction Complete Interrupt Flag bit mask. */
+#define DMA_CH3TRNIF_bp 3 /* Channel 3 Transaction Complete Interrupt Flag bit position. */
+
+#define DMA_CH2TRNIF_bm 0x04 /* Channel 2 Transaction Complete Interrupt Flag bit mask. */
+#define DMA_CH2TRNIF_bp 2 /* Channel 2 Transaction Complete Interrupt Flag bit position. */
+
+#define DMA_CH1TRNIF_bm 0x02 /* Channel 1 Transaction Complete Interrupt Flag bit mask. */
+#define DMA_CH1TRNIF_bp 1 /* Channel 1 Transaction Complete Interrupt Flag bit position. */
+
+#define DMA_CH0TRNIF_bm 0x01 /* Channel 0 Transaction Complete Interrupt Flag bit mask. */
+#define DMA_CH0TRNIF_bp 0 /* Channel 0 Transaction Complete Interrupt Flag bit position. */
+
+/* DMA.STATUS bit masks and bit positions */
+#define DMA_CH3BUSY_bm 0x80 /* Channel 3 Block Transfer Busy bit mask. */
+#define DMA_CH3BUSY_bp 7 /* Channel 3 Block Transfer Busy bit position. */
+
+#define DMA_CH2BUSY_bm 0x40 /* Channel 2 Block Transfer Busy bit mask. */
+#define DMA_CH2BUSY_bp 6 /* Channel 2 Block Transfer Busy bit position. */
+
+#define DMA_CH1BUSY_bm 0x20 /* Channel 1 Block Transfer Busy bit mask. */
+#define DMA_CH1BUSY_bp 5 /* Channel 1 Block Transfer Busy bit position. */
+
+#define DMA_CH0BUSY_bm 0x10 /* Channel 0 Block Transfer Busy bit mask. */
+#define DMA_CH0BUSY_bp 4 /* Channel 0 Block Transfer Busy bit position. */
+
+#define DMA_CH3PEND_bm 0x08 /* Channel 3 Block Transfer Pending bit mask. */
+#define DMA_CH3PEND_bp 3 /* Channel 3 Block Transfer Pending bit position. */
+
+#define DMA_CH2PEND_bm 0x04 /* Channel 2 Block Transfer Pending bit mask. */
+#define DMA_CH2PEND_bp 2 /* Channel 2 Block Transfer Pending bit position. */
+
+#define DMA_CH1PEND_bm 0x02 /* Channel 1 Block Transfer Pending bit mask. */
+#define DMA_CH1PEND_bp 1 /* Channel 1 Block Transfer Pending bit position. */
+
+#define DMA_CH0PEND_bm 0x01 /* Channel 0 Block Transfer Pending bit mask. */
+#define DMA_CH0PEND_bp 0 /* Channel 0 Block Transfer Pending bit position. */
+
+/* EVSYS - Event System */
+/* EVSYS.CH0MUX bit masks and bit positions */
+#define EVSYS_CHMUX_gm 0xFF /* Event Channel 0 Multiplexer group mask. */
+#define EVSYS_CHMUX_gp 0 /* Event Channel 0 Multiplexer group position. */
+#define EVSYS_CHMUX0_bm (1<<0) /* Event Channel 0 Multiplexer bit 0 mask. */
+#define EVSYS_CHMUX0_bp 0 /* Event Channel 0 Multiplexer bit 0 position. */
+#define EVSYS_CHMUX1_bm (1<<1) /* Event Channel 0 Multiplexer bit 1 mask. */
+#define EVSYS_CHMUX1_bp 1 /* Event Channel 0 Multiplexer bit 1 position. */
+#define EVSYS_CHMUX2_bm (1<<2) /* Event Channel 0 Multiplexer bit 2 mask. */
+#define EVSYS_CHMUX2_bp 2 /* Event Channel 0 Multiplexer bit 2 position. */
+#define EVSYS_CHMUX3_bm (1<<3) /* Event Channel 0 Multiplexer bit 3 mask. */
+#define EVSYS_CHMUX3_bp 3 /* Event Channel 0 Multiplexer bit 3 position. */
+#define EVSYS_CHMUX4_bm (1<<4) /* Event Channel 0 Multiplexer bit 4 mask. */
+#define EVSYS_CHMUX4_bp 4 /* Event Channel 0 Multiplexer bit 4 position. */
+#define EVSYS_CHMUX5_bm (1<<5) /* Event Channel 0 Multiplexer bit 5 mask. */
+#define EVSYS_CHMUX5_bp 5 /* Event Channel 0 Multiplexer bit 5 position. */
+#define EVSYS_CHMUX6_bm (1<<6) /* Event Channel 0 Multiplexer bit 6 mask. */
+#define EVSYS_CHMUX6_bp 6 /* Event Channel 0 Multiplexer bit 6 position. */
+#define EVSYS_CHMUX7_bm (1<<7) /* Event Channel 0 Multiplexer bit 7 mask. */
+#define EVSYS_CHMUX7_bp 7 /* Event Channel 0 Multiplexer bit 7 position. */
+
+/* EVSYS.CH1MUX bit masks and bit positions */
+/* EVSYS_CHMUX Predefined. */
+/* EVSYS_CHMUX Predefined. */
+
+/* EVSYS.CH2MUX bit masks and bit positions */
+/* EVSYS_CHMUX Predefined. */
+/* EVSYS_CHMUX Predefined. */
+
+/* EVSYS.CH3MUX bit masks and bit positions */
+/* EVSYS_CHMUX Predefined. */
+/* EVSYS_CHMUX Predefined. */
+
+/* EVSYS.CH4MUX bit masks and bit positions */
+/* EVSYS_CHMUX Predefined. */
+/* EVSYS_CHMUX Predefined. */
+
+/* EVSYS.CH5MUX bit masks and bit positions */
+/* EVSYS_CHMUX Predefined. */
+/* EVSYS_CHMUX Predefined. */
+
+/* EVSYS.CH6MUX bit masks and bit positions */
+/* EVSYS_CHMUX Predefined. */
+/* EVSYS_CHMUX Predefined. */
+
+/* EVSYS.CH7MUX bit masks and bit positions */
+/* EVSYS_CHMUX Predefined. */
+/* EVSYS_CHMUX Predefined. */
+
+/* EVSYS.CH0CTRL bit masks and bit positions */
+#define EVSYS_QDIRM_gm 0x60 /* Quadrature Decoder Index Recognition Mode group mask. */
+#define EVSYS_QDIRM_gp 5 /* Quadrature Decoder Index Recognition Mode group position. */
+#define EVSYS_QDIRM0_bm (1<<5) /* Quadrature Decoder Index Recognition Mode bit 0 mask. */
+#define EVSYS_QDIRM0_bp 5 /* Quadrature Decoder Index Recognition Mode bit 0 position. */
+#define EVSYS_QDIRM1_bm (1<<6) /* Quadrature Decoder Index Recognition Mode bit 1 mask. */
+#define EVSYS_QDIRM1_bp 6 /* Quadrature Decoder Index Recognition Mode bit 1 position. */
+
+#define EVSYS_QDIEN_bm 0x10 /* Quadrature Decoder Index Enable bit mask. */
+#define EVSYS_QDIEN_bp 4 /* Quadrature Decoder Index Enable bit position. */
+
+#define EVSYS_QDEN_bm 0x08 /* Quadrature Decoder Enable bit mask. */
+#define EVSYS_QDEN_bp 3 /* Quadrature Decoder Enable bit position. */
+
+#define EVSYS_DIGFILT_gm 0x07 /* Digital Filter group mask. */
+#define EVSYS_DIGFILT_gp 0 /* Digital Filter group position. */
+#define EVSYS_DIGFILT0_bm (1<<0) /* Digital Filter bit 0 mask. */
+#define EVSYS_DIGFILT0_bp 0 /* Digital Filter bit 0 position. */
+#define EVSYS_DIGFILT1_bm (1<<1) /* Digital Filter bit 1 mask. */
+#define EVSYS_DIGFILT1_bp 1 /* Digital Filter bit 1 position. */
+#define EVSYS_DIGFILT2_bm (1<<2) /* Digital Filter bit 2 mask. */
+#define EVSYS_DIGFILT2_bp 2 /* Digital Filter bit 2 position. */
+
+/* EVSYS.CH1CTRL bit masks and bit positions */
+/* EVSYS_DIGFILT Predefined. */
+/* EVSYS_DIGFILT Predefined. */
+
+/* EVSYS.CH2CTRL bit masks and bit positions */
+/* EVSYS_QDIRM Predefined. */
+/* EVSYS_QDIRM Predefined. */
+
+/* EVSYS_QDIEN Predefined. */
+/* EVSYS_QDIEN Predefined. */
+
+/* EVSYS_QDEN Predefined. */
+/* EVSYS_QDEN Predefined. */
+
+/* EVSYS_DIGFILT Predefined. */
+/* EVSYS_DIGFILT Predefined. */
+
+/* EVSYS.CH3CTRL bit masks and bit positions */
+/* EVSYS_DIGFILT Predefined. */
+/* EVSYS_DIGFILT Predefined. */
+
+/* EVSYS.CH4CTRL bit masks and bit positions */
+/* EVSYS_QDIRM Predefined. */
+/* EVSYS_QDIRM Predefined. */
+
+/* EVSYS_QDIEN Predefined. */
+/* EVSYS_QDIEN Predefined. */
+
+/* EVSYS_QDEN Predefined. */
+/* EVSYS_QDEN Predefined. */
+
+/* EVSYS_DIGFILT Predefined. */
+/* EVSYS_DIGFILT Predefined. */
+
+/* EVSYS.CH5CTRL bit masks and bit positions */
+/* EVSYS_DIGFILT Predefined. */
+/* EVSYS_DIGFILT Predefined. */
+
+/* EVSYS.CH6CTRL bit masks and bit positions */
+/* EVSYS_DIGFILT Predefined. */
+/* EVSYS_DIGFILT Predefined. */
+
+/* EVSYS.CH7CTRL bit masks and bit positions */
+/* EVSYS_DIGFILT Predefined. */
+/* EVSYS_DIGFILT Predefined. */
+
+/* NVM - Non Volatile Memory Controller */
+/* NVM.CMD bit masks and bit positions */
+#define NVM_CMD_gm 0x7F /* Command group mask. */
+#define NVM_CMD_gp 0 /* Command group position. */
+#define NVM_CMD0_bm (1<<0) /* Command bit 0 mask. */
+#define NVM_CMD0_bp 0 /* Command bit 0 position. */
+#define NVM_CMD1_bm (1<<1) /* Command bit 1 mask. */
+#define NVM_CMD1_bp 1 /* Command bit 1 position. */
+#define NVM_CMD2_bm (1<<2) /* Command bit 2 mask. */
+#define NVM_CMD2_bp 2 /* Command bit 2 position. */
+#define NVM_CMD3_bm (1<<3) /* Command bit 3 mask. */
+#define NVM_CMD3_bp 3 /* Command bit 3 position. */
+#define NVM_CMD4_bm (1<<4) /* Command bit 4 mask. */
+#define NVM_CMD4_bp 4 /* Command bit 4 position. */
+#define NVM_CMD5_bm (1<<5) /* Command bit 5 mask. */
+#define NVM_CMD5_bp 5 /* Command bit 5 position. */
+#define NVM_CMD6_bm (1<<6) /* Command bit 6 mask. */
+#define NVM_CMD6_bp 6 /* Command bit 6 position. */
+
+/* NVM.CTRLA bit masks and bit positions */
+#define NVM_CMDEX_bm 0x01 /* Command Execute bit mask. */
+#define NVM_CMDEX_bp 0 /* Command Execute bit position. */
+
+/* NVM.CTRLB bit masks and bit positions */
+#define NVM_EEMAPEN_bm 0x08 /* EEPROM Mapping Enable bit mask. */
+#define NVM_EEMAPEN_bp 3 /* EEPROM Mapping Enable bit position. */
+
+#define NVM_FPRM_bm 0x04 /* Flash Power Reduction Enable bit mask. */
+#define NVM_FPRM_bp 2 /* Flash Power Reduction Enable bit position. */
+
+#define NVM_EPRM_bm 0x02 /* EEPROM Power Reduction Enable bit mask. */
+#define NVM_EPRM_bp 1 /* EEPROM Power Reduction Enable bit position. */
+
+#define NVM_SPMLOCK_bm 0x01 /* SPM Lock bit mask. */
+#define NVM_SPMLOCK_bp 0 /* SPM Lock bit position. */
+
+/* NVM.INTCTRL bit masks and bit positions */
+#define NVM_SPMLVL_gm 0x0C /* SPM Interrupt Level group mask. */
+#define NVM_SPMLVL_gp 2 /* SPM Interrupt Level group position. */
+#define NVM_SPMLVL0_bm (1<<2) /* SPM Interrupt Level bit 0 mask. */
+#define NVM_SPMLVL0_bp 2 /* SPM Interrupt Level bit 0 position. */
+#define NVM_SPMLVL1_bm (1<<3) /* SPM Interrupt Level bit 1 mask. */
+#define NVM_SPMLVL1_bp 3 /* SPM Interrupt Level bit 1 position. */
+
+#define NVM_EELVL_gm 0x03 /* EEPROM Interrupt Level group mask. */
+#define NVM_EELVL_gp 0 /* EEPROM Interrupt Level group position. */
+#define NVM_EELVL0_bm (1<<0) /* EEPROM Interrupt Level bit 0 mask. */
+#define NVM_EELVL0_bp 0 /* EEPROM Interrupt Level bit 0 position. */
+#define NVM_EELVL1_bm (1<<1) /* EEPROM Interrupt Level bit 1 mask. */
+#define NVM_EELVL1_bp 1 /* EEPROM Interrupt Level bit 1 position. */
+
+/* NVM.STATUS bit masks and bit positions */
+#define NVM_NVMBUSY_bm 0x80 /* Non-volatile Memory Busy bit mask. */
+#define NVM_NVMBUSY_bp 7 /* Non-volatile Memory Busy bit position. */
+
+#define NVM_FBUSY_bm 0x40 /* Flash Memory Busy bit mask. */
+#define NVM_FBUSY_bp 6 /* Flash Memory Busy bit position. */
+
+#define NVM_EELOAD_bm 0x02 /* EEPROM Page Buffer Active Loading bit mask. */
+#define NVM_EELOAD_bp 1 /* EEPROM Page Buffer Active Loading bit position. */
+
+#define NVM_FLOAD_bm 0x01 /* Flash Page Buffer Active Loading bit mask. */
+#define NVM_FLOAD_bp 0 /* Flash Page Buffer Active Loading bit position. */
+
+/* NVM.LOCKBITS bit masks and bit positions */
+#define NVM_BLBB_gm 0xC0 /* Boot Lock Bits - Boot Section group mask. */
+#define NVM_BLBB_gp 6 /* Boot Lock Bits - Boot Section group position. */
+#define NVM_BLBB0_bm (1<<6) /* Boot Lock Bits - Boot Section bit 0 mask. */
+#define NVM_BLBB0_bp 6 /* Boot Lock Bits - Boot Section bit 0 position. */
+#define NVM_BLBB1_bm (1<<7) /* Boot Lock Bits - Boot Section bit 1 mask. */
+#define NVM_BLBB1_bp 7 /* Boot Lock Bits - Boot Section bit 1 position. */
+
+#define NVM_BLBA_gm 0x30 /* Boot Lock Bits - Application Section group mask. */
+#define NVM_BLBA_gp 4 /* Boot Lock Bits - Application Section group position. */
+#define NVM_BLBA0_bm (1<<4) /* Boot Lock Bits - Application Section bit 0 mask. */
+#define NVM_BLBA0_bp 4 /* Boot Lock Bits - Application Section bit 0 position. */
+#define NVM_BLBA1_bm (1<<5) /* Boot Lock Bits - Application Section bit 1 mask. */
+#define NVM_BLBA1_bp 5 /* Boot Lock Bits - Application Section bit 1 position. */
+
+#define NVM_BLBAT_gm 0x0C /* Boot Lock Bits - Application Table group mask. */
+#define NVM_BLBAT_gp 2 /* Boot Lock Bits - Application Table group position. */
+#define NVM_BLBAT0_bm (1<<2) /* Boot Lock Bits - Application Table bit 0 mask. */
+#define NVM_BLBAT0_bp 2 /* Boot Lock Bits - Application Table bit 0 position. */
+#define NVM_BLBAT1_bm (1<<3) /* Boot Lock Bits - Application Table bit 1 mask. */
+#define NVM_BLBAT1_bp 3 /* Boot Lock Bits - Application Table bit 1 position. */
+
+#define NVM_LB_gm 0x03 /* Lock Bits group mask. */
+#define NVM_LB_gp 0 /* Lock Bits group position. */
+#define NVM_LB0_bm (1<<0) /* Lock Bits bit 0 mask. */
+#define NVM_LB0_bp 0 /* Lock Bits bit 0 position. */
+#define NVM_LB1_bm (1<<1) /* Lock Bits bit 1 mask. */
+#define NVM_LB1_bp 1 /* Lock Bits bit 1 position. */
+
+/* AC - Analog Comparator */
+/* AC.AC0CTRL bit masks and bit positions */
+#define AC_INTMODE_gm 0xC0 /* Interrupt Mode group mask. */
+#define AC_INTMODE_gp 6 /* Interrupt Mode group position. */
+#define AC_INTMODE0_bm (1<<6) /* Interrupt Mode bit 0 mask. */
+#define AC_INTMODE0_bp 6 /* Interrupt Mode bit 0 position. */
+#define AC_INTMODE1_bm (1<<7) /* Interrupt Mode bit 1 mask. */
+#define AC_INTMODE1_bp 7 /* Interrupt Mode bit 1 position. */
+
+#define AC_INTLVL_gm 0x30 /* Interrupt Level group mask. */
+#define AC_INTLVL_gp 4 /* Interrupt Level group position. */
+#define AC_INTLVL0_bm (1<<4) /* Interrupt Level bit 0 mask. */
+#define AC_INTLVL0_bp 4 /* Interrupt Level bit 0 position. */
+#define AC_INTLVL1_bm (1<<5) /* Interrupt Level bit 1 mask. */
+#define AC_INTLVL1_bp 5 /* Interrupt Level bit 1 position. */
+
+#define AC_HSMODE_bm 0x08 /* High-speed Mode bit mask. */
+#define AC_HSMODE_bp 3 /* High-speed Mode bit position. */
+
+#define AC_HYSMODE_gm 0x06 /* Hysteresis Mode group mask. */
+#define AC_HYSMODE_gp 1 /* Hysteresis Mode group position. */
+#define AC_HYSMODE0_bm (1<<1) /* Hysteresis Mode bit 0 mask. */
+#define AC_HYSMODE0_bp 1 /* Hysteresis Mode bit 0 position. */
+#define AC_HYSMODE1_bm (1<<2) /* Hysteresis Mode bit 1 mask. */
+#define AC_HYSMODE1_bp 2 /* Hysteresis Mode bit 1 position. */
+
+#define AC_ENABLE_bm 0x01 /* Enable bit mask. */
+#define AC_ENABLE_bp 0 /* Enable bit position. */
+
+/* AC.AC1CTRL bit masks and bit positions */
+/* AC_INTMODE Predefined. */
+/* AC_INTMODE Predefined. */
+
+/* AC_INTLVL Predefined. */
+/* AC_INTLVL Predefined. */
+
+/* AC_HSMODE Predefined. */
+/* AC_HSMODE Predefined. */
+
+/* AC_HYSMODE Predefined. */
+/* AC_HYSMODE Predefined. */
+
+/* AC_ENABLE Predefined. */
+/* AC_ENABLE Predefined. */
+
+/* AC.AC0MUXCTRL bit masks and bit positions */
+#define AC_MUXPOS_gm 0x38 /* MUX Positive Input group mask. */
+#define AC_MUXPOS_gp 3 /* MUX Positive Input group position. */
+#define AC_MUXPOS0_bm (1<<3) /* MUX Positive Input bit 0 mask. */
+#define AC_MUXPOS0_bp 3 /* MUX Positive Input bit 0 position. */
+#define AC_MUXPOS1_bm (1<<4) /* MUX Positive Input bit 1 mask. */
+#define AC_MUXPOS1_bp 4 /* MUX Positive Input bit 1 position. */
+#define AC_MUXPOS2_bm (1<<5) /* MUX Positive Input bit 2 mask. */
+#define AC_MUXPOS2_bp 5 /* MUX Positive Input bit 2 position. */
+
+#define AC_MUXNEG_gm 0x07 /* MUX Negative Input group mask. */
+#define AC_MUXNEG_gp 0 /* MUX Negative Input group position. */
+#define AC_MUXNEG0_bm (1<<0) /* MUX Negative Input bit 0 mask. */
+#define AC_MUXNEG0_bp 0 /* MUX Negative Input bit 0 position. */
+#define AC_MUXNEG1_bm (1<<1) /* MUX Negative Input bit 1 mask. */
+#define AC_MUXNEG1_bp 1 /* MUX Negative Input bit 1 position. */
+#define AC_MUXNEG2_bm (1<<2) /* MUX Negative Input bit 2 mask. */
+#define AC_MUXNEG2_bp 2 /* MUX Negative Input bit 2 position. */
+
+/* AC.AC1MUXCTRL bit masks and bit positions */
+/* AC_MUXPOS Predefined. */
+/* AC_MUXPOS Predefined. */
+
+/* AC_MUXNEG Predefined. */
+/* AC_MUXNEG Predefined. */
+
+/* AC.CTRLA bit masks and bit positions */
+#define AC_AC1OUT_bm 0x02 /* Analog Comparator 1 Output Enable bit mask. */
+#define AC_AC1OUT_bp 1 /* Analog Comparator 1 Output Enable bit position. */
+
+#define AC_AC0OUT_bm 0x01 /* Analog Comparator 0 Output Enable bit mask. */
+#define AC_AC0OUT_bp 0 /* Analog Comparator 0 Output Enable bit position. */
+
+/* AC.CTRLB bit masks and bit positions */
+#define AC_SCALEFAC_gm 0x3F /* VCC Voltage Scaler Factor group mask. */
+#define AC_SCALEFAC_gp 0 /* VCC Voltage Scaler Factor group position. */
+#define AC_SCALEFAC0_bm (1<<0) /* VCC Voltage Scaler Factor bit 0 mask. */
+#define AC_SCALEFAC0_bp 0 /* VCC Voltage Scaler Factor bit 0 position. */
+#define AC_SCALEFAC1_bm (1<<1) /* VCC Voltage Scaler Factor bit 1 mask. */
+#define AC_SCALEFAC1_bp 1 /* VCC Voltage Scaler Factor bit 1 position. */
+#define AC_SCALEFAC2_bm (1<<2) /* VCC Voltage Scaler Factor bit 2 mask. */
+#define AC_SCALEFAC2_bp 2 /* VCC Voltage Scaler Factor bit 2 position. */
+#define AC_SCALEFAC3_bm (1<<3) /* VCC Voltage Scaler Factor bit 3 mask. */
+#define AC_SCALEFAC3_bp 3 /* VCC Voltage Scaler Factor bit 3 position. */
+#define AC_SCALEFAC4_bm (1<<4) /* VCC Voltage Scaler Factor bit 4 mask. */
+#define AC_SCALEFAC4_bp 4 /* VCC Voltage Scaler Factor bit 4 position. */
+#define AC_SCALEFAC5_bm (1<<5) /* VCC Voltage Scaler Factor bit 5 mask. */
+#define AC_SCALEFAC5_bp 5 /* VCC Voltage Scaler Factor bit 5 position. */
+
+/* AC.WINCTRL bit masks and bit positions */
+#define AC_WEN_bm 0x10 /* Window Mode Enable bit mask. */
+#define AC_WEN_bp 4 /* Window Mode Enable bit position. */
+
+#define AC_WINTMODE_gm 0x0C /* Window Interrupt Mode group mask. */
+#define AC_WINTMODE_gp 2 /* Window Interrupt Mode group position. */
+#define AC_WINTMODE0_bm (1<<2) /* Window Interrupt Mode bit 0 mask. */
+#define AC_WINTMODE0_bp 2 /* Window Interrupt Mode bit 0 position. */
+#define AC_WINTMODE1_bm (1<<3) /* Window Interrupt Mode bit 1 mask. */
+#define AC_WINTMODE1_bp 3 /* Window Interrupt Mode bit 1 position. */
+
+#define AC_WINTLVL_gm 0x03 /* Window Interrupt Level group mask. */
+#define AC_WINTLVL_gp 0 /* Window Interrupt Level group position. */
+#define AC_WINTLVL0_bm (1<<0) /* Window Interrupt Level bit 0 mask. */
+#define AC_WINTLVL0_bp 0 /* Window Interrupt Level bit 0 position. */
+#define AC_WINTLVL1_bm (1<<1) /* Window Interrupt Level bit 1 mask. */
+#define AC_WINTLVL1_bp 1 /* Window Interrupt Level bit 1 position. */
+
+/* AC.STATUS bit masks and bit positions */
+#define AC_WSTATE_gm 0xC0 /* Window Mode State group mask. */
+#define AC_WSTATE_gp 6 /* Window Mode State group position. */
+#define AC_WSTATE0_bm (1<<6) /* Window Mode State bit 0 mask. */
+#define AC_WSTATE0_bp 6 /* Window Mode State bit 0 position. */
+#define AC_WSTATE1_bm (1<<7) /* Window Mode State bit 1 mask. */
+#define AC_WSTATE1_bp 7 /* Window Mode State bit 1 position. */
+
+#define AC_AC1STATE_bm 0x20 /* Analog Comparator 1 State bit mask. */
+#define AC_AC1STATE_bp 5 /* Analog Comparator 1 State bit position. */
+
+#define AC_AC0STATE_bm 0x10 /* Analog Comparator 0 State bit mask. */
+#define AC_AC0STATE_bp 4 /* Analog Comparator 0 State bit position. */
+
+#define AC_WIF_bm 0x04 /* Window Mode Interrupt Flag bit mask. */
+#define AC_WIF_bp 2 /* Window Mode Interrupt Flag bit position. */
+
+#define AC_AC1IF_bm 0x02 /* Analog Comparator 1 Interrupt Flag bit mask. */
+#define AC_AC1IF_bp 1 /* Analog Comparator 1 Interrupt Flag bit position. */
+
+#define AC_AC0IF_bm 0x01 /* Analog Comparator 0 Interrupt Flag bit mask. */
+#define AC_AC0IF_bp 0 /* Analog Comparator 0 Interrupt Flag bit position. */
+
+/* ADC - Analog/Digital Converter */
+/* ADC_CH.CTRL bit masks and bit positions */
+#define ADC_CH_START_bm 0x80 /* Channel Start Conversion bit mask. */
+#define ADC_CH_START_bp 7 /* Channel Start Conversion bit position. */
+
+#define ADC_CH_GAIN_gm 0x1C /* Gain Factor group mask. */
+#define ADC_CH_GAIN_gp 2 /* Gain Factor group position. */
+#define ADC_CH_GAIN0_bm (1<<2) /* Gain Factor bit 0 mask. */
+#define ADC_CH_GAIN0_bp 2 /* Gain Factor bit 0 position. */
+#define ADC_CH_GAIN1_bm (1<<3) /* Gain Factor bit 1 mask. */
+#define ADC_CH_GAIN1_bp 3 /* Gain Factor bit 1 position. */
+#define ADC_CH_GAIN2_bm (1<<4) /* Gain Factor bit 2 mask. */
+#define ADC_CH_GAIN2_bp 4 /* Gain Factor bit 2 position. */
+
+#define ADC_CH_INPUTMODE_gm 0x03 /* Input Mode Select group mask. */
+#define ADC_CH_INPUTMODE_gp 0 /* Input Mode Select group position. */
+#define ADC_CH_INPUTMODE0_bm (1<<0) /* Input Mode Select bit 0 mask. */
+#define ADC_CH_INPUTMODE0_bp 0 /* Input Mode Select bit 0 position. */
+#define ADC_CH_INPUTMODE1_bm (1<<1) /* Input Mode Select bit 1 mask. */
+#define ADC_CH_INPUTMODE1_bp 1 /* Input Mode Select bit 1 position. */
+
+/* ADC_CH.MUXCTRL bit masks and bit positions */
+#define ADC_CH_MUXPOS_gm 0x78 /* MUX selection on Positive ADC input group mask. */
+#define ADC_CH_MUXPOS_gp 3 /* MUX selection on Positive ADC input group position. */
+#define ADC_CH_MUXPOS0_bm (1<<3) /* MUX selection on Positive ADC input bit 0 mask. */
+#define ADC_CH_MUXPOS0_bp 3 /* MUX selection on Positive ADC input bit 0 position. */
+#define ADC_CH_MUXPOS1_bm (1<<4) /* MUX selection on Positive ADC input bit 1 mask. */
+#define ADC_CH_MUXPOS1_bp 4 /* MUX selection on Positive ADC input bit 1 position. */
+#define ADC_CH_MUXPOS2_bm (1<<5) /* MUX selection on Positive ADC input bit 2 mask. */
+#define ADC_CH_MUXPOS2_bp 5 /* MUX selection on Positive ADC input bit 2 position. */
+#define ADC_CH_MUXPOS3_bm (1<<6) /* MUX selection on Positive ADC input bit 3 mask. */
+#define ADC_CH_MUXPOS3_bp 6 /* MUX selection on Positive ADC input bit 3 position. */
+
+#define ADC_CH_MUXINT_gm 0x78 /* MUX selection on Internal ADC input group mask. */
+#define ADC_CH_MUXINT_gp 3 /* MUX selection on Internal ADC input group position. */
+#define ADC_CH_MUXINT0_bm (1<<3) /* MUX selection on Internal ADC input bit 0 mask. */
+#define ADC_CH_MUXINT0_bp 3 /* MUX selection on Internal ADC input bit 0 position. */
+#define ADC_CH_MUXINT1_bm (1<<4) /* MUX selection on Internal ADC input bit 1 mask. */
+#define ADC_CH_MUXINT1_bp 4 /* MUX selection on Internal ADC input bit 1 position. */
+#define ADC_CH_MUXINT2_bm (1<<5) /* MUX selection on Internal ADC input bit 2 mask. */
+#define ADC_CH_MUXINT2_bp 5 /* MUX selection on Internal ADC input bit 2 position. */
+#define ADC_CH_MUXINT3_bm (1<<6) /* MUX selection on Internal ADC input bit 3 mask. */
+#define ADC_CH_MUXINT3_bp 6 /* MUX selection on Internal ADC input bit 3 position. */
+
+#define ADC_CH_MUXNEG_gm 0x07 /* MUX selection on Negative ADC input group mask. */
+#define ADC_CH_MUXNEG_gp 0 /* MUX selection on Negative ADC input group position. */
+#define ADC_CH_MUXNEG0_bm (1<<0) /* MUX selection on Negative ADC input bit 0 mask. */
+#define ADC_CH_MUXNEG0_bp 0 /* MUX selection on Negative ADC input bit 0 position. */
+#define ADC_CH_MUXNEG1_bm (1<<1) /* MUX selection on Negative ADC input bit 1 mask. */
+#define ADC_CH_MUXNEG1_bp 1 /* MUX selection on Negative ADC input bit 1 position. */
+#define ADC_CH_MUXNEG2_bm (1<<2) /* MUX selection on Negative ADC input bit 2 mask. */
+#define ADC_CH_MUXNEG2_bp 2 /* MUX selection on Negative ADC input bit 2 position. */
+
+/* ADC_CH.INTCTRL bit masks and bit positions */
+#define ADC_CH_INTMODE_gm 0x0C /* Interrupt Mode group mask. */
+#define ADC_CH_INTMODE_gp 2 /* Interrupt Mode group position. */
+#define ADC_CH_INTMODE0_bm (1<<2) /* Interrupt Mode bit 0 mask. */
+#define ADC_CH_INTMODE0_bp 2 /* Interrupt Mode bit 0 position. */
+#define ADC_CH_INTMODE1_bm (1<<3) /* Interrupt Mode bit 1 mask. */
+#define ADC_CH_INTMODE1_bp 3 /* Interrupt Mode bit 1 position. */
+
+#define ADC_CH_INTLVL_gm 0x03 /* Interrupt Level group mask. */
+#define ADC_CH_INTLVL_gp 0 /* Interrupt Level group position. */
+#define ADC_CH_INTLVL0_bm (1<<0) /* Interrupt Level bit 0 mask. */
+#define ADC_CH_INTLVL0_bp 0 /* Interrupt Level bit 0 position. */
+#define ADC_CH_INTLVL1_bm (1<<1) /* Interrupt Level bit 1 mask. */
+#define ADC_CH_INTLVL1_bp 1 /* Interrupt Level bit 1 position. */
+
+/* ADC_CH.INTFLAGS bit masks and bit positions */
+#define ADC_CH_CHIF_bm 0x01 /* Channel Interrupt Flag bit mask. */
+#define ADC_CH_CHIF_bp 0 /* Channel Interrupt Flag bit position. */
+
+/* ADC_CH.SCAN bit masks and bit positions */
+#define ADC_CH_OFFSET_gm 0xF0 /* Positive MUX setting offset group mask. */
+#define ADC_CH_OFFSET_gp 4 /* Positive MUX setting offset group position. */
+#define ADC_CH_OFFSET0_bm (1<<4) /* Positive MUX setting offset bit 0 mask. */
+#define ADC_CH_OFFSET0_bp 4 /* Positive MUX setting offset bit 0 position. */
+#define ADC_CH_OFFSET1_bm (1<<5) /* Positive MUX setting offset bit 1 mask. */
+#define ADC_CH_OFFSET1_bp 5 /* Positive MUX setting offset bit 1 position. */
+#define ADC_CH_OFFSET2_bm (1<<6) /* Positive MUX setting offset bit 2 mask. */
+#define ADC_CH_OFFSET2_bp 6 /* Positive MUX setting offset bit 2 position. */
+#define ADC_CH_OFFSET3_bm (1<<7) /* Positive MUX setting offset bit 3 mask. */
+#define ADC_CH_OFFSET3_bp 7 /* Positive MUX setting offset bit 3 position. */
+
+#define ADC_CH_SCANNUM_gm 0x0F /* Number of Channels included in scan group mask. */
+#define ADC_CH_SCANNUM_gp 0 /* Number of Channels included in scan group position. */
+#define ADC_CH_SCANNUM0_bm (1<<0) /* Number of Channels included in scan bit 0 mask. */
+#define ADC_CH_SCANNUM0_bp 0 /* Number of Channels included in scan bit 0 position. */
+#define ADC_CH_SCANNUM1_bm (1<<1) /* Number of Channels included in scan bit 1 mask. */
+#define ADC_CH_SCANNUM1_bp 1 /* Number of Channels included in scan bit 1 position. */
+#define ADC_CH_SCANNUM2_bm (1<<2) /* Number of Channels included in scan bit 2 mask. */
+#define ADC_CH_SCANNUM2_bp 2 /* Number of Channels included in scan bit 2 position. */
+#define ADC_CH_SCANNUM3_bm (1<<3) /* Number of Channels included in scan bit 3 mask. */
+#define ADC_CH_SCANNUM3_bp 3 /* Number of Channels included in scan bit 3 position. */
+
+/* ADC.CTRLA bit masks and bit positions */
+#define ADC_DMASEL_gm 0xC0 /* DMA Selection group mask. */
+#define ADC_DMASEL_gp 6 /* DMA Selection group position. */
+#define ADC_DMASEL0_bm (1<<6) /* DMA Selection bit 0 mask. */
+#define ADC_DMASEL0_bp 6 /* DMA Selection bit 0 position. */
+#define ADC_DMASEL1_bm (1<<7) /* DMA Selection bit 1 mask. */
+#define ADC_DMASEL1_bp 7 /* DMA Selection bit 1 position. */
+
+#define ADC_CH3START_bm 0x20 /* Channel 3 Start Conversion bit mask. */
+#define ADC_CH3START_bp 5 /* Channel 3 Start Conversion bit position. */
+
+#define ADC_CH2START_bm 0x10 /* Channel 2 Start Conversion bit mask. */
+#define ADC_CH2START_bp 4 /* Channel 2 Start Conversion bit position. */
+
+#define ADC_CH1START_bm 0x08 /* Channel 1 Start Conversion bit mask. */
+#define ADC_CH1START_bp 3 /* Channel 1 Start Conversion bit position. */
+
+#define ADC_CH0START_bm 0x04 /* Channel 0 Start Conversion bit mask. */
+#define ADC_CH0START_bp 2 /* Channel 0 Start Conversion bit position. */
+
+#define ADC_FLUSH_bm 0x02 /* Flush Pipeline bit mask. */
+#define ADC_FLUSH_bp 1 /* Flush Pipeline bit position. */
+
+#define ADC_ENABLE_bm 0x01 /* Enable ADC bit mask. */
+#define ADC_ENABLE_bp 0 /* Enable ADC bit position. */
+
+/* ADC.CTRLB bit masks and bit positions */
+#define ADC_IMPMODE_bm 0x80 /* Gain Stage Impedance Mode bit mask. */
+#define ADC_IMPMODE_bp 7 /* Gain Stage Impedance Mode bit position. */
+
+#define ADC_CURRLIMIT_gm 0x60 /* Current Limitation group mask. */
+#define ADC_CURRLIMIT_gp 5 /* Current Limitation group position. */
+#define ADC_CURRLIMIT0_bm (1<<5) /* Current Limitation bit 0 mask. */
+#define ADC_CURRLIMIT0_bp 5 /* Current Limitation bit 0 position. */
+#define ADC_CURRLIMIT1_bm (1<<6) /* Current Limitation bit 1 mask. */
+#define ADC_CURRLIMIT1_bp 6 /* Current Limitation bit 1 position. */
+
+#define ADC_CONMODE_bm 0x10 /* Conversion Mode bit mask. */
+#define ADC_CONMODE_bp 4 /* Conversion Mode bit position. */
+
+#define ADC_FREERUN_bm 0x08 /* Free Running Mode Enable bit mask. */
+#define ADC_FREERUN_bp 3 /* Free Running Mode Enable bit position. */
+
+#define ADC_RESOLUTION_gm 0x06 /* Result Resolution group mask. */
+#define ADC_RESOLUTION_gp 1 /* Result Resolution group position. */
+#define ADC_RESOLUTION0_bm (1<<1) /* Result Resolution bit 0 mask. */
+#define ADC_RESOLUTION0_bp 1 /* Result Resolution bit 0 position. */
+#define ADC_RESOLUTION1_bm (1<<2) /* Result Resolution bit 1 mask. */
+#define ADC_RESOLUTION1_bp 2 /* Result Resolution bit 1 position. */
+
+/* ADC.REFCTRL bit masks and bit positions */
+#define ADC_REFSEL_gm 0x70 /* Reference Selection group mask. */
+#define ADC_REFSEL_gp 4 /* Reference Selection group position. */
+#define ADC_REFSEL0_bm (1<<4) /* Reference Selection bit 0 mask. */
+#define ADC_REFSEL0_bp 4 /* Reference Selection bit 0 position. */
+#define ADC_REFSEL1_bm (1<<5) /* Reference Selection bit 1 mask. */
+#define ADC_REFSEL1_bp 5 /* Reference Selection bit 1 position. */
+#define ADC_REFSEL2_bm (1<<6) /* Reference Selection bit 2 mask. */
+#define ADC_REFSEL2_bp 6 /* Reference Selection bit 2 position. */
+
+#define ADC_BANDGAP_bm 0x02 /* Bandgap enable bit mask. */
+#define ADC_BANDGAP_bp 1 /* Bandgap enable bit position. */
+
+#define ADC_TEMPREF_bm 0x01 /* Temperature Reference Enable bit mask. */
+#define ADC_TEMPREF_bp 0 /* Temperature Reference Enable bit position. */
+
+/* ADC.EVCTRL bit masks and bit positions */
+#define ADC_SWEEP_gm 0xC0 /* Channel Sweep Selection group mask. */
+#define ADC_SWEEP_gp 6 /* Channel Sweep Selection group position. */
+#define ADC_SWEEP0_bm (1<<6) /* Channel Sweep Selection bit 0 mask. */
+#define ADC_SWEEP0_bp 6 /* Channel Sweep Selection bit 0 position. */
+#define ADC_SWEEP1_bm (1<<7) /* Channel Sweep Selection bit 1 mask. */
+#define ADC_SWEEP1_bp 7 /* Channel Sweep Selection bit 1 position. */
+
+#define ADC_EVSEL_gm 0x38 /* Event Input Select group mask. */
+#define ADC_EVSEL_gp 3 /* Event Input Select group position. */
+#define ADC_EVSEL0_bm (1<<3) /* Event Input Select bit 0 mask. */
+#define ADC_EVSEL0_bp 3 /* Event Input Select bit 0 position. */
+#define ADC_EVSEL1_bm (1<<4) /* Event Input Select bit 1 mask. */
+#define ADC_EVSEL1_bp 4 /* Event Input Select bit 1 position. */
+#define ADC_EVSEL2_bm (1<<5) /* Event Input Select bit 2 mask. */
+#define ADC_EVSEL2_bp 5 /* Event Input Select bit 2 position. */
+
+#define ADC_EVACT_gm 0x07 /* Event Action Select group mask. */
+#define ADC_EVACT_gp 0 /* Event Action Select group position. */
+#define ADC_EVACT0_bm (1<<0) /* Event Action Select bit 0 mask. */
+#define ADC_EVACT0_bp 0 /* Event Action Select bit 0 position. */
+#define ADC_EVACT1_bm (1<<1) /* Event Action Select bit 1 mask. */
+#define ADC_EVACT1_bp 1 /* Event Action Select bit 1 position. */
+#define ADC_EVACT2_bm (1<<2) /* Event Action Select bit 2 mask. */
+#define ADC_EVACT2_bp 2 /* Event Action Select bit 2 position. */
+
+/* ADC.PRESCALER bit masks and bit positions */
+#define ADC_PRESCALER_gm 0x07 /* Clock Prescaler Selection group mask. */
+#define ADC_PRESCALER_gp 0 /* Clock Prescaler Selection group position. */
+#define ADC_PRESCALER0_bm (1<<0) /* Clock Prescaler Selection bit 0 mask. */
+#define ADC_PRESCALER0_bp 0 /* Clock Prescaler Selection bit 0 position. */
+#define ADC_PRESCALER1_bm (1<<1) /* Clock Prescaler Selection bit 1 mask. */
+#define ADC_PRESCALER1_bp 1 /* Clock Prescaler Selection bit 1 position. */
+#define ADC_PRESCALER2_bm (1<<2) /* Clock Prescaler Selection bit 2 mask. */
+#define ADC_PRESCALER2_bp 2 /* Clock Prescaler Selection bit 2 position. */
+
+/* ADC.INTFLAGS bit masks and bit positions */
+#define ADC_CH3IF_bm 0x08 /* Channel 3 Interrupt Flag bit mask. */
+#define ADC_CH3IF_bp 3 /* Channel 3 Interrupt Flag bit position. */
+
+#define ADC_CH2IF_bm 0x04 /* Channel 2 Interrupt Flag bit mask. */
+#define ADC_CH2IF_bp 2 /* Channel 2 Interrupt Flag bit position. */
+
+#define ADC_CH1IF_bm 0x02 /* Channel 1 Interrupt Flag bit mask. */
+#define ADC_CH1IF_bp 1 /* Channel 1 Interrupt Flag bit position. */
+
+#define ADC_CH0IF_bm 0x01 /* Channel 0 Interrupt Flag bit mask. */
+#define ADC_CH0IF_bp 0 /* Channel 0 Interrupt Flag bit position. */
+
+/* DAC - Digital/Analog Converter */
+/* DAC.CTRLA bit masks and bit positions */
+#define DAC_IDOEN_bm 0x10 /* Internal Output Enable bit mask. */
+#define DAC_IDOEN_bp 4 /* Internal Output Enable bit position. */
+
+#define DAC_CH1EN_bm 0x08 /* Channel 1 Output Enable bit mask. */
+#define DAC_CH1EN_bp 3 /* Channel 1 Output Enable bit position. */
+
+#define DAC_CH0EN_bm 0x04 /* Channel 0 Output Enable bit mask. */
+#define DAC_CH0EN_bp 2 /* Channel 0 Output Enable bit position. */
+
+#define DAC_LPMODE_bm 0x02 /* Low Power Mode bit mask. */
+#define DAC_LPMODE_bp 1 /* Low Power Mode bit position. */
+
+#define DAC_ENABLE_bm 0x01 /* Enable bit mask. */
+#define DAC_ENABLE_bp 0 /* Enable bit position. */
+
+/* DAC.CTRLB bit masks and bit positions */
+#define DAC_CHSEL_gm 0x60 /* Channel Select group mask. */
+#define DAC_CHSEL_gp 5 /* Channel Select group position. */
+#define DAC_CHSEL0_bm (1<<5) /* Channel Select bit 0 mask. */
+#define DAC_CHSEL0_bp 5 /* Channel Select bit 0 position. */
+#define DAC_CHSEL1_bm (1<<6) /* Channel Select bit 1 mask. */
+#define DAC_CHSEL1_bp 6 /* Channel Select bit 1 position. */
+
+#define DAC_CH1TRIG_bm 0x02 /* Channel 1 Event Trig Enable bit mask. */
+#define DAC_CH1TRIG_bp 1 /* Channel 1 Event Trig Enable bit position. */
+
+#define DAC_CH0TRIG_bm 0x01 /* Channel 0 Event Trig Enable bit mask. */
+#define DAC_CH0TRIG_bp 0 /* Channel 0 Event Trig Enable bit position. */
+
+/* DAC.CTRLC bit masks and bit positions */
+#define DAC_REFSEL_gm 0x18 /* Reference Select group mask. */
+#define DAC_REFSEL_gp 3 /* Reference Select group position. */
+#define DAC_REFSEL0_bm (1<<3) /* Reference Select bit 0 mask. */
+#define DAC_REFSEL0_bp 3 /* Reference Select bit 0 position. */
+#define DAC_REFSEL1_bm (1<<4) /* Reference Select bit 1 mask. */
+#define DAC_REFSEL1_bp 4 /* Reference Select bit 1 position. */
+
+#define DAC_LEFTADJ_bm 0x01 /* Left-adjust Result bit mask. */
+#define DAC_LEFTADJ_bp 0 /* Left-adjust Result bit position. */
+
+/* DAC.EVCTRL bit masks and bit positions */
+#define DAC_EVSPLIT_bm 0x08 /* Separate Event Channel Input for Channel 1 bit mask. */
+#define DAC_EVSPLIT_bp 3 /* Separate Event Channel Input for Channel 1 bit position. */
+
+#define DAC_EVSEL_gm 0x07 /* Event Input Selection group mask. */
+#define DAC_EVSEL_gp 0 /* Event Input Selection group position. */
+#define DAC_EVSEL0_bm (1<<0) /* Event Input Selection bit 0 mask. */
+#define DAC_EVSEL0_bp 0 /* Event Input Selection bit 0 position. */
+#define DAC_EVSEL1_bm (1<<1) /* Event Input Selection bit 1 mask. */
+#define DAC_EVSEL1_bp 1 /* Event Input Selection bit 1 position. */
+#define DAC_EVSEL2_bm (1<<2) /* Event Input Selection bit 2 mask. */
+#define DAC_EVSEL2_bp 2 /* Event Input Selection bit 2 position. */
+
+/* DAC.STATUS bit masks and bit positions */
+#define DAC_CH1DRE_bm 0x02 /* Channel 1 Data Register Empty bit mask. */
+#define DAC_CH1DRE_bp 1 /* Channel 1 Data Register Empty bit position. */
+
+#define DAC_CH0DRE_bm 0x01 /* Channel 0 Data Register Empty bit mask. */
+#define DAC_CH0DRE_bp 0 /* Channel 0 Data Register Empty bit position. */
+
+/* DAC.CH0GAINCAL bit masks and bit positions */
+#define DAC_CH0GAINCAL_gm 0x7F /* Gain Calibration group mask. */
+#define DAC_CH0GAINCAL_gp 0 /* Gain Calibration group position. */
+#define DAC_CH0GAINCAL0_bm (1<<0) /* Gain Calibration bit 0 mask. */
+#define DAC_CH0GAINCAL0_bp 0 /* Gain Calibration bit 0 position. */
+#define DAC_CH0GAINCAL1_bm (1<<1) /* Gain Calibration bit 1 mask. */
+#define DAC_CH0GAINCAL1_bp 1 /* Gain Calibration bit 1 position. */
+#define DAC_CH0GAINCAL2_bm (1<<2) /* Gain Calibration bit 2 mask. */
+#define DAC_CH0GAINCAL2_bp 2 /* Gain Calibration bit 2 position. */
+#define DAC_CH0GAINCAL3_bm (1<<3) /* Gain Calibration bit 3 mask. */
+#define DAC_CH0GAINCAL3_bp 3 /* Gain Calibration bit 3 position. */
+#define DAC_CH0GAINCAL4_bm (1<<4) /* Gain Calibration bit 4 mask. */
+#define DAC_CH0GAINCAL4_bp 4 /* Gain Calibration bit 4 position. */
+#define DAC_CH0GAINCAL5_bm (1<<5) /* Gain Calibration bit 5 mask. */
+#define DAC_CH0GAINCAL5_bp 5 /* Gain Calibration bit 5 position. */
+#define DAC_CH0GAINCAL6_bm (1<<6) /* Gain Calibration bit 6 mask. */
+#define DAC_CH0GAINCAL6_bp 6 /* Gain Calibration bit 6 position. */
+
+/* DAC.CH0OFFSETCAL bit masks and bit positions */
+#define DAC_CH0OFFSETCAL_gm 0x7F /* Offset Calibration group mask. */
+#define DAC_CH0OFFSETCAL_gp 0 /* Offset Calibration group position. */
+#define DAC_CH0OFFSETCAL0_bm (1<<0) /* Offset Calibration bit 0 mask. */
+#define DAC_CH0OFFSETCAL0_bp 0 /* Offset Calibration bit 0 position. */
+#define DAC_CH0OFFSETCAL1_bm (1<<1) /* Offset Calibration bit 1 mask. */
+#define DAC_CH0OFFSETCAL1_bp 1 /* Offset Calibration bit 1 position. */
+#define DAC_CH0OFFSETCAL2_bm (1<<2) /* Offset Calibration bit 2 mask. */
+#define DAC_CH0OFFSETCAL2_bp 2 /* Offset Calibration bit 2 position. */
+#define DAC_CH0OFFSETCAL3_bm (1<<3) /* Offset Calibration bit 3 mask. */
+#define DAC_CH0OFFSETCAL3_bp 3 /* Offset Calibration bit 3 position. */
+#define DAC_CH0OFFSETCAL4_bm (1<<4) /* Offset Calibration bit 4 mask. */
+#define DAC_CH0OFFSETCAL4_bp 4 /* Offset Calibration bit 4 position. */
+#define DAC_CH0OFFSETCAL5_bm (1<<5) /* Offset Calibration bit 5 mask. */
+#define DAC_CH0OFFSETCAL5_bp 5 /* Offset Calibration bit 5 position. */
+#define DAC_CH0OFFSETCAL6_bm (1<<6) /* Offset Calibration bit 6 mask. */
+#define DAC_CH0OFFSETCAL6_bp 6 /* Offset Calibration bit 6 position. */
+
+/* DAC.CH1GAINCAL bit masks and bit positions */
+#define DAC_CH1GAINCAL_gm 0x7F /* Gain Calibration group mask. */
+#define DAC_CH1GAINCAL_gp 0 /* Gain Calibration group position. */
+#define DAC_CH1GAINCAL0_bm (1<<0) /* Gain Calibration bit 0 mask. */
+#define DAC_CH1GAINCAL0_bp 0 /* Gain Calibration bit 0 position. */
+#define DAC_CH1GAINCAL1_bm (1<<1) /* Gain Calibration bit 1 mask. */
+#define DAC_CH1GAINCAL1_bp 1 /* Gain Calibration bit 1 position. */
+#define DAC_CH1GAINCAL2_bm (1<<2) /* Gain Calibration bit 2 mask. */
+#define DAC_CH1GAINCAL2_bp 2 /* Gain Calibration bit 2 position. */
+#define DAC_CH1GAINCAL3_bm (1<<3) /* Gain Calibration bit 3 mask. */
+#define DAC_CH1GAINCAL3_bp 3 /* Gain Calibration bit 3 position. */
+#define DAC_CH1GAINCAL4_bm (1<<4) /* Gain Calibration bit 4 mask. */
+#define DAC_CH1GAINCAL4_bp 4 /* Gain Calibration bit 4 position. */
+#define DAC_CH1GAINCAL5_bm (1<<5) /* Gain Calibration bit 5 mask. */
+#define DAC_CH1GAINCAL5_bp 5 /* Gain Calibration bit 5 position. */
+#define DAC_CH1GAINCAL6_bm (1<<6) /* Gain Calibration bit 6 mask. */
+#define DAC_CH1GAINCAL6_bp 6 /* Gain Calibration bit 6 position. */
+
+/* DAC.CH1OFFSETCAL bit masks and bit positions */
+#define DAC_CH1OFFSETCAL_gm 0x7F /* Offset Calibration group mask. */
+#define DAC_CH1OFFSETCAL_gp 0 /* Offset Calibration group position. */
+#define DAC_CH1OFFSETCAL0_bm (1<<0) /* Offset Calibration bit 0 mask. */
+#define DAC_CH1OFFSETCAL0_bp 0 /* Offset Calibration bit 0 position. */
+#define DAC_CH1OFFSETCAL1_bm (1<<1) /* Offset Calibration bit 1 mask. */
+#define DAC_CH1OFFSETCAL1_bp 1 /* Offset Calibration bit 1 position. */
+#define DAC_CH1OFFSETCAL2_bm (1<<2) /* Offset Calibration bit 2 mask. */
+#define DAC_CH1OFFSETCAL2_bp 2 /* Offset Calibration bit 2 position. */
+#define DAC_CH1OFFSETCAL3_bm (1<<3) /* Offset Calibration bit 3 mask. */
+#define DAC_CH1OFFSETCAL3_bp 3 /* Offset Calibration bit 3 position. */
+#define DAC_CH1OFFSETCAL4_bm (1<<4) /* Offset Calibration bit 4 mask. */
+#define DAC_CH1OFFSETCAL4_bp 4 /* Offset Calibration bit 4 position. */
+#define DAC_CH1OFFSETCAL5_bm (1<<5) /* Offset Calibration bit 5 mask. */
+#define DAC_CH1OFFSETCAL5_bp 5 /* Offset Calibration bit 5 position. */
+#define DAC_CH1OFFSETCAL6_bm (1<<6) /* Offset Calibration bit 6 mask. */
+#define DAC_CH1OFFSETCAL6_bp 6 /* Offset Calibration bit 6 position. */
+
+/* RTC - Real-Time Counter */
+/* RTC.CTRL bit masks and bit positions */
+#define RTC_PRESCALER_gm 0x07 /* Prescaling Factor group mask. */
+#define RTC_PRESCALER_gp 0 /* Prescaling Factor group position. */
+#define RTC_PRESCALER0_bm (1<<0) /* Prescaling Factor bit 0 mask. */
+#define RTC_PRESCALER0_bp 0 /* Prescaling Factor bit 0 position. */
+#define RTC_PRESCALER1_bm (1<<1) /* Prescaling Factor bit 1 mask. */
+#define RTC_PRESCALER1_bp 1 /* Prescaling Factor bit 1 position. */
+#define RTC_PRESCALER2_bm (1<<2) /* Prescaling Factor bit 2 mask. */
+#define RTC_PRESCALER2_bp 2 /* Prescaling Factor bit 2 position. */
+
+/* RTC.STATUS bit masks and bit positions */
+#define RTC_SYNCBUSY_bm 0x01 /* Synchronization Busy Flag bit mask. */
+#define RTC_SYNCBUSY_bp 0 /* Synchronization Busy Flag bit position. */
+
+/* RTC.INTCTRL bit masks and bit positions */
+#define RTC_COMPINTLVL_gm 0x0C /* Compare Match Interrupt Level group mask. */
+#define RTC_COMPINTLVL_gp 2 /* Compare Match Interrupt Level group position. */
+#define RTC_COMPINTLVL0_bm (1<<2) /* Compare Match Interrupt Level bit 0 mask. */
+#define RTC_COMPINTLVL0_bp 2 /* Compare Match Interrupt Level bit 0 position. */
+#define RTC_COMPINTLVL1_bm (1<<3) /* Compare Match Interrupt Level bit 1 mask. */
+#define RTC_COMPINTLVL1_bp 3 /* Compare Match Interrupt Level bit 1 position. */
+
+#define RTC_OVFINTLVL_gm 0x03 /* Overflow Interrupt Level group mask. */
+#define RTC_OVFINTLVL_gp 0 /* Overflow Interrupt Level group position. */
+#define RTC_OVFINTLVL0_bm (1<<0) /* Overflow Interrupt Level bit 0 mask. */
+#define RTC_OVFINTLVL0_bp 0 /* Overflow Interrupt Level bit 0 position. */
+#define RTC_OVFINTLVL1_bm (1<<1) /* Overflow Interrupt Level bit 1 mask. */
+#define RTC_OVFINTLVL1_bp 1 /* Overflow Interrupt Level bit 1 position. */
+
+/* RTC.INTFLAGS bit masks and bit positions */
+#define RTC_COMPIF_bm 0x02 /* Compare Match Interrupt Flag bit mask. */
+#define RTC_COMPIF_bp 1 /* Compare Match Interrupt Flag bit position. */
+
+#define RTC_OVFIF_bm 0x01 /* Overflow Interrupt Flag bit mask. */
+#define RTC_OVFIF_bp 0 /* Overflow Interrupt Flag bit position. */
+
+/* TWI - Two-Wire Interface */
+/* TWI_MASTER.CTRLA bit masks and bit positions */
+#define TWI_MASTER_INTLVL_gm 0xC0 /* Interrupt Level group mask. */
+#define TWI_MASTER_INTLVL_gp 6 /* Interrupt Level group position. */
+#define TWI_MASTER_INTLVL0_bm (1<<6) /* Interrupt Level bit 0 mask. */
+#define TWI_MASTER_INTLVL0_bp 6 /* Interrupt Level bit 0 position. */
+#define TWI_MASTER_INTLVL1_bm (1<<7) /* Interrupt Level bit 1 mask. */
+#define TWI_MASTER_INTLVL1_bp 7 /* Interrupt Level bit 1 position. */
+
+#define TWI_MASTER_RIEN_bm 0x20 /* Read Interrupt Enable bit mask. */
+#define TWI_MASTER_RIEN_bp 5 /* Read Interrupt Enable bit position. */
+
+#define TWI_MASTER_WIEN_bm 0x10 /* Write Interrupt Enable bit mask. */
+#define TWI_MASTER_WIEN_bp 4 /* Write Interrupt Enable bit position. */
+
+#define TWI_MASTER_ENABLE_bm 0x08 /* Enable TWI Master bit mask. */
+#define TWI_MASTER_ENABLE_bp 3 /* Enable TWI Master bit position. */
+
+/* TWI_MASTER.CTRLB bit masks and bit positions */
+#define TWI_MASTER_TIMEOUT_gm 0x0C /* Inactive Bus Timeout group mask. */
+#define TWI_MASTER_TIMEOUT_gp 2 /* Inactive Bus Timeout group position. */
+#define TWI_MASTER_TIMEOUT0_bm (1<<2) /* Inactive Bus Timeout bit 0 mask. */
+#define TWI_MASTER_TIMEOUT0_bp 2 /* Inactive Bus Timeout bit 0 position. */
+#define TWI_MASTER_TIMEOUT1_bm (1<<3) /* Inactive Bus Timeout bit 1 mask. */
+#define TWI_MASTER_TIMEOUT1_bp 3 /* Inactive Bus Timeout bit 1 position. */
+
+#define TWI_MASTER_QCEN_bm 0x02 /* Quick Command Enable bit mask. */
+#define TWI_MASTER_QCEN_bp 1 /* Quick Command Enable bit position. */
+
+#define TWI_MASTER_SMEN_bm 0x01 /* Smart Mode Enable bit mask. */
+#define TWI_MASTER_SMEN_bp 0 /* Smart Mode Enable bit position. */
+
+/* TWI_MASTER.CTRLC bit masks and bit positions */
+#define TWI_MASTER_ACKACT_bm 0x04 /* Acknowledge Action bit mask. */
+#define TWI_MASTER_ACKACT_bp 2 /* Acknowledge Action bit position. */
+
+#define TWI_MASTER_CMD_gm 0x03 /* Command group mask. */
+#define TWI_MASTER_CMD_gp 0 /* Command group position. */
+#define TWI_MASTER_CMD0_bm (1<<0) /* Command bit 0 mask. */
+#define TWI_MASTER_CMD0_bp 0 /* Command bit 0 position. */
+#define TWI_MASTER_CMD1_bm (1<<1) /* Command bit 1 mask. */
+#define TWI_MASTER_CMD1_bp 1 /* Command bit 1 position. */
+
+/* TWI_MASTER.STATUS bit masks and bit positions */
+#define TWI_MASTER_RIF_bm 0x80 /* Read Interrupt Flag bit mask. */
+#define TWI_MASTER_RIF_bp 7 /* Read Interrupt Flag bit position. */
+
+#define TWI_MASTER_WIF_bm 0x40 /* Write Interrupt Flag bit mask. */
+#define TWI_MASTER_WIF_bp 6 /* Write Interrupt Flag bit position. */
+
+#define TWI_MASTER_CLKHOLD_bm 0x20 /* Clock Hold bit mask. */
+#define TWI_MASTER_CLKHOLD_bp 5 /* Clock Hold bit position. */
+
+#define TWI_MASTER_RXACK_bm 0x10 /* Received Acknowledge bit mask. */
+#define TWI_MASTER_RXACK_bp 4 /* Received Acknowledge bit position. */
+
+#define TWI_MASTER_ARBLOST_bm 0x08 /* Arbitration Lost bit mask. */
+#define TWI_MASTER_ARBLOST_bp 3 /* Arbitration Lost bit position. */
+
+#define TWI_MASTER_BUSERR_bm 0x04 /* Bus Error bit mask. */
+#define TWI_MASTER_BUSERR_bp 2 /* Bus Error bit position. */
+
+#define TWI_MASTER_BUSSTATE_gm 0x03 /* Bus State group mask. */
+#define TWI_MASTER_BUSSTATE_gp 0 /* Bus State group position. */
+#define TWI_MASTER_BUSSTATE0_bm (1<<0) /* Bus State bit 0 mask. */
+#define TWI_MASTER_BUSSTATE0_bp 0 /* Bus State bit 0 position. */
+#define TWI_MASTER_BUSSTATE1_bm (1<<1) /* Bus State bit 1 mask. */
+#define TWI_MASTER_BUSSTATE1_bp 1 /* Bus State bit 1 position. */
+
+/* TWI_SLAVE.CTRLA bit masks and bit positions */
+#define TWI_SLAVE_INTLVL_gm 0xC0 /* Interrupt Level group mask. */
+#define TWI_SLAVE_INTLVL_gp 6 /* Interrupt Level group position. */
+#define TWI_SLAVE_INTLVL0_bm (1<<6) /* Interrupt Level bit 0 mask. */
+#define TWI_SLAVE_INTLVL0_bp 6 /* Interrupt Level bit 0 position. */
+#define TWI_SLAVE_INTLVL1_bm (1<<7) /* Interrupt Level bit 1 mask. */
+#define TWI_SLAVE_INTLVL1_bp 7 /* Interrupt Level bit 1 position. */
+
+#define TWI_SLAVE_DIEN_bm 0x20 /* Data Interrupt Enable bit mask. */
+#define TWI_SLAVE_DIEN_bp 5 /* Data Interrupt Enable bit position. */
+
+#define TWI_SLAVE_APIEN_bm 0x10 /* Address/Stop Interrupt Enable bit mask. */
+#define TWI_SLAVE_APIEN_bp 4 /* Address/Stop Interrupt Enable bit position. */
+
+#define TWI_SLAVE_ENABLE_bm 0x08 /* Enable TWI Slave bit mask. */
+#define TWI_SLAVE_ENABLE_bp 3 /* Enable TWI Slave bit position. */
+
+#define TWI_SLAVE_PIEN_bm 0x04 /* Stop Interrupt Enable bit mask. */
+#define TWI_SLAVE_PIEN_bp 2 /* Stop Interrupt Enable bit position. */
+
+#define TWI_SLAVE_PMEN_bm 0x02 /* Promiscuous Mode Enable bit mask. */
+#define TWI_SLAVE_PMEN_bp 1 /* Promiscuous Mode Enable bit position. */
+
+#define TWI_SLAVE_SMEN_bm 0x01 /* Smart Mode Enable bit mask. */
+#define TWI_SLAVE_SMEN_bp 0 /* Smart Mode Enable bit position. */
+
+/* TWI_SLAVE.CTRLB bit masks and bit positions */
+#define TWI_SLAVE_ACKACT_bm 0x04 /* Acknowledge Action bit mask. */
+#define TWI_SLAVE_ACKACT_bp 2 /* Acknowledge Action bit position. */
+
+#define TWI_SLAVE_CMD_gm 0x03 /* Command group mask. */
+#define TWI_SLAVE_CMD_gp 0 /* Command group position. */
+#define TWI_SLAVE_CMD0_bm (1<<0) /* Command bit 0 mask. */
+#define TWI_SLAVE_CMD0_bp 0 /* Command bit 0 position. */
+#define TWI_SLAVE_CMD1_bm (1<<1) /* Command bit 1 mask. */
+#define TWI_SLAVE_CMD1_bp 1 /* Command bit 1 position. */
+
+/* TWI_SLAVE.STATUS bit masks and bit positions */
+#define TWI_SLAVE_DIF_bm 0x80 /* Data Interrupt Flag bit mask. */
+#define TWI_SLAVE_DIF_bp 7 /* Data Interrupt Flag bit position. */
+
+#define TWI_SLAVE_APIF_bm 0x40 /* Address/Stop Interrupt Flag bit mask. */
+#define TWI_SLAVE_APIF_bp 6 /* Address/Stop Interrupt Flag bit position. */
+
+#define TWI_SLAVE_CLKHOLD_bm 0x20 /* Clock Hold bit mask. */
+#define TWI_SLAVE_CLKHOLD_bp 5 /* Clock Hold bit position. */
+
+#define TWI_SLAVE_RXACK_bm 0x10 /* Received Acknowledge bit mask. */
+#define TWI_SLAVE_RXACK_bp 4 /* Received Acknowledge bit position. */
+
+#define TWI_SLAVE_COLL_bm 0x08 /* Collision bit mask. */
+#define TWI_SLAVE_COLL_bp 3 /* Collision bit position. */
+
+#define TWI_SLAVE_BUSERR_bm 0x04 /* Bus Error bit mask. */
+#define TWI_SLAVE_BUSERR_bp 2 /* Bus Error bit position. */
+
+#define TWI_SLAVE_DIR_bm 0x02 /* Read/Write Direction bit mask. */
+#define TWI_SLAVE_DIR_bp 1 /* Read/Write Direction bit position. */
+
+#define TWI_SLAVE_AP_bm 0x01 /* Slave Address or Stop bit mask. */
+#define TWI_SLAVE_AP_bp 0 /* Slave Address or Stop bit position. */
+
+/* TWI_SLAVE.ADDRMASK bit masks and bit positions */
+#define TWI_SLAVE_ADDRMASK_gm 0xFE /* Address Mask group mask. */
+#define TWI_SLAVE_ADDRMASK_gp 1 /* Address Mask group position. */
+#define TWI_SLAVE_ADDRMASK0_bm (1<<1) /* Address Mask bit 0 mask. */
+#define TWI_SLAVE_ADDRMASK0_bp 1 /* Address Mask bit 0 position. */
+#define TWI_SLAVE_ADDRMASK1_bm (1<<2) /* Address Mask bit 1 mask. */
+#define TWI_SLAVE_ADDRMASK1_bp 2 /* Address Mask bit 1 position. */
+#define TWI_SLAVE_ADDRMASK2_bm (1<<3) /* Address Mask bit 2 mask. */
+#define TWI_SLAVE_ADDRMASK2_bp 3 /* Address Mask bit 2 position. */
+#define TWI_SLAVE_ADDRMASK3_bm (1<<4) /* Address Mask bit 3 mask. */
+#define TWI_SLAVE_ADDRMASK3_bp 4 /* Address Mask bit 3 position. */
+#define TWI_SLAVE_ADDRMASK4_bm (1<<5) /* Address Mask bit 4 mask. */
+#define TWI_SLAVE_ADDRMASK4_bp 5 /* Address Mask bit 4 position. */
+#define TWI_SLAVE_ADDRMASK5_bm (1<<6) /* Address Mask bit 5 mask. */
+#define TWI_SLAVE_ADDRMASK5_bp 6 /* Address Mask bit 5 position. */
+#define TWI_SLAVE_ADDRMASK6_bm (1<<7) /* Address Mask bit 6 mask. */
+#define TWI_SLAVE_ADDRMASK6_bp 7 /* Address Mask bit 6 position. */
+
+#define TWI_SLAVE_ADDREN_bm 0x01 /* Address Enable bit mask. */
+#define TWI_SLAVE_ADDREN_bp 0 /* Address Enable bit position. */
+
+/* TWI.CTRL bit masks and bit positions */
+#define TWI_SDAHOLD_gm 0x06 /* SDA Hold Time Enable group mask. */
+#define TWI_SDAHOLD_gp 1 /* SDA Hold Time Enable group position. */
+#define TWI_SDAHOLD0_bm (1<<1) /* SDA Hold Time Enable bit 0 mask. */
+#define TWI_SDAHOLD0_bp 1 /* SDA Hold Time Enable bit 0 position. */
+#define TWI_SDAHOLD1_bm (1<<2) /* SDA Hold Time Enable bit 1 mask. */
+#define TWI_SDAHOLD1_bp 2 /* SDA Hold Time Enable bit 1 position. */
+
+#define TWI_EDIEN_bm 0x01 /* External Driver Interface Enable bit mask. */
+#define TWI_EDIEN_bp 0 /* External Driver Interface Enable bit position. */
+
+/* USB - USB */
+/* USB_EP.STATUS bit masks and bit positions */
+#define USB_EP_STALLF_bm 0x80 /* Endpoint Stall Flag bit mask. */
+#define USB_EP_STALLF_bp 7 /* Endpoint Stall Flag bit position. */
+
+#define USB_EP_CRC_bm 0x80 /* CRC Error Flag bit mask. */
+#define USB_EP_CRC_bp 7 /* CRC Error Flag bit position. */
+
+#define USB_EP_UNF_bm 0x40 /* Underflow Enpoint FLag bit mask. */
+#define USB_EP_UNF_bp 6 /* Underflow Enpoint FLag bit position. */
+
+#define USB_EP_OVF_bm 0x40 /* Overflow Enpoint Flag for Output Endpoints bit mask. */
+#define USB_EP_OVF_bp 6 /* Overflow Enpoint Flag for Output Endpoints bit position. */
+
+#define USB_EP_TRNCOMPL0_bm 0x20 /* Transaction Complete 0 Flag bit mask. */
+#define USB_EP_TRNCOMPL0_bp 5 /* Transaction Complete 0 Flag bit position. */
+
+#define USB_EP_TRNCOMPL1_bm 0x10 /* Transaction Complete 1 Flag bit mask. */
+#define USB_EP_TRNCOMPL1_bp 4 /* Transaction Complete 1 Flag bit position. */
+
+#define USB_EP_SETUP_bm 0x10 /* SETUP Transaction Complete Flag bit mask. */
+#define USB_EP_SETUP_bp 4 /* SETUP Transaction Complete Flag bit position. */
+
+#define USB_EP_BANK_bm 0x08 /* Bank Select bit mask. */
+#define USB_EP_BANK_bp 3 /* Bank Select bit position. */
+
+#define USB_EP_BUSNACK1_bm 0x04 /* Data Buffer 1 Not Acknowledge bit mask. */
+#define USB_EP_BUSNACK1_bp 2 /* Data Buffer 1 Not Acknowledge bit position. */
+
+#define USB_EP_BUSNACK0_bm 0x02 /* Data Buffer 0 Not Acknowledge bit mask. */
+#define USB_EP_BUSNACK0_bp 1 /* Data Buffer 0 Not Acknowledge bit position. */
+
+#define USB_EP_TOGGLE_bm 0x01 /* Data Toggle bit mask. */
+#define USB_EP_TOGGLE_bp 0 /* Data Toggle bit position. */
+
+/* USB_EP.CTRL bit masks and bit positions */
+#define USB_EP_TYPE_gm 0xC0 /* Endpoint Type group mask. */
+#define USB_EP_TYPE_gp 6 /* Endpoint Type group position. */
+#define USB_EP_TYPE0_bm (1<<6) /* Endpoint Type bit 0 mask. */
+#define USB_EP_TYPE0_bp 6 /* Endpoint Type bit 0 position. */
+#define USB_EP_TYPE1_bm (1<<7) /* Endpoint Type bit 1 mask. */
+#define USB_EP_TYPE1_bp 7 /* Endpoint Type bit 1 position. */
+
+#define USB_EP_MULTIPKT_bm 0x20 /* Multi Packet Transfer Enable bit mask. */
+#define USB_EP_MULTIPKT_bp 5 /* Multi Packet Transfer Enable bit position. */
+
+#define USB_EP_PINGPONG_bm 0x10 /* Ping-Pong Enable bit mask. */
+#define USB_EP_PINGPONG_bp 4 /* Ping-Pong Enable bit position. */
+
+#define USB_EP_INTDSBL_bm 0x08 /* Interrupt Disable bit mask. */
+#define USB_EP_INTDSBL_bp 3 /* Interrupt Disable bit position. */
+
+#define USB_EP_STALL_bm 0x04 /* Data Stall bit mask. */
+#define USB_EP_STALL_bp 2 /* Data Stall bit position. */
+
+#define USB_EP_BUFSIZE_gm 0x07 /* Data Buffer Size group mask. */
+#define USB_EP_BUFSIZE_gp 0 /* Data Buffer Size group position. */
+#define USB_EP_BUFSIZE0_bm (1<<0) /* Data Buffer Size bit 0 mask. */
+#define USB_EP_BUFSIZE0_bp 0 /* Data Buffer Size bit 0 position. */
+#define USB_EP_BUFSIZE1_bm (1<<1) /* Data Buffer Size bit 1 mask. */
+#define USB_EP_BUFSIZE1_bp 1 /* Data Buffer Size bit 1 position. */
+#define USB_EP_BUFSIZE2_bm (1<<2) /* Data Buffer Size bit 2 mask. */
+#define USB_EP_BUFSIZE2_bp 2 /* Data Buffer Size bit 2 position. */
+
+/* USB_EP.CNT bit masks and bit positions */
+#define USB_EP_ZLP_bm 0x8000 /* Zero Length Packet bit mask. */
+#define USB_EP_ZLP_bp 15 /* Zero Length Packet bit position. */
+
+/* USB.CTRLA bit masks and bit positions */
+#define USB_ENABLE_bm 0x80 /* USB Enable bit mask. */
+#define USB_ENABLE_bp 7 /* USB Enable bit position. */
+
+#define USB_SPEED_bm 0x40 /* Speed Select bit mask. */
+#define USB_SPEED_bp 6 /* Speed Select bit position. */
+
+#define USB_FIFOEN_bm 0x20 /* USB FIFO Enable bit mask. */
+#define USB_FIFOEN_bp 5 /* USB FIFO Enable bit position. */
+
+#define USB_STFRNUM_bm 0x10 /* Store Frame Number Enable bit mask. */
+#define USB_STFRNUM_bp 4 /* Store Frame Number Enable bit position. */
+
+#define USB_MAXEP_gm 0x0F /* Maximum Endpoint Addresses group mask. */
+#define USB_MAXEP_gp 0 /* Maximum Endpoint Addresses group position. */
+#define USB_MAXEP0_bm (1<<0) /* Maximum Endpoint Addresses bit 0 mask. */
+#define USB_MAXEP0_bp 0 /* Maximum Endpoint Addresses bit 0 position. */
+#define USB_MAXEP1_bm (1<<1) /* Maximum Endpoint Addresses bit 1 mask. */
+#define USB_MAXEP1_bp 1 /* Maximum Endpoint Addresses bit 1 position. */
+#define USB_MAXEP2_bm (1<<2) /* Maximum Endpoint Addresses bit 2 mask. */
+#define USB_MAXEP2_bp 2 /* Maximum Endpoint Addresses bit 2 position. */
+#define USB_MAXEP3_bm (1<<3) /* Maximum Endpoint Addresses bit 3 mask. */
+#define USB_MAXEP3_bp 3 /* Maximum Endpoint Addresses bit 3 position. */
+
+/* USB.CTRLB bit masks and bit positions */
+#define USB_PULLRST_bm 0x10 /* Pull during Reset bit mask. */
+#define USB_PULLRST_bp 4 /* Pull during Reset bit position. */
+
+#define USB_RWAKEUP_bm 0x04 /* Remote Wake-up bit mask. */
+#define USB_RWAKEUP_bp 2 /* Remote Wake-up bit position. */
+
+#define USB_GNACK_bm 0x02 /* Global NACK bit mask. */
+#define USB_GNACK_bp 1 /* Global NACK bit position. */
+
+#define USB_ATTACH_bm 0x01 /* Attach bit mask. */
+#define USB_ATTACH_bp 0 /* Attach bit position. */
+
+/* USB.STATUS bit masks and bit positions */
+#define USB_URESUME_bm 0x08 /* Upstream Resume bit mask. */
+#define USB_URESUME_bp 3 /* Upstream Resume bit position. */
+
+#define USB_RESUME_bm 0x04 /* Resume bit mask. */
+#define USB_RESUME_bp 2 /* Resume bit position. */
+
+#define USB_SUSPEND_bm 0x02 /* Bus Suspended bit mask. */
+#define USB_SUSPEND_bp 1 /* Bus Suspended bit position. */
+
+#define USB_BUSRST_bm 0x01 /* Bus Reset bit mask. */
+#define USB_BUSRST_bp 0 /* Bus Reset bit position. */
+
+/* USB.ADDR bit masks and bit positions */
+#define USB_ADDR_gm 0x7F /* Device Address group mask. */
+#define USB_ADDR_gp 0 /* Device Address group position. */
+#define USB_ADDR0_bm (1<<0) /* Device Address bit 0 mask. */
+#define USB_ADDR0_bp 0 /* Device Address bit 0 position. */
+#define USB_ADDR1_bm (1<<1) /* Device Address bit 1 mask. */
+#define USB_ADDR1_bp 1 /* Device Address bit 1 position. */
+#define USB_ADDR2_bm (1<<2) /* Device Address bit 2 mask. */
+#define USB_ADDR2_bp 2 /* Device Address bit 2 position. */
+#define USB_ADDR3_bm (1<<3) /* Device Address bit 3 mask. */
+#define USB_ADDR3_bp 3 /* Device Address bit 3 position. */
+#define USB_ADDR4_bm (1<<4) /* Device Address bit 4 mask. */
+#define USB_ADDR4_bp 4 /* Device Address bit 4 position. */
+#define USB_ADDR5_bm (1<<5) /* Device Address bit 5 mask. */
+#define USB_ADDR5_bp 5 /* Device Address bit 5 position. */
+#define USB_ADDR6_bm (1<<6) /* Device Address bit 6 mask. */
+#define USB_ADDR6_bp 6 /* Device Address bit 6 position. */
+
+/* USB.FIFOWP bit masks and bit positions */
+#define USB_FIFOWP_gm 0x1F /* FIFO Write Pointer group mask. */
+#define USB_FIFOWP_gp 0 /* FIFO Write Pointer group position. */
+#define USB_FIFOWP0_bm (1<<0) /* FIFO Write Pointer bit 0 mask. */
+#define USB_FIFOWP0_bp 0 /* FIFO Write Pointer bit 0 position. */
+#define USB_FIFOWP1_bm (1<<1) /* FIFO Write Pointer bit 1 mask. */
+#define USB_FIFOWP1_bp 1 /* FIFO Write Pointer bit 1 position. */
+#define USB_FIFOWP2_bm (1<<2) /* FIFO Write Pointer bit 2 mask. */
+#define USB_FIFOWP2_bp 2 /* FIFO Write Pointer bit 2 position. */
+#define USB_FIFOWP3_bm (1<<3) /* FIFO Write Pointer bit 3 mask. */
+#define USB_FIFOWP3_bp 3 /* FIFO Write Pointer bit 3 position. */
+#define USB_FIFOWP4_bm (1<<4) /* FIFO Write Pointer bit 4 mask. */
+#define USB_FIFOWP4_bp 4 /* FIFO Write Pointer bit 4 position. */
+
+/* USB.FIFORP bit masks and bit positions */
+#define USB_FIFORP_gm 0x1F /* FIFO Read Pointer group mask. */
+#define USB_FIFORP_gp 0 /* FIFO Read Pointer group position. */
+#define USB_FIFORP0_bm (1<<0) /* FIFO Read Pointer bit 0 mask. */
+#define USB_FIFORP0_bp 0 /* FIFO Read Pointer bit 0 position. */
+#define USB_FIFORP1_bm (1<<1) /* FIFO Read Pointer bit 1 mask. */
+#define USB_FIFORP1_bp 1 /* FIFO Read Pointer bit 1 position. */
+#define USB_FIFORP2_bm (1<<2) /* FIFO Read Pointer bit 2 mask. */
+#define USB_FIFORP2_bp 2 /* FIFO Read Pointer bit 2 position. */
+#define USB_FIFORP3_bm (1<<3) /* FIFO Read Pointer bit 3 mask. */
+#define USB_FIFORP3_bp 3 /* FIFO Read Pointer bit 3 position. */
+#define USB_FIFORP4_bm (1<<4) /* FIFO Read Pointer bit 4 mask. */
+#define USB_FIFORP4_bp 4 /* FIFO Read Pointer bit 4 position. */
+
+/* USB.INTCTRLA bit masks and bit positions */
+#define USB_SOFIE_bm 0x80 /* Start Of Frame Interrupt Enable bit mask. */
+#define USB_SOFIE_bp 7 /* Start Of Frame Interrupt Enable bit position. */
+
+#define USB_BUSEVIE_bm 0x40 /* Bus Event Interrupt Enable bit mask. */
+#define USB_BUSEVIE_bp 6 /* Bus Event Interrupt Enable bit position. */
+
+#define USB_BUSERRIE_bm 0x20 /* Bus Error Interrupt Enable bit mask. */
+#define USB_BUSERRIE_bp 5 /* Bus Error Interrupt Enable bit position. */
+
+#define USB_STALLIE_bm 0x10 /* STALL Interrupt Enable bit mask. */
+#define USB_STALLIE_bp 4 /* STALL Interrupt Enable bit position. */
+
+#define USB_INTLVL_gm 0x03 /* Interrupt Level group mask. */
+#define USB_INTLVL_gp 0 /* Interrupt Level group position. */
+#define USB_INTLVL0_bm (1<<0) /* Interrupt Level bit 0 mask. */
+#define USB_INTLVL0_bp 0 /* Interrupt Level bit 0 position. */
+#define USB_INTLVL1_bm (1<<1) /* Interrupt Level bit 1 mask. */
+#define USB_INTLVL1_bp 1 /* Interrupt Level bit 1 position. */
+
+/* USB.INTCTRLB bit masks and bit positions */
+#define USB_TRNIE_bm 0x02 /* Transaction Complete Interrupt Enable bit mask. */
+#define USB_TRNIE_bp 1 /* Transaction Complete Interrupt Enable bit position. */
+
+#define USB_SETUPIE_bm 0x01 /* SETUP Transaction Complete Interrupt Enable bit mask. */
+#define USB_SETUPIE_bp 0 /* SETUP Transaction Complete Interrupt Enable bit position. */
+
+/* USB.INTFLAGSACLR bit masks and bit positions */
+#define USB_SOFIF_bm 0x80 /* Start Of Frame Interrupt Flag bit mask. */
+#define USB_SOFIF_bp 7 /* Start Of Frame Interrupt Flag bit position. */
+
+#define USB_SUSPENDIF_bm 0x40 /* Suspend Interrupt Flag bit mask. */
+#define USB_SUSPENDIF_bp 6 /* Suspend Interrupt Flag bit position. */
+
+#define USB_RESUMEIF_bm 0x20 /* Resume Interrupt Flag bit mask. */
+#define USB_RESUMEIF_bp 5 /* Resume Interrupt Flag bit position. */
+
+#define USB_RSTIF_bm 0x10 /* Reset Interrupt Flag bit mask. */
+#define USB_RSTIF_bp 4 /* Reset Interrupt Flag bit position. */
+
+#define USB_CRCIF_bm 0x08 /* Isochronous CRC Error Interrupt Flag bit mask. */
+#define USB_CRCIF_bp 3 /* Isochronous CRC Error Interrupt Flag bit position. */
+
+#define USB_UNFIF_bm 0x04 /* Underflow Interrupt Flag bit mask. */
+#define USB_UNFIF_bp 2 /* Underflow Interrupt Flag bit position. */
+
+#define USB_OVFIF_bm 0x02 /* Overflow Interrupt Flag bit mask. */
+#define USB_OVFIF_bp 1 /* Overflow Interrupt Flag bit position. */
+
+#define USB_STALLIF_bm 0x01 /* STALL Interrupt Flag bit mask. */
+#define USB_STALLIF_bp 0 /* STALL Interrupt Flag bit position. */
+
+/* USB.INTFLAGSASET bit masks and bit positions */
+/* USB_SOFIF Predefined. */
+/* USB_SOFIF Predefined. */
+
+/* USB_SUSPENDIF Predefined. */
+/* USB_SUSPENDIF Predefined. */
+
+/* USB_RESUMEIF Predefined. */
+/* USB_RESUMEIF Predefined. */
+
+/* USB_RSTIF Predefined. */
+/* USB_RSTIF Predefined. */
+
+/* USB_CRCIF Predefined. */
+/* USB_CRCIF Predefined. */
+
+/* USB_UNFIF Predefined. */
+/* USB_UNFIF Predefined. */
+
+/* USB_OVFIF Predefined. */
+/* USB_OVFIF Predefined. */
+
+/* USB_STALLIF Predefined. */
+/* USB_STALLIF Predefined. */
+
+/* USB.INTFLAGSBCLR bit masks and bit positions */
+#define USB_TRNIF_bm 0x02 /* Transaction Complete Interrupt Flag bit mask. */
+#define USB_TRNIF_bp 1 /* Transaction Complete Interrupt Flag bit position. */
+
+#define USB_SETUPIF_bm 0x01 /* SETUP Transaction Complete Interrupt Flag bit mask. */
+#define USB_SETUPIF_bp 0 /* SETUP Transaction Complete Interrupt Flag bit position. */
+
+/* USB.INTFLAGSBSET bit masks and bit positions */
+/* USB_TRNIF Predefined. */
+/* USB_TRNIF Predefined. */
+
+/* USB_SETUPIF Predefined. */
+/* USB_SETUPIF Predefined. */
+
+/* PORT - I/O Port Configuration */
+/* PORT.INTCTRL bit masks and bit positions */
+#define PORT_INT1LVL_gm 0x0C /* Port Interrupt 1 Level group mask. */
+#define PORT_INT1LVL_gp 2 /* Port Interrupt 1 Level group position. */
+#define PORT_INT1LVL0_bm (1<<2) /* Port Interrupt 1 Level bit 0 mask. */
+#define PORT_INT1LVL0_bp 2 /* Port Interrupt 1 Level bit 0 position. */
+#define PORT_INT1LVL1_bm (1<<3) /* Port Interrupt 1 Level bit 1 mask. */
+#define PORT_INT1LVL1_bp 3 /* Port Interrupt 1 Level bit 1 position. */
+
+#define PORT_INT0LVL_gm 0x03 /* Port Interrupt 0 Level group mask. */
+#define PORT_INT0LVL_gp 0 /* Port Interrupt 0 Level group position. */
+#define PORT_INT0LVL0_bm (1<<0) /* Port Interrupt 0 Level bit 0 mask. */
+#define PORT_INT0LVL0_bp 0 /* Port Interrupt 0 Level bit 0 position. */
+#define PORT_INT0LVL1_bm (1<<1) /* Port Interrupt 0 Level bit 1 mask. */
+#define PORT_INT0LVL1_bp 1 /* Port Interrupt 0 Level bit 1 position. */
+
+/* PORT.INTFLAGS bit masks and bit positions */
+#define PORT_INT1IF_bm 0x02 /* Port Interrupt 1 Flag bit mask. */
+#define PORT_INT1IF_bp 1 /* Port Interrupt 1 Flag bit position. */
+
+#define PORT_INT0IF_bm 0x01 /* Port Interrupt 0 Flag bit mask. */
+#define PORT_INT0IF_bp 0 /* Port Interrupt 0 Flag bit position. */
+
+/* PORT.REMAP bit masks and bit positions */
+#define PORT_SPI_bm 0x20 /* SPI bit mask. */
+#define PORT_SPI_bp 5 /* SPI bit position. */
+
+#define PORT_USART0_bm 0x10 /* USART0 bit mask. */
+#define PORT_USART0_bp 4 /* USART0 bit position. */
+
+#define PORT_TC0D_bm 0x08 /* Timer/Counter 0 Output Compare D bit mask. */
+#define PORT_TC0D_bp 3 /* Timer/Counter 0 Output Compare D bit position. */
+
+#define PORT_TC0C_bm 0x04 /* Timer/Counter 0 Output Compare C bit mask. */
+#define PORT_TC0C_bp 2 /* Timer/Counter 0 Output Compare C bit position. */
+
+#define PORT_TC0B_bm 0x02 /* Timer/Counter 0 Output Compare B bit mask. */
+#define PORT_TC0B_bp 1 /* Timer/Counter 0 Output Compare B bit position. */
+
+#define PORT_TC0A_bm 0x01 /* Timer/Counter 0 Output Compare A bit mask. */
+#define PORT_TC0A_bp 0 /* Timer/Counter 0 Output Compare A bit position. */
+
+/* PORT.PIN0CTRL bit masks and bit positions */
+#define PORT_SRLEN_bm 0x80 /* Slew Rate Enable bit mask. */
+#define PORT_SRLEN_bp 7 /* Slew Rate Enable bit position. */
+
+#define PORT_INVEN_bm 0x40 /* Inverted I/O Enable bit mask. */
+#define PORT_INVEN_bp 6 /* Inverted I/O Enable bit position. */
+
+#define PORT_OPC_gm 0x38 /* Output/Pull Configuration group mask. */
+#define PORT_OPC_gp 3 /* Output/Pull Configuration group position. */
+#define PORT_OPC0_bm (1<<3) /* Output/Pull Configuration bit 0 mask. */
+#define PORT_OPC0_bp 3 /* Output/Pull Configuration bit 0 position. */
+#define PORT_OPC1_bm (1<<4) /* Output/Pull Configuration bit 1 mask. */
+#define PORT_OPC1_bp 4 /* Output/Pull Configuration bit 1 position. */
+#define PORT_OPC2_bm (1<<5) /* Output/Pull Configuration bit 2 mask. */
+#define PORT_OPC2_bp 5 /* Output/Pull Configuration bit 2 position. */
+
+#define PORT_ISC_gm 0x07 /* Input/Sense Configuration group mask. */
+#define PORT_ISC_gp 0 /* Input/Sense Configuration group position. */
+#define PORT_ISC0_bm (1<<0) /* Input/Sense Configuration bit 0 mask. */
+#define PORT_ISC0_bp 0 /* Input/Sense Configuration bit 0 position. */
+#define PORT_ISC1_bm (1<<1) /* Input/Sense Configuration bit 1 mask. */
+#define PORT_ISC1_bp 1 /* Input/Sense Configuration bit 1 position. */
+#define PORT_ISC2_bm (1<<2) /* Input/Sense Configuration bit 2 mask. */
+#define PORT_ISC2_bp 2 /* Input/Sense Configuration bit 2 position. */
+
+/* PORT.PIN1CTRL bit masks and bit positions */
+/* PORT_SRLEN Predefined. */
+/* PORT_SRLEN Predefined. */
+
+/* PORT_INVEN Predefined. */
+/* PORT_INVEN Predefined. */
+
+/* PORT_OPC Predefined. */
+/* PORT_OPC Predefined. */
+
+/* PORT_ISC Predefined. */
+/* PORT_ISC Predefined. */
+
+/* PORT.PIN2CTRL bit masks and bit positions */
+/* PORT_SRLEN Predefined. */
+/* PORT_SRLEN Predefined. */
+
+/* PORT_INVEN Predefined. */
+/* PORT_INVEN Predefined. */
+
+/* PORT_OPC Predefined. */
+/* PORT_OPC Predefined. */
+
+/* PORT_ISC Predefined. */
+/* PORT_ISC Predefined. */
+
+/* PORT.PIN3CTRL bit masks and bit positions */
+/* PORT_SRLEN Predefined. */
+/* PORT_SRLEN Predefined. */
+
+/* PORT_INVEN Predefined. */
+/* PORT_INVEN Predefined. */
+
+/* PORT_OPC Predefined. */
+/* PORT_OPC Predefined. */
+
+/* PORT_ISC Predefined. */
+/* PORT_ISC Predefined. */
+
+/* PORT.PIN4CTRL bit masks and bit positions */
+/* PORT_SRLEN Predefined. */
+/* PORT_SRLEN Predefined. */
+
+/* PORT_INVEN Predefined. */
+/* PORT_INVEN Predefined. */
+
+/* PORT_OPC Predefined. */
+/* PORT_OPC Predefined. */
+
+/* PORT_ISC Predefined. */
+/* PORT_ISC Predefined. */
+
+/* PORT.PIN5CTRL bit masks and bit positions */
+/* PORT_SRLEN Predefined. */
+/* PORT_SRLEN Predefined. */
+
+/* PORT_INVEN Predefined. */
+/* PORT_INVEN Predefined. */
+
+/* PORT_OPC Predefined. */
+/* PORT_OPC Predefined. */
+
+/* PORT_ISC Predefined. */
+/* PORT_ISC Predefined. */
+
+/* PORT.PIN6CTRL bit masks and bit positions */
+/* PORT_SRLEN Predefined. */
+/* PORT_SRLEN Predefined. */
+
+/* PORT_INVEN Predefined. */
+/* PORT_INVEN Predefined. */
+
+/* PORT_OPC Predefined. */
+/* PORT_OPC Predefined. */
+
+/* PORT_ISC Predefined. */
+/* PORT_ISC Predefined. */
+
+/* PORT.PIN7CTRL bit masks and bit positions */
+/* PORT_SRLEN Predefined. */
+/* PORT_SRLEN Predefined. */
+
+/* PORT_INVEN Predefined. */
+/* PORT_INVEN Predefined. */
+
+/* PORT_OPC Predefined. */
+/* PORT_OPC Predefined. */
+
+/* PORT_ISC Predefined. */
+/* PORT_ISC Predefined. */
+
+/* TC - 16-bit Timer/Counter With PWM */
+/* TC0.CTRLA bit masks and bit positions */
+#define TC0_CLKSEL_gm 0x0F /* Clock Selection group mask. */
+#define TC0_CLKSEL_gp 0 /* Clock Selection group position. */
+#define TC0_CLKSEL0_bm (1<<0) /* Clock Selection bit 0 mask. */
+#define TC0_CLKSEL0_bp 0 /* Clock Selection bit 0 position. */
+#define TC0_CLKSEL1_bm (1<<1) /* Clock Selection bit 1 mask. */
+#define TC0_CLKSEL1_bp 1 /* Clock Selection bit 1 position. */
+#define TC0_CLKSEL2_bm (1<<2) /* Clock Selection bit 2 mask. */
+#define TC0_CLKSEL2_bp 2 /* Clock Selection bit 2 position. */
+#define TC0_CLKSEL3_bm (1<<3) /* Clock Selection bit 3 mask. */
+#define TC0_CLKSEL3_bp 3 /* Clock Selection bit 3 position. */
+
+/* TC0.CTRLB bit masks and bit positions */
+#define TC0_CCDEN_bm 0x80 /* Compare or Capture D Enable bit mask. */
+#define TC0_CCDEN_bp 7 /* Compare or Capture D Enable bit position. */
+
+#define TC0_CCCEN_bm 0x40 /* Compare or Capture C Enable bit mask. */
+#define TC0_CCCEN_bp 6 /* Compare or Capture C Enable bit position. */
+
+#define TC0_CCBEN_bm 0x20 /* Compare or Capture B Enable bit mask. */
+#define TC0_CCBEN_bp 5 /* Compare or Capture B Enable bit position. */
+
+#define TC0_CCAEN_bm 0x10 /* Compare or Capture A Enable bit mask. */
+#define TC0_CCAEN_bp 4 /* Compare or Capture A Enable bit position. */
+
+#define TC0_WGMODE_gm 0x07 /* Waveform generation mode group mask. */
+#define TC0_WGMODE_gp 0 /* Waveform generation mode group position. */
+#define TC0_WGMODE0_bm (1<<0) /* Waveform generation mode bit 0 mask. */
+#define TC0_WGMODE0_bp 0 /* Waveform generation mode bit 0 position. */
+#define TC0_WGMODE1_bm (1<<1) /* Waveform generation mode bit 1 mask. */
+#define TC0_WGMODE1_bp 1 /* Waveform generation mode bit 1 position. */
+#define TC0_WGMODE2_bm (1<<2) /* Waveform generation mode bit 2 mask. */
+#define TC0_WGMODE2_bp 2 /* Waveform generation mode bit 2 position. */
+
+/* TC0.CTRLC bit masks and bit positions */
+#define TC0_CMPD_bm 0x08 /* Compare D Output Value bit mask. */
+#define TC0_CMPD_bp 3 /* Compare D Output Value bit position. */
+
+#define TC0_CMPC_bm 0x04 /* Compare C Output Value bit mask. */
+#define TC0_CMPC_bp 2 /* Compare C Output Value bit position. */
+
+#define TC0_CMPB_bm 0x02 /* Compare B Output Value bit mask. */
+#define TC0_CMPB_bp 1 /* Compare B Output Value bit position. */
+
+#define TC0_CMPA_bm 0x01 /* Compare A Output Value bit mask. */
+#define TC0_CMPA_bp 0 /* Compare A Output Value bit position. */
+
+/* TC0.CTRLD bit masks and bit positions */
+#define TC0_EVACT_gm 0xE0 /* Event Action group mask. */
+#define TC0_EVACT_gp 5 /* Event Action group position. */
+#define TC0_EVACT0_bm (1<<5) /* Event Action bit 0 mask. */
+#define TC0_EVACT0_bp 5 /* Event Action bit 0 position. */
+#define TC0_EVACT1_bm (1<<6) /* Event Action bit 1 mask. */
+#define TC0_EVACT1_bp 6 /* Event Action bit 1 position. */
+#define TC0_EVACT2_bm (1<<7) /* Event Action bit 2 mask. */
+#define TC0_EVACT2_bp 7 /* Event Action bit 2 position. */
+
+#define TC0_EVDLY_bm 0x10 /* Event Delay bit mask. */
+#define TC0_EVDLY_bp 4 /* Event Delay bit position. */
+
+#define TC0_EVSEL_gm 0x0F /* Event Source Select group mask. */
+#define TC0_EVSEL_gp 0 /* Event Source Select group position. */
+#define TC0_EVSEL0_bm (1<<0) /* Event Source Select bit 0 mask. */
+#define TC0_EVSEL0_bp 0 /* Event Source Select bit 0 position. */
+#define TC0_EVSEL1_bm (1<<1) /* Event Source Select bit 1 mask. */
+#define TC0_EVSEL1_bp 1 /* Event Source Select bit 1 position. */
+#define TC0_EVSEL2_bm (1<<2) /* Event Source Select bit 2 mask. */
+#define TC0_EVSEL2_bp 2 /* Event Source Select bit 2 position. */
+#define TC0_EVSEL3_bm (1<<3) /* Event Source Select bit 3 mask. */
+#define TC0_EVSEL3_bp 3 /* Event Source Select bit 3 position. */
+
+/* TC0.CTRLE bit masks and bit positions */
+#define TC0_BYTEM_gm 0x03 /* Byte Mode group mask. */
+#define TC0_BYTEM_gp 0 /* Byte Mode group position. */
+#define TC0_BYTEM0_bm (1<<0) /* Byte Mode bit 0 mask. */
+#define TC0_BYTEM0_bp 0 /* Byte Mode bit 0 position. */
+#define TC0_BYTEM1_bm (1<<1) /* Byte Mode bit 1 mask. */
+#define TC0_BYTEM1_bp 1 /* Byte Mode bit 1 position. */
+
+/* TC0.INTCTRLA bit masks and bit positions */
+#define TC0_ERRINTLVL_gm 0x0C /* Error Interrupt Level group mask. */
+#define TC0_ERRINTLVL_gp 2 /* Error Interrupt Level group position. */
+#define TC0_ERRINTLVL0_bm (1<<2) /* Error Interrupt Level bit 0 mask. */
+#define TC0_ERRINTLVL0_bp 2 /* Error Interrupt Level bit 0 position. */
+#define TC0_ERRINTLVL1_bm (1<<3) /* Error Interrupt Level bit 1 mask. */
+#define TC0_ERRINTLVL1_bp 3 /* Error Interrupt Level bit 1 position. */
+
+#define TC0_OVFINTLVL_gm 0x03 /* Overflow interrupt level group mask. */
+#define TC0_OVFINTLVL_gp 0 /* Overflow interrupt level group position. */
+#define TC0_OVFINTLVL0_bm (1<<0) /* Overflow interrupt level bit 0 mask. */
+#define TC0_OVFINTLVL0_bp 0 /* Overflow interrupt level bit 0 position. */
+#define TC0_OVFINTLVL1_bm (1<<1) /* Overflow interrupt level bit 1 mask. */
+#define TC0_OVFINTLVL1_bp 1 /* Overflow interrupt level bit 1 position. */
+
+/* TC0.INTCTRLB bit masks and bit positions */
+#define TC0_CCDINTLVL_gm 0xC0 /* Compare or Capture D Interrupt Level group mask. */
+#define TC0_CCDINTLVL_gp 6 /* Compare or Capture D Interrupt Level group position. */
+#define TC0_CCDINTLVL0_bm (1<<6) /* Compare or Capture D Interrupt Level bit 0 mask. */
+#define TC0_CCDINTLVL0_bp 6 /* Compare or Capture D Interrupt Level bit 0 position. */
+#define TC0_CCDINTLVL1_bm (1<<7) /* Compare or Capture D Interrupt Level bit 1 mask. */
+#define TC0_CCDINTLVL1_bp 7 /* Compare or Capture D Interrupt Level bit 1 position. */
+
+#define TC0_CCCINTLVL_gm 0x30 /* Compare or Capture C Interrupt Level group mask. */
+#define TC0_CCCINTLVL_gp 4 /* Compare or Capture C Interrupt Level group position. */
+#define TC0_CCCINTLVL0_bm (1<<4) /* Compare or Capture C Interrupt Level bit 0 mask. */
+#define TC0_CCCINTLVL0_bp 4 /* Compare or Capture C Interrupt Level bit 0 position. */
+#define TC0_CCCINTLVL1_bm (1<<5) /* Compare or Capture C Interrupt Level bit 1 mask. */
+#define TC0_CCCINTLVL1_bp 5 /* Compare or Capture C Interrupt Level bit 1 position. */
+
+#define TC0_CCBINTLVL_gm 0x0C /* Compare or Capture B Interrupt Level group mask. */
+#define TC0_CCBINTLVL_gp 2 /* Compare or Capture B Interrupt Level group position. */
+#define TC0_CCBINTLVL0_bm (1<<2) /* Compare or Capture B Interrupt Level bit 0 mask. */
+#define TC0_CCBINTLVL0_bp 2 /* Compare or Capture B Interrupt Level bit 0 position. */
+#define TC0_CCBINTLVL1_bm (1<<3) /* Compare or Capture B Interrupt Level bit 1 mask. */
+#define TC0_CCBINTLVL1_bp 3 /* Compare or Capture B Interrupt Level bit 1 position. */
+
+#define TC0_CCAINTLVL_gm 0x03 /* Compare or Capture A Interrupt Level group mask. */
+#define TC0_CCAINTLVL_gp 0 /* Compare or Capture A Interrupt Level group position. */
+#define TC0_CCAINTLVL0_bm (1<<0) /* Compare or Capture A Interrupt Level bit 0 mask. */
+#define TC0_CCAINTLVL0_bp 0 /* Compare or Capture A Interrupt Level bit 0 position. */
+#define TC0_CCAINTLVL1_bm (1<<1) /* Compare or Capture A Interrupt Level bit 1 mask. */
+#define TC0_CCAINTLVL1_bp 1 /* Compare or Capture A Interrupt Level bit 1 position. */
+
+/* TC0.CTRLFCLR bit masks and bit positions */
+#define TC0_CMD_gm 0x0C /* Command group mask. */
+#define TC0_CMD_gp 2 /* Command group position. */
+#define TC0_CMD0_bm (1<<2) /* Command bit 0 mask. */
+#define TC0_CMD0_bp 2 /* Command bit 0 position. */
+#define TC0_CMD1_bm (1<<3) /* Command bit 1 mask. */
+#define TC0_CMD1_bp 3 /* Command bit 1 position. */
+
+#define TC0_LUPD_bm 0x02 /* Lock Update bit mask. */
+#define TC0_LUPD_bp 1 /* Lock Update bit position. */
+
+#define TC0_DIR_bm 0x01 /* Direction bit mask. */
+#define TC0_DIR_bp 0 /* Direction bit position. */
+
+/* TC0.CTRLFSET bit masks and bit positions */
+/* TC0_CMD Predefined. */
+/* TC0_CMD Predefined. */
+
+/* TC0_LUPD Predefined. */
+/* TC0_LUPD Predefined. */
+
+/* TC0_DIR Predefined. */
+/* TC0_DIR Predefined. */
+
+/* TC0.CTRLGCLR bit masks and bit positions */
+#define TC0_CCDBV_bm 0x10 /* Compare or Capture D Buffer Valid bit mask. */
+#define TC0_CCDBV_bp 4 /* Compare or Capture D Buffer Valid bit position. */
+
+#define TC0_CCCBV_bm 0x08 /* Compare or Capture C Buffer Valid bit mask. */
+#define TC0_CCCBV_bp 3 /* Compare or Capture C Buffer Valid bit position. */
+
+#define TC0_CCBBV_bm 0x04 /* Compare or Capture B Buffer Valid bit mask. */
+#define TC0_CCBBV_bp 2 /* Compare or Capture B Buffer Valid bit position. */
+
+#define TC0_CCABV_bm 0x02 /* Compare or Capture A Buffer Valid bit mask. */
+#define TC0_CCABV_bp 1 /* Compare or Capture A Buffer Valid bit position. */
+
+#define TC0_PERBV_bm 0x01 /* Period Buffer Valid bit mask. */
+#define TC0_PERBV_bp 0 /* Period Buffer Valid bit position. */
+
+/* TC0.CTRLGSET bit masks and bit positions */
+/* TC0_CCDBV Predefined. */
+/* TC0_CCDBV Predefined. */
+
+/* TC0_CCCBV Predefined. */
+/* TC0_CCCBV Predefined. */
+
+/* TC0_CCBBV Predefined. */
+/* TC0_CCBBV Predefined. */
+
+/* TC0_CCABV Predefined. */
+/* TC0_CCABV Predefined. */
+
+/* TC0_PERBV Predefined. */
+/* TC0_PERBV Predefined. */
+
+/* TC0.INTFLAGS bit masks and bit positions */
+#define TC0_CCDIF_bm 0x80 /* Compare or Capture D Interrupt Flag bit mask. */
+#define TC0_CCDIF_bp 7 /* Compare or Capture D Interrupt Flag bit position. */
+
+#define TC0_CCCIF_bm 0x40 /* Compare or Capture C Interrupt Flag bit mask. */
+#define TC0_CCCIF_bp 6 /* Compare or Capture C Interrupt Flag bit position. */
+
+#define TC0_CCBIF_bm 0x20 /* Compare or Capture B Interrupt Flag bit mask. */
+#define TC0_CCBIF_bp 5 /* Compare or Capture B Interrupt Flag bit position. */
+
+#define TC0_CCAIF_bm 0x10 /* Compare or Capture A Interrupt Flag bit mask. */
+#define TC0_CCAIF_bp 4 /* Compare or Capture A Interrupt Flag bit position. */
+
+#define TC0_ERRIF_bm 0x02 /* Error Interrupt Flag bit mask. */
+#define TC0_ERRIF_bp 1 /* Error Interrupt Flag bit position. */
+
+#define TC0_OVFIF_bm 0x01 /* Overflow Interrupt Flag bit mask. */
+#define TC0_OVFIF_bp 0 /* Overflow Interrupt Flag bit position. */
+
+/* TC1.CTRLA bit masks and bit positions */
+#define TC1_CLKSEL_gm 0x0F /* Clock Selection group mask. */
+#define TC1_CLKSEL_gp 0 /* Clock Selection group position. */
+#define TC1_CLKSEL0_bm (1<<0) /* Clock Selection bit 0 mask. */
+#define TC1_CLKSEL0_bp 0 /* Clock Selection bit 0 position. */
+#define TC1_CLKSEL1_bm (1<<1) /* Clock Selection bit 1 mask. */
+#define TC1_CLKSEL1_bp 1 /* Clock Selection bit 1 position. */
+#define TC1_CLKSEL2_bm (1<<2) /* Clock Selection bit 2 mask. */
+#define TC1_CLKSEL2_bp 2 /* Clock Selection bit 2 position. */
+#define TC1_CLKSEL3_bm (1<<3) /* Clock Selection bit 3 mask. */
+#define TC1_CLKSEL3_bp 3 /* Clock Selection bit 3 position. */
+
+/* TC1.CTRLB bit masks and bit positions */
+#define TC1_CCBEN_bm 0x20 /* Compare or Capture B Enable bit mask. */
+#define TC1_CCBEN_bp 5 /* Compare or Capture B Enable bit position. */
+
+#define TC1_CCAEN_bm 0x10 /* Compare or Capture A Enable bit mask. */
+#define TC1_CCAEN_bp 4 /* Compare or Capture A Enable bit position. */
+
+#define TC1_WGMODE_gm 0x07 /* Waveform generation mode group mask. */
+#define TC1_WGMODE_gp 0 /* Waveform generation mode group position. */
+#define TC1_WGMODE0_bm (1<<0) /* Waveform generation mode bit 0 mask. */
+#define TC1_WGMODE0_bp 0 /* Waveform generation mode bit 0 position. */
+#define TC1_WGMODE1_bm (1<<1) /* Waveform generation mode bit 1 mask. */
+#define TC1_WGMODE1_bp 1 /* Waveform generation mode bit 1 position. */
+#define TC1_WGMODE2_bm (1<<2) /* Waveform generation mode bit 2 mask. */
+#define TC1_WGMODE2_bp 2 /* Waveform generation mode bit 2 position. */
+
+/* TC1.CTRLC bit masks and bit positions */
+#define TC1_CMPB_bm 0x02 /* Compare B Output Value bit mask. */
+#define TC1_CMPB_bp 1 /* Compare B Output Value bit position. */
+
+#define TC1_CMPA_bm 0x01 /* Compare A Output Value bit mask. */
+#define TC1_CMPA_bp 0 /* Compare A Output Value bit position. */
+
+/* TC1.CTRLD bit masks and bit positions */
+#define TC1_EVACT_gm 0xE0 /* Event Action group mask. */
+#define TC1_EVACT_gp 5 /* Event Action group position. */
+#define TC1_EVACT0_bm (1<<5) /* Event Action bit 0 mask. */
+#define TC1_EVACT0_bp 5 /* Event Action bit 0 position. */
+#define TC1_EVACT1_bm (1<<6) /* Event Action bit 1 mask. */
+#define TC1_EVACT1_bp 6 /* Event Action bit 1 position. */
+#define TC1_EVACT2_bm (1<<7) /* Event Action bit 2 mask. */
+#define TC1_EVACT2_bp 7 /* Event Action bit 2 position. */
+
+#define TC1_EVDLY_bm 0x10 /* Event Delay bit mask. */
+#define TC1_EVDLY_bp 4 /* Event Delay bit position. */
+
+#define TC1_EVSEL_gm 0x0F /* Event Source Select group mask. */
+#define TC1_EVSEL_gp 0 /* Event Source Select group position. */
+#define TC1_EVSEL0_bm (1<<0) /* Event Source Select bit 0 mask. */
+#define TC1_EVSEL0_bp 0 /* Event Source Select bit 0 position. */
+#define TC1_EVSEL1_bm (1<<1) /* Event Source Select bit 1 mask. */
+#define TC1_EVSEL1_bp 1 /* Event Source Select bit 1 position. */
+#define TC1_EVSEL2_bm (1<<2) /* Event Source Select bit 2 mask. */
+#define TC1_EVSEL2_bp 2 /* Event Source Select bit 2 position. */
+#define TC1_EVSEL3_bm (1<<3) /* Event Source Select bit 3 mask. */
+#define TC1_EVSEL3_bp 3 /* Event Source Select bit 3 position. */
+
+/* TC1.CTRLE bit masks and bit positions */
+#define TC1_BYTEM_bm 0x01 /* Byte Mode bit mask. */
+#define TC1_BYTEM_bp 0 /* Byte Mode bit position. */
+
+/* TC1.INTCTRLA bit masks and bit positions */
+#define TC1_ERRINTLVL_gm 0x0C /* Error Interrupt Level group mask. */
+#define TC1_ERRINTLVL_gp 2 /* Error Interrupt Level group position. */
+#define TC1_ERRINTLVL0_bm (1<<2) /* Error Interrupt Level bit 0 mask. */
+#define TC1_ERRINTLVL0_bp 2 /* Error Interrupt Level bit 0 position. */
+#define TC1_ERRINTLVL1_bm (1<<3) /* Error Interrupt Level bit 1 mask. */
+#define TC1_ERRINTLVL1_bp 3 /* Error Interrupt Level bit 1 position. */
+
+#define TC1_OVFINTLVL_gm 0x03 /* Overflow interrupt level group mask. */
+#define TC1_OVFINTLVL_gp 0 /* Overflow interrupt level group position. */
+#define TC1_OVFINTLVL0_bm (1<<0) /* Overflow interrupt level bit 0 mask. */
+#define TC1_OVFINTLVL0_bp 0 /* Overflow interrupt level bit 0 position. */
+#define TC1_OVFINTLVL1_bm (1<<1) /* Overflow interrupt level bit 1 mask. */
+#define TC1_OVFINTLVL1_bp 1 /* Overflow interrupt level bit 1 position. */
+
+/* TC1.INTCTRLB bit masks and bit positions */
+#define TC1_CCBINTLVL_gm 0x0C /* Compare or Capture B Interrupt Level group mask. */
+#define TC1_CCBINTLVL_gp 2 /* Compare or Capture B Interrupt Level group position. */
+#define TC1_CCBINTLVL0_bm (1<<2) /* Compare or Capture B Interrupt Level bit 0 mask. */
+#define TC1_CCBINTLVL0_bp 2 /* Compare or Capture B Interrupt Level bit 0 position. */
+#define TC1_CCBINTLVL1_bm (1<<3) /* Compare or Capture B Interrupt Level bit 1 mask. */
+#define TC1_CCBINTLVL1_bp 3 /* Compare or Capture B Interrupt Level bit 1 position. */
+
+#define TC1_CCAINTLVL_gm 0x03 /* Compare or Capture A Interrupt Level group mask. */
+#define TC1_CCAINTLVL_gp 0 /* Compare or Capture A Interrupt Level group position. */
+#define TC1_CCAINTLVL0_bm (1<<0) /* Compare or Capture A Interrupt Level bit 0 mask. */
+#define TC1_CCAINTLVL0_bp 0 /* Compare or Capture A Interrupt Level bit 0 position. */
+#define TC1_CCAINTLVL1_bm (1<<1) /* Compare or Capture A Interrupt Level bit 1 mask. */
+#define TC1_CCAINTLVL1_bp 1 /* Compare or Capture A Interrupt Level bit 1 position. */
+
+/* TC1.CTRLFCLR bit masks and bit positions */
+#define TC1_CMD_gm 0x0C /* Command group mask. */
+#define TC1_CMD_gp 2 /* Command group position. */
+#define TC1_CMD0_bm (1<<2) /* Command bit 0 mask. */
+#define TC1_CMD0_bp 2 /* Command bit 0 position. */
+#define TC1_CMD1_bm (1<<3) /* Command bit 1 mask. */
+#define TC1_CMD1_bp 3 /* Command bit 1 position. */
+
+#define TC1_LUPD_bm 0x02 /* Lock Update bit mask. */
+#define TC1_LUPD_bp 1 /* Lock Update bit position. */
+
+#define TC1_DIR_bm 0x01 /* Direction bit mask. */
+#define TC1_DIR_bp 0 /* Direction bit position. */
+
+/* TC1.CTRLFSET bit masks and bit positions */
+/* TC1_CMD Predefined. */
+/* TC1_CMD Predefined. */
+
+/* TC1_LUPD Predefined. */
+/* TC1_LUPD Predefined. */
+
+/* TC1_DIR Predefined. */
+/* TC1_DIR Predefined. */
+
+/* TC1.CTRLGCLR bit masks and bit positions */
+#define TC1_CCBBV_bm 0x04 /* Compare or Capture B Buffer Valid bit mask. */
+#define TC1_CCBBV_bp 2 /* Compare or Capture B Buffer Valid bit position. */
+
+#define TC1_CCABV_bm 0x02 /* Compare or Capture A Buffer Valid bit mask. */
+#define TC1_CCABV_bp 1 /* Compare or Capture A Buffer Valid bit position. */
+
+#define TC1_PERBV_bm 0x01 /* Period Buffer Valid bit mask. */
+#define TC1_PERBV_bp 0 /* Period Buffer Valid bit position. */
+
+/* TC1.CTRLGSET bit masks and bit positions */
+/* TC1_CCBBV Predefined. */
+/* TC1_CCBBV Predefined. */
+
+/* TC1_CCABV Predefined. */
+/* TC1_CCABV Predefined. */
+
+/* TC1_PERBV Predefined. */
+/* TC1_PERBV Predefined. */
+
+/* TC1.INTFLAGS bit masks and bit positions */
+#define TC1_CCBIF_bm 0x20 /* Compare or Capture B Interrupt Flag bit mask. */
+#define TC1_CCBIF_bp 5 /* Compare or Capture B Interrupt Flag bit position. */
+
+#define TC1_CCAIF_bm 0x10 /* Compare or Capture A Interrupt Flag bit mask. */
+#define TC1_CCAIF_bp 4 /* Compare or Capture A Interrupt Flag bit position. */
+
+#define TC1_ERRIF_bm 0x02 /* Error Interrupt Flag bit mask. */
+#define TC1_ERRIF_bp 1 /* Error Interrupt Flag bit position. */
+
+#define TC1_OVFIF_bm 0x01 /* Overflow Interrupt Flag bit mask. */
+#define TC1_OVFIF_bp 0 /* Overflow Interrupt Flag bit position. */
+
+/* TC2 - 16-bit Timer/Counter type 2 */
+/* TC2.CTRLA bit masks and bit positions */
+#define TC2_CLKSEL_gm 0x0F /* Clock Selection group mask. */
+#define TC2_CLKSEL_gp 0 /* Clock Selection group position. */
+#define TC2_CLKSEL0_bm (1<<0) /* Clock Selection bit 0 mask. */
+#define TC2_CLKSEL0_bp 0 /* Clock Selection bit 0 position. */
+#define TC2_CLKSEL1_bm (1<<1) /* Clock Selection bit 1 mask. */
+#define TC2_CLKSEL1_bp 1 /* Clock Selection bit 1 position. */
+#define TC2_CLKSEL2_bm (1<<2) /* Clock Selection bit 2 mask. */
+#define TC2_CLKSEL2_bp 2 /* Clock Selection bit 2 position. */
+#define TC2_CLKSEL3_bm (1<<3) /* Clock Selection bit 3 mask. */
+#define TC2_CLKSEL3_bp 3 /* Clock Selection bit 3 position. */
+
+/* TC2.CTRLB bit masks and bit positions */
+#define TC2_HCMPDEN_bm 0x80 /* High Byte Compare D Enable bit mask. */
+#define TC2_HCMPDEN_bp 7 /* High Byte Compare D Enable bit position. */
+
+#define TC2_HCMPCEN_bm 0x40 /* High Byte Compare C Enable bit mask. */
+#define TC2_HCMPCEN_bp 6 /* High Byte Compare C Enable bit position. */
+
+#define TC2_HCMPBEN_bm 0x20 /* High Byte Compare B Enable bit mask. */
+#define TC2_HCMPBEN_bp 5 /* High Byte Compare B Enable bit position. */
+
+#define TC2_HCMPAEN_bm 0x10 /* High Byte Compare A Enable bit mask. */
+#define TC2_HCMPAEN_bp 4 /* High Byte Compare A Enable bit position. */
+
+#define TC2_LCMPDEN_bm 0x08 /* Low Byte Compare D Enable bit mask. */
+#define TC2_LCMPDEN_bp 3 /* Low Byte Compare D Enable bit position. */
+
+#define TC2_LCMPCEN_bm 0x04 /* Low Byte Compare C Enable bit mask. */
+#define TC2_LCMPCEN_bp 2 /* Low Byte Compare C Enable bit position. */
+
+#define TC2_LCMPBEN_bm 0x02 /* Low Byte Compare B Enable bit mask. */
+#define TC2_LCMPBEN_bp 1 /* Low Byte Compare B Enable bit position. */
+
+#define TC2_LCMPAEN_bm 0x01 /* Low Byte Compare A Enable bit mask. */
+#define TC2_LCMPAEN_bp 0 /* Low Byte Compare A Enable bit position. */
+
+/* TC2.CTRLC bit masks and bit positions */
+#define TC2_HCMPD_bm 0x80 /* High Byte Compare D Output Value bit mask. */
+#define TC2_HCMPD_bp 7 /* High Byte Compare D Output Value bit position. */
+
+#define TC2_HCMPC_bm 0x40 /* High Byte Compare C Output Value bit mask. */
+#define TC2_HCMPC_bp 6 /* High Byte Compare C Output Value bit position. */
+
+#define TC2_HCMPB_bm 0x20 /* High Byte Compare B Output Value bit mask. */
+#define TC2_HCMPB_bp 5 /* High Byte Compare B Output Value bit position. */
+
+#define TC2_HCMPA_bm 0x10 /* High Byte Compare A Output Value bit mask. */
+#define TC2_HCMPA_bp 4 /* High Byte Compare A Output Value bit position. */
+
+#define TC2_LCMPD_bm 0x08 /* Low Byte Compare D Output Value bit mask. */
+#define TC2_LCMPD_bp 3 /* Low Byte Compare D Output Value bit position. */
+
+#define TC2_LCMPC_bm 0x04 /* Low Byte Compare C Output Value bit mask. */
+#define TC2_LCMPC_bp 2 /* Low Byte Compare C Output Value bit position. */
+
+#define TC2_LCMPB_bm 0x02 /* Low Byte Compare B Output Value bit mask. */
+#define TC2_LCMPB_bp 1 /* Low Byte Compare B Output Value bit position. */
+
+#define TC2_LCMPA_bm 0x01 /* Low Byte Compare A Output Value bit mask. */
+#define TC2_LCMPA_bp 0 /* Low Byte Compare A Output Value bit position. */
+
+/* TC2.CTRLE bit masks and bit positions */
+#define TC2_BYTEM_gm 0x03 /* Byte Mode group mask. */
+#define TC2_BYTEM_gp 0 /* Byte Mode group position. */
+#define TC2_BYTEM0_bm (1<<0) /* Byte Mode bit 0 mask. */
+#define TC2_BYTEM0_bp 0 /* Byte Mode bit 0 position. */
+#define TC2_BYTEM1_bm (1<<1) /* Byte Mode bit 1 mask. */
+#define TC2_BYTEM1_bp 1 /* Byte Mode bit 1 position. */
+
+/* TC2.INTCTRLA bit masks and bit positions */
+#define TC2_HUNFINTLVL_gm 0x0C /* High Byte Underflow Interrupt Level group mask. */
+#define TC2_HUNFINTLVL_gp 2 /* High Byte Underflow Interrupt Level group position. */
+#define TC2_HUNFINTLVL0_bm (1<<2) /* High Byte Underflow Interrupt Level bit 0 mask. */
+#define TC2_HUNFINTLVL0_bp 2 /* High Byte Underflow Interrupt Level bit 0 position. */
+#define TC2_HUNFINTLVL1_bm (1<<3) /* High Byte Underflow Interrupt Level bit 1 mask. */
+#define TC2_HUNFINTLVL1_bp 3 /* High Byte Underflow Interrupt Level bit 1 position. */
+
+#define TC2_LUNFINTLVL_gm 0x03 /* Low Byte Underflow interrupt level group mask. */
+#define TC2_LUNFINTLVL_gp 0 /* Low Byte Underflow interrupt level group position. */
+#define TC2_LUNFINTLVL0_bm (1<<0) /* Low Byte Underflow interrupt level bit 0 mask. */
+#define TC2_LUNFINTLVL0_bp 0 /* Low Byte Underflow interrupt level bit 0 position. */
+#define TC2_LUNFINTLVL1_bm (1<<1) /* Low Byte Underflow interrupt level bit 1 mask. */
+#define TC2_LUNFINTLVL1_bp 1 /* Low Byte Underflow interrupt level bit 1 position. */
+
+/* TC2.INTCTRLB bit masks and bit positions */
+#define TC2_LCMPDINTLVL_gm 0xC0 /* Low Byte Compare D Interrupt Level group mask. */
+#define TC2_LCMPDINTLVL_gp 6 /* Low Byte Compare D Interrupt Level group position. */
+#define TC2_LCMPDINTLVL0_bm (1<<6) /* Low Byte Compare D Interrupt Level bit 0 mask. */
+#define TC2_LCMPDINTLVL0_bp 6 /* Low Byte Compare D Interrupt Level bit 0 position. */
+#define TC2_LCMPDINTLVL1_bm (1<<7) /* Low Byte Compare D Interrupt Level bit 1 mask. */
+#define TC2_LCMPDINTLVL1_bp 7 /* Low Byte Compare D Interrupt Level bit 1 position. */
+
+#define TC2_LCMPCINTLVL_gm 0x30 /* Low Byte Compare C Interrupt Level group mask. */
+#define TC2_LCMPCINTLVL_gp 4 /* Low Byte Compare C Interrupt Level group position. */
+#define TC2_LCMPCINTLVL0_bm (1<<4) /* Low Byte Compare C Interrupt Level bit 0 mask. */
+#define TC2_LCMPCINTLVL0_bp 4 /* Low Byte Compare C Interrupt Level bit 0 position. */
+#define TC2_LCMPCINTLVL1_bm (1<<5) /* Low Byte Compare C Interrupt Level bit 1 mask. */
+#define TC2_LCMPCINTLVL1_bp 5 /* Low Byte Compare C Interrupt Level bit 1 position. */
+
+#define TC2_LCMPBINTLVL_gm 0x0C /* Low Byte Compare B Interrupt Level group mask. */
+#define TC2_LCMPBINTLVL_gp 2 /* Low Byte Compare B Interrupt Level group position. */
+#define TC2_LCMPBINTLVL0_bm (1<<2) /* Low Byte Compare B Interrupt Level bit 0 mask. */
+#define TC2_LCMPBINTLVL0_bp 2 /* Low Byte Compare B Interrupt Level bit 0 position. */
+#define TC2_LCMPBINTLVL1_bm (1<<3) /* Low Byte Compare B Interrupt Level bit 1 mask. */
+#define TC2_LCMPBINTLVL1_bp 3 /* Low Byte Compare B Interrupt Level bit 1 position. */
+
+#define TC2_LCMPAINTLVL_gm 0x03 /* Low Byte Compare A Interrupt Level group mask. */
+#define TC2_LCMPAINTLVL_gp 0 /* Low Byte Compare A Interrupt Level group position. */
+#define TC2_LCMPAINTLVL0_bm (1<<0) /* Low Byte Compare A Interrupt Level bit 0 mask. */
+#define TC2_LCMPAINTLVL0_bp 0 /* Low Byte Compare A Interrupt Level bit 0 position. */
+#define TC2_LCMPAINTLVL1_bm (1<<1) /* Low Byte Compare A Interrupt Level bit 1 mask. */
+#define TC2_LCMPAINTLVL1_bp 1 /* Low Byte Compare A Interrupt Level bit 1 position. */
+
+/* TC2.CTRLF bit masks and bit positions */
+#define TC2_CMD_gm 0x0C /* Command group mask. */
+#define TC2_CMD_gp 2 /* Command group position. */
+#define TC2_CMD0_bm (1<<2) /* Command bit 0 mask. */
+#define TC2_CMD0_bp 2 /* Command bit 0 position. */
+#define TC2_CMD1_bm (1<<3) /* Command bit 1 mask. */
+#define TC2_CMD1_bp 3 /* Command bit 1 position. */
+
+#define TC2_CMDEN_gm 0x03 /* Command Enable group mask. */
+#define TC2_CMDEN_gp 0 /* Command Enable group position. */
+#define TC2_CMDEN0_bm (1<<0) /* Command Enable bit 0 mask. */
+#define TC2_CMDEN0_bp 0 /* Command Enable bit 0 position. */
+#define TC2_CMDEN1_bm (1<<1) /* Command Enable bit 1 mask. */
+#define TC2_CMDEN1_bp 1 /* Command Enable bit 1 position. */
+
+/* TC2.INTFLAGS bit masks and bit positions */
+#define TC2_LCMPDIF_bm 0x80 /* Low Byte Compare D Interrupt Flag bit mask. */
+#define TC2_LCMPDIF_bp 7 /* Low Byte Compare D Interrupt Flag bit position. */
+
+#define TC2_LCMPCIF_bm 0x40 /* Low Byte Compare C Interrupt Flag bit mask. */
+#define TC2_LCMPCIF_bp 6 /* Low Byte Compare C Interrupt Flag bit position. */
+
+#define TC2_LCMPBIF_bm 0x20 /* Low Byte Compare B Interrupt Flag bit mask. */
+#define TC2_LCMPBIF_bp 5 /* Low Byte Compare B Interrupt Flag bit position. */
+
+#define TC2_LCMPAIF_bm 0x10 /* Low Byte Compare A Interrupt Flag bit mask. */
+#define TC2_LCMPAIF_bp 4 /* Low Byte Compare A Interrupt Flag bit position. */
+
+#define TC2_HUNFIF_bm 0x02 /* High Byte Underflow Interrupt Flag bit mask. */
+#define TC2_HUNFIF_bp 1 /* High Byte Underflow Interrupt Flag bit position. */
+
+#define TC2_LUNFIF_bm 0x01 /* Low Byte Underflow Interrupt Flag bit mask. */
+#define TC2_LUNFIF_bp 0 /* Low Byte Underflow Interrupt Flag bit position. */
+
+/* AWEX - Timer/Counter Advanced Waveform Extension */
+/* AWEX.CTRL bit masks and bit positions */
+#define AWEX_PGM_bm 0x20 /* Pattern Generation Mode bit mask. */
+#define AWEX_PGM_bp 5 /* Pattern Generation Mode bit position. */
+
+#define AWEX_CWCM_bm 0x10 /* Common Waveform Channel Mode bit mask. */
+#define AWEX_CWCM_bp 4 /* Common Waveform Channel Mode bit position. */
+
+#define AWEX_DTICCDEN_bm 0x08 /* Dead Time Insertion Compare Channel D Enable bit mask. */
+#define AWEX_DTICCDEN_bp 3 /* Dead Time Insertion Compare Channel D Enable bit position. */
+
+#define AWEX_DTICCCEN_bm 0x04 /* Dead Time Insertion Compare Channel C Enable bit mask. */
+#define AWEX_DTICCCEN_bp 2 /* Dead Time Insertion Compare Channel C Enable bit position. */
+
+#define AWEX_DTICCBEN_bm 0x02 /* Dead Time Insertion Compare Channel B Enable bit mask. */
+#define AWEX_DTICCBEN_bp 1 /* Dead Time Insertion Compare Channel B Enable bit position. */
+
+#define AWEX_DTICCAEN_bm 0x01 /* Dead Time Insertion Compare Channel A Enable bit mask. */
+#define AWEX_DTICCAEN_bp 0 /* Dead Time Insertion Compare Channel A Enable bit position. */
+
+/* AWEX.FDCTRL bit masks and bit positions */
+#define AWEX_FDDBD_bm 0x10 /* Fault Detect on Disable Break Disable bit mask. */
+#define AWEX_FDDBD_bp 4 /* Fault Detect on Disable Break Disable bit position. */
+
+#define AWEX_FDMODE_bm 0x04 /* Fault Detect Mode bit mask. */
+#define AWEX_FDMODE_bp 2 /* Fault Detect Mode bit position. */
+
+#define AWEX_FDACT_gm 0x03 /* Fault Detect Action group mask. */
+#define AWEX_FDACT_gp 0 /* Fault Detect Action group position. */
+#define AWEX_FDACT0_bm (1<<0) /* Fault Detect Action bit 0 mask. */
+#define AWEX_FDACT0_bp 0 /* Fault Detect Action bit 0 position. */
+#define AWEX_FDACT1_bm (1<<1) /* Fault Detect Action bit 1 mask. */
+#define AWEX_FDACT1_bp 1 /* Fault Detect Action bit 1 position. */
+
+/* AWEX.STATUS bit masks and bit positions */
+#define AWEX_FDF_bm 0x04 /* Fault Detect Flag bit mask. */
+#define AWEX_FDF_bp 2 /* Fault Detect Flag bit position. */
+
+#define AWEX_DTHSBUFV_bm 0x02 /* Dead Time High Side Buffer Valid bit mask. */
+#define AWEX_DTHSBUFV_bp 1 /* Dead Time High Side Buffer Valid bit position. */
+
+#define AWEX_DTLSBUFV_bm 0x01 /* Dead Time Low Side Buffer Valid bit mask. */
+#define AWEX_DTLSBUFV_bp 0 /* Dead Time Low Side Buffer Valid bit position. */
+
+/* AWEX.STATUSSET bit masks and bit positions */
+/* AWEX_FDF Predefined. */
+/* AWEX_FDF Predefined. */
+
+/* AWEX_DTHSBUFV Predefined. */
+/* AWEX_DTHSBUFV Predefined. */
+
+/* AWEX_DTLSBUFV Predefined. */
+/* AWEX_DTLSBUFV Predefined. */
+
+/* HIRES - Timer/Counter High-Resolution Extension */
+/* HIRES.CTRLA bit masks and bit positions */
+#define HIRES_HREN_gm 0x03 /* High Resolution Enable group mask. */
+#define HIRES_HREN_gp 0 /* High Resolution Enable group position. */
+#define HIRES_HREN0_bm (1<<0) /* High Resolution Enable bit 0 mask. */
+#define HIRES_HREN0_bp 0 /* High Resolution Enable bit 0 position. */
+#define HIRES_HREN1_bm (1<<1) /* High Resolution Enable bit 1 mask. */
+#define HIRES_HREN1_bp 1 /* High Resolution Enable bit 1 position. */
+
+/* USART - Universal Asynchronous Receiver-Transmitter */
+/* USART.STATUS bit masks and bit positions */
+#define USART_RXCIF_bm 0x80 /* Receive Interrupt Flag bit mask. */
+#define USART_RXCIF_bp 7 /* Receive Interrupt Flag bit position. */
+
+#define USART_TXCIF_bm 0x40 /* Transmit Interrupt Flag bit mask. */
+#define USART_TXCIF_bp 6 /* Transmit Interrupt Flag bit position. */
+
+#define USART_DREIF_bm 0x20 /* Data Register Empty Flag bit mask. */
+#define USART_DREIF_bp 5 /* Data Register Empty Flag bit position. */
+
+#define USART_FERR_bm 0x10 /* Frame Error bit mask. */
+#define USART_FERR_bp 4 /* Frame Error bit position. */
+
+#define USART_BUFOVF_bm 0x08 /* Buffer Overflow bit mask. */
+#define USART_BUFOVF_bp 3 /* Buffer Overflow bit position. */
+
+#define USART_PERR_bm 0x04 /* Parity Error bit mask. */
+#define USART_PERR_bp 2 /* Parity Error bit position. */
+
+#define USART_RXB8_bm 0x01 /* Receive Bit 8 bit mask. */
+#define USART_RXB8_bp 0 /* Receive Bit 8 bit position. */
+
+/* USART.CTRLA bit masks and bit positions */
+#define USART_RXCINTLVL_gm 0x30 /* Receive Interrupt Level group mask. */
+#define USART_RXCINTLVL_gp 4 /* Receive Interrupt Level group position. */
+#define USART_RXCINTLVL0_bm (1<<4) /* Receive Interrupt Level bit 0 mask. */
+#define USART_RXCINTLVL0_bp 4 /* Receive Interrupt Level bit 0 position. */
+#define USART_RXCINTLVL1_bm (1<<5) /* Receive Interrupt Level bit 1 mask. */
+#define USART_RXCINTLVL1_bp 5 /* Receive Interrupt Level bit 1 position. */
+
+#define USART_TXCINTLVL_gm 0x0C /* Transmit Interrupt Level group mask. */
+#define USART_TXCINTLVL_gp 2 /* Transmit Interrupt Level group position. */
+#define USART_TXCINTLVL0_bm (1<<2) /* Transmit Interrupt Level bit 0 mask. */
+#define USART_TXCINTLVL0_bp 2 /* Transmit Interrupt Level bit 0 position. */
+#define USART_TXCINTLVL1_bm (1<<3) /* Transmit Interrupt Level bit 1 mask. */
+#define USART_TXCINTLVL1_bp 3 /* Transmit Interrupt Level bit 1 position. */
+
+#define USART_DREINTLVL_gm 0x03 /* Data Register Empty Interrupt Level group mask. */
+#define USART_DREINTLVL_gp 0 /* Data Register Empty Interrupt Level group position. */
+#define USART_DREINTLVL0_bm (1<<0) /* Data Register Empty Interrupt Level bit 0 mask. */
+#define USART_DREINTLVL0_bp 0 /* Data Register Empty Interrupt Level bit 0 position. */
+#define USART_DREINTLVL1_bm (1<<1) /* Data Register Empty Interrupt Level bit 1 mask. */
+#define USART_DREINTLVL1_bp 1 /* Data Register Empty Interrupt Level bit 1 position. */
+
+/* USART.CTRLB bit masks and bit positions */
+#define USART_RXEN_bm 0x10 /* Receiver Enable bit mask. */
+#define USART_RXEN_bp 4 /* Receiver Enable bit position. */
+
+#define USART_TXEN_bm 0x08 /* Transmitter Enable bit mask. */
+#define USART_TXEN_bp 3 /* Transmitter Enable bit position. */
+
+#define USART_CLK2X_bm 0x04 /* Double transmission speed bit mask. */
+#define USART_CLK2X_bp 2 /* Double transmission speed bit position. */
+
+#define USART_MPCM_bm 0x02 /* Multi-processor Communication Mode bit mask. */
+#define USART_MPCM_bp 1 /* Multi-processor Communication Mode bit position. */
+
+#define USART_TXB8_bm 0x01 /* Transmit bit 8 bit mask. */
+#define USART_TXB8_bp 0 /* Transmit bit 8 bit position. */
+
+/* USART.CTRLC bit masks and bit positions */
+#define USART_CMODE_gm 0xC0 /* Communication Mode group mask. */
+#define USART_CMODE_gp 6 /* Communication Mode group position. */
+#define USART_CMODE0_bm (1<<6) /* Communication Mode bit 0 mask. */
+#define USART_CMODE0_bp 6 /* Communication Mode bit 0 position. */
+#define USART_CMODE1_bm (1<<7) /* Communication Mode bit 1 mask. */
+#define USART_CMODE1_bp 7 /* Communication Mode bit 1 position. */
+
+#define USART_PMODE_gm 0x30 /* Parity Mode group mask. */
+#define USART_PMODE_gp 4 /* Parity Mode group position. */
+#define USART_PMODE0_bm (1<<4) /* Parity Mode bit 0 mask. */
+#define USART_PMODE0_bp 4 /* Parity Mode bit 0 position. */
+#define USART_PMODE1_bm (1<<5) /* Parity Mode bit 1 mask. */
+#define USART_PMODE1_bp 5 /* Parity Mode bit 1 position. */
+
+#define USART_SBMODE_bm 0x08 /* Stop Bit Mode bit mask. */
+#define USART_SBMODE_bp 3 /* Stop Bit Mode bit position. */
+
+#define USART_CHSIZE_gm 0x07 /* Character Size group mask. */
+#define USART_CHSIZE_gp 0 /* Character Size group position. */
+#define USART_CHSIZE0_bm (1<<0) /* Character Size bit 0 mask. */
+#define USART_CHSIZE0_bp 0 /* Character Size bit 0 position. */
+#define USART_CHSIZE1_bm (1<<1) /* Character Size bit 1 mask. */
+#define USART_CHSIZE1_bp 1 /* Character Size bit 1 position. */
+#define USART_CHSIZE2_bm (1<<2) /* Character Size bit 2 mask. */
+#define USART_CHSIZE2_bp 2 /* Character Size bit 2 position. */
+
+/* USART.BAUDCTRLA bit masks and bit positions */
+#define USART_BSEL_gm 0xFF /* Baud Rate Selection Bits [7:0] group mask. */
+#define USART_BSEL_gp 0 /* Baud Rate Selection Bits [7:0] group position. */
+#define USART_BSEL0_bm (1<<0) /* Baud Rate Selection Bits [7:0] bit 0 mask. */
+#define USART_BSEL0_bp 0 /* Baud Rate Selection Bits [7:0] bit 0 position. */
+#define USART_BSEL1_bm (1<<1) /* Baud Rate Selection Bits [7:0] bit 1 mask. */
+#define USART_BSEL1_bp 1 /* Baud Rate Selection Bits [7:0] bit 1 position. */
+#define USART_BSEL2_bm (1<<2) /* Baud Rate Selection Bits [7:0] bit 2 mask. */
+#define USART_BSEL2_bp 2 /* Baud Rate Selection Bits [7:0] bit 2 position. */
+#define USART_BSEL3_bm (1<<3) /* Baud Rate Selection Bits [7:0] bit 3 mask. */
+#define USART_BSEL3_bp 3 /* Baud Rate Selection Bits [7:0] bit 3 position. */
+#define USART_BSEL4_bm (1<<4) /* Baud Rate Selection Bits [7:0] bit 4 mask. */
+#define USART_BSEL4_bp 4 /* Baud Rate Selection Bits [7:0] bit 4 position. */
+#define USART_BSEL5_bm (1<<5) /* Baud Rate Selection Bits [7:0] bit 5 mask. */
+#define USART_BSEL5_bp 5 /* Baud Rate Selection Bits [7:0] bit 5 position. */
+#define USART_BSEL6_bm (1<<6) /* Baud Rate Selection Bits [7:0] bit 6 mask. */
+#define USART_BSEL6_bp 6 /* Baud Rate Selection Bits [7:0] bit 6 position. */
+#define USART_BSEL7_bm (1<<7) /* Baud Rate Selection Bits [7:0] bit 7 mask. */
+#define USART_BSEL7_bp 7 /* Baud Rate Selection Bits [7:0] bit 7 position. */
+
+/* USART.BAUDCTRLB bit masks and bit positions */
+#define USART_BSCALE_gm 0xF0 /* Baud Rate Scale group mask. */
+#define USART_BSCALE_gp 4 /* Baud Rate Scale group position. */
+#define USART_BSCALE0_bm (1<<4) /* Baud Rate Scale bit 0 mask. */
+#define USART_BSCALE0_bp 4 /* Baud Rate Scale bit 0 position. */
+#define USART_BSCALE1_bm (1<<5) /* Baud Rate Scale bit 1 mask. */
+#define USART_BSCALE1_bp 5 /* Baud Rate Scale bit 1 position. */
+#define USART_BSCALE2_bm (1<<6) /* Baud Rate Scale bit 2 mask. */
+#define USART_BSCALE2_bp 6 /* Baud Rate Scale bit 2 position. */
+#define USART_BSCALE3_bm (1<<7) /* Baud Rate Scale bit 3 mask. */
+#define USART_BSCALE3_bp 7 /* Baud Rate Scale bit 3 position. */
+
+/* USART_BSEL Predefined. */
+/* USART_BSEL Predefined. */
+
+/* SPI - Serial Peripheral Interface */
+/* SPI.CTRL bit masks and bit positions */
+#define SPI_CLK2X_bm 0x80 /* Enable Double Speed bit mask. */
+#define SPI_CLK2X_bp 7 /* Enable Double Speed bit position. */
+
+#define SPI_ENABLE_bm 0x40 /* Enable Module bit mask. */
+#define SPI_ENABLE_bp 6 /* Enable Module bit position. */
+
+#define SPI_DORD_bm 0x20 /* Data Order Setting bit mask. */
+#define SPI_DORD_bp 5 /* Data Order Setting bit position. */
+
+#define SPI_MASTER_bm 0x10 /* Master Operation Enable bit mask. */
+#define SPI_MASTER_bp 4 /* Master Operation Enable bit position. */
+
+#define SPI_MODE_gm 0x0C /* SPI Mode group mask. */
+#define SPI_MODE_gp 2 /* SPI Mode group position. */
+#define SPI_MODE0_bm (1<<2) /* SPI Mode bit 0 mask. */
+#define SPI_MODE0_bp 2 /* SPI Mode bit 0 position. */
+#define SPI_MODE1_bm (1<<3) /* SPI Mode bit 1 mask. */
+#define SPI_MODE1_bp 3 /* SPI Mode bit 1 position. */
+
+#define SPI_PRESCALER_gm 0x03 /* Prescaler group mask. */
+#define SPI_PRESCALER_gp 0 /* Prescaler group position. */
+#define SPI_PRESCALER0_bm (1<<0) /* Prescaler bit 0 mask. */
+#define SPI_PRESCALER0_bp 0 /* Prescaler bit 0 position. */
+#define SPI_PRESCALER1_bm (1<<1) /* Prescaler bit 1 mask. */
+#define SPI_PRESCALER1_bp 1 /* Prescaler bit 1 position. */
+
+/* SPI.INTCTRL bit masks and bit positions */
+#define SPI_INTLVL_gm 0x03 /* Interrupt level group mask. */
+#define SPI_INTLVL_gp 0 /* Interrupt level group position. */
+#define SPI_INTLVL0_bm (1<<0) /* Interrupt level bit 0 mask. */
+#define SPI_INTLVL0_bp 0 /* Interrupt level bit 0 position. */
+#define SPI_INTLVL1_bm (1<<1) /* Interrupt level bit 1 mask. */
+#define SPI_INTLVL1_bp 1 /* Interrupt level bit 1 position. */
+
+/* SPI.STATUS bit masks and bit positions */
+#define SPI_IF_bm 0x80 /* Interrupt Flag bit mask. */
+#define SPI_IF_bp 7 /* Interrupt Flag bit position. */
+
+#define SPI_WRCOL_bm 0x40 /* Write Collision bit mask. */
+#define SPI_WRCOL_bp 6 /* Write Collision bit position. */
+
+/* IRCOM - IR Communication Module */
+/* IRCOM.CTRL bit masks and bit positions */
+#define IRCOM_EVSEL_gm 0x0F /* Event Channel Select group mask. */
+#define IRCOM_EVSEL_gp 0 /* Event Channel Select group position. */
+#define IRCOM_EVSEL0_bm (1<<0) /* Event Channel Select bit 0 mask. */
+#define IRCOM_EVSEL0_bp 0 /* Event Channel Select bit 0 position. */
+#define IRCOM_EVSEL1_bm (1<<1) /* Event Channel Select bit 1 mask. */
+#define IRCOM_EVSEL1_bp 1 /* Event Channel Select bit 1 position. */
+#define IRCOM_EVSEL2_bm (1<<2) /* Event Channel Select bit 2 mask. */
+#define IRCOM_EVSEL2_bp 2 /* Event Channel Select bit 2 position. */
+#define IRCOM_EVSEL3_bm (1<<3) /* Event Channel Select bit 3 mask. */
+#define IRCOM_EVSEL3_bp 3 /* Event Channel Select bit 3 position. */
+
+/* FUSE - Fuses and Lockbits */
+/* NVM_FUSES.FUSEBYTE0 bit masks and bit positions */
+#define NVM_FUSES_JTAGUSERID_gm 0xFF /* JTAG User ID group mask. */
+#define NVM_FUSES_JTAGUSERID_gp 0 /* JTAG User ID group position. */
+#define NVM_FUSES_JTAGUSERID0_bm (1<<0) /* JTAG User ID bit 0 mask. */
+#define NVM_FUSES_JTAGUSERID0_bp 0 /* JTAG User ID bit 0 position. */
+#define NVM_FUSES_JTAGUSERID1_bm (1<<1) /* JTAG User ID bit 1 mask. */
+#define NVM_FUSES_JTAGUSERID1_bp 1 /* JTAG User ID bit 1 position. */
+#define NVM_FUSES_JTAGUSERID2_bm (1<<2) /* JTAG User ID bit 2 mask. */
+#define NVM_FUSES_JTAGUSERID2_bp 2 /* JTAG User ID bit 2 position. */
+#define NVM_FUSES_JTAGUSERID3_bm (1<<3) /* JTAG User ID bit 3 mask. */
+#define NVM_FUSES_JTAGUSERID3_bp 3 /* JTAG User ID bit 3 position. */
+#define NVM_FUSES_JTAGUSERID4_bm (1<<4) /* JTAG User ID bit 4 mask. */
+#define NVM_FUSES_JTAGUSERID4_bp 4 /* JTAG User ID bit 4 position. */
+#define NVM_FUSES_JTAGUSERID5_bm (1<<5) /* JTAG User ID bit 5 mask. */
+#define NVM_FUSES_JTAGUSERID5_bp 5 /* JTAG User ID bit 5 position. */
+#define NVM_FUSES_JTAGUSERID6_bm (1<<6) /* JTAG User ID bit 6 mask. */
+#define NVM_FUSES_JTAGUSERID6_bp 6 /* JTAG User ID bit 6 position. */
+#define NVM_FUSES_JTAGUSERID7_bm (1<<7) /* JTAG User ID bit 7 mask. */
+#define NVM_FUSES_JTAGUSERID7_bp 7 /* JTAG User ID bit 7 position. */
+
+/* NVM_FUSES.FUSEBYTE1 bit masks and bit positions */
+#define NVM_FUSES_WDWP_gm 0xF0 /* Watchdog Window Timeout Period group mask. */
+#define NVM_FUSES_WDWP_gp 4 /* Watchdog Window Timeout Period group position. */
+#define NVM_FUSES_WDWP0_bm (1<<4) /* Watchdog Window Timeout Period bit 0 mask. */
+#define NVM_FUSES_WDWP0_bp 4 /* Watchdog Window Timeout Period bit 0 position. */
+#define NVM_FUSES_WDWP1_bm (1<<5) /* Watchdog Window Timeout Period bit 1 mask. */
+#define NVM_FUSES_WDWP1_bp 5 /* Watchdog Window Timeout Period bit 1 position. */
+#define NVM_FUSES_WDWP2_bm (1<<6) /* Watchdog Window Timeout Period bit 2 mask. */
+#define NVM_FUSES_WDWP2_bp 6 /* Watchdog Window Timeout Period bit 2 position. */
+#define NVM_FUSES_WDWP3_bm (1<<7) /* Watchdog Window Timeout Period bit 3 mask. */
+#define NVM_FUSES_WDWP3_bp 7 /* Watchdog Window Timeout Period bit 3 position. */
+
+#define NVM_FUSES_WDP_gm 0x0F /* Watchdog Timeout Period group mask. */
+#define NVM_FUSES_WDP_gp 0 /* Watchdog Timeout Period group position. */
+#define NVM_FUSES_WDP0_bm (1<<0) /* Watchdog Timeout Period bit 0 mask. */
+#define NVM_FUSES_WDP0_bp 0 /* Watchdog Timeout Period bit 0 position. */
+#define NVM_FUSES_WDP1_bm (1<<1) /* Watchdog Timeout Period bit 1 mask. */
+#define NVM_FUSES_WDP1_bp 1 /* Watchdog Timeout Period bit 1 position. */
+#define NVM_FUSES_WDP2_bm (1<<2) /* Watchdog Timeout Period bit 2 mask. */
+#define NVM_FUSES_WDP2_bp 2 /* Watchdog Timeout Period bit 2 position. */
+#define NVM_FUSES_WDP3_bm (1<<3) /* Watchdog Timeout Period bit 3 mask. */
+#define NVM_FUSES_WDP3_bp 3 /* Watchdog Timeout Period bit 3 position. */
+
+/* NVM_FUSES.FUSEBYTE2 bit masks and bit positions */
+#define NVM_FUSES_BOOTRST_bm 0x40 /* Boot Loader Section Reset Vector bit mask. */
+#define NVM_FUSES_BOOTRST_bp 6 /* Boot Loader Section Reset Vector bit position. */
+
+#define NVM_FUSES_TOSCSEL_bm 0x20 /* Timer Oscillator pin location bit mask. */
+#define NVM_FUSES_TOSCSEL_bp 5 /* Timer Oscillator pin location bit position. */
+
+#define NVM_FUSES_BODPD_gm 0x03 /* BOD Operation in Power-Down Mode group mask. */
+#define NVM_FUSES_BODPD_gp 0 /* BOD Operation in Power-Down Mode group position. */
+#define NVM_FUSES_BODPD0_bm (1<<0) /* BOD Operation in Power-Down Mode bit 0 mask. */
+#define NVM_FUSES_BODPD0_bp 0 /* BOD Operation in Power-Down Mode bit 0 position. */
+#define NVM_FUSES_BODPD1_bm (1<<1) /* BOD Operation in Power-Down Mode bit 1 mask. */
+#define NVM_FUSES_BODPD1_bp 1 /* BOD Operation in Power-Down Mode bit 1 position. */
+
+/* NVM_FUSES.FUSEBYTE4 bit masks and bit positions */
+#define NVM_FUSES_RSTDISBL_bm 0x10 /* External Reset Disable bit mask. */
+#define NVM_FUSES_RSTDISBL_bp 4 /* External Reset Disable bit position. */
+
+#define NVM_FUSES_SUT_gm 0x0C /* Start-up Time group mask. */
+#define NVM_FUSES_SUT_gp 2 /* Start-up Time group position. */
+#define NVM_FUSES_SUT0_bm (1<<2) /* Start-up Time bit 0 mask. */
+#define NVM_FUSES_SUT0_bp 2 /* Start-up Time bit 0 position. */
+#define NVM_FUSES_SUT1_bm (1<<3) /* Start-up Time bit 1 mask. */
+#define NVM_FUSES_SUT1_bp 3 /* Start-up Time bit 1 position. */
+
+#define NVM_FUSES_WDLOCK_bm 0x02 /* Watchdog Timer Lock bit mask. */
+#define NVM_FUSES_WDLOCK_bp 1 /* Watchdog Timer Lock bit position. */
+
+#define NVM_FUSES_JTAGEN_bm 0x01 /* JTAG Interface Enable bit mask. */
+#define NVM_FUSES_JTAGEN_bp 0 /* JTAG Interface Enable bit position. */
+
+/* NVM_FUSES.FUSEBYTE5 bit masks and bit positions */
+#define NVM_FUSES_BODACT_gm 0x30 /* BOD Operation in Active Mode group mask. */
+#define NVM_FUSES_BODACT_gp 4 /* BOD Operation in Active Mode group position. */
+#define NVM_FUSES_BODACT0_bm (1<<4) /* BOD Operation in Active Mode bit 0 mask. */
+#define NVM_FUSES_BODACT0_bp 4 /* BOD Operation in Active Mode bit 0 position. */
+#define NVM_FUSES_BODACT1_bm (1<<5) /* BOD Operation in Active Mode bit 1 mask. */
+#define NVM_FUSES_BODACT1_bp 5 /* BOD Operation in Active Mode bit 1 position. */
+
+#define NVM_FUSES_EESAVE_bm 0x08 /* Preserve EEPROM Through Chip Erase bit mask. */
+#define NVM_FUSES_EESAVE_bp 3 /* Preserve EEPROM Through Chip Erase bit position. */
+
+#define NVM_FUSES_BODLVL_gm 0x07 /* Brownout Detection Voltage Level group mask. */
+#define NVM_FUSES_BODLVL_gp 0 /* Brownout Detection Voltage Level group position. */
+#define NVM_FUSES_BODLVL0_bm (1<<0) /* Brownout Detection Voltage Level bit 0 mask. */
+#define NVM_FUSES_BODLVL0_bp 0 /* Brownout Detection Voltage Level bit 0 position. */
+#define NVM_FUSES_BODLVL1_bm (1<<1) /* Brownout Detection Voltage Level bit 1 mask. */
+#define NVM_FUSES_BODLVL1_bp 1 /* Brownout Detection Voltage Level bit 1 position. */
+#define NVM_FUSES_BODLVL2_bm (1<<2) /* Brownout Detection Voltage Level bit 2 mask. */
+#define NVM_FUSES_BODLVL2_bp 2 /* Brownout Detection Voltage Level bit 2 position. */
+
+/* LOCKBIT - Fuses and Lockbits */
+/* NVM_LOCKBITS.LOCKBITS bit masks and bit positions */
+#define NVM_LOCKBITS_BLBB_gm 0xC0 /* Boot Lock Bits - Boot Section group mask. */
+#define NVM_LOCKBITS_BLBB_gp 6 /* Boot Lock Bits - Boot Section group position. */
+#define NVM_LOCKBITS_BLBB0_bm (1<<6) /* Boot Lock Bits - Boot Section bit 0 mask. */
+#define NVM_LOCKBITS_BLBB0_bp 6 /* Boot Lock Bits - Boot Section bit 0 position. */
+#define NVM_LOCKBITS_BLBB1_bm (1<<7) /* Boot Lock Bits - Boot Section bit 1 mask. */
+#define NVM_LOCKBITS_BLBB1_bp 7 /* Boot Lock Bits - Boot Section bit 1 position. */
+
+#define NVM_LOCKBITS_BLBA_gm 0x30 /* Boot Lock Bits - Application Section group mask. */
+#define NVM_LOCKBITS_BLBA_gp 4 /* Boot Lock Bits - Application Section group position. */
+#define NVM_LOCKBITS_BLBA0_bm (1<<4) /* Boot Lock Bits - Application Section bit 0 mask. */
+#define NVM_LOCKBITS_BLBA0_bp 4 /* Boot Lock Bits - Application Section bit 0 position. */
+#define NVM_LOCKBITS_BLBA1_bm (1<<5) /* Boot Lock Bits - Application Section bit 1 mask. */
+#define NVM_LOCKBITS_BLBA1_bp 5 /* Boot Lock Bits - Application Section bit 1 position. */
+
+#define NVM_LOCKBITS_BLBAT_gm 0x0C /* Boot Lock Bits - Application Table group mask. */
+#define NVM_LOCKBITS_BLBAT_gp 2 /* Boot Lock Bits - Application Table group position. */
+#define NVM_LOCKBITS_BLBAT0_bm (1<<2) /* Boot Lock Bits - Application Table bit 0 mask. */
+#define NVM_LOCKBITS_BLBAT0_bp 2 /* Boot Lock Bits - Application Table bit 0 position. */
+#define NVM_LOCKBITS_BLBAT1_bm (1<<3) /* Boot Lock Bits - Application Table bit 1 mask. */
+#define NVM_LOCKBITS_BLBAT1_bp 3 /* Boot Lock Bits - Application Table bit 1 position. */
+
+#define NVM_LOCKBITS_LB_gm 0x03 /* Lock Bits group mask. */
+#define NVM_LOCKBITS_LB_gp 0 /* Lock Bits group position. */
+#define NVM_LOCKBITS_LB0_bm (1<<0) /* Lock Bits bit 0 mask. */
+#define NVM_LOCKBITS_LB0_bp 0 /* Lock Bits bit 0 position. */
+#define NVM_LOCKBITS_LB1_bm (1<<1) /* Lock Bits bit 1 mask. */
+#define NVM_LOCKBITS_LB1_bp 1 /* Lock Bits bit 1 position. */
+
+
+
+// Generic Port Pins
+
+#define PIN0_bm 0x01
+#define PIN0_bp 0
+#define PIN1_bm 0x02
+#define PIN1_bp 1
+#define PIN2_bm 0x04
+#define PIN2_bp 2
+#define PIN3_bm 0x08
+#define PIN3_bp 3
+#define PIN4_bm 0x10
+#define PIN4_bp 4
+#define PIN5_bm 0x20
+#define PIN5_bp 5
+#define PIN6_bm 0x40
+#define PIN6_bp 6
+#define PIN7_bm 0x80
+#define PIN7_bp 7
+
+/* ========== Interrupt Vector Definitions ========== */
+/* Vector 0 is the reset vector */
+
+/* OSC interrupt vectors */
+#define OSC_OSCF_vect_num 1
+#define OSC_OSCF_vect _VECTOR(1) /* Oscillator Failure Interrupt (NMI) */
+
+/* PORTC interrupt vectors */
+#define PORTC_INT0_vect_num 2
+#define PORTC_INT0_vect _VECTOR(2) /* External Interrupt 0 */
+#define PORTC_INT1_vect_num 3
+#define PORTC_INT1_vect _VECTOR(3) /* External Interrupt 1 */
+
+/* PORTR interrupt vectors */
+#define PORTR_INT0_vect_num 4
+#define PORTR_INT0_vect _VECTOR(4) /* External Interrupt 0 */
+#define PORTR_INT1_vect_num 5
+#define PORTR_INT1_vect _VECTOR(5) /* External Interrupt 1 */
+
+/* DMA interrupt vectors */
+#define DMA_CH0_vect_num 6
+#define DMA_CH0_vect _VECTOR(6) /* Channel 0 Interrupt */
+#define DMA_CH1_vect_num 7
+#define DMA_CH1_vect _VECTOR(7) /* Channel 1 Interrupt */
+#define DMA_CH2_vect_num 8
+#define DMA_CH2_vect _VECTOR(8) /* Channel 2 Interrupt */
+#define DMA_CH3_vect_num 9
+#define DMA_CH3_vect _VECTOR(9) /* Channel 3 Interrupt */
+
+/* RTC interrupt vectors */
+#define RTC_OVF_vect_num 10
+#define RTC_OVF_vect _VECTOR(10) /* Overflow Interrupt */
+#define RTC_COMP_vect_num 11
+#define RTC_COMP_vect _VECTOR(11) /* Compare Interrupt */
+
+/* TWIC interrupt vectors */
+#define TWIC_TWIS_vect_num 12
+#define TWIC_TWIS_vect _VECTOR(12) /* TWI Slave Interrupt */
+#define TWIC_TWIM_vect_num 13
+#define TWIC_TWIM_vect _VECTOR(13) /* TWI Master Interrupt */
+
+/* TCC0 interrupt vectors */
+#define TCC0_OVF_vect_num 14
+#define TCC0_OVF_vect _VECTOR(14) /* Overflow Interrupt */
+
+/* TCC2 interrupt vectors */
+#define TCC2_LUNF_vect_num 14
+#define TCC2_LUNF_vect _VECTOR(14) /* Low Byte Underflow Interrupt */
+
+/* TCC0 interrupt vectors */
+#define TCC0_ERR_vect_num 15
+#define TCC0_ERR_vect _VECTOR(15) /* Error Interrupt */
+
+/* TCC2 interrupt vectors */
+#define TCC2_HUNF_vect_num 15
+#define TCC2_HUNF_vect _VECTOR(15) /* High Byte Underflow Interrupt */
+
+/* TCC0 interrupt vectors */
+#define TCC0_CCA_vect_num 16
+#define TCC0_CCA_vect _VECTOR(16) /* Compare or Capture A Interrupt */
+
+/* TCC2 interrupt vectors */
+#define TCC2_LCMPA_vect_num 16
+#define TCC2_LCMPA_vect _VECTOR(16) /* Low Byte Compare A Interrupt */
+
+/* TCC0 interrupt vectors */
+#define TCC0_CCB_vect_num 17
+#define TCC0_CCB_vect _VECTOR(17) /* Compare or Capture B Interrupt */
+
+/* TCC2 interrupt vectors */
+#define TCC2_LCMPB_vect_num 17
+#define TCC2_LCMPB_vect _VECTOR(17) /* Low Byte Compare B Interrupt */
+
+/* TCC0 interrupt vectors */
+#define TCC0_CCC_vect_num 18
+#define TCC0_CCC_vect _VECTOR(18) /* Compare or Capture C Interrupt */
+
+/* TCC2 interrupt vectors */
+#define TCC2_LCMPC_vect_num 18
+#define TCC2_LCMPC_vect _VECTOR(18) /* Low Byte Compare C Interrupt */
+
+/* TCC0 interrupt vectors */
+#define TCC0_CCD_vect_num 19
+#define TCC0_CCD_vect _VECTOR(19) /* Compare or Capture D Interrupt */
+
+/* TCC2 interrupt vectors */
+#define TCC2_LCMPD_vect_num 19
+#define TCC2_LCMPD_vect _VECTOR(19) /* Low Byte Compare D Interrupt */
+
+/* TCC1 interrupt vectors */
+#define TCC1_OVF_vect_num 20
+#define TCC1_OVF_vect _VECTOR(20) /* Overflow Interrupt */
+#define TCC1_ERR_vect_num 21
+#define TCC1_ERR_vect _VECTOR(21) /* Error Interrupt */
+#define TCC1_CCA_vect_num 22
+#define TCC1_CCA_vect _VECTOR(22) /* Compare or Capture A Interrupt */
+#define TCC1_CCB_vect_num 23
+#define TCC1_CCB_vect _VECTOR(23) /* Compare or Capture B Interrupt */
+
+/* SPIC interrupt vectors */
+#define SPIC_INT_vect_num 24
+#define SPIC_INT_vect _VECTOR(24) /* SPI Interrupt */
+
+/* USARTC0 interrupt vectors */
+#define USARTC0_RXC_vect_num 25
+#define USARTC0_RXC_vect _VECTOR(25) /* Reception Complete Interrupt */
+#define USARTC0_DRE_vect_num 26
+#define USARTC0_DRE_vect _VECTOR(26) /* Data Register Empty Interrupt */
+#define USARTC0_TXC_vect_num 27
+#define USARTC0_TXC_vect _VECTOR(27) /* Transmission Complete Interrupt */
+
+/* USARTC1 interrupt vectors */
+#define USARTC1_RXC_vect_num 28
+#define USARTC1_RXC_vect _VECTOR(28) /* Reception Complete Interrupt */
+#define USARTC1_DRE_vect_num 29
+#define USARTC1_DRE_vect _VECTOR(29) /* Data Register Empty Interrupt */
+#define USARTC1_TXC_vect_num 30
+#define USARTC1_TXC_vect _VECTOR(30) /* Transmission Complete Interrupt */
+
+/* AES interrupt vectors */
+#define AES_INT_vect_num 31
+#define AES_INT_vect _VECTOR(31) /* AES Interrupt */
+
+/* NVM interrupt vectors */
+#define NVM_EE_vect_num 32
+#define NVM_EE_vect _VECTOR(32) /* EE Interrupt */
+#define NVM_SPM_vect_num 33
+#define NVM_SPM_vect _VECTOR(33) /* SPM Interrupt */
+
+/* PORTB interrupt vectors */
+#define PORTB_INT0_vect_num 34
+#define PORTB_INT0_vect _VECTOR(34) /* External Interrupt 0 */
+#define PORTB_INT1_vect_num 35
+#define PORTB_INT1_vect _VECTOR(35) /* External Interrupt 1 */
+
+/* ACB interrupt vectors */
+#define ACB_AC0_vect_num 36
+#define ACB_AC0_vect _VECTOR(36) /* AC0 Interrupt */
+#define ACB_AC1_vect_num 37
+#define ACB_AC1_vect _VECTOR(37) /* AC1 Interrupt */
+#define ACB_ACW_vect_num 38
+#define ACB_ACW_vect _VECTOR(38) /* ACW Window Mode Interrupt */
+
+/* ADCB interrupt vectors */
+#define ADCB_CH0_vect_num 39
+#define ADCB_CH0_vect _VECTOR(39) /* Interrupt 0 */
+#define ADCB_CH1_vect_num 40
+#define ADCB_CH1_vect _VECTOR(40) /* Interrupt 1 */
+#define ADCB_CH2_vect_num 41
+#define ADCB_CH2_vect _VECTOR(41) /* Interrupt 2 */
+#define ADCB_CH3_vect_num 42
+#define ADCB_CH3_vect _VECTOR(42) /* Interrupt 3 */
+
+/* PORTE interrupt vectors */
+#define PORTE_INT0_vect_num 43
+#define PORTE_INT0_vect _VECTOR(43) /* External Interrupt 0 */
+#define PORTE_INT1_vect_num 44
+#define PORTE_INT1_vect _VECTOR(44) /* External Interrupt 1 */
+
+/* TWIE interrupt vectors */
+#define TWIE_TWIS_vect_num 45
+#define TWIE_TWIS_vect _VECTOR(45) /* TWI Slave Interrupt */
+#define TWIE_TWIM_vect_num 46
+#define TWIE_TWIM_vect _VECTOR(46) /* TWI Master Interrupt */
+
+/* TCE0 interrupt vectors */
+#define TCE0_OVF_vect_num 47
+#define TCE0_OVF_vect _VECTOR(47) /* Overflow Interrupt */
+
+/* TCE2 interrupt vectors */
+#define TCE2_LUNF_vect_num 47
+#define TCE2_LUNF_vect _VECTOR(47) /* Low Byte Underflow Interrupt */
+
+/* TCE0 interrupt vectors */
+#define TCE0_ERR_vect_num 48
+#define TCE0_ERR_vect _VECTOR(48) /* Error Interrupt */
+
+/* TCE2 interrupt vectors */
+#define TCE2_HUNF_vect_num 48
+#define TCE2_HUNF_vect _VECTOR(48) /* High Byte Underflow Interrupt */
+
+/* TCE0 interrupt vectors */
+#define TCE0_CCA_vect_num 49
+#define TCE0_CCA_vect _VECTOR(49) /* Compare or Capture A Interrupt */
+
+/* TCE2 interrupt vectors */
+#define TCE2_LCMPA_vect_num 49
+#define TCE2_LCMPA_vect _VECTOR(49) /* Low Byte Compare A Interrupt */
+
+/* TCE0 interrupt vectors */
+#define TCE0_CCB_vect_num 50
+#define TCE0_CCB_vect _VECTOR(50) /* Compare or Capture B Interrupt */
+
+/* TCE2 interrupt vectors */
+#define TCE2_LCMPB_vect_num 50
+#define TCE2_LCMPB_vect _VECTOR(50) /* Low Byte Compare B Interrupt */
+
+/* TCE0 interrupt vectors */
+#define TCE0_CCC_vect_num 51
+#define TCE0_CCC_vect _VECTOR(51) /* Compare or Capture C Interrupt */
+
+/* TCE2 interrupt vectors */
+#define TCE2_LCMPC_vect_num 51
+#define TCE2_LCMPC_vect _VECTOR(51) /* Low Byte Compare C Interrupt */
+
+/* TCE0 interrupt vectors */
+#define TCE0_CCD_vect_num 52
+#define TCE0_CCD_vect _VECTOR(52) /* Compare or Capture D Interrupt */
+
+/* TCE2 interrupt vectors */
+#define TCE2_LCMPD_vect_num 52
+#define TCE2_LCMPD_vect _VECTOR(52) /* Low Byte Compare D Interrupt */
+
+/* TCE1 interrupt vectors */
+#define TCE1_OVF_vect_num 53
+#define TCE1_OVF_vect _VECTOR(53) /* Overflow Interrupt */
+#define TCE1_ERR_vect_num 54
+#define TCE1_ERR_vect _VECTOR(54) /* Error Interrupt */
+#define TCE1_CCA_vect_num 55
+#define TCE1_CCA_vect _VECTOR(55) /* Compare or Capture A Interrupt */
+#define TCE1_CCB_vect_num 56
+#define TCE1_CCB_vect _VECTOR(56) /* Compare or Capture B Interrupt */
+
+/* SPIE interrupt vectors */
+#define SPIE_INT_vect_num 57
+#define SPIE_INT_vect _VECTOR(57) /* SPI Interrupt */
+
+/* USARTE0 interrupt vectors */
+#define USARTE0_RXC_vect_num 58
+#define USARTE0_RXC_vect _VECTOR(58) /* Reception Complete Interrupt */
+#define USARTE0_DRE_vect_num 59
+#define USARTE0_DRE_vect _VECTOR(59) /* Data Register Empty Interrupt */
+#define USARTE0_TXC_vect_num 60
+#define USARTE0_TXC_vect _VECTOR(60) /* Transmission Complete Interrupt */
+
+/* USARTE1 interrupt vectors */
+#define USARTE1_RXC_vect_num 61
+#define USARTE1_RXC_vect _VECTOR(61) /* Reception Complete Interrupt */
+#define USARTE1_DRE_vect_num 62
+#define USARTE1_DRE_vect _VECTOR(62) /* Data Register Empty Interrupt */
+#define USARTE1_TXC_vect_num 63
+#define USARTE1_TXC_vect _VECTOR(63) /* Transmission Complete Interrupt */
+
+/* PORTD interrupt vectors */
+#define PORTD_INT0_vect_num 64
+#define PORTD_INT0_vect _VECTOR(64) /* External Interrupt 0 */
+#define PORTD_INT1_vect_num 65
+#define PORTD_INT1_vect _VECTOR(65) /* External Interrupt 1 */
+
+/* PORTA interrupt vectors */
+#define PORTA_INT0_vect_num 66
+#define PORTA_INT0_vect _VECTOR(66) /* External Interrupt 0 */
+#define PORTA_INT1_vect_num 67
+#define PORTA_INT1_vect _VECTOR(67) /* External Interrupt 1 */
+
+/* ACA interrupt vectors */
+#define ACA_AC0_vect_num 68
+#define ACA_AC0_vect _VECTOR(68) /* AC0 Interrupt */
+#define ACA_AC1_vect_num 69
+#define ACA_AC1_vect _VECTOR(69) /* AC1 Interrupt */
+#define ACA_ACW_vect_num 70
+#define ACA_ACW_vect _VECTOR(70) /* ACW Window Mode Interrupt */
+
+/* ADCA interrupt vectors */
+#define ADCA_CH0_vect_num 71
+#define ADCA_CH0_vect _VECTOR(71) /* Interrupt 0 */
+#define ADCA_CH1_vect_num 72
+#define ADCA_CH1_vect _VECTOR(72) /* Interrupt 1 */
+#define ADCA_CH2_vect_num 73
+#define ADCA_CH2_vect _VECTOR(73) /* Interrupt 2 */
+#define ADCA_CH3_vect_num 74
+#define ADCA_CH3_vect _VECTOR(74) /* Interrupt 3 */
+
+/* TCD0 interrupt vectors */
+#define TCD0_OVF_vect_num 77
+#define TCD0_OVF_vect _VECTOR(77) /* Overflow Interrupt */
+
+/* TCD2 interrupt vectors */
+#define TCD2_LUNF_vect_num 77
+#define TCD2_LUNF_vect _VECTOR(77) /* Low Byte Underflow Interrupt */
+
+/* TCD0 interrupt vectors */
+#define TCD0_ERR_vect_num 78
+#define TCD0_ERR_vect _VECTOR(78) /* Error Interrupt */
+
+/* TCD2 interrupt vectors */
+#define TCD2_HUNF_vect_num 78
+#define TCD2_HUNF_vect _VECTOR(78) /* High Byte Underflow Interrupt */
+
+/* TCD0 interrupt vectors */
+#define TCD0_CCA_vect_num 79
+#define TCD0_CCA_vect _VECTOR(79) /* Compare or Capture A Interrupt */
+
+/* TCD2 interrupt vectors */
+#define TCD2_LCMPA_vect_num 79
+#define TCD2_LCMPA_vect _VECTOR(79) /* Low Byte Compare A Interrupt */
+
+/* TCD0 interrupt vectors */
+#define TCD0_CCB_vect_num 80
+#define TCD0_CCB_vect _VECTOR(80) /* Compare or Capture B Interrupt */
+
+/* TCD2 interrupt vectors */
+#define TCD2_LCMPB_vect_num 80
+#define TCD2_LCMPB_vect _VECTOR(80) /* Low Byte Compare B Interrupt */
+
+/* TCD0 interrupt vectors */
+#define TCD0_CCC_vect_num 81
+#define TCD0_CCC_vect _VECTOR(81) /* Compare or Capture C Interrupt */
+
+/* TCD2 interrupt vectors */
+#define TCD2_LCMPC_vect_num 81
+#define TCD2_LCMPC_vect _VECTOR(81) /* Low Byte Compare C Interrupt */
+
+/* TCD0 interrupt vectors */
+#define TCD0_CCD_vect_num 82
+#define TCD0_CCD_vect _VECTOR(82) /* Compare or Capture D Interrupt */
+
+/* TCD2 interrupt vectors */
+#define TCD2_LCMPD_vect_num 82
+#define TCD2_LCMPD_vect _VECTOR(82) /* Low Byte Compare D Interrupt */
+
+/* TCD1 interrupt vectors */
+#define TCD1_OVF_vect_num 83
+#define TCD1_OVF_vect _VECTOR(83) /* Overflow Interrupt */
+#define TCD1_ERR_vect_num 84
+#define TCD1_ERR_vect _VECTOR(84) /* Error Interrupt */
+#define TCD1_CCA_vect_num 85
+#define TCD1_CCA_vect _VECTOR(85) /* Compare or Capture A Interrupt */
+#define TCD1_CCB_vect_num 86
+#define TCD1_CCB_vect _VECTOR(86) /* Compare or Capture B Interrupt */
+
+/* SPID interrupt vectors */
+#define SPID_INT_vect_num 87
+#define SPID_INT_vect _VECTOR(87) /* SPI Interrupt */
+
+/* USARTD0 interrupt vectors */
+#define USARTD0_RXC_vect_num 88
+#define USARTD0_RXC_vect _VECTOR(88) /* Reception Complete Interrupt */
+#define USARTD0_DRE_vect_num 89
+#define USARTD0_DRE_vect _VECTOR(89) /* Data Register Empty Interrupt */
+#define USARTD0_TXC_vect_num 90
+#define USARTD0_TXC_vect _VECTOR(90) /* Transmission Complete Interrupt */
+
+/* USARTD1 interrupt vectors */
+#define USARTD1_RXC_vect_num 91
+#define USARTD1_RXC_vect _VECTOR(91) /* Reception Complete Interrupt */
+#define USARTD1_DRE_vect_num 92
+#define USARTD1_DRE_vect _VECTOR(92) /* Data Register Empty Interrupt */
+#define USARTD1_TXC_vect_num 93
+#define USARTD1_TXC_vect _VECTOR(93) /* Transmission Complete Interrupt */
+
+/* PORTF interrupt vectors */
+#define PORTF_INT0_vect_num 104
+#define PORTF_INT0_vect _VECTOR(104) /* External Interrupt 0 */
+#define PORTF_INT1_vect_num 105
+#define PORTF_INT1_vect _VECTOR(105) /* External Interrupt 1 */
+
+/* TCF0 interrupt vectors */
+#define TCF0_OVF_vect_num 108
+#define TCF0_OVF_vect _VECTOR(108) /* Overflow Interrupt */
+
+/* TCF2 interrupt vectors */
+#define TCF2_LUNF_vect_num 108
+#define TCF2_LUNF_vect _VECTOR(108) /* Low Byte Underflow Interrupt */
+
+/* TCF0 interrupt vectors */
+#define TCF0_ERR_vect_num 109
+#define TCF0_ERR_vect _VECTOR(109) /* Error Interrupt */
+
+/* TCF2 interrupt vectors */
+#define TCF2_HUNF_vect_num 109
+#define TCF2_HUNF_vect _VECTOR(109) /* High Byte Underflow Interrupt */
+
+/* TCF0 interrupt vectors */
+#define TCF0_CCA_vect_num 110
+#define TCF0_CCA_vect _VECTOR(110) /* Compare or Capture A Interrupt */
+
+/* TCF2 interrupt vectors */
+#define TCF2_LCMPA_vect_num 110
+#define TCF2_LCMPA_vect _VECTOR(110) /* Low Byte Compare A Interrupt */
+
+/* TCF0 interrupt vectors */
+#define TCF0_CCB_vect_num 111
+#define TCF0_CCB_vect _VECTOR(111) /* Compare or Capture B Interrupt */
+
+/* TCF2 interrupt vectors */
+#define TCF2_LCMPB_vect_num 111
+#define TCF2_LCMPB_vect _VECTOR(111) /* Low Byte Compare B Interrupt */
+
+/* TCF0 interrupt vectors */
+#define TCF0_CCC_vect_num 112
+#define TCF0_CCC_vect _VECTOR(112) /* Compare or Capture C Interrupt */
+
+/* TCF2 interrupt vectors */
+#define TCF2_LCMPC_vect_num 112
+#define TCF2_LCMPC_vect _VECTOR(112) /* Low Byte Compare C Interrupt */
+
+/* TCF0 interrupt vectors */
+#define TCF0_CCD_vect_num 113
+#define TCF0_CCD_vect _VECTOR(113) /* Compare or Capture D Interrupt */
+
+/* TCF2 interrupt vectors */
+#define TCF2_LCMPD_vect_num 113
+#define TCF2_LCMPD_vect _VECTOR(113) /* Low Byte Compare D Interrupt */
+
+/* USARTF0 interrupt vectors */
+#define USARTF0_RXC_vect_num 119
+#define USARTF0_RXC_vect _VECTOR(119) /* Reception Complete Interrupt */
+#define USARTF0_DRE_vect_num 120
+#define USARTF0_DRE_vect _VECTOR(120) /* Data Register Empty Interrupt */
+#define USARTF0_TXC_vect_num 121
+#define USARTF0_TXC_vect _VECTOR(121) /* Transmission Complete Interrupt */
+
+/* USB interrupt vectors */
+#define USB_BUSEVENT_vect_num 125
+#define USB_BUSEVENT_vect _VECTOR(125) /* SOF, suspend, resume, reset bus event interrupts, crc, underflow, overflow and stall error interrupts */
+#define USB_TRNCOMPL_vect_num 126
+#define USB_TRNCOMPL_vect _VECTOR(126) /* Transaction complete interrupt */
+
+#define _VECTOR_SIZE 4 /* Size of individual vector. */
+#define _VECTORS_SIZE (127 * _VECTOR_SIZE)
+
+
+/* ========== Constants ========== */
+
+#define PROGMEM_START (0x0000)
+#define PROGMEM_SIZE (204800)
+#define PROGMEM_END (PROGMEM_START + PROGMEM_SIZE - 1)
+
+#define APP_SECTION_START (0x0000)
+#define APP_SECTION_SIZE (196608)
+#define APP_SECTION_PAGE_SIZE (512)
+#define APP_SECTION_END (APP_SECTION_START + APP_SECTION_SIZE - 1)
+
+#define APPTABLE_SECTION_START (0x2E000)
+#define APPTABLE_SECTION_SIZE (8192)
+#define APPTABLE_SECTION_PAGE_SIZE (512)
+#define APPTABLE_SECTION_END (APPTABLE_SECTION_START + APPTABLE_SECTION_SIZE - 1)
+
+#define BOOT_SECTION_START (0x30000)
+#define BOOT_SECTION_SIZE (8192)
+#define BOOT_SECTION_PAGE_SIZE (512)
+#define BOOT_SECTION_END (BOOT_SECTION_START + BOOT_SECTION_SIZE - 1)
+
+#define DATAMEM_START (0x0000)
+#define DATAMEM_SIZE (24576)
+#define DATAMEM_END (DATAMEM_START + DATAMEM_SIZE - 1)
+
+#define IO_START (0x0000)
+#define IO_SIZE (4096)
+#define IO_PAGE_SIZE (0)
+#define IO_END (IO_START + IO_SIZE - 1)
+
+#define MAPPED_EEPROM_START (0x1000)
+#define MAPPED_EEPROM_SIZE (2048)
+#define MAPPED_EEPROM_PAGE_SIZE (0)
+#define MAPPED_EEPROM_END (MAPPED_EEPROM_START + MAPPED_EEPROM_SIZE - 1)
+
+#define INTERNAL_SRAM_START (0x2000)
+#define INTERNAL_SRAM_SIZE (16384)
+#define INTERNAL_SRAM_PAGE_SIZE (0)
+#define INTERNAL_SRAM_END (INTERNAL_SRAM_START + INTERNAL_SRAM_SIZE - 1)
+
+#define EEPROM_START (0x0000)
+#define EEPROM_SIZE (2048)
+#define EEPROM_PAGE_SIZE (32)
+#define EEPROM_END (EEPROM_START + EEPROM_SIZE - 1)
+
+#define SIGNATURES_START (0x0000)
+#define SIGNATURES_SIZE (3)
+#define SIGNATURES_PAGE_SIZE (0)
+#define SIGNATURES_END (SIGNATURES_START + SIGNATURES_SIZE - 1)
+
+#define FUSES_START (0x0000)
+#define FUSES_SIZE (6)
+#define FUSES_PAGE_SIZE (0)
+#define FUSES_END (FUSES_START + FUSES_SIZE - 1)
+
+#define LOCKBITS_START (0x0000)
+#define LOCKBITS_SIZE (1)
+#define LOCKBITS_PAGE_SIZE (0)
+#define LOCKBITS_END (LOCKBITS_START + LOCKBITS_SIZE - 1)
+
+#define USER_SIGNATURES_START (0x0000)
+#define USER_SIGNATURES_SIZE (512)
+#define USER_SIGNATURES_PAGE_SIZE (512)
+#define USER_SIGNATURES_END (USER_SIGNATURES_START + USER_SIGNATURES_SIZE - 1)
+
+#define PROD_SIGNATURES_START (0x0000)
+#define PROD_SIGNATURES_SIZE (52)
+#define PROD_SIGNATURES_PAGE_SIZE (512)
+#define PROD_SIGNATURES_END (PROD_SIGNATURES_START + PROD_SIGNATURES_SIZE - 1)
+
+#define FLASHSTART PROGMEM_START
+#define FLASHEND PROGMEM_END
+#define SPM_PAGESIZE 512
+#define RAMSTART INTERNAL_SRAM_START
+#define RAMSIZE INTERNAL_SRAM_SIZE
+#define RAMEND INTERNAL_SRAM_END
+#define E2END EEPROM_END
+#define E2PAGESIZE EEPROM_PAGE_SIZE
+
+
+/* ========== Fuses ========== */
+#define FUSE_MEMORY_SIZE 6
+
+/* Fuse Byte 0 */
+#define FUSE_JTAGUSERID0 (unsigned char)~_BV(0) /* JTAG User ID Bit 0 */
+#define FUSE_JTAGUSERID1 (unsigned char)~_BV(1) /* JTAG User ID Bit 1 */
+#define FUSE_JTAGUSERID2 (unsigned char)~_BV(2) /* JTAG User ID Bit 2 */
+#define FUSE_JTAGUSERID3 (unsigned char)~_BV(3) /* JTAG User ID Bit 3 */
+#define FUSE_JTAGUSERID4 (unsigned char)~_BV(4) /* JTAG User ID Bit 4 */
+#define FUSE_JTAGUSERID5 (unsigned char)~_BV(5) /* JTAG User ID Bit 5 */
+#define FUSE_JTAGUSERID6 (unsigned char)~_BV(6) /* JTAG User ID Bit 6 */
+#define FUSE_JTAGUSERID7 (unsigned char)~_BV(7) /* JTAG User ID Bit 7 */
+#define FUSE0_DEFAULT (0xFF)
+
+/* Fuse Byte 1 */
+#define FUSE_WDP0 (unsigned char)~_BV(0) /* Watchdog Timeout Period Bit 0 */
+#define FUSE_WDP1 (unsigned char)~_BV(1) /* Watchdog Timeout Period Bit 1 */
+#define FUSE_WDP2 (unsigned char)~_BV(2) /* Watchdog Timeout Period Bit 2 */
+#define FUSE_WDP3 (unsigned char)~_BV(3) /* Watchdog Timeout Period Bit 3 */
+#define FUSE_WDWP0 (unsigned char)~_BV(4) /* Watchdog Window Timeout Period Bit 0 */
+#define FUSE_WDWP1 (unsigned char)~_BV(5) /* Watchdog Window Timeout Period Bit 1 */
+#define FUSE_WDWP2 (unsigned char)~_BV(6) /* Watchdog Window Timeout Period Bit 2 */
+#define FUSE_WDWP3 (unsigned char)~_BV(7) /* Watchdog Window Timeout Period Bit 3 */
+#define FUSE1_DEFAULT (0xFF)
+
+/* Fuse Byte 2 */
+#define FUSE_BODPD0 (unsigned char)~_BV(0) /* BOD Operation in Power-Down Mode Bit 0 */
+#define FUSE_BODPD1 (unsigned char)~_BV(1) /* BOD Operation in Power-Down Mode Bit 1 */
+#define FUSE_TOSCSEL (unsigned char)~_BV(5) /* Timer Oscillator pin location */
+#define FUSE_BOOTRST (unsigned char)~_BV(6) /* Boot Loader Section Reset Vector */
+#define FUSE2_DEFAULT (0xFF)
+
+/* Fuse Byte 3 Reserved */
+
+/* Fuse Byte 4 */
+#define FUSE_JTAGEN (unsigned char)~_BV(0) /* JTAG Interface Enable */
+#define FUSE_WDLOCK (unsigned char)~_BV(1) /* Watchdog Timer Lock */
+#define FUSE_SUT0 (unsigned char)~_BV(2) /* Start-up Time Bit 0 */
+#define FUSE_SUT1 (unsigned char)~_BV(3) /* Start-up Time Bit 1 */
+#define FUSE_RSTDISBL (unsigned char)~_BV(4) /* External Reset Disable */
+#define FUSE4_DEFAULT (0xFF)
+
+/* Fuse Byte 5 */
+#define FUSE_BODLVL0 (unsigned char)~_BV(0) /* Brownout Detection Voltage Level Bit 0 */
+#define FUSE_BODLVL1 (unsigned char)~_BV(1) /* Brownout Detection Voltage Level Bit 1 */
+#define FUSE_BODLVL2 (unsigned char)~_BV(2) /* Brownout Detection Voltage Level Bit 2 */
+#define FUSE_EESAVE (unsigned char)~_BV(3) /* Preserve EEPROM Through Chip Erase */
+#define FUSE_BODACT0 (unsigned char)~_BV(4) /* BOD Operation in Active Mode Bit 0 */
+#define FUSE_BODACT1 (unsigned char)~_BV(5) /* BOD Operation in Active Mode Bit 1 */
+#define FUSE5_DEFAULT (0xFF)
+
+/* ========== Lock Bits ========== */
+#define __LOCK_BITS_EXIST
+#define __BOOT_LOCK_APPLICATION_TABLE_BITS_EXIST
+#define __BOOT_LOCK_APPLICATION_BITS_EXIST
+#define __BOOT_LOCK_BOOT_BITS_EXIST
+
+/* ========== Signature ========== */
+#define SIGNATURE_0 0x1E
+#define SIGNATURE_1 0x97
+#define SIGNATURE_2 0x44
+
+/* ========== Power Reduction Condition Definitions ========== */
+
+/* PR.PRGEN */
+#define __AVR_HAVE_PRGEN (PR_USB_bm|PR_AES_bm|PR_EBI_bm|PR_RTC_bm|PR_EVSYS_bm|PR_DMA_bm)
+#define __AVR_HAVE_PRGEN_USB
+#define __AVR_HAVE_PRGEN_AES
+#define __AVR_HAVE_PRGEN_EBI
+#define __AVR_HAVE_PRGEN_RTC
+#define __AVR_HAVE_PRGEN_EVSYS
+#define __AVR_HAVE_PRGEN_DMA
+
+/* PR.PRPA */
+#define __AVR_HAVE_PRPA (PR_DAC_bm|PR_ADC_bm|PR_AC_bm)
+#define __AVR_HAVE_PRPA_DAC
+#define __AVR_HAVE_PRPA_ADC
+#define __AVR_HAVE_PRPA_AC
+
+/* PR.PRPB */
+#define __AVR_HAVE_PRPB (PR_DAC_bm|PR_ADC_bm|PR_AC_bm)
+#define __AVR_HAVE_PRPB_DAC
+#define __AVR_HAVE_PRPB_ADC
+#define __AVR_HAVE_PRPB_AC
+
+/* PR.PRPC */
+#define __AVR_HAVE_PRPC (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm)
+#define __AVR_HAVE_PRPC_TWI
+#define __AVR_HAVE_PRPC_USART1
+#define __AVR_HAVE_PRPC_USART0
+#define __AVR_HAVE_PRPC_SPI
+#define __AVR_HAVE_PRPC_HIRES
+#define __AVR_HAVE_PRPC_TC1
+#define __AVR_HAVE_PRPC_TC0
+
+/* PR.PRPD */
+#define __AVR_HAVE_PRPD (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm)
+#define __AVR_HAVE_PRPD_TWI
+#define __AVR_HAVE_PRPD_USART1
+#define __AVR_HAVE_PRPD_USART0
+#define __AVR_HAVE_PRPD_SPI
+#define __AVR_HAVE_PRPD_HIRES
+#define __AVR_HAVE_PRPD_TC1
+#define __AVR_HAVE_PRPD_TC0
+
+/* PR.PRPE */
+#define __AVR_HAVE_PRPE (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm)
+#define __AVR_HAVE_PRPE_TWI
+#define __AVR_HAVE_PRPE_USART1
+#define __AVR_HAVE_PRPE_USART0
+#define __AVR_HAVE_PRPE_SPI
+#define __AVR_HAVE_PRPE_HIRES
+#define __AVR_HAVE_PRPE_TC1
+#define __AVR_HAVE_PRPE_TC0
+
+/* PR.PRPF */
+#define __AVR_HAVE_PRPF (PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm)
+#define __AVR_HAVE_PRPF_TWI
+#define __AVR_HAVE_PRPF_USART1
+#define __AVR_HAVE_PRPF_USART0
+#define __AVR_HAVE_PRPF_SPI
+#define __AVR_HAVE_PRPF_HIRES
+#define __AVR_HAVE_PRPF_TC1
+#define __AVR_HAVE_PRPF_TC0
+
+
+#endif /* #ifdef _AVR_ATXMEGA192A3U_H_INCLUDED */
+
diff --git a/src/avr/emu/src/avr/pgmspace.h b/src/avr/emu/src/avr/pgmspace.h
new file mode 100644
index 0000000..5377eb9
--- /dev/null
+++ b/src/avr/emu/src/avr/pgmspace.h
@@ -0,0 +1,41 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#define PRPSTR "s"
+#define PROGMEM
+#define PGM_P const char *
+#define PSTR(X) X
+#define vfprintf_P vfprintf
+#define printf_P printf
+#define puts_P puts
+#define sprintf_P sprintf
+#define strcmp_P strcmp
+#define pgm_read_ptr(x) *(x)
+#define pgm_read_word(x) *(x)
+#define pgm_read_byte(x) *(x)
diff --git a/src/avr/emu/src/avr/wdt.h b/src/avr/emu/src/avr/wdt.h
new file mode 100644
index 0000000..bcf6f99
--- /dev/null
+++ b/src/avr/emu/src/avr/wdt.h
@@ -0,0 +1,33 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#define WDTO_250MS 0
+#define wdt_enable(...)
+#define wdt_disable()
+#define wdt_reset()
diff --git a/src/avr/emu/src/emu.c b/src/avr/emu/src/emu.c
new file mode 100644
index 0000000..a0b06a5
--- /dev/null
+++ b/src/avr/emu/src/emu.c
@@ -0,0 +1,163 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+void __SPIC_INT_vect(); // DRV8711 SPI
+void __I2C_ISR(); // I2C from RPi
+void __ADCA_CH0_vect(); // Analog input
+void __ADCA_CH1_vect(); // Analog input
+void __RS485_DRE_vect(); // RS848
+void __RS485_TXC_vect(); // RS848
+void __RS485_RXC_vect(); // RS848
+void __SERIAL_DRE_vect(); // Serial to RPi
+void __SERIAL_RXC_vect(); // Serial from RPi
+void __STEP_LOW_LEVEL_ISR(); // Stepper lo interrupt
+void __STEP_TIMER_ISR(); // Stepper hi interrupt
+void __RTC_OVF_vect(); // RTC tick
+
+void motor_emulate_steps(int motor);
+
+extern int __argc;
+extern char **__argv;
+
+
+volatile uint8_t io_mem[4096] = {0};
+
+
+bool fast = false;
+int serialByte = -1;
+uint8_t i2cData[I2C_MAX_DATA];
+int i2cIndex = 0;
+bool haveI2C = false;
+fd_set readFDs;
+
+
+void cli() {}
+void sei() {}
+
+
+void emu_init() {
+ // Parse command line args
+ for (int i = 0; i < __argc; i++)
+ if (strcmp(__argv[i], "--fast") == 0) fast = true;
+
+ // Mark clocks ready
+ OSC.STATUS = OSC_XOSCRDY_bm | OSC_PLLRDY_bm | OSC_RC32KRDY_bm;
+
+ // So usart_flush() returns
+ SERIAL_PORT.STATUS = USART_DREIF_bm | USART_TXCIF_bm;
+
+ // Clear motor fault
+ PIN_PORT(MOTOR_FAULT_PIN)->IN |= PIN_BM(MOTOR_FAULT_PIN);
+
+ FD_ZERO(&readFDs);
+}
+
+
+void emu_callback() {
+ fflush(stdout);
+
+ if (RST.CTRL == RST_SWRST_bm) exit(0);
+
+ struct timeval t = {0, fast ? 0 : 1000};
+ bool readData = true;
+ while (readData) {
+ readData = false;
+
+ // Try to read
+ FD_SET(0, &readFDs);
+ if (fcntl(3, F_GETFL) != -1) FD_SET(3, &readFDs);
+
+ if (0 < select(4, &readFDs, 0, 0, &t)) {
+ uint8_t data;
+
+ if (serialByte == -1 && FD_ISSET(0, &readFDs) && read(0, &data, 1) == 1)
+ serialByte = data;
+
+ if (!haveI2C && FD_ISSET(3, &readFDs) && read(3, &data, 1) == 1) {
+ if (data == '\n') haveI2C = true;
+ else if (i2cIndex < I2C_MAX_DATA) i2cData[i2cIndex++] = data;
+ }
+ }
+
+ // Send message to i2c port
+ if (haveI2C && (I2C_DEV.SLAVE.CTRLA & TWI_SLAVE_INTLVL_LO_gc)) {
+ // START
+ I2C_DEV.SLAVE.STATUS = TWI_SLAVE_APIF_bm | TWI_SLAVE_AP_bm;
+ __I2C_ISR();
+
+ // DATA
+ for (int i = 0; i < i2cIndex; i++) {
+ I2C_DEV.SLAVE.STATUS = TWI_SLAVE_DIF_bm;
+ I2C_DEV.SLAVE.DATA = i2cData[i];
+ __I2C_ISR();
+ }
+
+ // STOP
+ I2C_DEV.SLAVE.STATUS = TWI_SLAVE_APIF_bm;
+ __I2C_ISR();
+
+ i2cIndex = 0;
+ haveI2C = false;
+ readData = true;
+ }
+
+ // Send byte to serial port
+ if (serialByte != -1 && SERIAL_PORT.CTRLA & USART_RXCINTLVL_MED_gc) {
+ SERIAL_PORT.DATA = (uint8_t)serialByte;
+ __SERIAL_RXC_vect();
+
+ if (SERIAL_PORT.CTRLA & USART_RXCINTLVL_MED_gc) {
+ serialByte = -1;
+ readData = true;
+ }
+ }
+ }
+
+ // Call stepper ISRs
+ if (ADCB_CH0_INTCTRL == ADC_CH_INTLVL_LO_gc) __STEP_LOW_LEVEL_ISR();
+ for (int motor = 0; motor < 4; motor++) motor_emulate_steps(motor);
+ __STEP_TIMER_ISR();
+
+ // Call RTC
+ __RTC_OVF_vect();
+
+ // Throttle with remaining time
+ if (t.tv_usec) usleep(t.tv_usec);
+}
diff --git a/src/avr/emu/src/util/atomic.h b/src/avr/emu/src/util/atomic.h
new file mode 100644
index 0000000..86dab20
--- /dev/null
+++ b/src/avr/emu/src/util/atomic.h
@@ -0,0 +1,31 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#define ATOMIC_BLOCK(x)
+#define ATOMIC_RESTORESTATE
diff --git a/src/avr/emu/src/util/crc16.h b/src/avr/emu/src/util/crc16.h
new file mode 100644
index 0000000..e343874
--- /dev/null
+++ b/src/avr/emu/src/util/crc16.h
@@ -0,0 +1,30 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#define _crc16_update(...) 0
diff --git a/src/avr/emu/src/util/delay.h b/src/avr/emu/src/util/delay.h
new file mode 100644
index 0000000..e67c76a
--- /dev/null
+++ b/src/avr/emu/src/util/delay.h
@@ -0,0 +1,33 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include
+
+#define _delay_ms(x) usleep((x) * 1000)
+#define _delay_us(x) usleep(x)
diff --git a/src/avr/src/SCurve.cpp b/src/avr/src/SCurve.cpp
new file mode 100644
index 0000000..73bbe30
--- /dev/null
+++ b/src/avr/src/SCurve.cpp
@@ -0,0 +1,175 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+
+#include "SCurve.h"
+
+#include
+
+
+SCurve::SCurve(float maxV, float maxA, float maxJ) :
+ maxV(maxV), maxA(maxA), maxJ(maxJ), v(0), a(0), j(0) {}
+
+
+unsigned SCurve::getPhase() const {
+ if (!v) return 0;
+
+ // Handle negative velocity
+ float v = this->v;
+ float a = this->a;
+ if (v < 0) {
+ v = -v;
+ a = -a;
+ }
+
+ if (0 < a) {
+ if (0 < j) return 1;
+ if (!j) return 2;
+ return 3;
+ }
+
+ if (!a) return 4;
+ if (j < 0) return 5;
+ if (!j) return 6;
+
+ return 7;
+}
+
+
+float SCurve::getStoppingDist() const {return stoppingDist(v, a, maxA, maxJ);}
+
+
+float SCurve::next(float t, float targetV) {
+ // Compute next acceleration
+ float nextA = nextAccel(t, targetV, v, a, maxA, maxJ);
+
+ // Compute next velocity
+ float deltaV = nextA * t;
+ if ((deltaV < 0 && targetV < v && v + deltaV < targetV) ||
+ (0 < deltaV && v < targetV && targetV < v + deltaV)) {
+ nextA = (targetV - v) / t;
+ v = targetV;
+
+ } else v += deltaV;
+
+ // Compute jerk = delta accel / time
+ j = (nextA - a) / t;
+ a = nextA;
+
+ return v;
+}
+
+
+float SCurve::stoppingDist(float v, float a, float maxA, float maxJ) {
+ // Already stopped
+ if (!v) return 0;
+
+ // Handle negative velocity
+ if (v < 0) {
+ v = -v;
+ a = -a;
+ }
+
+ float d = 0;
+
+ // Compute distance and velocity change to accel = 0
+ if (0 < a) {
+ // Compute distance to decrease accel to zero
+ float t = a / maxJ;
+ d += distance(t, v, a, -maxJ);
+ v += velocity(t, a, -maxJ);
+ a = 0;
+ }
+
+ // Compute max deccel
+ float maxDeccel = -sqrt(v * maxJ + 0.5 * a * a);
+ if (maxDeccel < -maxA) maxDeccel = -maxA;
+
+ // Compute distance and velocity change to max deccel
+ if (maxDeccel < a) {
+ float t = (a - maxDeccel) / maxJ;
+ d += distance(t, v, a, -maxJ);
+ v += velocity(t, a, -maxJ);
+ a = maxDeccel;
+ }
+
+ // Compute velocity change over remaining accel
+ float deltaV = 0.5 * a * a / maxJ;
+
+ // Compute constant deccel period
+ if (deltaV < v) {
+ float t = (v - deltaV) / -a;
+ d += distance(t, v, a, 0);
+ v += velocity(t, a, 0);
+ }
+
+ // Compute distance to zero vel
+ d += distance(-a / maxJ, v, a, maxJ);
+
+ return d;
+}
+
+
+float SCurve::nextAccel(float t, float targetV, float v, float a, float maxA,
+ float maxJ) {
+ bool increasing = v < targetV;
+ float deltaA = acceleration(t, maxJ);
+
+ if (increasing && a < -deltaA)
+ return a + deltaA; // negative accel, increasing speed
+
+ if (!increasing && deltaA < a)
+ return a - deltaA; // positive accel, decreasing speed
+
+ float deltaV = fabs(targetV - v);
+ float targetA = sqrt(2 * deltaV * maxJ);
+ if (maxA < targetA) targetA = maxA;
+
+ if (increasing) {
+ if (targetA < a + deltaA) return targetA;
+ return a + deltaA;
+
+ } else {
+ if (a - deltaA < -targetA) return -targetA;
+ return a - deltaA;
+ }
+}
+
+
+float SCurve::distance(float t, float v, float a, float j) {
+ // v * t + 1/2 * a * t^2 + 1/6 * j * t^3
+ return t * (v + t * (0.5 * a + 1.0 / 6.0 * j * t));
+}
+
+
+float SCurve::velocity(float t, float a, float j) {
+ // a * t + 1/2 * j * t^2
+ return t * (a + 0.5 * j * t);
+}
+
+
+float SCurve::acceleration(float t, float j) {return j * t;}
diff --git a/src/avr/src/SCurve.h b/src/avr/src/SCurve.h
new file mode 100644
index 0000000..d48786a
--- /dev/null
+++ b/src/avr/src/SCurve.h
@@ -0,0 +1,66 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include
+
+
+class SCurve {
+ float maxV;
+ float maxA;
+ float maxJ;
+
+ float v;
+ float a;
+ float j;
+
+public:
+ SCurve(float maxV = 0, float maxA = 0, float maxJ = 0);
+
+ float getMaxVelocity() const {return maxV;}
+ void setMaxVelocity(float v) {maxV = v;}
+ float getMaxAcceleration() const {return maxA;}
+ void setMaxAcceleration(float a) {maxA = a;}
+ float getMaxJerk() const {return maxJ;}
+ void setMaxJerk(float j) {maxJ = j;}
+
+ float getVelocity() const {return v;}
+ float getAcceleration() const {return a;}
+ float getJerk() const {return j;}
+
+ unsigned getPhase() const;
+ float getStoppingDist() const;
+ float next(float t, float targetV);
+
+ static float stoppingDist(float v, float a, float maxA, float maxJ);
+ static float nextAccel(float t, float targetV, float v, float a, float maxA,
+ float maxJ);
+ static float distance(float t, float v, float a, float j);
+ static float velocity(float t, float a, float j);
+ static float acceleration(float t, float j);
+};
diff --git a/src/avr/src/analog.c b/src/avr/src/analog.c
new file mode 100644
index 0000000..918f4fa
--- /dev/null
+++ b/src/avr/src/analog.c
@@ -0,0 +1,90 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "analog.h"
+
+#include "config.h"
+
+#include
+
+#include
+
+
+typedef struct {
+ uint8_t pin;
+ uint16_t value;
+} analog_port_t;
+
+
+analog_port_t ports[] = {
+ {.pin = ANALOG_1_PIN},
+ {.pin = ANALOG_2_PIN},
+};
+
+
+ISR(ADCA_CH0_vect) {ports[0].value = ADCA.CH0.RES;}
+ISR(ADCA_CH1_vect) {ports[1].value = ADCA.CH1.RES;}
+
+
+void analog_init() {
+ // Channel 0
+ ADCA.CH0.CTRL = ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_SINGLEENDED_gc;
+ ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN6_gc;
+ ADCA.CH0.INTCTRL = ADC_CH_INTLVL_LO_gc;
+
+ // Channel 1
+ ADCA.CH1.CTRL = ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_SINGLEENDED_gc;
+ ADCA.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN7_gc;
+ ADCA.CH1.INTCTRL = ADC_CH_INTLVL_LO_gc;
+
+ // ADC
+ ADCA.REFCTRL = ADC_REFSEL_INTVCC_gc; // 3.3V / 1.6 = 2.06V
+ ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc;
+ ADCA.EVCTRL = ADC_SWEEP_01_gc;
+ ADCA.CTRLA = ADC_FLUSH_bm | ADC_ENABLE_bm;
+}
+
+
+float analog_get(unsigned port) {
+ if (1 < port) return 0;
+ return ports[port].value * (1.0 / 0x1000);
+}
+
+
+void analog_rtc_callback() {
+ static uint8_t count = 0;
+
+ // Every 1/4 sec
+ if (++count == 250) {
+ count = 0;
+ ADCA.CTRLA |= ADC_CH0START_bm | ADC_CH1START_bm;
+ }
+}
+
+
+// Var callbacks
+float get_analog_input(int port) {return analog_get(port);}
diff --git a/src/avr/src/analog.h b/src/avr/src/analog.h
new file mode 100644
index 0000000..6aaf592
--- /dev/null
+++ b/src/avr/src/analog.h
@@ -0,0 +1,33 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+
+void analog_init();
+float analog_get(unsigned port);
+void analog_rtc_callback();
diff --git a/src/avr/src/axis.c b/src/avr/src/axis.c
new file mode 100644
index 0000000..1f891f5
--- /dev/null
+++ b/src/avr/src/axis.c
@@ -0,0 +1,124 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "axis.h"
+#include "motor.h"
+#include "switch.h"
+#include "util.h"
+
+#include
+#include
+#include
+
+
+int motor_map[AXES] = {-1, -1, -1, -1, -1, -1};
+
+
+typedef struct {
+ float velocity_max; // max velocity in mm/min or deg/min
+ float accel_max; // max acceleration in mm/min^2
+ float jerk_max; // max jerk (Jm) in km/min^3
+} axis_t;
+
+
+axis_t axes[MOTORS] = {};
+
+
+bool axis_is_enabled(int axis) {
+ int motor = axis_get_motor(axis);
+ return motor != -1 && motor_is_enabled(motor) &&
+ !fp_ZERO(axis_get_velocity_max(axis));
+}
+
+
+int axis_get_id(char axis) {
+ const char *axes = "XYZABCUVW";
+ const char *ptr = strchr(axes, toupper(axis));
+ return ptr == 0 ? -1 : (ptr - axes);
+}
+
+
+int axis_get_motor(int axis) {return motor_map[axis];}
+
+
+bool axis_get_homed(int axis) {
+ return axis_is_enabled(axis) ? motor_get_homed(axis_get_motor(axis)) : false;
+}
+
+
+float axis_get_soft_limit(int axis, bool min) {
+ if (!axis_is_enabled(axis)) return min ? -INFINITY : INFINITY;
+ return motor_get_soft_limit(axis_get_motor(axis), min);
+}
+
+
+// Map axes to first matching motor
+void axis_map_motors() {
+ for (int axis = 0; axis < AXES; axis++)
+ for (int motor = 0; motor < MOTORS; motor++)
+ if (motor_get_axis(motor) == axis) {
+ motor_map[axis] = motor;
+ break;
+ }
+}
+
+
+#define AXIS_VAR_GET(NAME, TYPE) \
+ TYPE get_##NAME(int axis) {return axes[axis].NAME;}
+
+
+#define AXIS_VAR_SET(NAME, TYPE) \
+ void set_##NAME(int axis, TYPE value) {axes[axis].NAME = value;}
+
+
+/// Velocity is scaled by 1,000
+float axis_get_velocity_max(int axis) {
+ int motor = axis_get_motor(axis);
+ return motor == -1 ? 0 : axes[motor].velocity_max * VELOCITY_MULTIPLIER;
+}
+AXIS_VAR_GET(velocity_max, float)
+
+
+/// Acceleration is scaled by 1,000
+float axis_get_accel_max(int axis) {
+ int motor = axis_get_motor(axis);
+ return motor == -1 ? 0 : axes[motor].accel_max * ACCEL_MULTIPLIER;
+}
+AXIS_VAR_GET(accel_max, float)
+
+
+/// Jerk is scaled by 1,000,000
+float axis_get_jerk_max(int axis) {
+ int motor = axis_get_motor(axis);
+ return motor == -1 ? 0 : axes[motor].jerk_max * JERK_MULTIPLIER;
+}
+AXIS_VAR_GET(jerk_max, float)
+
+
+AXIS_VAR_SET(velocity_max, float)
+AXIS_VAR_SET(accel_max, float)
+AXIS_VAR_SET(jerk_max, float)
diff --git a/src/avr/src/axis.h b/src/avr/src/axis.h
new file mode 100644
index 0000000..50aae9b
--- /dev/null
+++ b/src/avr/src/axis.h
@@ -0,0 +1,50 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "config.h"
+
+#include
+
+
+enum {
+ AXIS_X, AXIS_Y, AXIS_Z,
+ AXIS_A, AXIS_B, AXIS_C,
+};
+
+
+bool axis_is_enabled(int axis);
+int axis_get_id(char axis);
+int axis_get_motor(int axis);
+bool axis_get_homed(int axis);
+float axis_get_soft_limit(int axis, bool min);
+void axis_map_motors();
+
+float axis_get_velocity_max(int axis);
+float axis_get_accel_max(int axis);
+float axis_get_jerk_max(int axis);
diff --git a/src/avr/src/base64.c b/src/avr/src/base64.c
new file mode 100644
index 0000000..e6bbe99
--- /dev/null
+++ b/src/avr/src/base64.c
@@ -0,0 +1,151 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "base64.h"
+
+#include "util.h"
+
+#include
+
+
+static const char *_b64_encode =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+
+static const int8_t _b64_decode[] = { // 43-122
+ 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+};
+
+
+static int8_t _decode(char c) {
+ return (c < 43 || 122 < c) ? -1 : _b64_decode[c - 43];
+}
+
+
+static char _encode(uint8_t b) {return _b64_encode[b & 63];}
+
+
+static void _skip_space(const char **s, const char *end) {
+ while (*s < end && isspace(**s)) (*s)++;
+}
+
+
+static char _next(const char **s, const char *end) {
+ char c = *(*s)++;
+ _skip_space(s, end);
+ return c;
+}
+
+
+unsigned b64_encoded_length(unsigned len, bool pad) {
+ unsigned elen = len / 3 * 4;
+
+ switch (len % 3) {
+ case 1: elen += pad ? 4 : 2; break;
+ case 2: elen += pad ? 4 : 3; break;
+ }
+
+ return elen;
+}
+
+
+void b64_encode(const uint8_t *in, unsigned len, char *out, bool pad) {
+ const uint8_t *end = in + len;
+ int padding = 0;
+ uint8_t a, b, c;
+
+ while (in < end) {
+ a = *in++;
+
+ if (in < end) {
+ b = *in++;
+
+ if (in < end) c = *in++;
+ else {c = 0; padding = 1;}
+
+ } else {c = b = 0; padding = 2;}
+
+ *out++ = _encode(63 & (a >> 2));
+ *out++ = _encode(63 & (a << 4 | b >> 4));
+
+ if (pad && padding == 2) *out++ = '=';
+ else *out++ = _encode(63 & (b << 2 | c >> 6));
+
+ if (pad && padding) *out++ = '=';
+ else *out++ = _encode(63 & c);
+ }
+}
+
+
+bool b64_decode(const char *in, unsigned len, uint8_t *out) {
+ const char *end = in + len;
+
+ _skip_space(&in, end);
+
+ while (in < end) {
+ int8_t w = _decode(_next(&in, end));
+ int8_t x = in < end ? _decode(_next(&in, end)) : -2;
+ int8_t y = in < end ? _decode(_next(&in, end)) : -2;
+ int8_t z = in < end ? _decode(_next(&in, end)) : -2;
+
+ if (w == -2 || x == -2 || w == -1 || x == -1 || y == -1 || z == -1)
+ return false;
+
+ *out++ = (uint8_t)(w << 2 | x >> 4);
+ if (y != -2) {
+ *out++ = (uint8_t)(x << 4 | y >> 2);
+ if (z != -2) *out++ = (uint8_t)(y << 6 | z);
+ }
+ }
+
+ return true;
+}
+
+
+bool b64_decode_float(const char *s, float *f) {
+ union {
+ float f;
+ uint8_t b[4];
+ } u;
+
+ if (!b64_decode(s, 6, u.b)) return false;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define XORSWAP(a, b) a ^= (b ^ (b ^= a)
+ XORSWAP(u.b[0], u.b[3]);
+ XORSWAP(u.b[1], u.b[2]);
+#endif
+
+ *f = u.f;
+
+ return true;
+}
diff --git a/src/avr/src/base64.h b/src/avr/src/base64.h
new file mode 100644
index 0000000..ed6e6a6
--- /dev/null
+++ b/src/avr/src/base64.h
@@ -0,0 +1,37 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include
+#include
+
+
+unsigned b64_encoded_length(unsigned len, bool pad);
+void b64_encode(const uint8_t *in, unsigned len, char *out, bool pad);
+bool b64_decode(const char *in, unsigned len, uint8_t *out);
+bool b64_decode_float(const char *s, float *f);
diff --git a/src/avr/src/command.c b/src/avr/src/command.c
new file mode 100644
index 0000000..916c388
--- /dev/null
+++ b/src/avr/src/command.c
@@ -0,0 +1,278 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "command.h"
+
+#include "usart.h"
+#include "hardware.h"
+#include "vars.h"
+#include "estop.h"
+#include "i2c.h"
+#include "config.h"
+#include "pgmspace.h"
+#include "state.h"
+#include "exec.h"
+#include "base64.h"
+#include "rtc.h"
+#include "stepper.h"
+#include "cpp_magic.h"
+
+#include
+
+#include
+#include
+#include
+#include
+
+
+#define RING_BUF_NAME sync_q
+#define RING_BUF_TYPE uint8_t
+#define RING_BUF_INDEX_TYPE volatile uint16_t
+#define RING_BUF_SIZE SYNC_QUEUE_SIZE
+#define RING_BUF_ATOMIC_COPY 1
+#include "ringbuf.def"
+
+
+static struct {
+ bool active;
+ uint16_t id;
+ uint32_t last_empty;
+ volatile uint16_t count;
+ float position[AXES];
+} cmd = {0,};
+
+
+// Define command callbacks
+#define CMD(CODE, NAME, SYNC) \
+ stat_t command_##NAME(char *); \
+ IF(SYNC)(unsigned command_##NAME##_size();) \
+ IF(SYNC)(void command_##NAME##_exec(void *);)
+#include "command.def"
+#undef CMD
+
+
+// Name
+#define CMD(CODE, NAME, SYNC) \
+ static const char command_##NAME##_name[] PROGMEM = #NAME;
+#include "command.def"
+#undef CMD
+
+
+static bool _is_synchronous(char code) {
+ switch (code) {
+#define CMD(CODE, NAME, SYNC, ...) case COMMAND_##NAME: return SYNC;
+#include "command.def"
+#undef CMD
+ }
+ return false;
+}
+
+
+static stat_t _dispatch(char *s) {
+ switch (*s) {
+#define CMD(CODE, NAME, SYNC, ...) \
+ case COMMAND_##NAME: return command_##NAME(s);
+#include "command.def"
+#undef CMD
+ }
+
+ return STAT_INVALID_COMMAND;
+}
+
+
+static unsigned _size(char code) {
+ switch (code) {
+#define CMD(CODE, NAME, SYNC, ...) \
+ IF(SYNC)(case COMMAND_##NAME: return command_##NAME##_size();)
+#include "command.def"
+#undef CMD
+ }
+
+ return 0;
+}
+
+
+static void _exec_cb(char code, uint8_t *data) {
+ switch (code) {
+#define CMD(CODE, NAME, SYNC, ...) \
+ IF(SYNC)(case COMMAND_##NAME: command_##NAME##_exec(data); break;)
+#include "command.def"
+#undef CMD
+ }
+}
+
+
+static void _i2c_cb(uint8_t *data, uint8_t length) {
+ stat_t status = _dispatch((char *)data);
+ if (status) STATUS_ERROR(status, "i2c: %s", data);
+}
+
+
+void command_init() {i2c_set_read_callback(_i2c_cb);}
+bool command_is_active() {return cmd.active;}
+unsigned command_get_count() {return cmd.count;}
+
+
+void command_print_json() {
+ bool first = true;
+ static const char fmt[] PROGMEM = "\"%c\":{\"name\":\"%" PRPSTR "\"}";
+
+#define CMD(CODE, NAME, SYNC) \
+ if (first) first = false; else putchar(','); \
+ printf_P(fmt, CODE, command_##NAME##_name);
+
+#include "command.def"
+#undef CMD
+}
+
+
+void command_flush_queue() {
+ sync_q_init();
+ cmd.count = 0;
+ command_reset_position();
+}
+
+
+void command_push(char code, void *_data) {
+ uint8_t *data = (uint8_t *)_data;
+ unsigned size = _size(code);
+
+ if (!_is_synchronous(code)) estop_trigger(STAT_Q_INVALID_PUSH);
+ if (sync_q_space() <= size) estop_trigger(STAT_Q_OVERRUN);
+
+ sync_q_push(code);
+ for (unsigned i = 0; i < size; i++) sync_q_push(*data++);
+
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) cmd.count++;
+}
+
+
+bool command_callback() {
+ static char *block = 0;
+
+ if (!block) block = usart_readline();
+ if (!block) return false; // No command
+
+ stat_t status = STAT_OK;
+
+ // Special processing for synchronous commands
+ if (_is_synchronous(*block)) {
+ if (estop_triggered()) status = STAT_MACHINE_ALARMED;
+ else if (state_is_flushing()) status = STAT_NOP; // Flush command
+ else if (state_is_resuming() || sync_q_space() <= _size(*block))
+ return false; // Wait
+ }
+
+ // Dispatch non-empty commands
+ if (*block && status == STAT_OK) {
+ status = _dispatch(block);
+ if (status == STAT_OK) cmd.active = true; // Disables LCD booting message
+ }
+
+ switch (status) {
+ case STAT_OK: break;
+ case STAT_NOP: break;
+ case STAT_MACHINE_ALARMED: STATUS_WARNING(status, ""); break;
+ default: STATUS_ERROR(status, "%s", block); break;
+ }
+
+ block = 0; // Command consumed
+
+ return true;
+}
+
+
+void command_set_axis_position(int axis, const float p) {
+ cmd.position[axis] = p;
+}
+
+
+void command_set_position(const float position[AXES]) {
+ memcpy(cmd.position, position, sizeof(cmd.position));
+}
+
+
+void command_get_position(float position[AXES]) {
+ memcpy(position, cmd.position, sizeof(cmd.position));
+}
+
+
+void command_reset_position() {
+ float position[AXES];
+ exec_get_position(position);
+ command_set_position(position);
+}
+
+
+char command_peek() {return (char)(cmd.count ? sync_q_peek() : 0);}
+
+
+uint8_t *command_next() {
+ if (!cmd.count) return 0;
+ cmd.count--;
+
+ if (sync_q_empty()) estop_trigger(STAT_Q_UNDERRUN);
+
+ static uint8_t data[INPUT_BUFFER_LEN];
+
+ data[0] = sync_q_next();
+
+ if (!_is_synchronous((char)data[0])) estop_trigger(STAT_INVALID_QCMD);
+
+ unsigned size = _size((char)data[0]);
+ for (unsigned i = 0; i < size; i++)
+ data[i + 1] = sync_q_next();
+
+ return data;
+}
+
+
+// Returns true if command queued
+// Called by exec.c from low-level interrupt
+bool command_exec() {
+ if (!cmd.count) {
+ cmd.last_empty = rtc_get_time();
+ state_idle();
+ return false;
+ }
+
+ // On restart wait a bit to give queue a chance to fill
+ if (cmd.count < EXEC_FILL_TARGET &&
+ !rtc_expired(cmd.last_empty + EXEC_DELAY)) return false;
+
+ uint8_t *data = command_next();
+ state_running();
+
+ _exec_cb((char)*data, data + 1);
+
+ return true;
+}
+
+
+// Var callbacks
+uint16_t get_id() {return cmd.id;}
+void set_id(uint16_t id) {cmd.id = id;}
diff --git a/src/avr/src/command.def b/src/avr/src/command.def
new file mode 100644
index 0000000..c413a90
--- /dev/null
+++ b/src/avr/src/command.def
@@ -0,0 +1,50 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+//(CODE, NAME, SYNC)
+CMD('$', var, 0) // Set or get variable
+CMD('#', sync_var, 1) // Set variable synchronous
+CMD('s', seek, 1) // [switch][flags:active|error]
+CMD('a', set_axis, 1) // [axis][position] Set axis position
+CMD('l', line, 1) // [targetVel][maxJerk][axes][times]
+CMD('%', sync_speed, 1) // [offset][speed] Command synchronized speed
+CMD('p', speed, 1) // [speed] Spindle speed
+CMD('I', input, 1) // [a|d][port][mode][timeout] Read input
+CMD('d', dwell, 1) // [seconds]
+CMD('P', pause, 1) // [type] Pause control
+CMD('S', stop, 0) // Stop move, spindle and load outputs
+CMD('U', unpause, 0) // Unpause
+CMD('j', jog, 0) // [axes]
+CMD('r', report, 0) // <0|1>[var] Enable or disable var reporting
+CMD('R', reboot, 0) // Reboot the controller
+CMD('c', resume, 0) // Continue processing after a flush
+CMD('E', estop, 0) // Emergency stop
+CMD('X', shutdown, 0) // Power shutdown
+CMD('C', clear, 0) // Clear estop
+CMD('F', flush, 0) // Flush command queue
+CMD('D', dump, 0) // Report all variables
+CMD('h', help, 0) // Print this help screen
diff --git a/src/avr/src/command.h b/src/avr/src/command.h
new file mode 100644
index 0000000..24fa928
--- /dev/null
+++ b/src/avr/src/command.h
@@ -0,0 +1,58 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "config.h"
+#include "status.h"
+
+#include
+#include
+
+
+// Commands
+typedef enum {
+#define CMD(CODE, NAME, ...) COMMAND_##NAME = CODE,
+#include "command.def"
+#undef CMD
+} command_t;
+
+
+void command_init();
+bool command_is_active();
+unsigned command_get_count();
+void command_print_json();
+void command_flush_queue();
+void command_push(char code, void *data);
+bool command_callback();
+void command_set_axis_position(int axis, const float p);
+void command_set_position(const float position[AXES]);
+void command_get_position(float position[AXES]);
+void command_reset_position();
+char command_peek();
+uint8_t *command_next();
+bool command_exec();
diff --git a/src/avr/src/command.json.in b/src/avr/src/command.json.in
new file mode 100644
index 0000000..9e51ea9
--- /dev/null
+++ b/src/avr/src/command.json.in
@@ -0,0 +1,11 @@
+#include "cpp_magic.h"
+{
+#define CMD(CODE, NAME, SYNC) \
+ #NAME: { \
+ "code": CODE, \
+ "sync": IF_ELSE(SYNC)(true, false) \
+ },
+#include "command.def"
+#undef CMD
+ "_": {}
+}
diff --git a/src/avr/src/commands.c b/src/avr/src/commands.c
new file mode 100644
index 0000000..8796b09
--- /dev/null
+++ b/src/avr/src/commands.c
@@ -0,0 +1,83 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "config.h"
+#include "stepper.h"
+#include "command.h"
+#include "vars.h"
+#include "base64.h"
+#include "hardware.h"
+#include "report.h"
+#include "exec.h"
+
+#include
+
+
+stat_t command_dwell(char *cmd) {
+ float seconds;
+ if (!b64_decode_float(cmd + 1, &seconds)) return STAT_BAD_FLOAT;
+ command_push(*cmd, &seconds);
+ return STAT_OK;
+}
+
+
+static stat_t _dwell_exec() {
+ exec_set_cb(0); // Immediately clear the callback
+ return STAT_OK;
+}
+
+
+unsigned command_dwell_size() {return sizeof(float);}
+
+
+void command_dwell_exec(void *seconds) {
+ st_prep_dwell(*(float *)seconds);
+ exec_set_cb(_dwell_exec); // Command must set an exec callback
+}
+
+
+stat_t command_help(char *cmd) {
+ printf_P(PSTR("\n{\"commands\":{"));
+ command_print_json();
+ printf_P(PSTR("},\"variables\":{"));
+ vars_print_json();
+ printf_P(PSTR("}}\n"));
+
+ return STAT_OK;
+}
+
+
+stat_t command_reboot(char *cmd) {
+ hw_request_hard_reset();
+ return STAT_OK;
+}
+
+
+stat_t command_dump(char *cmd) {
+ report_request_full();
+ return STAT_OK;
+}
diff --git a/src/avr/src/config.h b/src/avr/src/config.h
new file mode 100644
index 0000000..7b01aac
--- /dev/null
+++ b/src/avr/src/config.h
@@ -0,0 +1,222 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "pins.h"
+
+#include
+
+
+// Pins
+enum {
+ STALL_0_PIN = PIN_ID(PORT_A, 0),
+ STALL_1_PIN,
+ STALL_2_PIN,
+ STALL_3_PIN,
+ TOOL_DIR_PIN,
+ TOOL_ENABLE_PIN,
+ ANALOG_1_PIN,
+ ANALOG_2_PIN,
+
+ MIN_0_PIN = PIN_ID(PORT_B, 0),
+ MAX_0_PIN,
+ MIN_3_PIN,
+ MAX_3_PIN,
+ MIN_1_PIN,
+ MAX_1_PIN,
+ MIN_2_PIN,
+ MAX_2_PIN,
+
+ SDA_PIN = PIN_ID(PORT_C, 0),
+ SCL_PIN,
+ SERIAL_RX_PIN,
+ SERIAL_TX_PIN,
+ SERIAL_CTS_PIN,
+ SPI_CLK_PIN,
+ SPI_MISO_PIN,
+ SPI_MOSI_PIN,
+
+ STEP_0_PIN = PIN_ID(PORT_D, 0),
+ SPI_CS_0_PIN,
+ SPI_CS_3_PIN,
+ SPI_CS_2_PIN,
+ PWM_PIN,
+ SWITCH_2_PIN,
+ RS485_RO_PIN,
+ RS485_DI_PIN,
+
+ STEP_1_PIN = PIN_ID(PORT_E, 0),
+ SPI_CS_1_PIN,
+ DIR_0_PIN,
+ DIR_1_PIN,
+ STEP_3_PIN,
+ SWITCH_1_PIN,
+ DIR_2_PIN,
+ DIR_3_PIN,
+
+ STEP_2_PIN = PIN_ID(PORT_F, 0),
+ RS485_RW_PIN,
+ FAULT_PIN,
+ ESTOP_PIN,
+ MOTOR_FAULT_PIN,
+ MOTOR_ENABLE_PIN,
+ TEST_PIN,
+ PROBE_PIN,
+};
+
+#define SPI_SS_PIN SERIAL_CTS_PIN // Needed for SPI configuration
+
+
+#define AXES 6 // number of axes
+#define MOTORS 4 // number of motors on the board
+#define OUTS 6 // number of supported pin outputs
+#define ANALOG 2 // number of supported analog inputs
+#define VFDREG 32 // number of supported VFD modbus registers
+
+// Switch settings. See switch.c
+#define SWITCH_DEBOUNCE 5 // ms, default value
+#define SWITCH_LOCKOUT 250 // ms, default value
+#define SWITCH_MAX_DEBOUNCE 5000 // ms
+#define SWITCH_MAX_LOCKOUT 60000 // ms
+
+
+// Motor ISRs
+#define STALL_ISR_vect PORTA_INT1_vect
+#define FAULT_ISR_vect PORTF_INT1_vect
+
+
+/* Interrupt usage:
+ *
+ * HI Step timers stepper.c
+ * HI Serial RX usart.c
+ * MED Serial TX usart.c (* see note)
+ * MED Modbus serial interrupts modbus.c
+ * LO Segment execution SW interrupt stepper.c
+ * LO I2C Slave i2c.c
+ * LO Real-time clock interrupt rtc.c
+ * LO DRV8711 SPI drv8711.c
+ * LO A2D interrupts analog.c
+ *
+ * (*) The TX cannot run at LO level or exception reports and other prints
+ * called from a LO interrupt (as in prep_line()) will kill the system
+ * in a permanent loop call in usart_putc() (usart.c).
+ */
+
+// Timer assignments
+// NOTE, TCC1 is unused
+#define TIMER_STEP TCC0 // Step timer (see stepper.h)
+#define TIMER_PWM TCD1 // PWM timer (see pwm.c)
+
+
+// Timer setup for stepper and dwells
+#define STEP_TIMER_DIV 8
+#define STEP_TIMER_FREQ (F_CPU / STEP_TIMER_DIV)
+#define STEP_TIMER_POLL ((uint16_t)(STEP_TIMER_FREQ * 0.001)) // 1ms
+#define STEP_TIMER_ISR TCC0_OVF_vect
+#define STEP_LOW_LEVEL_ISR ADCB_CH0_vect
+#define STEP_PULSE_WIDTH (F_CPU * 0.000002) // 2uS w/ clk/1
+#define SEGMENT_MS 4
+#define SEGMENT_TIME (SEGMENT_MS / 60000.0) // mins
+
+
+// DRV8711 settings
+// NOTE, PWM frequency = 1 / (2 * DTIME + TBLANK + TOFF)
+// We have PWM frequency = 1 / (2 * 850nS + 1uS + 6.5uS) ~= 110kHz
+#define DRV8711_OFF 12
+#define DRV8711_BLANK (0x32 | DRV8711_BLANK_ABT_bm)
+#define DRV8711_DECAY (DRV8711_DECAY_DECMOD_MIXED | 16)
+
+#define DRV8711_DRIVE (DRV8711_DRIVE_IDRIVEP_50 | \
+ DRV8711_DRIVE_IDRIVEN_100 | \
+ DRV8711_DRIVE_TDRIVEP_500 | \
+ DRV8711_DRIVE_TDRIVEN_500 | \
+ DRV8711_DRIVE_OCPDEG_1 | \
+ DRV8711_DRIVE_OCPTH_500)
+#define DRV8711_TORQUE DRV8711_TORQUE_SMPLTH_200
+// NOTE, Datasheet suggests 850ns DTIME with the optional gate resistor
+// installed. See page 30 section 8.1.2 of DRV8711 datasheet.
+#define DRV8711_CTRL (DRV8711_CTRL_ISGAIN_5 | \
+ DRV8711_CTRL_DTIME_850)
+
+
+// RS485 settings
+#define RS485_PORT USARTD1
+#define RS485_DRE_vect USARTD1_DRE_vect
+#define RS485_TXC_vect USARTD1_TXC_vect
+#define RS485_RXC_vect USARTD1_RXC_vect
+
+
+// Modbus settings
+#define MODBUS_TIMEOUT 100 // ms. response timeout
+#define MODBUS_RETRIES 4 // Number of retries before failure
+#define MODBUS_BUF_SIZE 18 // Max bytes in rx/tx buffers
+#define VFD_QUERY_DELAY 100 // ms
+
+
+// Serial settings
+#define SERIAL_BAUD USART_BAUD_230400 // 115200
+#define SERIAL_PORT USARTC0
+#define SERIAL_DRE_vect USARTC0_DRE_vect
+#define SERIAL_RXC_vect USARTC0_RXC_vect
+#define SERIAL_CTS_THRESH 4
+
+
+// PWM settings
+#define POWER_MAX_UPDATES SEGMENT_MS
+
+// Input
+#define INPUT_BUFFER_LEN 128 // text buffer size (255 max)
+
+
+// Report
+#define REPORT_RATE 250 // ms
+
+
+// I2C
+#define I2C_DEV TWIC
+#define I2C_ISR TWIC_TWIS_vect
+#define I2C_ADDR 0x2b
+#define I2C_MAX_DATA 8
+
+
+// Motor
+#define MOTOR_IDLE_TIMEOUT 0.25 // secs, motor off after this time
+#define MIN_STEP_CORRECTION 2
+
+#define MIN_VELOCITY 10 // mm/min
+#define CURRENT_SENSE_RESISTOR 0.05 // ohms
+#define CURRENT_SENSE_REF 2.75 // volts
+#define MAX_CURRENT 6 // amps
+#define MAX_IDLE_CURRENT 2 // amps
+#define VELOCITY_MULTIPLIER 1000.0
+#define ACCEL_MULTIPLIER 1000000.0
+#define JERK_MULTIPLIER 1000000.0
+#define SYNC_QUEUE_SIZE 4096
+#define EXEC_FILL_TARGET 8
+#define EXEC_DELAY 250 // ms
+#define JOG_STOPPING_UNDERSHOOT 1 // % of stopping distance
diff --git a/src/avr/src/cpp_magic.h b/src/avr/src/cpp_magic.h
new file mode 100644
index 0000000..f677c1a
--- /dev/null
+++ b/src/avr/src/cpp_magic.h
@@ -0,0 +1,507 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+/* This header file contains a library of advanced C Pre-Processor (CPP) macros
+ * which implement various useful functions, such as iteration, in the
+ * pre-processor.
+ *
+ * Though the file name (quite validly) labels this as magic, there should be
+ * enough documentation in the comments for a reader only casually familiar
+ * with the CPP to be able to understand how everything works.
+ *
+ * The majority of the magic tricks used in this file are based on those
+ * described by pfultz2 in his "Cloak" library:
+ *
+ * https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
+ *
+ * Major differences are a greater level of detailed explanation in this
+ * implementation and also a refusal to include any macros which require a O(N)
+ * macro definitions to handle O(N) arguments (with the exception of DEFERn).
+ */
+
+#pragma once
+
+/**
+ * Force the pre-processor to expand the macro a large number of times.
+ * Usage:
+ *
+ * EVAL(expression)
+ *
+ * This is useful when you have a macro which evaluates to a valid
+ * macro expression which is not subsequently expanded in the same
+ * pass. A contrived, but easy to understand, example of such a macro
+ * follows. Note that though this example is contrived, this behaviour
+ * is abused to implement bounded recursion in macros such as FOR.
+ *
+ * #define A(x) x+1
+ * #define EMPTY
+ * #define NOT_QUITE_RIGHT(x) A EMPTY (x)
+ * NOT_QUITE_RIGHT(999)
+ *
+ * Here's what happens inside the C preprocessor:
+ *
+ * 1. It sees a macro "NOT_QUITE_RIGHT" and performs a single macro
+ * expansion pass on its arguments. Since the argument is "999" and
+ * this isn't a macro, this is a boring step resulting in no
+ * change.
+ *
+ * 2. The NOT_QUITE_RIGHT macro is substituted for its definition
+ * giving "A EMPTY() (x)".
+ *
+ * 3. The expander moves from left-to-right trying to expand the
+ * macro: The first token, A, cannot be expanded since there are no
+ * brackets immediately following it. The second token EMPTY(),
+ * however, can be expanded (recursively in this manner) and is
+ * replaced with "".
+ *
+ * 4. Expansion continues from the start of the substituted test
+ * (which in this case is just empty), and sees "(999)" but since
+ * no macro name is present, nothing is done. This results in a
+ * final expansion of "A (999)".
+ *
+ * Unfortunately, this doesn't quite meet expectations since you may
+ * expect that "A (999)" would have been expanded into
+ * "999+1". Unfortunately this requires a second expansion pass but
+ * luckily we can force the macro processor to make more passes by
+ * abusing the first step of macro expansion: the preprocessor expands
+ * arguments in their own pass. If we define a macro which does
+ * nothing except produce its arguments e.g.:
+ *
+ * #define PASS_THROUGH(...) __VA_ARGS__
+ *
+ * We can now do "PASS_THROUGH(NOT_QUITE_RIGHT(999))" causing
+ * "NOT_QUITE_RIGHT" to be expanded to "A (999)", as described above,
+ * when the arguments are expanded. Now when the body of PASS_THROUGH
+ * is expanded, "A (999)" gets expanded to "999+1".
+ *
+ * The EVAL defined below is essentially equivalent to a large nesting
+ * of "PASS_THROUGH(PASS_THROUGH(PASS_THROUGH(..." which results in
+ * the preprocessor making a large number of expansion passes over the
+ * given expression.
+ */
+#define EVAL(...) EVAL1024(__VA_ARGS__)
+#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
+#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
+#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
+#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
+#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
+#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
+#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
+#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
+#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
+#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
+#define EVAL1(...) __VA_ARGS__
+
+
+// Macros which expand to common values
+#define PASS(...) __VA_ARGS__
+#define EMPTY()
+#define COMMA() ,
+#define SEMI() ;
+#define PLUS() +
+#define ZERO() 0
+#define ONE() 1
+
+/**
+ * Causes a function-style macro to require an additional pass to be expanded.
+ *
+ * This is useful, for example, when trying to implement recursion since the
+ * recursive step must not be expanded in a single pass as the pre-processor
+ * will catch it and prevent it.
+ *
+ * Usage:
+ *
+ * DEFER1(IN_NEXT_PASS)(args, to, the, macro)
+ *
+ * How it works:
+ *
+ * 1. When DEFER1 is expanded, first its arguments are expanded which are
+ * simply IN_NEXT_PASS. Since this is a function-style macro and it has no
+ * arguments, nothing will happen.
+ * 2. The body of DEFER1 will now be expanded resulting in EMPTY() being
+ * deleted. This results in "IN_NEXT_PASS (args, to, the macro)". Note that
+ * since the macro expander has already passed IN_NEXT_PASS by the time it
+ * expands EMPTY() and so it won't spot that the brackets which remain can be
+ * applied to IN_NEXT_PASS.
+ * 3. At this point the macro expansion completes. If one more pass is made,
+ * IN_NEXT_PASS(args, to, the, macro) will be expanded as desired.
+ */
+#define DEFER1(id) id EMPTY()
+
+/**
+ * As with DEFER1 except here n additional passes are required for DEFERn.
+ *
+ * The mechanism is analogous.
+ *
+ * Note that there doesn't appear to be a way of combining DEFERn macros in
+ * order to achieve exponentially increasing defers e.g. as is done by EVAL.
+ */
+#define DEFER2(id) id EMPTY EMPTY()()
+#define DEFER3(id) id EMPTY EMPTY EMPTY()()()
+#define DEFER4(id) id EMPTY EMPTY EMPTY EMPTY()()()()
+#define DEFER5(id) id EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()
+#define DEFER6(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()
+#define DEFER7(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()
+#define DEFER8(id) \
+ id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()()
+
+
+/**
+ * Indirection around the standard ## concatenation operator. This simply
+ * ensures that the arguments are expanded (once) before concatenation.
+ */
+#define CAT(a, ...) a ## __VA_ARGS__
+#define CAT3(a, b, ...) a ## b ## __VA_ARGS__
+
+
+/**
+ * Get the first argument and ignore the rest.
+ */
+#define FIRST(a, ...) a
+
+/**
+ * Get the second argument and ignore the rest.
+ */
+#define SECOND(a, b, ...) b
+
+/**
+ * Expects a single input (not containing commas). Returns 1 if the input is
+ * PROBE() and otherwise returns 0.
+ *
+ * This can be useful as the basis of a NOT function.
+ *
+ * This macro abuses the fact that PROBE() contains a comma while other valid
+ * inputs must not.
+ */
+#define IS_PROBE(...) SECOND(__VA_ARGS__, 0)
+#define PROBE() ~, 1
+
+
+/**
+ * Logical negation. 0 is defined as false and everything else as true.
+ *
+ * When 0, _NOT_0 will be found which evaluates to the PROBE. When 1
+ * (or any other value) is given, an appropriately named macro won't
+ * be found and the concatenated string will be produced. IS_PROBE
+ * then simply checks to see if the PROBE was returned, cleanly
+ * converting the argument into a 1 or 0.
+ */
+#define NOT(x) IS_PROBE(CAT(_NOT_, x))
+#define _NOT_0 PROBE()
+
+/**
+ * Macro version of C's famous "cast to bool" operator (i.e. !!) which takes
+ * anything and casts it to 0 if it is 0 and 1 otherwise.
+ */
+#define BOOL(x) NOT(NOT(x))
+
+/**
+ * Logical OR. Simply performs a lookup.
+ */
+#define OR(a,b) CAT3(_OR_, a, b)
+#define _OR_00 0
+#define _OR_01 1
+#define _OR_10 1
+#define _OR_11 1
+
+/**
+ * Logical AND. Simply performs a lookup.
+ */
+#define AND(a,b) CAT3(_AND_, a, b)
+#define _AND_00 0
+#define _AND_01 0
+#define _AND_10 0
+#define _AND_11 1
+
+
+/**
+ * Macro if statement. Usage:
+ *
+ * IF(c)(expansion when true)
+ *
+ * Here's how:
+ *
+ * 1. The preprocessor expands the arguments to _IF casting the condition to '0'
+ * or '1'.
+ * 2. The casted condition is concatencated with _IF_ giving _IF_0 or _IF_1.
+ * 3. The _IF_0 and _IF_1 macros either returns the argument or doesn't (e.g.
+ * they implement the "choice selection" part of the macro).
+ * 4. Note that the "true" clause is in the extra set of brackets; thus these
+ * become the arguments to _IF_0 or _IF_1 and thus a selection is made!
+ */
+#define IF(c) _IF(BOOL(c))
+#define _IF(c) CAT(_IF_,c)
+#define _IF_0(...)
+#define _IF_1(...) __VA_ARGS__
+
+/**
+ * Macro if/else statement. Usage:
+ *
+ * IF_ELSE(c)( \
+ * expansion when true, \
+ * expansion when false \
+ * )
+ *
+ * The mechanism is analogous to IF.
+ */
+#define IF_ELSE(c) _IF_ELSE(BOOL(c))
+#define _IF_ELSE(c) CAT(_IF_ELSE_,c)
+#define _IF_ELSE_0(t,f) f
+#define _IF_ELSE_1(t,f) t
+
+
+/**
+ * Macro which checks if it has any arguments. Returns '0' if there are no
+ * arguments, '1' otherwise.
+ *
+ * Limitation: HAS_ARGS(,1,2,3) returns 0 -- this check essentially only checks
+ * that the first argument exists.
+ *
+ * This macro works as follows:
+ *
+ * 1. _END_OF_ARGUMENTS_ is concatenated with the first argument.
+ * 2. If the first argument is not present then only "_END_OF_ARGUMENTS_" will
+ * remain, otherwise "_END_OF_ARGUMENTS something_here" will remain.
+ * 3. In the former case, the _END_OF_ARGUMENTS_() macro expands to a
+ * 0 when it is expanded. In the latter, a non-zero result remains.
+ * 4. BOOL is used to force non-zero results into 1 giving the clean 0 or 1
+ * output required.
+ */
+#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)())
+#define _END_OF_ARGUMENTS_() 0
+
+
+/**
+ * Macro map/list comprehension. Usage:
+ *
+ * MAP(op, sep, ...)
+ *
+ * Produces a 'sep()'-separated list of the result of op(arg) for each arg.
+ *
+ * Example Usage:
+ *
+ * #define MAKE_HAPPY(x) happy_##x
+ * #define COMMA() ,
+ * MAP(MAKE_HAPPY, COMMA, 1,2,3)
+ *
+ * Which expands to:
+ *
+ * happy_1 , happy_2 , happy_3
+ *
+ * How it works:
+ *
+ * 1. The MAP macro simply maps the inner MAP_INNER function in an EVAL which
+ * forces it to be expanded a large number of times, thus enabling many steps
+ * of iteration (see step 6).
+ * 2. The MAP_INNER macro is substituted for its body.
+ * 3. In the body, op(cur_val) is substituted giving the value for this
+ * iteration.
+ * 4. The IF macro expands according to whether further iterations are required.
+ * This expansion either produces _IF_0 or _IF_1.
+ * 5. Since the IF is followed by a set of brackets containing the "if true"
+ * clause, these become the argument to _IF_0 or _IF_1. At this point, the
+ * macro in the brackets will be expanded giving the separator followed by
+ * _MAP_INNER EMPTY()()(op, sep, __VA_ARGS__).
+ * 5. If the IF was not taken, the above will simply be discarded and everything
+ * stops. If the IF is taken, The expression is then processed a second time
+ * yielding "_MAP_INNER()(op, sep, __VA_ARGS__)". Note that this call looks
+ * very similar to the essentially the same as the original call except the
+ * first argument has been dropped.
+ * 6. At this point expansion of MAP_INNER will terminate. However, since we can
+ * force more rounds of expansion using EVAL1. In the argument-expansion pass
+ * of the EVAL1, _MAP_INNER() is expanded to MAP_INNER which is then expanded
+ * using the arguments which follow it as in step 2-5. This is followed by a
+ * second expansion pass as the substitution of EVAL1() is expanded executing
+ * 2-5 a second time. This results in up to two iterations occurring. Using
+ * many nested EVAL1 macros, i.e. the very-deeply-nested EVAL macro, will in
+ * this manner produce further iterations, hence the outer MAP macro doing
+ * this for us.
+ *
+ * Important tricks used:
+ *
+ * * If we directly produce "MAP_INNER" in an expansion of MAP_INNER,
+ * a special case in the preprocessor will prevent it being expanded
+ * in the future, even if we EVAL. As a result, the MAP_INNER macro
+ * carefully only expands to something containing "_MAP_INNER()"
+ * which requires a further expansion step to invoke MAP_INNER and
+ * thus implementing the recursion.
+ *
+ * * To prevent _MAP_INNER being expanded within the macro we must
+ * first defer its expansion during its initial pass as an argument
+ * to _IF_0 or _IF_1. We must then defer its expansion a second time
+ * as part of the body of the _IF_0. As a result hence the DEFER2.
+ *
+ * * _MAP_INNER seemingly gets away with producing itself because it
+ * actually only produces MAP_INNER. It just happens that when
+ * _MAP_INNER() is expanded in this case it is followed by some
+ * arguments which get consumed by MAP_INNER and produce a
+ * _MAP_INNER. As such, the macro expander never marks _MAP_INNER
+ * as expanding to itself and thus it will still be expanded in
+ * future productions of itself.
+ */
+#define MAP(...) \
+ IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_INNER(__VA_ARGS__)))
+#define MAP_INNER(op,sep,cur_val, ...) \
+ op(cur_val) \
+ IF(HAS_ARGS(__VA_ARGS__))( \
+ sep() DEFER2(_MAP_INNER)()(op, sep, ##__VA_ARGS__) \
+ )
+#define _MAP_INNER() MAP_INNER
+
+
+/**
+ * This is a variant of the MAP macro which also includes as an argument to the
+ * operation a valid C variable name which is different for each iteration.
+ *
+ * Usage:
+ * MAP_WITH_ID(op, sep, ...)
+ *
+ * Where op is a macro op(val, id) which takes a list value and an ID. This ID
+ * will simply be a unary number using the digit "I", that is, I, II, III, IIII,
+ * and so on.
+ *
+ * Example:
+ *
+ * #define MAKE_STATIC_VAR(type, name) static type name;
+ * MAP_WITH_ID(MAKE_STATIC_VAR, EMPTY, int, int, int, bool, char)
+ *
+ * Which expands to:
+ *
+ * static int I; static int II; static int III; static bool IIII;
+ * static char IIIII;
+ *
+ * The mechanism is analogous to the MAP macro.
+ */
+#define MAP_WITH_ID(op,sep,...) \
+ IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_WITH_ID_INNER(op,sep,I, ##__VA_ARGS__)))
+#define MAP_WITH_ID_INNER(op,sep,id,cur_val, ...) \
+ op(cur_val,id) \
+ IF(HAS_ARGS(__VA_ARGS__))( \
+ sep() DEFER2(_MAP_WITH_ID_INNER)()(op, sep, CAT(id,I), ##__VA_ARGS__) \
+ )
+#define _MAP_WITH_ID_INNER() MAP_WITH_ID_INNER
+
+
+/**
+ * This is a variant of the MAP macro which iterates over pairs rather than
+ * singletons.
+ *
+ * Usage:
+ * MAP_PAIRS(op, sep, ...)
+ *
+ * Where op is a macro op(val_1, val_2) which takes two list values.
+ *
+ * Example:
+ *
+ * #define MAKE_STATIC_VAR(type, name) static type name;
+ * MAP_PAIRS(MAKE_STATIC_VAR, EMPTY, char, my_char, int, my_int)
+ *
+ * Which expands to:
+ *
+ * static char my_char; static int my_int;
+ *
+ * The mechanism is analogous to the MAP macro.
+ */
+#define MAP_PAIRS(op,sep,...) \
+ IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_PAIRS_INNER(op,sep,__VA_ARGS__)))
+#define MAP_PAIRS_INNER(op,sep,cur_val_1, cur_val_2, ...) \
+ op(cur_val_1,cur_val_2) \
+ IF(HAS_ARGS(__VA_ARGS__))( \
+ sep() DEFER2(_MAP_PAIRS_INNER)()(op, sep, __VA_ARGS__) \
+ )
+#define _MAP_PAIRS_INNER() MAP_PAIRS_INNER
+
+/**
+ * This is a variant of the MAP macro which iterates over a two-element sliding
+ * window.
+ *
+ * Usage:
+ * MAP_SLIDE(op, last_op, sep, ...)
+ *
+ * Where op is a macro op(val_1, val_2) which takes the two list values
+ * currently in the window. last_op is a macro taking a single value which is
+ * called for the last argument.
+ *
+ * Example:
+ *
+ * #define SIMON_SAYS_OP(simon, next) IF(NOT(simon()))(next)
+ * #define SIMON_SAYS_LAST_OP(val) last_but_not_least_##val
+ * #define SIMON_SAYS() 0
+ *
+ * MAP_SLIDE(SIMON_SAYS_OP, SIMON_SAYS_LAST_OP, EMPTY, wiggle, SIMON_SAYS,
+ * dance, move, SIMON_SAYS, boogie, stop)
+ *
+ * Which expands to:
+ *
+ * dance boogie last_but_not_least_stop
+ *
+ * The mechanism is analogous to the MAP macro.
+ */
+#define MAP_SLIDE(op,last_op,sep,...) \
+ IF(HAS_ARGS(__VA_ARGS__))(EVAL(MAP_SLIDE_INNER(op,last_op,sep,__VA_ARGS__)))
+#define MAP_SLIDE_INNER(op,last_op,sep,cur_val, ...) \
+ IF(HAS_ARGS(__VA_ARGS__))(op(cur_val,FIRST(__VA_ARGS__))) \
+ IF(NOT(HAS_ARGS(__VA_ARGS__)))(last_op(cur_val)) \
+ IF(HAS_ARGS(__VA_ARGS__))( \
+ sep() DEFER2(_MAP_SLIDE_INNER)()(op, last_op, sep, __VA_ARGS__) \
+ )
+#define _MAP_SLIDE_INNER() MAP_SLIDE_INNER
+
+
+/**
+ * Strip any excess commas from a set of arguments.
+ */
+#define REMOVE_TRAILING_COMMAS(...) \
+ MAP(PASS, COMMA, __VA_ARGS__)
+
+
+/**
+ * Evaluates an array of macros passing 1 argument
+ */
+#define EMAP1(...) \
+ IF(HAS_ARGS(__VA_ARGS__))(EVAL(EMAP1_INNER(__VA_ARGS__)))
+
+#define EMAP1_INNER(ARG1, OP, ...) \
+ _##OP(ARG1) \
+ IF(HAS_ARGS(__VA_ARGS__)) \
+ (DEFER2(_EMAP1_INNER)()(ARG1, ##__VA_ARGS__))
+
+#define _EMAP1_INNER() EMAP1_INNER
+
+
+/**
+ * Evaluates an array of macros passing 2 arguments
+ */
+#define EMAP2(...) \
+ IF(HAS_ARGS(__VA_ARGS__))(EVAL(EMAP2_INNER(__VA_ARGS__)))
+
+#define EMAP2_INNER(ARG1, ARG2, OP, ...) \
+ _##OP(ARG1, ARG2) \
+ IF(HAS_ARGS(__VA_ARGS__)) \
+ (DEFER2(_EMAP2_INNER)()(ARG1, ARG2, ##__VA_ARGS__))
+
+#define _EMAP2_INNER() EMAP2_INNER
diff --git a/src/avr/src/drv8711.c b/src/avr/src/drv8711.c
new file mode 100644
index 0000000..5db2355
--- /dev/null
+++ b/src/avr/src/drv8711.c
@@ -0,0 +1,546 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "drv8711.h"
+#include "status.h"
+#include "stepper.h"
+#include "switch.h"
+#include "estop.h"
+#include "seek.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+#define DRIVERS MOTORS
+
+
+#define DRV8711_WORD_BYTE_PTR(WORD, LOW) (((uint8_t *)&(WORD)) + !(LOW))
+
+
+typedef enum {
+ SS_WRITE_OFF,
+ SS_WRITE_BLANK,
+ SS_WRITE_DECAY,
+ SS_WRITE_STALL,
+ SS_WRITE_DRIVE,
+ SS_WRITE_TORQUE,
+ SS_WRITE_CTRL,
+ SS_READ_OFF,
+ SS_READ_STATUS,
+ SS_CLEAR_STATUS,
+} spi_state_t;
+
+
+bool motor_fault = false;
+
+
+typedef struct {
+ float current;
+ uint8_t torque;
+} current_t;
+
+
+typedef struct {
+ uint8_t cs_pin;
+ switch_id_t stall_sw;
+
+ uint8_t status;
+ uint16_t flags;
+ bool reset_flags;
+ bool stalled;
+
+ drv8711_state_t state;
+ current_t drive;
+ current_t idle;
+ current_t stall;
+ uint16_t stall_vdiv;
+ uint8_t stall_thresh;
+ uint8_t last_thresh;
+ uint16_t sample_time;
+ //float stall_current;
+
+ uint8_t microstep;
+ stall_callback_t stall_cb;
+
+ uint8_t last_torque;
+ uint8_t last_microstep;
+
+ spi_state_t spi_state;
+} drv8711_driver_t;
+
+
+static drv8711_driver_t drivers[DRIVERS] = {
+ {.cs_pin = SPI_CS_0_PIN, .stall_sw = SW_STALL_0},
+ {.cs_pin = SPI_CS_1_PIN, .stall_sw = SW_STALL_1},
+ {.cs_pin = SPI_CS_2_PIN, .stall_sw = SW_STALL_2},
+ {.cs_pin = SPI_CS_3_PIN, .stall_sw = SW_STALL_3},
+};
+
+
+typedef struct {
+ bool advance;
+ uint8_t disable_cs_pin;
+
+ uint16_t command;
+ uint16_t response;
+ uint8_t driver;
+ bool low_byte;
+} spi_t;
+
+static spi_t spi = {0};
+
+
+static void _current_set(current_t *c, float current) {
+ const float gain = DRV8711_CTRL_GAIN(DRV8711_CTRL);
+ const float max_current = CURRENT_SENSE_REF / (CURRENT_SENSE_RESISTOR * gain);
+
+ // Limit to max configurable current (11A)
+ if (max_current < current) current = max_current;
+
+ c->current = current;
+ c->torque = round(current * CURRENT_SENSE_RESISTOR / CURRENT_SENSE_REF *
+ gain * 255);
+}
+
+
+static bool _driver_fault(drv8711_driver_t *drv) {return drv->flags & 0x1f;}
+
+
+static bool _driver_active(drv8711_driver_t *drv) {
+ return drv->state == DRV8711_ACTIVE;
+}
+
+
+static float _driver_get_current(drv8711_driver_t *drv) {
+ if (_driver_fault(drv)) return 0;
+
+ switch (drv->state) {
+ case DRV8711_IDLE: return drv->idle.current;
+ case DRV8711_ACTIVE: return drv->drive.current;
+ default: return 0; // Off
+ }
+}
+
+
+static uint8_t _driver_get_torque(drv8711_driver_t *drv) {
+ if (estop_triggered()) return 0;
+
+ if(seek_active()) return drv->stall.torque;
+
+ switch (drv->state) {
+ case DRV8711_IDLE: return drv->idle.torque;
+ case DRV8711_ACTIVE: return drv->drive.torque;
+ default: return 0; // Off
+ }
+}
+
+
+static uint16_t _driver_spi_command(drv8711_driver_t *drv) {
+ switch (drv->spi_state) {
+ case SS_WRITE_OFF: return DRV8711_WRITE(DRV8711_OFF_REG, DRV8711_OFF);
+ case SS_WRITE_BLANK: return DRV8711_WRITE(DRV8711_BLANK_REG, DRV8711_BLANK);
+ case SS_WRITE_DECAY: return DRV8711_WRITE(DRV8711_DECAY_REG, DRV8711_DECAY);
+
+ case SS_WRITE_STALL: {
+ //uint16_t reg = drv->stall_thresh | DRV8711_STALL_SDCNT_2 | drv->stall_vdiv; //ORIGINAL
+ //uint16_t reg = 50 | DRV8711_STALL_SDCNT_8 | DRV8711_STALL_VDIV_4; //WORKS
+ uint16_t reg = drv->stall_thresh | DRV8711_STALL_SDCNT_8 | drv->stall_vdiv;
+ drv->last_thresh = drv->stall_thresh;
+ return DRV8711_WRITE(DRV8711_STALL_REG, reg);
+ }
+
+ case SS_WRITE_DRIVE: return DRV8711_WRITE(DRV8711_DRIVE_REG, DRV8711_DRIVE);
+
+ case SS_WRITE_TORQUE:
+ drv->last_torque = _driver_get_torque(drv);
+ return DRV8711_WRITE(DRV8711_TORQUE_REG, DRV8711_TORQUE | drv->last_torque);
+
+ case SS_WRITE_CTRL: {
+ // NOTE, we disable the driver if it's not active. The chip gets hot
+ // idling with the driver enabled.
+ bool enable = _driver_get_torque(drv);
+ drv->last_microstep = drv->microstep;
+ return DRV8711_WRITE(DRV8711_CTRL_REG, DRV8711_CTRL |
+ (drv->microstep << 3) |
+ (enable ? DRV8711_CTRL_ENBL_bm : 0));
+ }
+
+ case SS_READ_OFF: return DRV8711_READ(DRV8711_OFF_REG);
+ case SS_READ_STATUS: return DRV8711_READ(DRV8711_STATUS_REG);
+
+ case SS_CLEAR_STATUS:
+ drv->reset_flags = false;
+ drv->flags = 0;
+ return DRV8711_WRITE(DRV8711_STATUS_REG, 0x0fff & ~drv->status);
+ }
+
+ return 0; // Should not get here
+}
+
+
+static spi_state_t _driver_spi_next(drv8711_driver_t *drv) {
+ // Process response
+ switch (drv->spi_state) {
+ case SS_READ_OFF:
+ // We read back the OFF register to test for communication failure.
+ if ((spi.response & 0x1ff) != DRV8711_OFF)
+ drv->flags |= DRV8711_COMM_ERROR_bm;
+ else drv->flags &= ~DRV8711_COMM_ERROR_bm;
+ break;
+
+ case SS_READ_STATUS: {
+ drv->status = spi.response;
+
+ // NOTE If there is a power fault and the drivers are not powered
+ // then the status flags will read 0xff but the motor fault line will
+ // not be asserted. So, fault flags are not valid with out motor fault.
+ // Also, a real stall cannot occur if the driver is inactive.
+ bool active = _driver_active(drv);
+ uint8_t mask =
+ ((motor_fault && !drv->reset_flags) ? 0xff : 0) | (active ? 0xc0 : 0);
+ drv->flags = (drv->flags & 0xff00) | (mask & drv->status);
+
+ // EStop on fatal driver faults
+ if (_driver_fault(drv)) estop_trigger(STAT_MOTOR_FAULT);
+ break;
+ }
+
+ default: break;
+ }
+
+ switch (drv->spi_state) {
+ case SS_READ_OFF:
+ if (drv->flags & DRV8711_COMM_ERROR_bm) return SS_WRITE_OFF; // Retry
+ break;
+
+ case SS_READ_STATUS:
+ if (drv->reset_flags) return SS_CLEAR_STATUS;
+ if (drv->last_torque != _driver_get_torque(drv)) return SS_WRITE_TORQUE;
+ if (drv->last_microstep != drv->microstep) return SS_WRITE_CTRL;
+ if (drv->last_thresh != drv->stall_thresh) return SS_WRITE_STALL;
+ // Fall through
+
+ case SS_CLEAR_STATUS: return SS_READ_OFF;
+
+ default: break;
+ }
+
+ return (spi_state_t)(drv->spi_state + 1); // Next
+}
+
+
+static void _spi_send() {
+ drv8711_driver_t *drv = &drivers[spi.driver];
+
+ // Flush any status errors (TODO check SPI errors)
+ uint8_t x = SPIC.STATUS;
+ x = x;
+
+ // Read byte
+ *DRV8711_WORD_BYTE_PTR(spi.response, !spi.low_byte) = SPIC.DATA;
+
+ // Advance state and process response
+ if (spi.advance) {
+ spi.advance = false;
+
+ // Handle response and set next state
+ drv->spi_state = _driver_spi_next(drv);
+
+ // Next driver
+ if (++spi.driver == DRIVERS) spi.driver = 0; // Wrap around
+ drv = &drivers[spi.driver];
+ }
+
+ // Disable CS
+ if (spi.disable_cs_pin) {
+ OUTCLR_PIN(spi.disable_cs_pin); // Set low (inactive)
+ _delay_us(1);
+ spi.disable_cs_pin = 0;
+ }
+
+ if (spi.low_byte) {
+ spi.disable_cs_pin = drv->cs_pin; // Schedule next CS disable
+ spi.advance = true; // Word complete
+
+ } else {
+ // Enable CS
+ OUTSET_PIN(drv->cs_pin); // Set high (active)
+ _delay_us(1);
+
+ // Get next command
+ spi.command = _driver_spi_command(drv);
+ }
+
+ // Write byte and prep next read
+ SPIC.DATA = *DRV8711_WORD_BYTE_PTR(spi.command, spi.low_byte);
+
+ // Next byte
+ spi.low_byte = !spi.low_byte;
+}
+
+
+ISR(SPIC_INT_vect) {_spi_send();}
+
+
+static void _stall_change(int driver, bool stalled) {
+ drivers[driver].stalled = stalled;
+
+ // Call stall callback
+ if (stalled && drivers[driver].stall_cb)
+ drivers[driver].stall_cb(driver);
+}
+
+
+static void _stall_switch_cb(switch_id_t sw, bool active) {
+ switch (sw) {
+ case SW_STALL_0: _stall_change(0, active); break;
+ case SW_STALL_1: _stall_change(1, active); break;
+ case SW_STALL_2: _stall_change(2, active); break;
+ case SW_STALL_3: _stall_change(3, active); break;
+ default: break;
+ }
+}
+
+
+static void _motor_fault_switch_cb(switch_id_t sw, bool active) {
+ motor_fault = active;
+}
+
+
+void drv8711_init() {
+ // Setup pins
+ // Must set the SS pin either in/high or out/any for master mode to work
+ // Note, this pin is also used by the USART as the CTS line
+ DIRSET_PIN(SPI_SS_PIN); // Output
+ OUTSET_PIN(SPI_CLK_PIN); // High
+ DIRSET_PIN(SPI_CLK_PIN); // Output
+ DIRCLR_PIN(SPI_MISO_PIN); // Input
+ OUTSET_PIN(SPI_MOSI_PIN); // High
+ DIRSET_PIN(SPI_MOSI_PIN); // Output
+
+ // Motor driver enable
+ OUTSET_PIN(MOTOR_ENABLE_PIN); // Active high
+ DIRSET_PIN(MOTOR_ENABLE_PIN); // Output
+
+ for (int i = 0; i < DRIVERS; i++) {
+ uint8_t cs_pin = drivers[i].cs_pin;
+ OUTSET_PIN(cs_pin); // High
+ DIRSET_PIN(cs_pin); // Output
+
+ switch_id_t stall_sw = drivers[i].stall_sw;
+ switch_set_type(stall_sw, SW_NORMALLY_OPEN);
+ switch_set_callback(stall_sw, _stall_switch_cb);
+
+ drivers[i].reset_flags = true; // Reset flags once on startup
+ }
+
+ switch_set_type(SW_MOTOR_FAULT, SW_NORMALLY_OPEN);
+ switch_set_callback(SW_MOTOR_FAULT, _motor_fault_switch_cb);
+
+ // Configure SPI
+ PR.PRPC &= ~PR_SPI_bm; // Disable power reduction
+ SPIC.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_0_gc |
+ SPI_PRESCALER_DIV16_gc; // enable, big endian, master, mode, clock div
+ PIN_PORT(SPI_CLK_PIN)->REMAP = PORT_SPI_bm; // Swap SCK and MOSI
+ SPIC.INTCTRL = SPI_INTLVL_LO_gc; // interupt level
+
+ _spi_send(); // Kick it off
+}
+
+
+drv8711_state_t drv8711_get_state(int driver) {
+ if (driver < 0 || DRIVERS <= driver) return DRV8711_DISABLED;
+ return drivers[driver].state;
+}
+
+
+void drv8711_set_state(int driver, drv8711_state_t state) {
+ if (driver < 0 || DRIVERS <= driver) return;
+ drivers[driver].state = state;
+}
+
+
+void drv8711_set_microsteps(int driver, uint16_t msteps) {
+ if (driver < 0 || DRIVERS <= driver) return;
+ switch (msteps) {
+ case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 256:
+ break;
+ default: return; // Invalid
+ }
+
+ drivers[driver].microstep = round(logf(msteps) / logf(2));
+}
+
+
+
+void drv8711_set_stall_callback(int driver, stall_callback_t cb) {
+ drivers[driver].stall_cb = cb;
+}
+
+
+float get_drive_current(int driver) {
+ if (driver < 0 || DRIVERS <= driver) return 0;
+ return drivers[driver].drive.current;
+}
+
+
+void set_drive_current(int driver, float value) {
+ if (driver < 0 || DRIVERS <= driver || value < 0) return;
+ if (MAX_CURRENT < value) value = MAX_CURRENT;
+ _current_set(&drivers[driver].drive, value);
+}
+
+
+float get_idle_current(int driver) {
+ if (driver < 0 || DRIVERS <= driver) return 0;
+ return drivers[driver].idle.current;
+}
+
+
+void set_idle_current(int driver, float value) {
+ if (driver < 0 || DRIVERS <= driver || value < 0 || MAX_IDLE_CURRENT < value)
+ return;
+
+ _current_set(&drivers[driver].idle, value);
+}
+
+
+float get_active_current(int driver) {
+ if (driver < 0 || DRIVERS <= driver) return 0;
+ return _driver_get_current(&drivers[driver]);
+}
+
+
+bool get_motor_fault() {return motor_fault;}
+
+
+void set_driver_flags(int driver, uint16_t flags) {
+ drivers[driver].reset_flags = true;
+}
+
+
+uint16_t get_driver_flags(int driver) {return drivers[driver].flags;}
+bool get_driver_stalled(int driver) {return drivers[driver].stalled;}
+
+
+float get_stall_volts(int driver) {
+ if (driver < 0 || DRIVERS <= driver) return 0;
+
+ float vdiv;
+ switch (drivers[driver].stall_vdiv) {
+ case DRV8711_STALL_VDIV_4: vdiv = 4; break;
+ case DRV8711_STALL_VDIV_8: vdiv = 8; break;
+ case DRV8711_STALL_VDIV_16: vdiv = 16; break;
+ default: vdiv = 32; break;
+ }
+
+ return 1.8 / 256 * vdiv * drivers[driver].stall_thresh;
+}
+
+
+void set_stall_volts(int driver, float volts) {
+ if (driver < 0 || DRIVERS <= driver) return;
+
+ uint16_t vdiv = DRV8711_STALL_VDIV_32;
+ uint16_t thresh = (uint16_t)(volts * 256 / 1.8);
+
+ if (thresh < 4 << 8) {
+ thresh >>= 2;
+ vdiv = DRV8711_STALL_VDIV_4;
+
+ } else if (thresh < 8 << 8) {
+ thresh >>= 3;
+ vdiv = DRV8711_STALL_VDIV_8;
+
+ } else if (thresh < 16 << 8) {
+ thresh >>= 4;
+ vdiv = DRV8711_STALL_VDIV_16;
+
+ } else {
+ if (thresh < 32 << 8) thresh >>= 5;
+ else thresh = 255;
+ }
+
+ drivers[driver].stall_vdiv = vdiv;
+ drivers[driver].stall_thresh = thresh;
+}
+
+void set_stall_sample_time(int driver, uint16_t sample_time)
+{
+ if (driver < 0 || DRIVERS <= driver) return;
+
+ switch (sample_time) {
+ case 50: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_50; break;
+ case 100: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_100; break;
+ case 200: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_200; break;
+ case 300: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_300; break;
+ case 400: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_400; break;
+ case 600: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_600; break;
+ case 800: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_800; break;
+ case 1000: drivers[driver].sample_time = DRV8711_TORQUE_SMPLTH_1000; break;
+ default: return; // Invalid
+ }
+
+}
+
+uint16_t get_stall_sample_time(int driver)
+{
+ if (driver < 0 || DRIVERS <= driver) return 0;
+
+ uint16_t sample_time = 0;
+ switch (drivers[driver].sample_time) {
+ case DRV8711_TORQUE_SMPLTH_50: sample_time = 50; break;
+ case DRV8711_TORQUE_SMPLTH_100: sample_time = 100; break;
+ case DRV8711_TORQUE_SMPLTH_200: sample_time = 200; break;
+ case DRV8711_TORQUE_SMPLTH_300: sample_time = 300; break;
+ case DRV8711_TORQUE_SMPLTH_400: sample_time = 400; break;
+ case DRV8711_TORQUE_SMPLTH_600: sample_time = 600; break;
+ case DRV8711_TORQUE_SMPLTH_800: sample_time = 800; break;
+ case DRV8711_TORQUE_SMPLTH_1000: sample_time = 1000; break;
+ default: sample_time = 50; break;
+ }
+
+ return sample_time;
+}
+
+float get_stall_current(int driver) {
+ if (driver < 0 || DRIVERS <= driver) return 0;
+ return drivers[driver].stall.current;
+}
+
+
+void set_stall_current(int driver, float value) {
+ if (driver < 0 || DRIVERS <= driver || value < 0) return;
+ if (MAX_CURRENT < value) value = MAX_CURRENT;
+ _current_set(&drivers[driver].stall, value);
+}
diff --git a/src/avr/src/drv8711.h b/src/avr/src/drv8711.h
new file mode 100644
index 0000000..78c3859
--- /dev/null
+++ b/src/avr/src/drv8711.h
@@ -0,0 +1,188 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+
+#include "config.h"
+#include "status.h"
+#include "motor.h"
+
+#include
+#include
+
+enum {
+ DRV8711_CTRL_REG,
+ DRV8711_TORQUE_REG,
+ DRV8711_OFF_REG,
+ DRV8711_BLANK_REG,
+ DRV8711_DECAY_REG,
+ DRV8711_STALL_REG,
+ DRV8711_DRIVE_REG,
+ DRV8711_STATUS_REG,
+};
+
+
+enum {
+ DRV8711_CTRL_ENBL_bm = 1 << 0,
+ DRV8711_CTRL_RDIR_bm = 1 << 1,
+ DRV8711_CTRL_RSTEP_bm = 1 << 2,
+ DRV8711_CTRL_MODE_1 = 0 << 3,
+ DRV8711_CTRL_MODE_2 = 1 << 3,
+ DRV8711_CTRL_MODE_4 = 2 << 3,
+ DRV8711_CTRL_MODE_8 = 3 << 3,
+ DRV8711_CTRL_MODE_16 = 4 << 3,
+ DRV8711_CTRL_MODE_32 = 5 << 3,
+ DRV8711_CTRL_MODE_64 = 6 << 3,
+ DRV8711_CTRL_MODE_128 = 7 << 3,
+ DRV8711_CTRL_MODE_256 = 8 << 3,
+ DRV8711_CTRL_EXSTALL_bm = 1 << 7,
+ DRV8711_CTRL_ISGAIN_5 = 0 << 8,
+ DRV8711_CTRL_ISGAIN_10 = 1 << 8,
+ DRV8711_CTRL_ISGAIN_20 = 2 << 8,
+ DRV8711_CTRL_ISGAIN_40 = 3 << 8,
+ DRV8711_CTRL_DTIME_400 = 0 << 10,
+ DRV8711_CTRL_DTIME_450 = 1 << 10,
+ DRV8711_CTRL_DTIME_650 = 2 << 10,
+ DRV8711_CTRL_DTIME_850 = 3 << 10,
+};
+
+
+enum {
+ DRV8711_TORQUE_SMPLTH_50 = 0 << 8,
+ DRV8711_TORQUE_SMPLTH_100 = 1 << 8,
+ DRV8711_TORQUE_SMPLTH_200 = 2 << 8,
+ DRV8711_TORQUE_SMPLTH_300 = 3 << 8,
+ DRV8711_TORQUE_SMPLTH_400 = 4 << 8,
+ DRV8711_TORQUE_SMPLTH_600 = 5 << 8,
+ DRV8711_TORQUE_SMPLTH_800 = 6 << 8,
+ DRV8711_TORQUE_SMPLTH_1000 = 7 << 8,
+};
+
+
+enum {
+ DRV8711_OFF_PWMMODE_bm = 1 << 8,
+};
+
+
+enum {
+ DRV8711_BLANK_ABT_bm = 1 << 8,
+};
+
+
+enum {
+ DRV8711_DECAY_DECMOD_SLOW = 0 << 8,
+ DRV8711_DECAY_DECMOD_OPT = 1 << 8,
+ DRV8711_DECAY_DECMOD_FAST = 2 << 8,
+ DRV8711_DECAY_DECMOD_MIXED = 3 << 8,
+ DRV8711_DECAY_DECMOD_AUTO_OPT = 4 << 8,
+ DRV8711_DECAY_DECMOD_AUTO_MIXED = 5 << 8,
+};
+
+
+enum {
+ DRV8711_STALL_SDCNT_1 = 0 << 8,
+ DRV8711_STALL_SDCNT_2 = 1 << 8,
+ DRV8711_STALL_SDCNT_4 = 2 << 8,
+ DRV8711_STALL_SDCNT_8 = 3 << 8,
+ DRV8711_STALL_VDIV_32 = 0 << 10,
+ DRV8711_STALL_VDIV_16 = 1 << 10,
+ DRV8711_STALL_VDIV_8 = 2 << 10,
+ DRV8711_STALL_VDIV_4 = 3 << 10,
+};
+
+
+enum {
+ DRV8711_DRIVE_OCPTH_250 = 0 << 0,
+ DRV8711_DRIVE_OCPTH_500 = 1 << 0,
+ DRV8711_DRIVE_OCPTH_750 = 2 << 0,
+ DRV8711_DRIVE_OCPTH_1000 = 3 << 0,
+ DRV8711_DRIVE_OCPDEG_1 = 0 << 2,
+ DRV8711_DRIVE_OCPDEG_2 = 1 << 2,
+ DRV8711_DRIVE_OCPDEG_4 = 2 << 2,
+ DRV8711_DRIVE_OCPDEG_8 = 3 << 2,
+ DRV8711_DRIVE_TDRIVEN_250 = 0 << 4,
+ DRV8711_DRIVE_TDRIVEN_500 = 1 << 4,
+ DRV8711_DRIVE_TDRIVEN_1000 = 2 << 4,
+ DRV8711_DRIVE_TDRIVEN_2000 = 3 << 4,
+ DRV8711_DRIVE_TDRIVEP_250 = 0 << 6,
+ DRV8711_DRIVE_TDRIVEP_500 = 1 << 6,
+ DRV8711_DRIVE_TDRIVEP_1000 = 2 << 6,
+ DRV8711_DRIVE_TDRIVEP_2000 = 3 << 6,
+ DRV8711_DRIVE_IDRIVEN_100 = 0 << 8,
+ DRV8711_DRIVE_IDRIVEN_200 = 1 << 8,
+ DRV8711_DRIVE_IDRIVEN_300 = 2 << 8,
+ DRV8711_DRIVE_IDRIVEN_400 = 3 << 8,
+ DRV8711_DRIVE_IDRIVEP_50 = 0 << 10,
+ DRV8711_DRIVE_IDRIVEP_100 = 1 << 10,
+ DRV8711_DRIVE_IDRIVEP_150 = 2 << 10,
+ DRV8711_DRIVE_IDRIVEP_200 = 3 << 10,
+};
+
+
+enum {
+ DRV8711_STATUS_OTS_bm = 1 << 0,
+ DRV8711_STATUS_AOCP_bm = 1 << 1,
+ DRV8711_STATUS_BOCP_bm = 1 << 2,
+ DRV8711_STATUS_APDF_bm = 1 << 3,
+ DRV8711_STATUS_BPDF_bm = 1 << 4,
+ DRV8711_STATUS_UVLO_bm = 1 << 5,
+ DRV8711_STATUS_STD_bm = 1 << 6,
+ DRV8711_STATUS_STDLAT_bm = 1 << 7,
+ DRV8711_COMM_ERROR_bm = 1 << 8,
+};
+
+
+#define DRV8711_READ(ADDR) ((1 << 15) | ((ADDR) << 12))
+#define DRV8711_WRITE(ADDR, DATA) (((ADDR) << 12) | ((DATA) & 0xfff))
+#define DRV8711_CMD_ADDR(CMD) (((CMD) >> 12) & 7)
+#define DRV8711_CMD_IS_READ(CMD) ((1 << 15) & (CMD))
+
+#define DRV8711_CTRL_ISGAIN_BM (3 << 8)
+#define DRV8711_CTRL_GET_GAIN(CTRL) ((CTRL) & DRV8711_CTRL_ISGAIN_BM)
+
+#define DRV8711_CTRL_GAIN(CTRL) \
+ (DRV8711_CTRL_GET_GAIN(CTRL) == DRV8711_CTRL_ISGAIN_5 ? 5 : \
+ (DRV8711_CTRL_GET_GAIN(CTRL) == DRV8711_CTRL_ISGAIN_10 ? 10 : \
+ (DRV8711_CTRL_GET_GAIN(CTRL) == DRV8711_CTRL_ISGAIN_20 ? 20 : 40)))
+
+
+typedef enum {
+ DRV8711_DISABLED,
+ DRV8711_IDLE,
+ DRV8711_ACTIVE,
+} drv8711_state_t;
+
+
+typedef void (*stall_callback_t)(int driver);
+
+
+void drv8711_init();
+drv8711_state_t drv8711_get_state(int driver);
+void drv8711_set_state(int driver, drv8711_state_t state);
+void drv8711_set_microsteps(int driver, uint16_t msteps);
+void drv8711_set_stall_callback(int driver, stall_callback_t cb);
diff --git a/src/avr/src/emu.h b/src/avr/src/emu.h
new file mode 100644
index 0000000..cb3d605
--- /dev/null
+++ b/src/avr/src/emu.h
@@ -0,0 +1,36 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#ifdef __AVR__
+#define emu_init()
+#define emu_callback()
+
+#else
+void emu_init();
+void emu_callback();
+
+#endif
diff --git a/src/avr/src/estop.c b/src/avr/src/estop.c
new file mode 100644
index 0000000..1e9bacb
--- /dev/null
+++ b/src/avr/src/estop.c
@@ -0,0 +1,126 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "estop.h"
+#include "motor.h"
+#include "stepper.h"
+#include "spindle.h"
+#include "switch.h"
+#include "hardware.h"
+#include "config.h"
+#include "state.h"
+#include "outputs.h"
+#include "jog.h"
+#include "exec.h"
+
+
+static stat_t estop_reason = STAT_OK;
+
+
+static void _switch_callback(switch_id_t id, bool active) {
+ if (active) estop_trigger(STAT_ESTOP_SWITCH);
+ else estop_clear();
+}
+
+
+void estop_init() {
+ switch_set_callback(SW_ESTOP, _switch_callback);
+ if (switch_is_active(SW_ESTOP)) estop_trigger(STAT_ESTOP_SWITCH);
+}
+
+
+bool estop_triggered() {return estop_reason != STAT_OK;}
+
+
+void estop_trigger(stat_t reason) {
+ if (estop_triggered()) return;
+ estop_reason = reason;
+
+ // Set fault signal
+ outputs_set_active(FAULT_PIN, true);
+
+ // Shutdown peripherals
+ st_shutdown();
+ spindle_estop();
+ jog_stop();
+ outputs_stop();
+
+ // Set machine state
+ state_estop();
+}
+
+
+void estop_clear() {
+ // It is important that we don't clear the estop if it's not set because
+ // it can cause a reboot loop.
+ if (!estop_triggered()) return;
+
+ // Check if estop switch is set
+ if (switch_is_active(SW_ESTOP)) {
+ estop_reason = STAT_ESTOP_SWITCH;
+ return; // Can't clear while estop switch is still active
+ }
+
+ // Clear fault signal
+ outputs_set_active(FAULT_PIN, false);
+
+ estop_reason = STAT_OK;
+
+ // Reboot
+ // Note, hardware.c waits until any spindle stop command has been delivered
+ hw_request_hard_reset();
+}
+
+
+// Var callbacks
+bool get_estop() {return estop_triggered();}
+
+
+void set_estop(bool value) {
+ if (value == estop_triggered()) return;
+ if (value) estop_trigger(STAT_ESTOP_USER);
+ else estop_clear();
+}
+
+
+PGM_P get_estop_reason() {return status_to_pgmstr(estop_reason);}
+
+
+// Command callbacks
+stat_t command_estop(char *cmd) {
+ estop_trigger(STAT_ESTOP_USER);
+ return STAT_OK;
+}
+
+
+stat_t command_shutdown(char *cmd) {
+ estop_trigger(STAT_POWER_SHUTDOWN);
+ return STAT_OK;
+}
+
+
+stat_t command_clear(char *cmd) {estop_clear(); return STAT_OK;}
diff --git a/src/avr/src/estop.h b/src/avr/src/estop.h
new file mode 100644
index 0000000..652f5c0
--- /dev/null
+++ b/src/avr/src/estop.h
@@ -0,0 +1,42 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "status.h"
+
+#include
+
+
+void estop_init();
+bool estop_triggered();
+void estop_trigger(stat_t reason);
+void estop_clear();
+
+
+#define ESTOP_ASSERT(COND, CODE) \
+ do {if (!(COND)) estop_trigger(CODE);} while (0)
diff --git a/src/avr/src/exec.c b/src/avr/src/exec.c
new file mode 100644
index 0000000..bc4d9df
--- /dev/null
+++ b/src/avr/src/exec.c
@@ -0,0 +1,306 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "exec.h"
+
+#include "stepper.h"
+#include "motor.h"
+#include "axis.h"
+#include "util.h"
+#include "command.h"
+#include "switch.h"
+#include "seek.h"
+#include "estop.h"
+#include "state.h"
+#include "spindle.h"
+#include "config.h"
+#include "SCurve.h"
+
+
+static struct {
+ exec_cb_t cb;
+
+ float position[AXES];
+ float velocity;
+ float accel;
+ float jerk;
+ float peak_vel;
+ float peak_accel;
+
+ float feed_override;
+
+ struct {
+ float target[AXES];
+ float time;
+ float vel;
+ float accel;
+ float max_accel;
+ float max_jerk;
+ power_update_t power_updates[2 * POWER_MAX_UPDATES];
+ exec_cb_t cb;
+ } seg;
+} ex;
+
+
+static void _limit_switch_cb(switch_id_t sw, bool active) {
+ if (sw == seek_get_switch()) return;
+ if (ex.velocity && active) estop_trigger(STAT_ESTOP_SWITCH);
+}
+
+
+void exec_init() {
+ memset(&ex, 0, sizeof(ex));
+ ex.feed_override = 1; // TODO implement feed override
+
+ // Set callback for limit switches
+ for (int sw = SW_MIN_0; sw <= SW_MAX_3; sw++)
+ switch_set_callback((switch_id_t)sw, _limit_switch_cb);
+}
+
+
+void exec_get_position(float p[AXES]) {
+ memcpy(p, ex.position, sizeof(ex.position));
+}
+
+
+float exec_get_axis_position(int axis) {return ex.position[axis];}
+
+
+void exec_set_velocity(float v) {
+ ex.velocity = v;
+ if (ex.peak_vel < v) ex.peak_vel = v;
+}
+
+
+float exec_get_velocity() {return ex.velocity;}
+
+
+void exec_set_acceleration(float a) {
+ ex.accel = a;
+ if (ex.peak_accel < a) ex.peak_accel = a;
+}
+
+
+float exec_get_acceleration() {return ex.accel;}
+void exec_set_jerk(float j) {ex.jerk = j;}
+
+
+void exec_set_cb(exec_cb_t cb) {ex.cb = cb;}
+
+
+void exec_move_to_target(const float target[]) {
+ ESTOP_ASSERT(isfinite(target[AXIS_X]) && isfinite(target[AXIS_Y]) &&
+ isfinite(target[AXIS_Z]) && isfinite(target[AXIS_A]) &&
+ isfinite(target[AXIS_B]) && isfinite(target[AXIS_C]),
+ STAT_BAD_FLOAT);
+
+ // Prep power updates
+ st_prep_power(ex.seg.power_updates);
+
+ // Shift power updates
+ for (unsigned i = 0; i < POWER_MAX_UPDATES; i++) {
+ ex.seg.power_updates[i] = ex.seg.power_updates[i + POWER_MAX_UPDATES];
+ ex.seg.power_updates[i + POWER_MAX_UPDATES].state = POWER_IGNORE;
+ }
+
+ // Update position
+ copy_vector(ex.position, target);
+
+ // Call the stepper prep function
+ st_prep_line(target);
+}
+
+
+stat_t _segment_exec() {
+ float t = ex.seg.time;
+ float v = ex.seg.vel;
+ float a = ex.seg.accel;
+
+ // Handle pause
+ if (state_get() == STATE_STOPPING) {
+ a = SCurve::nextAccel(SEGMENT_TIME, 0, ex.velocity, ex.accel,
+ ex.seg.max_accel, ex.seg.max_jerk);
+ v = ex.velocity + SEGMENT_TIME * a;
+ t *= ex.seg.vel / v;
+
+ if (v < MIN_VELOCITY || seek_switch_found()) {
+ t = v = 0;
+ ex.seg.cb = 0;
+ command_reset_position();
+ state_holding();
+ seek_end();
+ spindle_update_speed();
+ }
+ }
+
+ // Wait for next seg if time is too short and we are still moving
+ if (t < SEGMENT_TIME && (!t || v)) {
+ if (!v) {
+ exec_set_velocity(0);
+ exec_set_acceleration(0);
+ exec_set_jerk(0);
+ ex.seg.time = 0;
+ }
+ ex.cb = ex.seg.cb;
+ return STAT_AGAIN;
+ }
+
+ // Update velocity and accel
+ exec_set_velocity(v);
+ exec_set_acceleration(a);
+
+ if (t <= SEGMENT_TIME) {
+ // Move
+ exec_move_to_target(ex.seg.target);
+ ex.seg.time = 0;
+
+ } else {
+ // Compute next target
+ float ratio = SEGMENT_TIME / t;
+ float target[AXES];
+ for (int axis = 0; axis < AXES; axis++) {
+ float diff = ex.seg.target[axis] - ex.position[axis];
+ target[axis] = ex.position[axis] + ratio * diff;
+ }
+
+ // Move
+ exec_move_to_target(target);
+
+ // Update time
+ if (t == ex.seg.time) ex.seg.time -= SEGMENT_TIME;
+ else ex.seg.time -= SEGMENT_TIME * v / ex.seg.vel;
+ }
+
+ // Check switch
+ if (seek_switch_found()) state_seek_hold();
+
+ return STAT_OK;
+}
+
+
+stat_t exec_segment(float time, const float target[], float vel, float accel,
+ float maxAccel, float maxJerk,
+ const power_update_t power_updates[]) {
+ // Copy power updates in to the correct position given the time offset
+ float nextT = ex.seg.time + time;
+ const float stepT = 1.0 / 60000; // 1ms in mins
+ float t = 0.5 / 60000; // 0.5ms in mins
+ unsigned j = 0;
+ for (unsigned i = 0; t < nextT && j < POWER_MAX_UPDATES; i++) {
+ if (ex.seg.time < t) ex.seg.power_updates[i] = power_updates[j++];
+ t += stepT;
+ }
+
+ copy_vector(ex.seg.target, target);
+ ex.seg.time = nextT;
+ ex.seg.vel = vel;
+ ex.seg.accel = accel;
+ ex.seg.max_accel = maxAccel;
+ ex.seg.max_jerk = maxJerk;
+ ex.seg.cb = ex.cb;
+ ex.cb = _segment_exec;
+
+ // TODO To be precise, seek_end() should not be called until the current
+ // segment has completed execution.
+ if (!ex.seg.cb) seek_end(); // No callback when at line end
+
+ return _segment_exec();
+}
+
+
+// Called by stepper.c from low-level interrupt
+stat_t exec_next() {
+ // Hold if we've reached zero velocity between commands and stopping
+ if (!ex.cb && !exec_get_velocity() && state_get() == STATE_STOPPING)
+ state_holding();
+
+ if (state_get() == STATE_HOLDING) return STAT_NOP;
+ if (!ex.cb && !command_exec()) return STAT_NOP; // Queue empty
+ if (!ex.cb) return STAT_AGAIN; // Non-exec command
+ return ex.cb(); // Exec
+}
+
+
+// Variable callbacks
+float get_axis_position(int axis) {return ex.position[axis];}
+float get_velocity() {return ex.velocity / VELOCITY_MULTIPLIER;}
+float get_acceleration() {return ex.accel / ACCEL_MULTIPLIER;}
+float get_jerk() {return ex.jerk / JERK_MULTIPLIER;}
+float get_peak_vel() {return ex.peak_vel / VELOCITY_MULTIPLIER;}
+void set_peak_vel(float x) {ex.peak_vel = 0;}
+float get_peak_accel() {return ex.peak_accel / ACCEL_MULTIPLIER;}
+void set_peak_accel(float x) {ex.peak_accel = 0;}
+uint16_t get_feed_override() {return ex.feed_override * 1000;}
+void set_feed_override(uint16_t value) {ex.feed_override = value / 1000.0;}
+
+
+// Command callbacks
+typedef struct {
+ uint8_t axis;
+ float position;
+} set_axis_t;
+
+
+stat_t command_set_axis(char *cmd) {
+ cmd++; // Skip command name
+
+ // Decode axis
+ int axis = axis_get_id(*cmd++);
+ if (axis < 0) return STAT_INVALID_ARGUMENTS;
+
+ // Decode position
+ float position;
+ if (!decode_float(&cmd, &position)) return STAT_BAD_FLOAT;
+
+ // Check for end of command
+ if (*cmd) return STAT_INVALID_ARGUMENTS;
+
+ // Update command
+ command_set_axis_position((uint8_t)axis, position);
+
+ // Queue
+ set_axis_t set_axis = {(uint8_t)axis, position};
+ command_push(COMMAND_set_axis, &set_axis);
+
+ return STAT_OK;
+}
+
+
+unsigned command_set_axis_size() {return sizeof(set_axis_t);}
+
+
+void command_set_axis_exec(void *data) {
+ set_axis_t *cmd = (set_axis_t *)data;
+
+ // Update exec
+ ex.position[cmd->axis] = cmd->position;
+
+ // Update motors
+ for (int motor = 0; motor < MOTORS; motor++)
+ if (motor_get_axis(motor) == cmd->axis)
+ motor_set_position(motor, cmd->position);
+}
diff --git a/src/avr/src/exec.h b/src/avr/src/exec.h
new file mode 100644
index 0000000..af238cd
--- /dev/null
+++ b/src/avr/src/exec.h
@@ -0,0 +1,59 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+
+#include "config.h"
+#include "spindle.h"
+#include "status.h"
+
+#include
+#include
+
+
+typedef stat_t (*exec_cb_t)();
+
+
+void exec_init();
+
+void exec_get_position(float p[AXES]);
+float exec_get_axis_position(int axis);
+float exec_get_power_scale();
+void exec_set_velocity(float v);
+float exec_get_velocity();
+void exec_set_acceleration(float a);
+float exec_get_acceleration();
+void exec_set_jerk(float j);
+
+void exec_set_cb(exec_cb_t cb);
+
+void exec_move_to_target(const float target[]);
+stat_t exec_segment(float time, const float target[], float vel, float accel,
+ float maxAccel, float maxJerk,
+ const power_update_t power_updates[]);
+stat_t exec_next();
diff --git a/src/avr/src/hardware.c b/src/avr/src/hardware.c
new file mode 100644
index 0000000..ec18f75
--- /dev/null
+++ b/src/avr/src/hardware.c
@@ -0,0 +1,158 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "hardware.h"
+#include "rtc.h"
+#include "usart.h"
+#include "config.h"
+#include "pgmspace.h"
+
+#include
+#include
+#include
+
+#include
+#include
+
+
+typedef struct {
+ char id[26];
+ bool hard_reset; // flag to perform a hard reset
+} hw_t;
+
+static hw_t hw = {{0}};
+
+
+#define PROD_SIGS (*(NVM_PROD_SIGNATURES_t *)0x0000)
+#define HEXNIB(x) "0123456789abcdef"[(x) & 0xf]
+
+
+static void _init_clock() {
+#if 0 // 32Mhz Int RC
+ OSC.CTRL |= OSC_RC32MEN_bm | OSC_RC32KEN_bm; // Enable 32MHz & 32KHz osc
+ while (!(OSC.STATUS & OSC_RC32KRDY_bm)); // Wait for 32Khz oscillator
+ while (!(OSC.STATUS & OSC_RC32MRDY_bm)); // Wait for 32MHz oscillator
+
+ // Defaults to calibrate against internal 32Khz clock
+ DFLLRC32M.CTRL = DFLL_ENABLE_bm; // Enable DFLL
+ CCP = CCP_IOREG_gc; // Disable register security
+ CLK.CTRL = CLK_SCLKSEL_RC32M_gc; // Switch to 32MHz clock
+
+#else
+ // 12-16 MHz crystal; 0.4-16 MHz XTAL w/ 16K CLK startup
+ OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
+ OSC.CTRL = OSC_XOSCEN_bm; // enable external crystal oscillator
+ while (!(OSC.STATUS & OSC_XOSCRDY_bm)); // wait for oscillator ready
+
+ OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2; // PLL source, 2x (32 MHz sys clock)
+ OSC.CTRL = OSC_PLLEN_bm | OSC_XOSCEN_bm; // Enable PLL & External Oscillator
+ while (!(OSC.STATUS & OSC_PLLRDY_bm)); // wait for PLL ready
+
+ CCP = CCP_IOREG_gc;
+ CLK.CTRL = CLK_SCLKSEL_PLL_gc; // switch to PLL clock
+#endif
+
+ OSC.CTRL &= ~OSC_RC2MEN_bm; // disable internal 2 MHz clock
+}
+
+
+#ifdef __AVR__
+static void _load_hw_id_byte(int i, register8_t *reg) {
+ NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
+ uint8_t byte = pgm_read_byte(reg);
+ NVM.CMD = NVM_CMD_NO_OPERATION_gc;
+
+ hw.id[i] = HEXNIB(byte >> 4);
+ hw.id[i + 1] = HEXNIB(byte);
+}
+#endif // __AVR__
+
+
+static void _read_hw_id() {
+#ifdef __AVR__
+ int i = 0;
+ _load_hw_id_byte(i, &PROD_SIGS.LOTNUM5); i += 2;
+ _load_hw_id_byte(i, &PROD_SIGS.LOTNUM4); i += 2;
+ _load_hw_id_byte(i, &PROD_SIGS.LOTNUM3); i += 2;
+ _load_hw_id_byte(i, &PROD_SIGS.LOTNUM2); i += 2;
+ _load_hw_id_byte(i, &PROD_SIGS.LOTNUM1); i += 2;
+ _load_hw_id_byte(i, &PROD_SIGS.LOTNUM0); i += 2;
+ hw.id[i++] = '-';
+ _load_hw_id_byte(i, &PROD_SIGS.WAFNUM); i += 2;
+ hw.id[i++] = '-';
+ _load_hw_id_byte(i, &PROD_SIGS.COORDX1); i += 2;
+ _load_hw_id_byte(i, &PROD_SIGS.COORDX0); i += 2;
+ hw.id[i++] = '-';
+ _load_hw_id_byte(i, &PROD_SIGS.COORDY1); i += 2;
+ _load_hw_id_byte(i, &PROD_SIGS.COORDY0); i += 2;
+ hw.id[i] = 0;
+
+#else // __AVR__
+ for (int i = 0; i < 25; i++)
+ hw.id[i] = '0';
+ hw.id[25] = 0;
+#endif // __AVR__
+}
+
+
+/// Lowest level hardware init
+void hw_init() {
+ _init_clock(); // set system clock
+ rtc_init(); // real time counter
+ _read_hw_id();
+
+ // Round-robin, interrupts in application section, all interupts levels
+ CCP = CCP_IOREG_gc;
+ PMIC.CTRL =
+ PMIC_RREN_bm | PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;
+}
+
+
+void hw_request_hard_reset() {hw.hard_reset = true;}
+
+
+static void _hard_reset() {
+ usart_flush();
+ cli();
+ CCP = CCP_IOREG_gc;
+ RST.CTRL = RST_SWRST_bm;
+}
+
+
+/// Controller's rest handler
+void hw_reset_handler() {
+ if (!hw.hard_reset) return;
+
+ // Flush serial port and wait for EEPROM writes to finish
+ while (!usart_tx_empty() || !eeprom_is_ready())
+ continue;
+
+ _hard_reset();
+}
+
+
+const char *get_hw_id() {return hw.id;}
diff --git a/src/avr/src/hardware.h b/src/avr/src/hardware.h
new file mode 100644
index 0000000..e2be012
--- /dev/null
+++ b/src/avr/src/hardware.h
@@ -0,0 +1,40 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "status.h"
+
+#include
+
+
+void hw_init();
+void hw_request_hard_reset();
+void hw_reset_handler();
+
+uint8_t hw_disable_watchdog();
+void hw_restore_watchdog(uint8_t state);
diff --git a/src/avr/src/huanyang.c b/src/avr/src/huanyang.c
new file mode 100644
index 0000000..26481e1
--- /dev/null
+++ b/src/avr/src/huanyang.c
@@ -0,0 +1,301 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "huanyang.h"
+#include "config.h"
+#include "modbus.h"
+#include "estop.h"
+
+#include
+
+#include
+#include
+
+
+/*
+ Huanyang is not quite Modbus compliant.
+
+ Message format is:
+
+ [id][func][length][data][checksum]
+
+ Where:
+
+ id - 1-byte Peer ID
+ func - 1-byte One of hy_func_t
+ length - 1-byte Length data in bytes
+ data - length bytes - Command arguments
+ checksum - 16-bit CRC: x^16 + x^15 + x^2 + 1 (0xa001) initial: 0xffff
+*/
+
+
+// See VFD manual pg56 3.1.3
+typedef enum {
+ HUANYANG_FUNC_READ = 1, // [len=1][hy_addr_t]
+ HUANYANG_FUNC_WRITE, // [len=3][hy_addr_t][data]
+ HUANYANG_CTRL_WRITE, // [len=1][hy_ctrl_state_t]
+ HUANYANG_CTRL_READ, // [len=1][hy_ctrl_addr_t]
+ HUANYANG_FREQ_WRITE, // [len=2][freq]
+ HUANYANG_RESERVED_1,
+ HUANYANG_RESERVED_2,
+ HUANYANG_LOOP_TEST,
+} hy_func_t;
+
+
+// Sent in HUANYANG_CTRL_WRITE
+// See VFD manual pg57 3.1.3.c
+typedef enum {
+ HUANYANG_RUN = 1 << 0,
+ HUANYANG_FORWARD = 1 << 1,
+ HUANYANG_REVERSE = 1 << 2,
+ HUANYANG_STOP = 1 << 3,
+ HUANYANG_REV_FWD = 1 << 4,
+ HUANYANG_JOG = 1 << 5,
+ HUANYANG_JOG_FORWARD = 1 << 6,
+ HUANYANG_JOG_REVERSE = 1 << 7,
+} hy_ctrl_state_t;
+
+
+// Returned by HUANYANG_CTRL_WRITE
+// See VFD manual pg57 3.1.3.c
+typedef enum {
+ HUANYANG_STATUS_RUN = 1 << 0,
+ HUANYANG_STATUS_JOG = 1 << 1,
+ HUANYANG_STATUS_COMMAND_REV = 1 << 2,
+ HUANYANG_STATUS_RUNNING = 1 << 3,
+ HUANYANG_STATUS_JOGGING = 1 << 4,
+ HUANYANG_STATUS_JOGGING_REV = 1 << 5,
+ HUANYANG_STATUS_BRAKING = 1 << 6,
+ HUANYANG_STATUS_TRACK_START = 1 << 7,
+} hy_ctrl_status_t;
+
+
+// Sent in HUANYANG_CTRL_READ
+// See VFD manual pg57 3.1.3.d
+typedef enum {
+ HUANYANG_TARGET_FREQ,
+ HUANYANG_ACTUAL_FREQ,
+ HUANYANG_ACTUAL_CURRENT,
+ HUANYANG_ACTUAL_RPM,
+ HUANYANG_DCV,
+ HUANYANG_ACV,
+ HUANYANG_COUNTER,
+ HUANYANG_TEMPERATURE,
+} hy_ctrl_addr_t;
+
+
+static struct {
+ uint8_t state;
+
+ deinit_cb_t deinit_cb;
+ bool shutdown;
+ bool changed;
+ float power;
+
+ float actual_freq;
+ float actual_current;
+ uint16_t actual_rpm;
+ uint16_t temperature;
+
+ float max_freq;
+ float min_freq;
+ uint16_t rated_rpm;
+
+ uint8_t status;
+} hy;
+
+
+static void _func_read_response(hy_addr_t addr, uint16_t value) {
+ switch (addr) {
+ case HY_PD005_MAX_FREQUENCY: hy.max_freq = value * 0.01; break;
+ case HY_PD011_FREQUENCY_LOWER_LIMIT: hy.min_freq = value * 0.01; break;
+ case HY_PD144_RATED_MOTOR_RPM: hy.rated_rpm = value; break;
+ default: break;
+ }
+}
+
+
+static void _ctrl_read_response(hy_ctrl_addr_t addr, uint16_t value) {
+ switch (addr) {
+ case HUANYANG_ACTUAL_FREQ: hy.actual_freq = value * 0.01; break;
+ case HUANYANG_ACTUAL_CURRENT: hy.actual_current = value * 0.01; break;
+ case HUANYANG_ACTUAL_RPM: hy.actual_rpm = value; break;
+ case HUANYANG_TEMPERATURE: hy.temperature = value; break;
+ default: break;
+ }
+}
+
+
+static uint16_t _read_word(const uint8_t *data) {
+ return (uint16_t)data[0] << 8 | data[1];
+}
+
+
+static void _handle_response(hy_func_t func, const uint8_t *data) {
+ switch (func) {
+ case HUANYANG_FUNC_READ:
+ _func_read_response((hy_addr_t)*data, _read_word(data + 1));
+ break;
+
+ case HUANYANG_FUNC_WRITE: break;
+ case HUANYANG_CTRL_WRITE: hy.status = *data; break;
+
+ case HUANYANG_CTRL_READ:
+ _ctrl_read_response((hy_ctrl_addr_t)*data, _read_word(data + 1));
+ break;
+
+ case HUANYANG_FREQ_WRITE: break;
+ default: break;
+ }
+}
+
+
+static void _next_command();
+
+
+static bool _shutdown() {
+ if (!hy.shutdown && !estop_triggered()) return false;
+ modbus_deinit();
+ if (hy.deinit_cb) hy.deinit_cb();
+ return true;
+}
+
+
+static void _modbus_cb(uint8_t func, uint8_t bytes, const uint8_t *data) {
+ if (!data) { // Modbus command failed
+ if (_shutdown()) return;
+ hy.state = 0;
+
+ } else if (bytes == *data + 1) {
+ _handle_response((hy_func_t)func, data + 1);
+
+ if (func == HUANYANG_CTRL_WRITE && _shutdown()) return;
+
+ // Next command
+ if (++hy.state == 9) {
+ if (hy.shutdown || hy.changed) hy.state = 0;
+ else hy.state = 5;
+ hy.changed = false;
+ }
+ }
+
+ _next_command();
+}
+
+
+static void _func_read(hy_addr_t addr) {
+ uint8_t data[2] = {1, addr};
+ modbus_func(HUANYANG_FUNC_READ, 2, data, 4, _modbus_cb);
+}
+
+
+static void _ctrl_write(hy_ctrl_state_t state) {
+ uint8_t data[2] = {1, state};
+ modbus_func(HUANYANG_CTRL_WRITE, 2, data, 2, _modbus_cb);
+}
+
+
+static void _ctrl_read(hy_ctrl_addr_t addr) {
+ uint8_t data[2] = {1, addr};
+ modbus_func(HUANYANG_CTRL_READ, 2, data, 4, _modbus_cb);
+}
+
+
+static void _freq_write(uint16_t freq) {
+ uint8_t data[3] = {2, (uint8_t)(freq >> 8), (uint8_t)freq};
+ modbus_func(HUANYANG_FREQ_WRITE, 3, data, 3, _modbus_cb);
+}
+
+
+static void _next_command() {
+ switch (hy.state) {
+ case 0: { // Update direction
+ hy_ctrl_state_t state = HUANYANG_STOP;
+ if (!hy.shutdown && !estop_triggered()) {
+ if (0 < hy.power)
+ state = (hy_ctrl_state_t)(HUANYANG_RUN | HUANYANG_FORWARD);
+ else if (hy.power < 0)
+ state = (hy_ctrl_state_t)(HUANYANG_RUN | HUANYANG_REV_FWD);
+ }
+
+ _ctrl_write(state);
+ break;
+ }
+
+ case 1: _func_read(HY_PD005_MAX_FREQUENCY); break;
+ case 2: _func_read(HY_PD011_FREQUENCY_LOWER_LIMIT); break;
+ case 3: _func_read(HY_PD144_RATED_MOTOR_RPM); break;
+
+ case 4: { // Update freqency
+ // Compute frequency in Hz
+ float freq = fabs(hy.power * hy.max_freq);
+
+ // Frequency write command
+ _freq_write(freq * 100);
+ break;
+ }
+
+ case 5: _ctrl_read(HUANYANG_ACTUAL_FREQ); break;
+ case 6: _ctrl_read(HUANYANG_ACTUAL_CURRENT); break;
+ case 7: _ctrl_read(HUANYANG_ACTUAL_RPM); break;
+ case 8: _ctrl_read(HUANYANG_TEMPERATURE); break;
+ }
+}
+
+
+void huanyang_init() {
+ modbus_init();
+ memset(&hy, 0, sizeof(hy));
+ _next_command();
+}
+
+
+void huanyang_deinit(deinit_cb_t cb) {
+ hy.deinit_cb = cb;
+ hy.shutdown = true;
+}
+
+
+void huanyang_set(float power) {
+ if (hy.power != power && !hy.shutdown)
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ hy.power = power;
+ hy.changed = true;
+ }
+}
+
+
+float huanyang_get() {return hy.actual_freq / hy.max_freq;}
+uint8_t huanyang_get_status() {return hy.status;}
+
+// Variable callbacks
+float get_hy_freq() {return hy.actual_freq;}
+float get_hy_current() {return hy.actual_current;}
+uint16_t get_hy_temp() {return hy.temperature;}
+float get_hy_max_freq() {return hy.max_freq;}
+float get_hy_min_freq() {return hy.min_freq;}
+uint16_t get_hy_rated_rpm() {return hy.rated_rpm;}
diff --git a/src/avr/src/huanyang.h b/src/avr/src/huanyang.h
new file mode 100644
index 0000000..ccad449
--- /dev/null
+++ b/src/avr/src/huanyang.h
@@ -0,0 +1,226 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "spindle.h"
+
+
+void huanyang_init();
+void huanyang_deinit(deinit_cb_t cb);
+void huanyang_set(float power);
+float huanyang_get();
+uint8_t huanyang_get_status();
+
+
+/// See Huanyang VFD user manual
+typedef enum {
+ HY_PD000_PARAMETER_LOCK,
+ HY_PD001_SOURCE_OF_OPERATION_COMMANDS,
+ HY_PD002_SOURCE_OF_OPERATING_FREQUENCY,
+ HY_PD003_MAIN_FREQUENCY,
+ HY_PD004_BASE_FREQUENCY,
+ HY_PD005_MAX_FREQUENCY,
+ HY_PD006_INTERMEDIATE_FREQUENCY,
+ HY_PD007_MIN_FREQUENCY,
+ HY_PD008_MAX_VOLTAGE,
+ HY_PD009_INTERMEDIATE_VOLTAGE,
+ HY_PD010_MIN_VOLTAGE,
+ HY_PD011_FREQUENCY_LOWER_LIMIT,
+ HY_PD012_RESERVED,
+ HY_PD013_PARAMETER_RESET,
+ HY_PD014_ACCEL_TIME_1,
+ HY_PD015_DECEL_TIME_1,
+ HY_PD016_ACCEL_TIME_2,
+ HY_PD017_DECEL_TIME_2,
+ HY_PD018_ACCEL_TIME_3,
+ HY_PD019_DECEL_TIME_3,
+ HY_PD020_ACCEL_TIME_4,
+ HY_PD021_DECEL_TIME_4,
+ HY_PD022_FACTORY_RESERVED,
+ HY_PD023_REV_ROTATION_SELECT,
+ HY_PD024_STOP_KEY,
+ HY_PD025_STARTING_MODE,
+ HY_PD026_STOPPING_MODE,
+ HY_PD027_STARTING_FREQUENCY,
+ HY_PD028_STOPPING_FREQUENCY,
+ HY_PD029_DC_BRAKING_TIME_AT_START,
+ HY_PD030_DC_BRAKING_TIME_AT_STOP,
+ HY_PD031_DC_BRAKING_VOLTAGE_LEVEL,
+ HY_PD032_FREQUENCY_TRACK_TIME,
+ HY_PD033_CURRENT_LEVEL_FOR_FREQUENCY_TRACK,
+ HY_PD034_VOLTAGE_RISE_TIME_FOR_FREQUENCY_TRACK,
+ HY_PD035_FREQUENCY_STEP_LENGTH,
+ HY_PD036,
+ HY_PD037,
+ HY_PD038,
+ HY_PD039,
+ HY_PD040,
+ HY_PD041_CARRIER_FREQUENCY,
+ HY_PD042_JOGGING_FREQUENCY,
+ HY_PD043_S_CURVE_TIME,
+ HY_PD044_MULTI_INPUT_FOR,
+ HY_PD045_MULTI_INPUT_REV,
+ HY_PD046_MULTI_INPUT_RST,
+ HY_PD047_MULTI_INPUT_SPH,
+ HY_PD048_MULTI_INPUT_SPM,
+ HY_PD049_MULTI_INPUT_SPL,
+ HY_PD050_MULTI_OUTPUT_DRV,
+ HY_PD051_MULTI_OUTPUT_UPF,
+ HY_PD052_MULTI_OUTPUT_FA_FB_FC,
+ HY_PD053_MULTI_OUTPUT_KA_KB,
+ HY_PD054_MULTI_OUTPUT_AM,
+ HY_PD055_AM_ANALOG_OUTPUT_GAIN,
+ HY_PD056_SKIP_FREQUENCY_1,
+ HY_PD057_SKIP_FREQUENCY_2,
+ HY_PD058_SKIP_FREQUENCY_3,
+ HY_PD059_SKIP_FREQUENCY_RANGE,
+ HY_PD060_UNIFORM_FREQUENCY_1,
+ HY_PD061_UNIFORM_FREQUENCY_2,
+ HY_PD062_UNIFORM_FREQUENCY_RANGE,
+ HY_PD063_TIMER_1_TIME,
+ HY_PD064_TIMER_2_TIME,
+ HY_PD065_COUNTING_VALUE,
+ HY_PD066_INTERMEDIATE_COUNTER,
+ HY_PD067,
+ HY_PD068,
+ HY_PD069,
+ HY_PD070_ANALOG_INPUT,
+ HY_PD071_ANALOG_FILTERING_CONSTANT,
+ HY_PD072_HIGHER_ANALOG_FREQUENCY,
+ HY_PD073_LOWER_ANALOG_FREQUENCY,
+ HY_PD074_BIAS_DIRECTION_AT_HIGHER_FREQUENCY,
+ HY_PD075_BIAS_DIRECTION_AT_LOWER_FREQUENCY,
+ HY_PD076_ANALOG_NEGATIVE_BIAS_REVERSE,
+ HY_PD077_UP_DOWN_FUNCTION,
+ HY_PD078_UP_DOWN_SPEED,
+ HY_PD079,
+ HY_PD080_PLC_OPERATION,
+ HY_PD081_AUTO_PLC,
+ HY_PD082_PLC_RUNNING_DIRECTION,
+ HY_PD083,
+ HY_PD084_PLC_RAMP_TIME,
+ HY_PD085,
+ HY_PD086_FREQUENCY_2,
+ HY_PD087_FREQUENCY_3,
+ HY_PD088_FREQUENCY_4,
+ HY_PD089_FREQUENCY_5,
+ HY_PD090_FREQUENCY_6,
+ HY_PD091_FREQUENCY_7,
+ HY_PD092_FREQUENCY_8,
+ HY_PD093,
+ HY_PD094,
+ HY_PD095,
+ HY_PD096,
+ HY_PD097,
+ HY_PD098,
+ HY_PD099,
+ HY_PD100,
+ HY_PD101_TIMER_1,
+ HY_PD102_TIMER_2,
+ HY_PD103_TIMER_3,
+ HY_PD104_TIMER_4,
+ HY_PD105_TIMER_5,
+ HY_PD106_TIMER_6,
+ HY_PD107_TIMER_7,
+ HY_PD108_TIMER_8,
+ HY_PD109,
+ HY_PD110,
+ HY_PD111,
+ HY_PD112,
+ HY_PD113,
+ HY_PD114,
+ HY_PD115,
+ HY_PD116,
+ HY_PD117_AUTOPLC_MEMORY_FUNCTION,
+ HY_PD118_OVER_VOLTAGE_STALL_PREVENTION,
+ HY_PD119_STALL_PREVENTION_LEVEL_AT_RAMP_UP,
+ HY_PD120_STALL_PREVENTION_LEVEL_AT_CONSTANT_SPEED,
+ HY_PD121_DECEL_TIME_FOR_STALL_PREVENTION_AT_CONSTANT_SPEED,
+ HY_PD122_STALL_PREVENTION_LEVEL_AT_DECELERATION,
+ HY_PD123_OVER_TORQUE_DETECT_MODE,
+ HY_PD124_OVER_TORQUE_DETECT_LEVEL,
+ HY_PD125_OVER_TORQUE_DETECT_TIME,
+ HY_PD126,
+ HY_PD127,
+ HY_PD128,
+ HY_PD129,
+ HY_PD130_NUMBER_OF_AUXILIARY_PUMP,
+ HY_PD131_CONTINUOUS_RUNNING_TIME_OF_AUXILIARY_PUMPS,
+ HY_PD132_INTERLOCKING_TIME_OF_AUXILIARY_PUMP,
+ HY_PD133_HIGH_SPEED_RUNNING_TIME,
+ HY_PD134_LOW_SPEED_RUNNING_TIME,
+ HY_PD135_STOPPING_VOLTAGE_LEVEL,
+ HY_PD136_LASTING_TIME_OF_STOPPING_VOLTAGE_LEVEL,
+ HY_PD137_WAKEUP_VOLTAGE_LEVEL,
+ HY_PD138_SLEEP_FREQUENCY,
+ HY_PD139_LASTING_TIME_OF_SLEEP_FREQUENCY,
+ HY_PD140,
+ HY_PD141_RATED_MOTOR_VOLTAGE,
+ HY_PD142_RATED_MOTOR_CURRENT,
+ HY_PD143_MOTOR_POLE_NUMBER,
+ HY_PD144_RATED_MOTOR_RPM,
+ HY_PD145_AUTO_TORQUE_COMPENSATION,
+ HY_PD146_MOTOR_NO_LOAD_CURRENT,
+ HY_PD147_MOTOR_SLIP_COMPENSATION,
+ HY_PD148,
+ HY_PD149,
+ HY_PD150_AUTO_VOLTAGE_REGULATION,
+ HY_PD151_AUTO_ENERGY_SAVING,
+ HY_PD152_FAULT_RESTART_TIME,
+ HY_PD153_RESTART_AFTER_INSTANTANEOUS_STOP,
+ HY_PD154_ALLOWABLE_POWER_BREAKDOWN_TIME,
+ HY_PD155_NUMBER_OF_ABNORMAL_RESTART,
+ HY_PD156_PROPORTIONAL_CONSTANT,
+ HY_PD157_INTEGRAL_TIME,
+ HY_PD158_DIFFERENTIAL_TIME,
+ HY_PD159_TARGET_VALUE,
+ HY_PD160_PID_TARGET_VALUE,
+ HY_PD161_PID_UPPER_LIMIT,
+ HY_PD162_PID_LOWER_LIMIT,
+ HY_PD163_COMMUNICATION_ADDRESSES,
+ HY_PD164_COMMUNICATION_BAUD_RATE,
+ HY_PD165_COMMUNICATION_DATA_METHOD,
+ HY_PD166,
+ HY_PD167,
+ HY_PD168,
+ HY_PD169,
+ HY_PD170_DISPLAY_ITEMS,
+ HY_PD171_DISPLAY_ITEMS_OPEN,
+ HY_PD172_FAULT_CLEAR,
+ HY_PD173,
+ HY_PD174_RATED_CURRENT_OF_INVERTER,
+ HY_PD175_INVERTER_MODEL,
+ HY_PD176_INVERTER_FREQUENCY_STANDARD,
+ HY_PD177_FAULT_RECORD_1,
+ HY_PD178_FAULT_RECORD_2,
+ HY_PD179_FAULT_RECORD_3,
+ HY_PD180_FAULT_RECORD_4,
+ HY_PD181_SOFTWARE_VERSION,
+ HY_PD182_MANUFACTURE_DATE,
+ HY_PD183_SERIAL_NO,
+} hy_addr_t;
diff --git a/src/avr/src/i2c.c b/src/avr/src/i2c.c
new file mode 100644
index 0000000..d115a1b
--- /dev/null
+++ b/src/avr/src/i2c.c
@@ -0,0 +1,129 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "i2c.h"
+
+#include
+
+#include
+
+
+typedef struct {
+ i2c_read_cb_t read_cb;
+ i2c_write_cb_t write_cb;
+ uint8_t data[I2C_MAX_DATA + 1];
+ uint8_t length;
+ bool done;
+ bool write;
+} i2c_t;
+
+static i2c_t i2c = {0};
+
+
+static void _i2c_reset_command() {
+ i2c.length = 0;
+ i2c.done = true;
+ i2c.write = false;
+}
+
+
+static void _i2c_end_command() {
+ if (i2c.length && !i2c.write && i2c.read_cb) {
+ i2c.data[i2c.length] = 0; // Null terminate
+ i2c.read_cb(i2c.data, i2c.length);
+ }
+
+ _i2c_reset_command();
+}
+
+
+static void _i2c_command_byte(uint8_t byte) {
+ i2c.data[i2c.length++] = byte;
+}
+
+
+ISR(I2C_ISR) {
+ uint8_t status = I2C_DEV.SLAVE.STATUS;
+
+ // Error or collision
+ if (status & (TWI_SLAVE_BUSERR_bm | TWI_SLAVE_COLL_bm)) {
+ _i2c_reset_command();
+ return; // Ignore
+
+ } else if ((status & TWI_SLAVE_APIF_bm) && (status & TWI_SLAVE_AP_bm)) {
+ // START + address match
+ I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; // ACK address byte
+ _i2c_end_command(); // Handle repeated START
+
+ } else if (status & TWI_SLAVE_APIF_bm) {
+ // STOP
+ I2C_DEV.SLAVE.STATUS = TWI_SLAVE_APIF_bm; // Clear interrupt flag
+ _i2c_end_command();
+
+ } else if (status & TWI_SLAVE_DIF_bm) {
+ i2c.write = status & TWI_SLAVE_DIR_bm;
+
+ // DATA
+ if (i2c.write) { // Write
+ // Check if master ACKed last byte sent
+ if (i2c.length && (status & TWI_SLAVE_RXACK_bm || i2c.done))
+ I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; // End transaction
+
+ else {
+ // Send some data
+ i2c.done = false;
+ I2C_DEV.SLAVE.DATA = i2c.write_cb(i2c.length++, &i2c.done);
+ I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; // Continue transaction
+ }
+
+ } else { // Read
+ _i2c_command_byte(I2C_DEV.SLAVE.DATA);
+
+ // ACK and continue transaction
+ I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc;
+ }
+ }
+}
+
+
+static uint8_t _i2c_default_write_cb(uint8_t offset, bool *done) {
+ *done = true;
+ return 0;
+}
+
+
+void i2c_init() {
+ i2c_set_write_callback(_i2c_default_write_cb);
+
+ I2C_DEV.SLAVE.CTRLA = TWI_SLAVE_INTLVL_LO_gc | TWI_SLAVE_DIEN_bm |
+ TWI_SLAVE_ENABLE_bm | TWI_SLAVE_APIEN_bm | TWI_SLAVE_PIEN_bm;
+ I2C_DEV.SLAVE.ADDR = I2C_ADDR << 1;
+}
+
+
+void i2c_set_read_callback(i2c_read_cb_t cb) {i2c.read_cb = cb;}
+void i2c_set_write_callback(i2c_write_cb_t cb) {i2c.write_cb = cb;}
diff --git a/src/avr/src/i2c.h b/src/avr/src/i2c.h
new file mode 100644
index 0000000..7cd55ca
--- /dev/null
+++ b/src/avr/src/i2c.h
@@ -0,0 +1,41 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "config.h"
+
+#include
+#include
+
+typedef void (*i2c_read_cb_t)(uint8_t *data, uint8_t length);
+typedef uint8_t (*i2c_write_cb_t)(uint8_t offset, bool *done);
+
+
+void i2c_init();
+void i2c_set_read_callback(i2c_read_cb_t cb);
+void i2c_set_write_callback(i2c_write_cb_t cb);
diff --git a/src/avr/src/io.c b/src/avr/src/io.c
new file mode 100644
index 0000000..94ffcda
--- /dev/null
+++ b/src/avr/src/io.c
@@ -0,0 +1,118 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "io.h"
+
+#include "status.h"
+#include "util.h"
+#include "command.h"
+#include "exec.h"
+#include "rtc.h"
+#include "analog.h"
+
+#include
+#include
+#include
+
+
+typedef struct {
+ int8_t port;
+ bool digital;
+ input_mode_t mode;
+ float timeout;
+} input_cmd_t;
+
+
+static input_cmd_t active_cmd = {-1,};
+static uint32_t timeout;
+
+
+void io_callback() {
+ if (active_cmd.port == -1) return;
+
+ bool done = false;
+ float result = 0;
+ if (active_cmd.mode == INPUT_IMMEDIATE || rtc_expired(timeout)) done = true;
+
+ // TODO handle modes
+
+ if (done) {
+ if (active_cmd.digital) { // TODO
+ } else result = analog_get(active_cmd.port);
+
+ printf_P(PSTR("{\"result\": %f}\n"), (double)result);
+ active_cmd.port = -1;
+ }
+}
+
+
+static stat_t _exec_cb() {
+ if (active_cmd.port == -1) exec_set_cb(0);
+ return STAT_NOP;
+}
+
+
+// Command callbacks
+stat_t command_input(char *cmd) {
+ input_cmd_t input_cmd;
+ cmd++; // Skip command
+
+ // Analog or digital
+ if (*cmd == 'd') input_cmd.digital = true;
+ else if (*cmd == 'a') input_cmd.digital = false;
+ else return STAT_INVALID_ARGUMENTS;
+ cmd++;
+
+ // Port index
+ if (!isdigit(*cmd)) return STAT_INVALID_ARGUMENTS;
+ input_cmd.port = *cmd - '0';
+ cmd++;
+
+ // Mode
+ if (!isdigit(*cmd)) return STAT_INVALID_ARGUMENTS;
+ input_cmd.mode = (input_mode_t)(*cmd - '0');
+ if (INPUT_LOW < input_cmd.mode) return STAT_INVALID_ARGUMENTS;
+ cmd++;
+
+ // Timeout
+ if (!decode_float(&cmd, &input_cmd.timeout)) return STAT_BAD_FLOAT;
+
+ command_push(COMMAND_input, &input_cmd);
+
+ return STAT_OK;
+}
+
+
+unsigned command_input_size() {return sizeof(input_cmd_t);}
+
+
+void command_input_exec(void *data) {
+ active_cmd = *(input_cmd_t *)data;
+
+ timeout = rtc_get_time() + active_cmd.timeout * 1000;
+ exec_set_cb(_exec_cb);
+}
diff --git a/src/avr/src/io.h b/src/avr/src/io.h
new file mode 100644
index 0000000..1f8948b
--- /dev/null
+++ b/src/avr/src/io.h
@@ -0,0 +1,40 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+
+typedef enum {
+ INPUT_IMMEDIATE,
+ INPUT_RISE,
+ INPUT_FALL,
+ INPUT_HIGH,
+ INPUT_LOW,
+} input_mode_t;
+
+
+void io_callback();
diff --git a/src/avr/src/jog.c b/src/avr/src/jog.c
new file mode 100644
index 0000000..64df035
--- /dev/null
+++ b/src/avr/src/jog.c
@@ -0,0 +1,169 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "jog.h"
+
+#include "axis.h"
+#include "util.h"
+#include "exec.h"
+#include "state.h"
+#include "command.h"
+#include "config.h"
+#include "SCurve.h"
+
+#include
+#include
+#include
+#include
+#include
+
+
+typedef struct {
+ bool holding;
+ bool writing;
+
+ SCurve scurves[AXES];
+ float next[AXES];
+ float targetV[AXES];
+} jr_t;
+
+jr_t jr = {0};
+
+
+stat_t jog_exec() {
+ bool done = true;
+
+ // Compute per axis velocities and target positions
+ float target[AXES] = {0,};
+ float velocity_sqr = 0;
+
+ for (int axis = 0; axis < AXES; axis++) {
+ if (!axis_is_enabled(axis)) continue;
+
+ // Load next velocity
+ if (!jr.writing)
+ jr.targetV[axis] = jr.next[axis] * axis_get_velocity_max(axis);
+
+ float p = exec_get_axis_position(axis);
+ float vel = jr.scurves[axis].getVelocity();
+ float targetV = jr.targetV[axis];
+ float min = axis_get_soft_limit(axis, true);
+ float max = axis_get_soft_limit(axis, false);
+ bool softLimited = min != max && axis_get_homed(axis);
+
+ // Apply soft limits, if enabled and homed
+ if (softLimited && MIN_VELOCITY < fabs(targetV)) {
+ float dist = jr.scurves[axis].getStoppingDist() *
+ (1 + (JOG_STOPPING_UNDERSHOOT / 100.0));
+
+ if (vel < 0 && p - dist <= min) targetV = -MIN_VELOCITY;
+ if (0 < vel && max <= p + dist) targetV = MIN_VELOCITY;
+ }
+
+ // Compute next velocity
+ float v = jr.scurves[axis].next(SEGMENT_TIME, targetV);
+
+ // Don't overshoot soft limits
+ float deltaP = v * SEGMENT_TIME;
+ if (softLimited && 0 < deltaP && max < p + deltaP) p = max;
+ else if (softLimited && deltaP < 0 && p + deltaP < min) p = min;
+ else p += deltaP;
+
+ // Not done jogging if still moving
+ if (MIN_VELOCITY < fabs(v) || MIN_VELOCITY < fabs(targetV)) done = false;
+
+ velocity_sqr += square(v);
+ target[axis] = p;
+ }
+
+ // Check if we are done
+ if (done) {
+ command_reset_position();
+ exec_set_velocity(0);
+ exec_set_cb(0);
+ if (jr.holding) state_holding();
+ else state_idle();
+
+ return STAT_NOP; // Done, no move executed
+ }
+
+ // Set velocity and target
+ exec_set_velocity(sqrt(velocity_sqr));
+ exec_move_to_target(target);
+
+ return STAT_OK;
+}
+
+
+void jog_stop() {
+ if (state_get() != STATE_JOGGING) return;
+ jr.writing = true;
+ for (int axis = 0; axis < AXES; axis++) jr.next[axis] = 0;
+ jr.writing = false;
+}
+
+
+stat_t command_jog(char *cmd) {
+ // Ignore jog commands when not READY, HOLDING or JOGGING
+ if (state_get() != STATE_READY && state_get() != STATE_HOLDING &&
+ state_get() != STATE_JOGGING)
+ return STAT_NOP;
+
+ // Skip over command code
+ cmd++;
+
+ // Get velocities
+ float velocity[AXES] = {0,};
+ stat_t status = decode_axes(&cmd, velocity);
+ if (status) return status;
+
+ // Check for end of command
+ if (*cmd) return STAT_INVALID_ARGUMENTS;
+
+ // Start jogging
+ if (state_get() != STATE_JOGGING) {
+ memset(&jr, 0, sizeof(jr));
+
+ jr.holding = state_get() == STATE_HOLDING;
+
+ for (int axis = 0; axis < AXES; axis++)
+ if (axis_is_enabled(axis))
+ jr.scurves[axis] =
+ SCurve(axis_get_velocity_max(axis), axis_get_accel_max(axis),
+ axis_get_jerk_max(axis));
+
+ state_jogging();
+ exec_set_cb(jog_exec);
+ }
+
+ // Set next velocities
+ jr.writing = true;
+ for (int axis = 0; axis < AXES; axis++) jr.next[axis] = velocity[axis];
+ jr.writing = false;
+
+ return STAT_OK;
+}
diff --git a/src/avr/src/jog.h b/src/avr/src/jog.h
new file mode 100644
index 0000000..ea093ab
--- /dev/null
+++ b/src/avr/src/jog.h
@@ -0,0 +1,34 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "status.h"
+
+
+stat_t jog_exec();
+void jog_stop();
diff --git a/src/avr/src/lcd.c b/src/avr/src/lcd.c
new file mode 100644
index 0000000..7802eb4
--- /dev/null
+++ b/src/avr/src/lcd.c
@@ -0,0 +1,143 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "lcd.h"
+#include "rtc.h"
+#include "hardware.h"
+#include "command.h"
+
+#include
+#include
+#include
+
+#include
+
+
+void lcd_init(uint8_t addr) {
+ // Enable I2C master
+ TWIC.MASTER.BAUD = F_CPU / 2 / 100000 - 5; // 100 KHz
+ TWIC.MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
+ TWIC.MASTER.CTRLB = TWI_MASTER_TIMEOUT_DISABLED_gc;
+ TWIC.MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
+
+ _delay_ms(50);
+ lcd_nibble(addr, 3 << 4); // Home
+ _delay_ms(50);
+ lcd_nibble(addr, 3 << 4); // Home
+ _delay_ms(50);
+ lcd_nibble(addr, 3 << 4); // Home
+ lcd_nibble(addr, 2 << 4); // 4-bit
+
+ lcd_write(addr,
+ LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS | LCD_4_BIT_MODE, 0);
+ lcd_write(addr, LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON, 0);
+ lcd_write(addr, LCD_ENTRY_MODE_SET | LCD_ENTRY_SHIFT_INC, 0);
+
+ lcd_write(addr, LCD_CLEAR_DISPLAY, 0);
+ lcd_write(addr, LCD_RETURN_HOME, 0);
+}
+
+
+static void _master_wait() {
+#ifdef __AVR__
+ while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm)) continue;
+#endif
+}
+
+
+static void _write_i2c(uint8_t addr, uint8_t data) {
+ data |= BACKLIGHT_BIT;
+
+ TWIC.MASTER.ADDR = addr << 1;
+ _master_wait();
+
+ TWIC.MASTER.DATA = data;
+ _master_wait();
+
+ TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
+
+ _delay_us(100);
+}
+
+
+void lcd_nibble(uint8_t addr, uint8_t data) {
+ _write_i2c(addr, data);
+ _write_i2c(addr, data | ENABLE_BIT);
+ _delay_us(500);
+ _write_i2c(addr, data & ~ENABLE_BIT);
+ _delay_us(100);
+}
+
+
+void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags) {
+ lcd_nibble(addr, flags | (cmd & 0xf0));
+ lcd_nibble(addr, flags | ((cmd << 4) & 0xf0));
+}
+
+
+void lcd_goto(uint8_t addr, uint8_t x, uint8_t y) {
+ static uint8_t row[] = {0, 64, 20, 84};
+ lcd_write(addr, LCD_SET_DDRAM_ADDR | (row[y] + x), 0);
+}
+
+
+void lcd_putchar(uint8_t addr, uint8_t c) {
+ lcd_write(addr, c, REG_SELECT_BIT);
+}
+
+
+void lcd_pgmstr(uint8_t addr, const char *s) {
+ while (true) {
+ char c = pgm_read_byte(s++);
+ if (!c) break;
+ lcd_putchar(addr, c);
+ }
+}
+
+
+void _splash(uint8_t addr) {
+ lcd_init(addr);
+ lcd_goto(addr, 1, 1);
+ lcd_pgmstr(addr, PSTR("Controller booting"));
+ lcd_goto(addr, 3, 2);
+ lcd_pgmstr(addr, PSTR("Please wait..."));
+}
+
+
+void lcd_splash() {
+ wdt_disable();
+ _splash(0x27);
+ _splash(0x3f);
+ wdt_enable(WDTO_250MS);
+}
+
+
+void lcd_rtc_callback() {
+ // Display the splash if we haven't gotten any commands in 1sec since boot
+ if (!command_is_active() && rtc_get_time() == 1000)
+ lcd_splash();
+}
diff --git a/src/avr/src/lcd.h b/src/avr/src/lcd.h
new file mode 100644
index 0000000..b7369f0
--- /dev/null
+++ b/src/avr/src/lcd.h
@@ -0,0 +1,103 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "pgmspace.h"
+
+#include
+
+
+// Control flags
+enum {
+ REG_SELECT_BIT = 1 << 0,
+ READ_BIT = 1 << 1,
+ ENABLE_BIT = 1 << 2,
+ BACKLIGHT_BIT = 1 << 3,
+};
+
+
+// Commands
+enum {
+ LCD_CLEAR_DISPLAY = 1 << 0,
+ LCD_RETURN_HOME = 1 << 1,
+ LCD_ENTRY_MODE_SET = 1 << 2,
+ LCD_DISPLAY_CONTROL = 1 << 3,
+ LCD_CURSOR_SHIFT = 1 << 4,
+ LCD_FUNCTION_SET = 1 << 5,
+ LCD_SET_CGRAM_ADDR = 1 << 6,
+ LCD_SET_DDRAM_ADDR = 1 << 7,
+};
+
+
+// Entry Mode Set flags
+#define LCD_ENTRY_SHIFT_DISPLAY (1 << 0)
+#define LCD_ENTRY_SHIFT_INC (1 << 1)
+#define LCD_ENTRY_SHIFT_DEC (0 << 1)
+
+
+// Display Control flags
+#define LCD_BLINK_ON (1 << 0)
+#define LCD_BLINK_OFF (0 << 0)
+#define LCD_CURSOR_ON (1 << 1)
+#define LCD_CURSOR_OFF (0 << 1)
+#define LCD_DISPLAY_ON (1 << 2)
+#define LCD_DISPLAY_OFF (0 << 2)
+
+
+// Cursor Shift flags
+#define LCD_SHIFT_RIGHT (1 << 2)
+#define LCD_SHIFT_LEFT (0 << 2)
+#define LCD_SHIFT_DISPLAY (1 << 3)
+#define LCD_SHIFT_CURSOR (0 << 3)
+
+
+// Function Set flags
+#define LCD_5x11_DOTS (1 << 2)
+#define LCD_5x8_DOTS (0 << 2)
+#define LCD_2_LINE (1 << 3)
+#define LCD_1_LINE (0 << 3)
+#define LCD_8_BIT_MODE (1 << 4)
+#define LCD_4_BIT_MODE (0 << 4)
+
+
+// Text justification flags
+enum {
+ JUSTIFY_LEFT = 0,
+ JUSTIFY_RIGHT = 1,
+ JUSTIFY_CENTER = 2,
+};
+
+
+void lcd_init(uint8_t addr);
+void lcd_nibble(uint8_t addr, uint8_t data);
+void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags);
+void lcd_goto(uint8_t addr, uint8_t x, uint8_t y);
+void lcd_putchar(uint8_t addr, uint8_t c);
+void lcd_pgmstr(uint8_t addr, const char *s);
+void lcd_splash();
+void lcd_rtc_callback();
diff --git a/src/avr/src/line.c b/src/avr/src/line.c
new file mode 100644
index 0000000..132c14f
--- /dev/null
+++ b/src/avr/src/line.c
@@ -0,0 +1,274 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "config.h"
+#include "exec.h"
+#include "command.h"
+#include "spindle.h"
+#include "util.h"
+#include "SCurve.h"
+
+#include
+#include
+#include
+
+
+typedef struct {
+ float start[AXES];
+ float target[AXES];
+ float times[7];
+ float target_vel;
+ float max_accel;
+ float max_jerk;
+
+ float unit[AXES];
+ float length;
+} line_t;
+
+
+static struct {
+ line_t line;
+
+ int section;
+ int seg;
+
+ float iD; // Initial section distance
+ float iV; // Initial section velocity
+ float iA; // Initial section acceleration
+ float jerk;
+ float lV; // Last velocity
+ float lD; // Last distance
+
+ power_update_t power_updates[POWER_MAX_UPDATES];
+} l;
+
+
+static void _segment_target(float target[AXES], float d) {
+ for (int axis = 0; axis < AXES; axis++)
+ target[axis] = l.line.start[axis] + l.line.unit[axis] * d;
+}
+
+
+static float _segment_distance(float t) {
+ return l.iD + SCurve::distance(t, l.iV, l.iA, l.jerk);
+}
+
+
+static float _segment_velocity(float t) {
+ return l.iV + SCurve::velocity(t, l.iA, l.jerk);
+}
+
+
+static float _segment_accel(float t) {
+ return l.iA + SCurve::acceleration(t, l.jerk);
+}
+
+
+static bool _section_next() {
+ while (++l.section < 7) {
+ if (!l.line.times[l.section]) continue;
+
+ // Jerk
+ switch (l.section) {
+ case 0: case 6: l.jerk = l.line.max_jerk; break;
+ case 2: case 4: l.jerk = -l.line.max_jerk; break;
+ default: l.jerk = 0;
+ }
+ exec_set_jerk(l.jerk);
+
+ // Acceleration
+ switch (l.section) {
+ case 1: case 2: l.iA = l.line.max_jerk * l.line.times[0]; break;
+ case 5: case 6: l.iA = -l.line.max_jerk * l.line.times[4]; break;
+ default: l.iA = 0;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+static stat_t _exec_segment(float time, const float target[], float vel,
+ float accel) {
+ return exec_segment(time, target, vel, accel, l.line.max_accel,
+ l.line.max_jerk, l.power_updates);
+}
+
+
+static stat_t _line_exec() {
+ // Compute times
+ float section_time = l.line.times[l.section];
+ float seg_time = SEGMENT_TIME;
+ float t = ++l.seg * SEGMENT_TIME;
+
+ // Don't exceed section time
+ if (section_time < t) {
+ seg_time = section_time - (l.seg - 1) * SEGMENT_TIME;
+ t = section_time;
+ }
+
+ // Compute distance and velocity
+ float d = _segment_distance(t);
+ float v = _segment_velocity(t);
+ float a = _segment_accel(t);
+
+ // Don't allow overshoot
+ if (l.line.length < d) d = l.line.length;
+
+ // Handle synchronous speeds
+ spindle_load_power_updates(l.power_updates, l.lD, d);
+ l.lD = d;
+
+ // Check if section complete
+ if (t == section_time) {
+ if (_section_next()) {
+ // Setup next section
+ l.seg = 0;
+ l.iD = d;
+ l.iV = v;
+
+ } else {
+ exec_set_cb(0);
+
+ // Last segment of last section
+ // Use exact target values to correct for floating-point errors
+ return _exec_segment(seg_time, l.line.target, l.line.target_vel, a);
+ }
+ }
+
+ // Compute target position from distance
+ float target[AXES];
+ _segment_target(target, d);
+
+ // Segment move
+ return _exec_segment(seg_time, target, v, a);
+}
+
+
+stat_t command_line(char *cmd) {
+ line_t line = {};
+
+ cmd++; // Skip command code
+
+ // Get start position
+ command_get_position(line.start);
+
+ // Get target velocity
+ if (!decode_float(&cmd, &line.target_vel)) return STAT_BAD_FLOAT;
+ if (line.target_vel < 0) return STAT_INVALID_ARGUMENTS;
+
+ // Get max accel
+ if (!decode_float(&cmd, &line.max_accel)) return STAT_BAD_FLOAT;
+ if (line.max_accel < 0) return STAT_INVALID_ARGUMENTS;
+
+ // Get max jerk
+ if (!decode_float(&cmd, &line.max_jerk)) return STAT_BAD_FLOAT;
+ if (line.max_jerk < 0) return STAT_INVALID_ARGUMENTS;
+
+ // Get target position
+ copy_vector(line.target, line.start);
+ stat_t status = decode_axes(&cmd, line.target);
+ if (status) return status;
+
+ // Get times
+ bool has_time = false;
+ while (*cmd) {
+ if (*cmd < '0' || '6' < *cmd) break;
+ int section = *cmd - '0';
+ cmd++;
+
+ float time;
+ if (!decode_float(&cmd, &time)) return STAT_BAD_FLOAT;
+
+ if (time < 0) return STAT_NEGATIVE_SCURVE_TIME;
+ line.times[section] = time;
+ if (time) has_time = true;
+ }
+
+ if (!has_time) return STAT_ALL_ZERO_SCURVE_TIMES;
+
+ // Check for end of command
+ if (*cmd) return STAT_INVALID_ARGUMENTS;
+
+ // Set next start position
+ command_set_position(line.target);
+
+ // Compute direction vector
+ for (int axis = 0; axis < AXES; axis++) {
+ line.unit[axis] = line.target[axis] - line.start[axis];
+ line.length += line.unit[axis] * line.unit[axis];
+ }
+
+ line.length = sqrt(line.length);
+ for (int axis = 0; axis < AXES; axis++)
+ if (line.unit[axis]) line.unit[axis] /= line.length;
+
+ // Queue
+ command_push(COMMAND_line, &line);
+
+ return STAT_OK;
+}
+
+
+unsigned command_line_size() {return sizeof(line_t);}
+
+
+void command_line_exec(void *data) {
+ l.line = *(line_t *)data;
+
+ // Setup first section
+ l.seg = 0;
+ l.iD = 0;
+ l.lD = 0;
+ // If current velocity is non-zero use last target velocity
+ l.iV = exec_get_velocity() ? l.lV : 0;
+ l.lV = l.line.target_vel;
+
+ // Find first section
+ l.section = -1;
+ if (!_section_next()) return;
+
+#if 0
+ // Compare start position to actual position
+ float diff[AXES];
+ bool report = false;
+ exec_get_position(diff);
+ for (int i = 0; i < AXES; i++) {
+ diff[i] -= l.line.start[i];
+ if (0.1 < fabs(diff[i])) report = true;
+ }
+
+ if (report)
+ STATUS_DEBUG("diff: %.4f %.4f %.4f %.4f",
+ diff[0], diff[1], diff[2], diff[3]);
+#endif
+
+ // Set callback
+ exec_set_cb(_line_exec);
+}
diff --git a/src/avr/src/main.c b/src/avr/src/main.c
new file mode 100644
index 0000000..21a7296
--- /dev/null
+++ b/src/avr/src/main.c
@@ -0,0 +1,101 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "hardware.h"
+#include "stepper.h"
+#include "motor.h"
+#include "switch.h"
+#include "usart.h"
+#include "drv8711.h"
+#include "vars.h"
+#include "rtc.h"
+#include "report.h"
+#include "command.h"
+#include "estop.h"
+#include "i2c.h"
+#include "pgmspace.h"
+#include "outputs.h"
+#include "analog.h"
+#include "modbus.h"
+#include "io.h"
+#include "exec.h"
+#include "state.h"
+#include "emu.h"
+
+#include
+
+#include
+#include
+
+
+// For emu
+int __argc;
+char **__argv;
+
+
+int main(int argc, char *argv[]) {
+ __argc = argc;
+ __argv = argv;
+
+ wdt_enable(WDTO_250MS);
+
+ // Init
+ cli(); // disable interrupts
+
+ emu_init(); // Init emulator
+ hw_init(); // hardware setup - must be first
+ outputs_init(); // output pins
+ switch_init(); // switches
+ estop_init(); // emergency stop handler
+ analog_init(); // analog input pins
+ usart_init(); // serial port
+ i2c_init(); // i2c port
+ drv8711_init(); // motor drivers
+ stepper_init(); // steppers
+ motor_init(); // motors
+ exec_init(); // motion exec
+ vars_init(); // configuration variables
+ command_init(); // command queue
+
+ sei(); // enable interrupts
+
+ // Splash
+ printf_P(PSTR("\n{\"firmware\":\"Buildbotics AVR\"}\n"));
+
+ // Main loop
+ while (true) {
+ emu_callback(); // Emulator callback
+ hw_reset_handler(); // handle hard reset requests
+ state_callback(); // manage state
+ command_callback(); // process next command
+ modbus_callback(); // handle modbus events
+ io_callback(); // handle io input
+ report_callback(); // report changes
+ }
+
+ return 0;
+}
diff --git a/src/avr/src/messages.def b/src/avr/src/messages.def
new file mode 100644
index 0000000..2f9aa33
--- /dev/null
+++ b/src/avr/src/messages.def
@@ -0,0 +1,62 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+STAT_MSG(OK, "OK")
+STAT_MSG(AGAIN, "Run command again")
+STAT_MSG(NOP, "No op")
+STAT_MSG(INTERNAL_ERROR, "Internal error")
+STAT_MSG(ESTOP_USER, "User triggered EStop")
+STAT_MSG(ESTOP_SWITCH, "Switch triggered EStop")
+STAT_MSG(POWER_SHUTDOWN, "Power shutdown")
+STAT_MSG(UNRECOGNIZED_NAME, "Unrecognized command or variable name")
+STAT_MSG(INVALID_COMMAND, "Invalid command")
+STAT_MSG(INVALID_ARGUMENTS, "Invalid arguments")
+STAT_MSG(TOO_MANY_ARGUMENTS, "Too many arguments")
+STAT_MSG(TOO_FEW_ARGUMENTS, "Too few arguments")
+STAT_MSG(MACHINE_ALARMED, "Machine alarmed - Command not processed")
+STAT_MSG(EXPECTED_MOVE, "A move expected but none queued")
+STAT_MSG(BAD_FLOAT, "Failed to parse float")
+STAT_MSG(BAD_INT, "Failed to parse integer")
+STAT_MSG(INVALID_VALUE, "Invalid value")
+STAT_MSG(INVALID_TYPE, "Invalid type")
+STAT_MSG(READ_ONLY, "Variable is read only")
+STAT_MSG(ALL_ZERO_SCURVE_TIMES, "All zero s-curve times")
+STAT_MSG(NEGATIVE_SCURVE_TIME, "Negative s-curve time")
+STAT_MSG(SEEK_NOT_ENABLED, "Switch not enabled")
+STAT_MSG(SEEK_NOT_FOUND, "Switch not found")
+STAT_MSG(MOTOR_ID_INVALID, "Invalid motor ID")
+STAT_MSG(MOTOR_NOT_PREPPED, "Motor move not prepped")
+STAT_MSG(MOTOR_NOT_READY, "Motor not ready for move")
+STAT_MSG(MOTOR_FAULT, "Motor fault")
+STAT_MSG(STEPPER_NULL_MOVE, "Null move in stepper driver")
+STAT_MSG(STEPPER_NOT_READY, "Stepper driver not ready for move")
+STAT_MSG(LONG_SEG_TIME, "Long segment time")
+STAT_MSG(MODBUS_BUF_LENGTH, "Modbus invalid buffer length")
+STAT_MSG(INVALID_QCMD, "Invalid command in queue")
+STAT_MSG(Q_OVERRUN, "Command queue overrun")
+STAT_MSG(Q_UNDERRUN, "Command queue underrun")
+STAT_MSG(Q_INVALID_PUSH, "Invalid command pushed to queue")
diff --git a/src/avr/src/messages.json.in b/src/avr/src/messages.json.in
new file mode 100644
index 0000000..d12e38f
--- /dev/null
+++ b/src/avr/src/messages.json.in
@@ -0,0 +1,7 @@
+#include "cpp_magic.h"
+[
+#define STAT_MSG(NAME, MSG) [#NAME, MSG],
+#include "messages.def"
+#undef CMD
+ []
+]
diff --git a/src/avr/src/modbus.c b/src/avr/src/modbus.c
new file mode 100644
index 0000000..2e63c1e
--- /dev/null
+++ b/src/avr/src/modbus.c
@@ -0,0 +1,486 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "modbus.h"
+#include "usart.h"
+#include "status.h"
+#include "rtc.h"
+#include "util.h"
+#include "estop.h"
+#include "config.h"
+
+#include
+#include
+#include
+
+#include
+#include
+
+
+typedef enum {
+ MODBUS_DISCONNECTED,
+ MODBUS_OK,
+ MODBUS_CRC,
+ MODBUS_INVALID,
+ MODBUS_TIMEDOUT,
+} modbus_status_t;
+
+
+static struct {
+ bool debug;
+ uint8_t id;
+ baud_t baud;
+ parity_t parity;
+} cfg = {false, 1, USART_BAUD_9600, USART_NONE};
+
+
+static struct {
+ uint8_t bytes;
+ uint8_t command[MODBUS_BUF_SIZE];
+ uint8_t command_length;
+ uint8_t response[MODBUS_BUF_SIZE];
+ uint8_t response_length;
+
+ uint16_t addr;
+ modbus_rw_cb_t rw_cb;
+ modbus_cb_t receive_cb;
+
+ uint32_t last_write;
+ uint32_t last_read;
+ uint8_t retry;
+ uint8_t status;
+ uint16_t crc_errs;
+ bool write_ready;
+ bool response_ready;
+ bool transmit_complete;
+ bool busy;
+} state = {0};
+
+
+static uint16_t _crc16(const uint8_t *buffer, unsigned length) {
+ uint16_t crc = 0xffff;
+
+ for (unsigned i = 0; i < length; i++)
+ crc = _crc16_update(crc, buffer[i]);
+
+ return crc;
+}
+
+
+static void _set_write(bool x) {SET_PIN(RS485_RW_PIN, x);}
+
+
+#define INTLVL_SET(REG, NAME, LEVEL) \
+ REG = ((REG) & ~NAME##INTLVL_gm) | NAME##INTLVL_##LEVEL##_gc
+
+
+#define INTLVL_ENABLE(REG, NAME, LEVEL, ENABLE) do { \
+ if (ENABLE) INTLVL_SET(REG, NAME, LEVEL); \
+ else INTLVL_SET(REG, NAME, OFF); \
+ } while (0)
+
+
+static void _set_dre_interrupt(bool enable) {
+ INTLVL_ENABLE(RS485_PORT.CTRLA, USART_DRE, MED, enable);
+}
+
+
+static void _set_txc_interrupt(bool enable) {
+ INTLVL_ENABLE(RS485_PORT.CTRLA, USART_TXC, MED, enable);
+}
+
+
+static void _set_rxc_interrupt(bool enable) {
+ INTLVL_ENABLE(RS485_PORT.CTRLA, USART_RXC, MED, enable);
+}
+
+
+static void _write_word(uint8_t *dst, uint16_t value, bool little_endian) {
+ dst[!little_endian] = value;
+ dst[little_endian] = value >> 8;
+}
+
+
+static uint16_t _read_word(const uint8_t *data, bool little_endian) {
+ return (uint16_t)data[little_endian] << 8 | data[!little_endian];
+}
+
+
+static bool _check_response() {
+ // Check CRC
+ uint16_t computed = _crc16(state.response, state.response_length - 2);
+ uint16_t expected =
+ _read_word(state.response + state.response_length - 2, true);
+
+ if (computed != expected) {
+ if (cfg.debug) {
+ char sent[state.command_length * 2 + 1];
+ char response[state.response_length * 2 + 1];
+ format_hex_buf(sent, state.command, state.command_length);
+ format_hex_buf(response, state.response, state.response_length);
+
+ STATUS_WARNING(STAT_OK, "modbus: invalid CRC, received=0x%04x "
+ "computed=0x%04x sent=0x%s received=0x%s",
+ expected, computed, sent, response);
+ }
+
+ state.crc_errs++;
+ state.status = MODBUS_CRC;
+ return false;
+ }
+
+ // Check that slave id matches
+ if (state.command[0] != state.response[0]) {
+ STATUS_WARNING(STAT_OK, "modbus: unexpected slave id, expected=%u got=%u",
+ state.command[0], state.response[0]);
+ state.status = MODBUS_INVALID;
+ return false;
+ }
+
+ // Check that function code matches
+ if (state.command[1] != state.response[1]) {
+ STATUS_WARNING(STAT_OK, "modbus: invalid function code, expected=%u got=%u",
+ state.command[1], state.response[1]);
+ state.status = MODBUS_INVALID;
+ return false;
+ }
+
+ return true;
+}
+
+
+static void _notify(uint8_t func, uint8_t bytes, const uint8_t *data) {
+ if (!state.receive_cb) return;
+
+ modbus_cb_t cb = state.receive_cb;
+ state.receive_cb = 0; // May be set in callback
+
+ cb(func, bytes, data);
+}
+
+
+static void _handle_response() {
+ if (!state.response_ready) return;
+ state.response_ready = false;
+
+ if (!_check_response()) return;
+
+ state.last_write = 0; // Clear timeout timer
+ state.last_read = rtc_get_time(); // Set delay timer
+ state.retry = 0; // Reset retry counter
+ state.status = MODBUS_OK;
+ state.busy = false;
+
+ _notify(state.response[1], state.response_length - 4, state.response + 2);
+}
+
+
+/// Data register empty interrupt
+ISR(RS485_DRE_vect) {
+ RS485_PORT.DATA = state.command[state.bytes++];
+
+ if (state.bytes == state.command_length) {
+ _set_dre_interrupt(false);
+ _set_txc_interrupt(true);
+ state.bytes = 0;
+ }
+}
+
+
+/// Transmit complete interrupt
+ISR(RS485_TXC_vect) {
+ _set_txc_interrupt(false);
+ _set_rxc_interrupt(true);
+ _set_write(false); // Switch to read mode
+ state.transmit_complete = true;
+}
+
+
+/// Data received interrupt
+ISR(RS485_RXC_vect) {
+ state.response[state.bytes] = RS485_PORT.DATA;
+
+ // Ignore leading zeros
+ if (state.bytes || state.response[0]) state.bytes++;
+
+ if (state.bytes == state.response_length) {
+ _set_rxc_interrupt(false);
+ _set_write(true); // Back to write mode
+ state.bytes = 0;
+ state.response_ready = true;
+ }
+}
+
+
+static void _read_cb(uint8_t func, uint8_t bytes, const uint8_t *data) {
+ if (func == MODBUS_READ_OUTPUT_REG && data[0] == bytes - 1) {
+ if (state.rw_cb)
+ for (uint8_t i = 0; i < bytes >> 1; i++)
+ state.rw_cb(true, state.addr + i, _read_word(data + i * 2 + 1, false));
+ return;
+ }
+
+ if (state.rw_cb) state.rw_cb(false, state.addr, 0);
+}
+
+
+static void _write_cb(uint8_t func, uint8_t bytes, const uint8_t *data) {
+ if ((func == MODBUS_WRITE_OUTPUT_REG ||
+ func == MODBUS_WRITE_OUTPUT_REGS) && bytes == 4 &&
+ _read_word(data, false) == state.addr) {
+ if (state.rw_cb)
+ state.rw_cb(true, state.addr, _read_word(state.command + 4, false));
+ return;
+ }
+
+ if (state.rw_cb) state.rw_cb(false, state.addr, 0);
+}
+
+
+static void _reset() {
+ _set_dre_interrupt(false);
+ _set_txc_interrupt(false);
+ _set_rxc_interrupt(false);
+ _set_write(true); // RS485 write mode
+
+ // Flush USART
+ uint8_t x = RS485_PORT.DATA;
+ x = RS485_PORT.STATUS;
+ x = x;
+
+ // Clear state
+ state.write_ready = false;
+ state.busy = false;
+}
+
+
+static void _retry() {
+ state.last_write = 0;
+ state.bytes = 0;
+ state.retry++;
+
+ _set_write(true); // RS485 write mode
+
+ _set_txc_interrupt(false);
+ _set_rxc_interrupt(false);
+ _set_dre_interrupt(true);
+
+ // Try changing pin polarity
+ if (state.retry == MODBUS_RETRIES) {
+ PINCTRL_PIN(RS485_RO_PIN) ^= PORT_INVEN_bm;
+ PINCTRL_PIN(RS485_DI_PIN) ^= PORT_INVEN_bm;
+ }
+
+ if (cfg.debug) STATUS_DEBUG("modbus: retry %d", state.retry);
+}
+
+
+static void _timeout() {
+ if (cfg.debug) STATUS_DEBUG("modbus: timedout");
+
+ if (state.status == MODBUS_OK || state.status == MODBUS_DISCONNECTED)
+ state.status = MODBUS_TIMEDOUT;
+
+ _reset();
+ _notify(state.command[1], 0, 0);
+}
+
+
+static stop_t _get_stop() {
+ // RTU mode characters must always be 11-bits long
+ return cfg.parity == USART_NONE ? USART_2STOP : USART_1STOP;
+}
+
+
+void modbus_init() {
+ PR.PRPD &= ~PR_USART1_bm; // Disable power reduction
+
+ DIRCLR_PIN(RS485_RO_PIN); // Input
+ OUTSET_PIN(RS485_DI_PIN); // High
+ DIRSET_PIN(RS485_DI_PIN); // Output
+ OUTSET_PIN(RS485_RW_PIN); // High
+ DIRSET_PIN(RS485_RW_PIN); // Output
+
+ _reset();
+ memset(&state, 0, sizeof(state));
+ state.status = MODBUS_DISCONNECTED;
+
+ usart_init_port(&RS485_PORT, cfg.baud, cfg.parity, USART_8BITS, _get_stop());
+}
+
+
+void modbus_deinit() {
+ _reset();
+ memset(&state, 0, sizeof(state));
+ state.status = MODBUS_DISCONNECTED;
+
+ // Disable USART
+ RS485_PORT.CTRLB &= ~(USART_RXEN_bm | USART_TXEN_bm);
+
+ // Float write pins
+ DIRCLR_PIN(RS485_DI_PIN);
+ DIRCLR_PIN(RS485_RW_PIN);
+}
+
+
+bool modbus_busy() {return state.busy;}
+
+
+static void _start_write() {
+ if (!state.write_ready) return;
+
+ // The minimum delay between modbus messages is 3.5 characters. There are
+ // 11-bits per character in RTU mode. Character time is calculated as
+ // follows:
+ //
+ // char time = 11-bits / baud * 3.5
+ //
+ // At 9600 baud the minimum delay is 4.01ms. At 19200 it's 2.005ms. All
+ // supported higher baud rates require the 1.75ms minimum delay. We round up
+ // and add 1ms to ensure the delay is never less than the required minimum.
+ if (state.last_read &&
+ !rtc_expired(state.last_read + (cfg.baud == USART_BAUD_9600 ? 5 : 3)))
+ return;
+ state.last_read = 0;
+
+ state.write_ready = false;
+ _set_dre_interrupt(true);
+}
+
+
+void modbus_func(uint8_t func, uint8_t send, const uint8_t *data,
+ uint8_t receive, modbus_cb_t receive_cb) {
+ state.bytes = 0;
+ state.command_length = send + 4;
+ state.response_length = receive + 4;
+ state.receive_cb = receive_cb;
+ state.last_write = 0;
+ state.retry = 0;
+
+ ESTOP_ASSERT(state.command_length <= MODBUS_BUF_SIZE, STAT_MODBUS_BUF_LENGTH);
+ ESTOP_ASSERT(state.response_length <= MODBUS_BUF_SIZE,
+ STAT_MODBUS_BUF_LENGTH);
+
+ state.command[0] = cfg.id;
+ state.command[1] = func;
+ memcpy(state.command + 2, data, send);
+ _write_word(state.command + send + 2, _crc16(state.command, send + 2), true);
+
+ state.busy = true;
+ state.write_ready = true;
+ _start_write();
+}
+
+
+void modbus_read(uint16_t addr, uint16_t count, modbus_rw_cb_t cb) {
+ state.rw_cb = cb;
+ state.addr = addr;
+ uint8_t cmd[4];
+ _write_word(cmd, addr, false);
+ _write_word(cmd + 2, count, false);
+ modbus_func(MODBUS_READ_OUTPUT_REG, 4, cmd, 2 * count + 1, _read_cb);
+}
+
+
+void modbus_write(uint16_t addr, uint16_t value, modbus_rw_cb_t cb) {
+ state.rw_cb = cb;
+ state.addr = addr;
+ uint8_t cmd[4];
+ _write_word(cmd, addr, false);
+ _write_word(cmd + 2, value, false);
+ modbus_func(MODBUS_WRITE_OUTPUT_REG, 4, cmd, 4, _write_cb);
+}
+
+
+void modbus_multi_write(uint16_t addr, uint16_t value, modbus_rw_cb_t cb) {
+ state.rw_cb = cb;
+ state.addr = addr;
+ uint8_t cmd[7];
+ _write_word(cmd, addr, false); // Start address
+ _write_word(cmd + 2, 1, false); // Number of regs
+ cmd[4] = 2; // Number of bytes
+ _write_word(cmd + 5, value, false); // Value
+ modbus_func(MODBUS_WRITE_OUTPUT_REGS, 7, cmd, 4, _write_cb);
+}
+
+
+void modbus_callback() {
+ if (state.transmit_complete) {
+ state.last_write = rtc_get_time();
+ state.transmit_complete = false;
+ }
+
+ _handle_response();
+ _start_write();
+
+ // Timeout out writes
+ if (!state.last_write || !rtc_expired(state.last_write + MODBUS_TIMEOUT))
+ return;
+ state.last_write = 0;
+
+ if (cfg.debug && state.bytes) {
+ char sent[state.command_length * 2 + 1];
+ char received[state.bytes * 2 + 1];
+
+ format_hex_buf(sent, state.command, state.command_length);
+ format_hex_buf(received, state.response, state.bytes);
+
+ STATUS_DEBUG("modbus: sent 0x%s received 0x%s expected %u bytes",
+ sent, received, state.response_length);
+ }
+
+ if (state.retry < 2 * MODBUS_RETRIES) _retry();
+ else _timeout();
+}
+
+
+// Variable callbacks
+bool get_mb_debug() {return cfg.debug;}
+void set_mb_debug(bool value) {cfg.debug = value;}
+uint8_t get_mb_id() {return cfg.id;}
+void set_mb_id(uint8_t id) {cfg.id = id;}
+uint8_t get_mb_baud() {return cfg.baud;}
+
+
+void set_mb_baud(uint8_t baud) {
+ cfg.baud = (baud_t)baud;
+ usart_set_baud(&RS485_PORT, cfg.baud);
+}
+
+
+uint8_t get_mb_parity() {return cfg.parity;}
+
+
+void set_mb_parity(uint8_t parity) {
+ cfg.parity = (parity_t)parity;
+ usart_set_parity(&RS485_PORT, cfg.parity);
+ usart_set_stop(&RS485_PORT, _get_stop());
+}
+
+
+uint8_t get_mb_status() {return state.status;}
+uint16_t get_mb_crc_errs() {return state.crc_errs;}
diff --git a/src/avr/src/modbus.h b/src/avr/src/modbus.h
new file mode 100644
index 0000000..89b2cbb
--- /dev/null
+++ b/src/avr/src/modbus.h
@@ -0,0 +1,112 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+/******************************************************************************\
+
+ Modbus RTU command format is as follows:
+
+ Function 01: Read Coil Status
+ Function 02: Read Input Status
+
+ Send: [id][func][addr][count][crc]
+ Receive: [id][func][bytes][flags][crc]
+
+ Function 03: Read Holding Registers
+ Function 04: Read Input Registers
+
+ Send: [id][func][addr][count][crc]
+ Receive: [id][func][bytes][regs][crc]
+
+ Function 05: Force Single Coil
+ Function 06: Preset Single Register
+
+ Send: [id][func][addr][value][crc]
+ Receive: [id][func][addr][value][crc]
+
+ Function 15: Force Multiple Coils
+
+ Send: [id][func][addr][count][bytes][flags][crc]
+ Receive: [id][func][addr][count][crc]
+
+ Function 16: Preset Multiple Registers
+
+ Send: [id][func][addr][count][bytes][regs][crc]
+ Receive: [id][func][addr][count][crc]
+
+ Where:
+
+ id: 1-byte Slave ID
+ func: 1-byte Function code
+ addr: 2-byte Data address
+ count: 2-byte Address count
+ bytes: 1-byte Number of bytes to follow
+ value: 2-byte Value read or written
+ bits: n-bytes Flags indicating on/off
+ regs: n-bytes register values to write
+ checksum: 16-bit CRC: x^16 + x^15 + x^2 + 1 (0x8005) initial: 0xffff
+
+\******************************************************************************/
+
+#pragma once
+
+
+#include
+#include
+
+
+typedef enum {
+ MODBUS_READ_COILS = 1,
+ MODBUS_READ_CONTACTS = 2,
+ MODBUS_READ_OUTPUT_REG = 3,
+ MODBUS_READ_INPUT_REG = 4,
+ MODBUS_WRITE_COIL = 5,
+ MODBUS_WRITE_OUTPUT_REG = 6,
+ MODBUS_WRITE_COILS = 15,
+ MODBUS_WRITE_OUTPUT_REGS = 16,
+} modbus_function_code_t;
+
+
+typedef enum {
+ MODBUS_COIL_BASE = 0,
+ MODBUS_CONTACT_BASE = 10000,
+ MODBUS_INPUT_REG_BASE = 30000,
+ MODBUS_OUTPUT_REG_BASE = 40000,
+} modbus_base_addrs_t;
+
+
+typedef void (*modbus_cb_t)(uint8_t func, uint8_t bytes, const uint8_t *data);
+typedef void (*modbus_rw_cb_t)(bool ok, uint16_t addr, uint16_t value);
+
+void modbus_init();
+void modbus_deinit();
+bool modbus_busy();
+void modbus_func(uint8_t func, uint8_t send, const uint8_t *data,
+ uint8_t receive, modbus_cb_t cb);
+void modbus_read(uint16_t addr, uint16_t count, modbus_rw_cb_t cb);
+void modbus_write(uint16_t addr, uint16_t value, modbus_rw_cb_t cb);
+void modbus_multi_write(uint16_t addr, uint16_t value, modbus_rw_cb_t cb);
+void modbus_callback();
diff --git a/src/avr/src/motor.c b/src/avr/src/motor.c
new file mode 100644
index 0000000..adb0b63
--- /dev/null
+++ b/src/avr/src/motor.c
@@ -0,0 +1,497 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "motor.h"
+#include "config.h"
+#include "hardware.h"
+#include "cpp_magic.h"
+#include "rtc.h"
+#include "report.h"
+#include "stepper.h"
+#include "drv8711.h"
+#include "estop.h"
+#include "axis.h"
+#include "util.h"
+#include "pgmspace.h"
+#include "exec.h"
+
+#include
+
+#include
+#include
+#include
+#include
+
+
+typedef struct {
+ // Config
+ uint8_t axis; // map motor to axis
+ uint8_t step_pin;
+ uint8_t dir_pin;
+ TC0_t *timer;
+ DMA_CH_t *dma;
+ uint8_t dma_trigger;
+
+ bool slave;
+ uint16_t microsteps; // microsteps per full step
+ uint16_t stall_microsteps;
+ bool reverse;
+ bool enabled;
+ float step_angle; // degrees per whole step
+ float travel_rev; // mm or deg of travel per motor revolution
+ float min_soft_limit;
+ float max_soft_limit;
+ bool homed;
+
+ // Computed
+ float steps_per_unit;
+
+ // Runtime state
+ uint32_t power_timeout;
+ int32_t commanded;
+ int32_t encoder;
+ int16_t error;
+ bool last_negative;
+
+ // Move prep
+ bool prepped;
+ uint8_t clock;
+ uint16_t timer_period;
+ bool negative;
+ int32_t position;
+} motor_t;
+
+
+static motor_t motors[MOTORS] = {
+ {
+ .axis = AXIS_X,
+ .step_pin = STEP_0_PIN,
+ .dir_pin = DIR_0_PIN,
+ .timer = &TCD0,
+ .dma = &DMA.CH0,
+ .dma_trigger = DMA_CH_TRIGSRC_TCD0_CCA_gc,
+ }, {
+ .axis = AXIS_Y,
+ .step_pin = STEP_1_PIN,
+ .dir_pin = DIR_1_PIN,
+ .timer = &TCE0,
+ .dma = &DMA.CH1,
+ .dma_trigger = DMA_CH_TRIGSRC_TCE0_CCA_gc,
+ }, {
+ .axis = AXIS_Z,
+ .step_pin = STEP_2_PIN,
+ .dir_pin = DIR_2_PIN,
+ .timer = &TCF0,
+ .dma = &DMA.CH2,
+ .dma_trigger = DMA_CH_TRIGSRC_TCF0_CCA_gc,
+ }, {
+ .axis = AXIS_A,
+ .step_pin = STEP_3_PIN,
+ .dir_pin = DIR_3_PIN,
+ .timer = (TC0_t *)&TCE1,
+ .dma = &DMA.CH3,
+ .dma_trigger = DMA_CH_TRIGSRC_TCE1_CCA_gc,
+ }
+};
+
+
+static uint8_t _dummy;
+
+
+static void _update_config(int motor) {
+ motor_t *m = &motors[motor];
+
+ m->steps_per_unit = 360.0 * m->microsteps / m->travel_rev / m->step_angle;
+}
+
+
+void motor_init() {
+ // Enable DMA
+ DMA.CTRL = DMA_RESET_bm;
+ DMA.CTRL = DMA_ENABLE_bm;
+ DMA.INTFLAGS = 0xff; // clear all pending interrupts
+
+ for (int motor = 0; motor < MOTORS; motor++) {
+ motor_t *m = &motors[motor];
+
+ // Default soft limits
+ m->min_soft_limit = -INFINITY;
+ m->max_soft_limit = INFINITY;
+
+ _update_config(motor);
+
+ // Setup motor timer
+ m->timer->CTRLB = TC_WGMODE_SINGLESLOPE_gc | TC1_CCAEN_bm;
+ m->timer->CCA = STEP_PULSE_WIDTH;
+
+ // Setup DMA channel as timer event counter
+ m->dma->ADDRCTRL = DMA_CH_SRCDIR_FIXED_gc | DMA_CH_DESTDIR_FIXED_gc;
+ m->dma->TRIGSRC = m->dma_trigger;
+
+ // Note, the DMA transfer must read CCA to clear the trigger
+ m->dma->SRCADDR0 = (((uintptr_t)&m->timer->CCA) >> 0) & 0xff;
+ m->dma->SRCADDR1 = (((uintptr_t)&m->timer->CCA) >> 8) & 0xff;
+ m->dma->SRCADDR2 = 0;
+
+ m->dma->DESTADDR0 = (((uintptr_t)&_dummy) >> 0) & 0xff;
+ m->dma->DESTADDR1 = (((uintptr_t)&_dummy) >> 8) & 0xff;
+ m->dma->DESTADDR2 = 0;
+
+ m->dma->CTRLA = DMA_CH_SINGLE_bm | DMA_CH_BURSTLEN_1BYTE_gc;
+
+ // IO pins
+ PINCTRL_PIN(m->step_pin) = PORT_INVEN_bm; // Inverted output
+ DIRSET_PIN(m->step_pin); // Output
+ DIRSET_PIN(m->dir_pin); // Output
+ }
+
+ axis_map_motors();
+}
+
+
+bool motor_is_enabled(int motor) {return motors[motor].enabled;}
+int motor_get_axis(int motor) {return motors[motor].axis;}
+
+
+static int32_t _position_to_steps(int motor, float position) {
+ return (int32_t)round(position * motors[motor].steps_per_unit);
+}
+
+
+void motor_set_position(int motor, float position) {
+ motor_t *m = &motors[motor];
+ m->commanded = m->encoder = m->position = _position_to_steps(motor, position);
+ m->error = 0;
+}
+
+
+float motor_get_soft_limit(int motor, bool min) {
+ return min ? motors[motor].min_soft_limit : motors[motor].max_soft_limit;
+}
+
+
+bool motor_get_homed(int motor) {return motors[motor].homed;}
+
+
+static void _update_power(int motor) {
+ motor_t *m = &motors[motor];
+
+ if (m->enabled) {
+ bool timedout = rtc_expired(m->power_timeout);
+ // NOTE, we have ~5ms to update the driver config
+ drv8711_set_state(motor, timedout ? DRV8711_IDLE : DRV8711_ACTIVE);
+
+ } else drv8711_set_state(motor, DRV8711_DISABLED);
+}
+
+
+/// Callback to manage motor power sequencing and power-down timing.
+stat_t motor_rtc_callback() { // called by controller
+ for (int motor = 0; motor < MOTORS; motor++)
+ _update_power(motor);
+
+ return STAT_OK;
+}
+
+
+void motor_emulate_steps(int motor) {
+ motor_t *m = &motors[motor];
+ m->dma->TRFCNT = 0xffff - abs(m->commanded - m->encoder);
+}
+
+
+void motor_end_move(int motor) {
+ motor_t &m = motors[motor];
+
+ if (!m.timer->CTRLA) return;
+
+ // Stop clock
+ m.timer->CTRLA = 0;
+
+ // Wait for pending DMA transfers
+ while (m.dma->CTRLB & DMA_CH_CHPEND_bm) continue;
+
+ // Get actual step count from DMA channel
+ const int32_t steps = 0xffff - m.dma->TRFCNT;
+
+ // Accumulate encoder & compute error
+ m.encoder += m.last_negative ? -steps : steps;
+ m.error = m.commanded - m.encoder;
+}
+
+
+void motor_load_move(int motor) {
+ motor_t &m = motors[motor];
+
+ // Clear move
+ ESTOP_ASSERT(m.prepped, STAT_MOTOR_NOT_PREPPED);
+ m.prepped = false;
+
+ motor_end_move(motor);
+
+ if (!m.timer_period) return; // Leave clock stopped
+
+ // Set direction, compensating for polarity but only when moving
+ const bool dir = m.negative ^ m.reverse;
+ if (dir != IN_PIN(m.dir_pin)) {
+ SET_PIN(m.dir_pin, dir);
+
+ // We need at least 200ns between direction change and next step.
+ if (m.timer->CCA < m.timer->CNT) m.timer->CNT = m.timer->CCA + 1;
+ }
+
+ // Reset DMA step counter
+ m.dma->CTRLA &= ~DMA_CH_ENABLE_bm;
+ m.dma->TRFCNT = 0xffff;
+ m.dma->CTRLA |= DMA_CH_ENABLE_bm;
+
+ // To avoid causing couter wrap around, it is important to start the clock
+ // before setting PERBUF. If PERBUF is set before the clock is started PER
+ // updates immediately and possibly mid step.
+
+ // Set clock and period
+ m.timer->CTRLA = m.clock; // Start clock
+ m.timer->PERBUF = m.timer_period; // Set next frequency
+ m.last_negative = m.negative;
+ m.commanded = m.position;
+}
+
+
+void motor_prep_move(int motor, float target) {
+ // Validate input
+ ESTOP_ASSERT(0 <= motor && motor < MOTORS, STAT_MOTOR_ID_INVALID);
+ ESTOP_ASSERT(isfinite(target), STAT_BAD_FLOAT);
+
+ motor_t &m = motors[motor];
+ ESTOP_ASSERT(!m.prepped, STAT_MOTOR_NOT_READY);
+
+ // Travel in steps
+ int32_t position = _position_to_steps(motor, target);
+ int24_t steps = position - m.position;
+ m.position = position;
+
+ // Error correction
+ int16_t correction = abs(m.error);
+ if (MIN_STEP_CORRECTION <= correction) {
+ // Dampen correction oscillation
+ correction >>= 1;
+
+ // Make correction
+ steps += m.error < 0 ? -correction : correction;
+ }
+
+ // Positive steps from here on
+ m.negative = steps < 0;
+ if (m.negative) steps = -steps;
+
+ // Start with clock / 2
+ const float seg_clocks = SEGMENT_TIME * (F_CPU * 60 / 2);
+ float ticks_per_step = seg_clocks / steps;
+
+ // Use faster clock with faster step rates for increased resolution.
+ if (ticks_per_step < 0x7fff) {
+ ticks_per_step *= 2;
+ m.clock = TC_CLKSEL_DIV1_gc;
+
+ // Limit clock if step rate is too fast
+ // We allow a slight fudge here (i.e. 1.9 instead 2) because the motor
+ // driver is able to handle it and otherwise we could not actually hit
+ // an average rate of 250k usteps/sec.
+ if (ticks_per_step < STEP_PULSE_WIDTH * 1.9)
+ ticks_per_step = STEP_PULSE_WIDTH * 1.9; // Too fast
+
+ } else m.clock = TC_CLKSEL_DIV2_gc; // NOTE, pulse width will be twice as long
+
+ // Disable clock if too slow
+ if (0xffff <= ticks_per_step) ticks_per_step = 0;
+
+ m.timer_period = steps ? round(ticks_per_step) : 0;
+
+ // Power motor
+ if (!m.enabled) {
+ m.timer_period = 0;
+ m.encoder = m.commanded = m.position;
+ m.error = 0;
+
+ } else if (m.timer_period) // Motor is moving so reset power timeout
+ m.power_timeout = rtc_get_time() + MOTOR_IDLE_TIMEOUT * 1000;
+ _update_power(motor);
+
+ // Queue move
+ m.prepped = true;
+}
+
+
+// Var callbacks
+bool get_motor_enabled(int motor) {return motors[motor].enabled;}
+
+
+void set_motor_enabled(int motor, bool enabled) {
+ if (motors[motor].slave) return;
+
+ for (int m = motor; m < MOTORS; m++)
+ if (motors[m].axis == motors[motor].axis)
+ motors[m].enabled = enabled;
+}
+
+
+float get_step_angle(int motor) {return motors[motor].step_angle;}
+
+
+void set_step_angle(int motor, float value) {
+ if (motors[motor].slave) return;
+
+ for (int m = motor; m < MOTORS; m++)
+ if (motors[m].axis == motors[motor].axis) {
+ motors[m].step_angle = value;
+ _update_config(m);
+ }
+}
+
+
+float get_travel(int motor) {return motors[motor].travel_rev;}
+
+
+void set_travel(int motor, float value) {
+ if (motors[motor].slave) return;
+
+ for (int m = motor; m < MOTORS; m++)
+ if (motors[m].axis == motors[motor].axis) {
+ motors[m].travel_rev = value;
+ _update_config(m);
+ }
+}
+
+
+uint16_t get_microstep(int motor) {return motors[motor].microsteps;}
+
+void set_microstep(int motor, uint16_t value) {
+ switch (value) {
+ case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 256:
+ break;
+ default: return;
+ }
+
+ if (motors[motor].slave) return;
+
+ for (int m = motor; m < MOTORS; m++)
+ if (motors[m].axis == motors[motor].axis) {
+ motors[m].microsteps = value;
+ _update_config(m);
+ drv8711_set_microsteps(m, value);
+ }
+}
+
+uint16_t get_stall_microstep(int motor) {return motors[motor].stall_microsteps;}
+
+void set_stall_microstep(int motor, uint16_t value) {
+ switch (value) {
+ case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: case 256:
+ break;
+ default: return;
+ }
+
+ if (motors[motor].slave) return;
+
+ for (int m = motor; m < MOTORS; m++)
+ if (motors[m].axis == motors[motor].axis) {
+ motors[m].stall_microsteps = value;
+ //_update_config(m);
+ //drv8711_set_stall_microsteps(m, value);
+ }
+}
+
+void enable_stall_microstep(int m)
+{
+ //for (int m = 0; m < MOTORS; m++)
+ //{
+ motor_t *motorTemp = &motors[m];
+ motorTemp->steps_per_unit = 360.0 * motorTemp->stall_microsteps / motorTemp->travel_rev / motorTemp->step_angle;
+ drv8711_set_microsteps(m, motors[m].stall_microsteps);
+ //}
+}
+
+void disable_stall_microstep()
+{
+ for(int m =0; m < MOTORS; m++)
+ {
+ _update_config(m); //Restore the steps_per_unit
+ drv8711_set_microsteps(m, motors[m].microsteps);
+ }
+}
+
+char get_motor_axis(int motor) {return motors[motor].axis;}
+
+
+void set_motor_axis(int motor, uint8_t axis) {
+ if (MOTORS <= motor || AXES <= axis || axis == motors[motor].axis) return;
+ motors[motor].axis = axis;
+ axis_map_motors();
+
+ // Reset encoder
+ motor_set_position(motor, exec_get_axis_position(axis));
+
+ // Check if this is now a slave motor
+ motors[motor].slave = false;
+ for (int m = 0; m < motor; m++)
+ if (motors[m].axis == motors[motor].axis) {
+ // Sync with master
+ set_step_angle(motor, motors[m].step_angle);
+ set_travel(motor, motors[m].travel_rev);
+ set_microstep(motor, motors[m].microsteps);
+ set_stall_microstep(motor, motors[m].stall_microsteps);
+ set_motor_enabled(motor, motors[m].enabled);
+ motors[motor].slave = true; // Must be last
+ break;
+ }
+}
+
+
+bool get_reverse(int motor) {return motors[motor].reverse;}
+void set_reverse(int motor, bool value) {motors[motor].reverse = value;}
+
+
+float get_min_soft_limit(int motor) {return motors[motor].min_soft_limit;}
+float get_max_soft_limit(int motor) {return motors[motor].max_soft_limit;}
+
+
+void set_min_soft_limit(int motor, float limit) {
+ motors[motor].min_soft_limit = limit;
+}
+
+
+void set_max_soft_limit(int motor, float limit) {
+ motors[motor].max_soft_limit = limit;
+}
+
+
+bool get_homed(int motor) {return motors[motor].homed;}
+void set_homed(int motor, bool homed) {motors[motor].homed = homed;}
+
+
+int32_t get_encoder(int m) {return motors[m].encoder;}
+int32_t get_error(int m) {return motors[m].error;}
diff --git a/src/avr/src/motor.h b/src/avr/src/motor.h
new file mode 100644
index 0000000..242e771
--- /dev/null
+++ b/src/avr/src/motor.h
@@ -0,0 +1,61 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "status.h"
+
+#include
+#include
+
+
+typedef enum {
+ MOTOR_DISABLED, // motor enable is deactivated
+ MOTOR_ALWAYS_POWERED, // motor is always powered while machine is ON
+ MOTOR_POWERED_IN_CYCLE, // motor fully powered during cycles,
+ // de-powered out of cycle
+ MOTOR_POWERED_ONLY_WHEN_MOVING, // idles shortly after stopped, even in cycle
+} motor_power_mode_t;
+
+
+void motor_init();
+
+bool motor_is_enabled(int motor);
+int motor_get_axis(int motor);
+void motor_set_position(int motor, float position);
+float motor_get_soft_limit(int motor, bool min);
+bool motor_get_homed(int motor);
+
+stat_t motor_rtc_callback();
+
+void motor_end_move(int motor);
+void motor_load_move(int motor);
+void motor_prep_move(int motor, float target);
+
+void enable_stall_microstep(int m);
+void disable_stall_microstep();
+
diff --git a/src/avr/src/outputs.c b/src/avr/src/outputs.c
new file mode 100644
index 0000000..f989ec7
--- /dev/null
+++ b/src/avr/src/outputs.c
@@ -0,0 +1,161 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "outputs.h"
+#include "config.h"
+
+
+typedef struct {
+ uint8_t pin;
+ bool active;
+ output_state_t state;
+ output_mode_t mode;
+} output_t;
+
+
+output_t outputs[OUTS] = {
+ {TOOL_ENABLE_PIN},
+ {TOOL_DIR_PIN},
+ {SWITCH_1_PIN},
+ {SWITCH_2_PIN},
+ {FAULT_PIN},
+ {TEST_PIN},
+};
+
+
+static output_t *_get_output(uint8_t pin) {
+ switch (pin) {
+ case TOOL_ENABLE_PIN: return &outputs[0];
+ case TOOL_DIR_PIN: return &outputs[1];
+ case SWITCH_1_PIN: return &outputs[2];
+ case SWITCH_2_PIN: return &outputs[3];
+ case FAULT_PIN: return &outputs[4];
+ case TEST_PIN: return &outputs[5];
+ }
+
+ return 0;
+}
+
+
+static void _update_state(output_t *output) {
+ switch (output->mode) {
+ case OUT_DISABLED: output->state = OUT_TRI; break;
+ case OUT_LO_HI: output->state = output->active ? OUT_HI : OUT_LO; break;
+ case OUT_HI_LO: output->state = output->active ? OUT_LO : OUT_HI; break;
+ case OUT_TRI_LO: output->state = output->active ? OUT_LO : OUT_TRI; break;
+ case OUT_TRI_HI: output->state = output->active ? OUT_HI : OUT_TRI; break;
+ case OUT_LO_TRI: output->state = output->active ? OUT_TRI : OUT_LO; break;
+ case OUT_HI_TRI: output->state = output->active ? OUT_TRI : OUT_HI; break;
+ }
+
+ switch (output->state) {
+ case OUT_TRI: DIRCLR_PIN(output->pin); break;
+ case OUT_HI: OUTSET_PIN(output->pin); DIRSET_PIN(output->pin); break;
+ case OUT_LO: OUTCLR_PIN(output->pin); DIRSET_PIN(output->pin); break;
+ }
+}
+
+
+void outputs_init() {
+ for (int i = 0; i < OUTS; i++) _update_state(&outputs[i]);
+}
+
+
+bool outputs_is_active(uint8_t pin) {
+ output_t *output = _get_output(pin);
+ return output ? output->active : false;
+}
+
+
+void outputs_set_active(uint8_t pin, bool active) {
+ output_t *output = _get_output(pin);
+ if (!output) return;
+
+ output->active = active;
+ _update_state(output);
+}
+
+
+bool outputs_toggle(uint8_t pin) {
+ output_t *output = _get_output(pin);
+ if (!output) return false;
+
+ output->active = !output->active;
+ _update_state(output);
+ return output->active;
+}
+
+
+void outputs_set_mode(uint8_t pin, output_mode_t mode) {
+ output_t *output = _get_output(pin);
+ if (!output) return;
+ output->mode = mode;
+ _update_state(output);
+}
+
+
+output_state_t outputs_get_state(uint8_t pin) {
+ output_t *output = _get_output(pin);
+ if (output) return OUT_TRI;
+ return output->state;
+}
+
+
+void outputs_stop() {
+ outputs_set_active(SWITCH_1_PIN, false);
+ outputs_set_active(SWITCH_2_PIN, false);
+}
+
+
+// Var callbacks
+uint8_t get_output_state(int id) {
+ return OUTS <= id ? OUT_TRI : outputs[id].state;
+}
+
+
+bool get_output_active(int id) {
+ return OUTS <= id ? false : outputs[id].active;
+}
+
+
+void set_output_active(int id, bool active) {
+ if (OUTS <= id) return;
+ outputs[id].active = active;
+ _update_state(&outputs[id]);
+}
+
+
+uint8_t get_output_mode(int id) {
+ return OUTS <= id ? OUT_DISABLED : outputs[id].mode;
+}
+
+
+void set_output_mode(int id, uint8_t mode) {
+ if (OUTS <= id) return;
+ outputs[id].mode = (output_mode_t)mode;
+ _update_state(&outputs[id]);
+}
diff --git a/src/avr/src/outputs.h b/src/avr/src/outputs.h
new file mode 100644
index 0000000..e0f6636
--- /dev/null
+++ b/src/avr/src/outputs.h
@@ -0,0 +1,59 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include
+#include
+
+
+typedef enum {
+ OUT_LO,
+ OUT_HI,
+ OUT_TRI,
+} output_state_t;
+
+
+/// OUT__
+typedef enum {
+ OUT_DISABLED,
+ OUT_LO_HI,
+ OUT_HI_LO,
+ OUT_TRI_LO,
+ OUT_TRI_HI,
+ OUT_LO_TRI,
+ OUT_HI_TRI,
+} output_mode_t;
+
+
+void outputs_init();
+bool outputs_is_active(uint8_t pin);
+void outputs_set_active(uint8_t pin, bool active);
+bool outputs_toggle(uint8_t pin);
+void outputs_set_mode(uint8_t pin, output_mode_t mode);
+output_state_t outputs_get_state(uint8_t pin);
+void outputs_stop();
diff --git a/src/avr/src/pgmspace.h b/src/avr/src/pgmspace.h
new file mode 100644
index 0000000..9d7f25f
--- /dev/null
+++ b/src/avr/src/pgmspace.h
@@ -0,0 +1,36 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include
+
+#ifdef __AVR__
+#define PRPSTR "S"
+#else
+#define PRPSTR "s"
+#endif
diff --git a/src/avr/src/pins.c b/src/avr/src/pins.c
new file mode 100644
index 0000000..65782fd
--- /dev/null
+++ b/src/avr/src/pins.c
@@ -0,0 +1,31 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "pins.h"
+
+
+PORT_t *pin_ports[] = {&PORTA, &PORTB, &PORTC, &PORTD, &PORTE, &PORTF};
diff --git a/src/avr/src/pins.h b/src/avr/src/pins.h
new file mode 100644
index 0000000..6d6cd8b
--- /dev/null
+++ b/src/avr/src/pins.h
@@ -0,0 +1,57 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+enum {PORT_A = 1, PORT_B, PORT_C, PORT_D, PORT_E, PORT_F};
+
+#define PIN_INDEX(PIN) (PIN & 7)
+#define PORT_INDEX(PIN) ((PIN >> 3) - 1)
+
+#define PIN_PORT(PIN) pin_ports[PORT_INDEX(PIN)]
+#define PIN_BM(PIN) (1 << PIN_INDEX(PIN))
+
+#define PIN_ID(PORT, PIN) (PORT << 3 | (PIN & 7))
+
+#include
+
+extern PORT_t *pin_ports[];
+
+#define DIRSET_PIN(PIN) PIN_PORT(PIN)->DIRSET = PIN_BM(PIN)
+#define DIRCLR_PIN(PIN) PIN_PORT(PIN)->DIRCLR = PIN_BM(PIN)
+#define OUTCLR_PIN(PIN) PIN_PORT(PIN)->OUTCLR = PIN_BM(PIN)
+#define OUTSET_PIN(PIN) PIN_PORT(PIN)->OUTSET = PIN_BM(PIN)
+#define OUTTGL_PIN(PIN) PIN_PORT(PIN)->OUTTGL = PIN_BM(PIN)
+#define OUT_PIN(PIN) (!!(PIN_PORT(PIN)->OUT & PIN_BM(PIN)))
+#define IN_PIN(PIN) (!!(PIN_PORT(PIN)->IN & PIN_BM(PIN)))
+#define PINCTRL_PIN(PIN) ((&PIN_PORT(PIN)->PIN0CTRL)[PIN_INDEX(PIN)])
+
+#define SET_PIN(PIN, X) \
+ do {if (X) OUTSET_PIN(PIN); else OUTCLR_PIN(PIN);} while (0);
+
+#define PIN_EVSYS_CHMUX(PIN) \
+ (EVSYS_CHMUX_PORTA_PIN0_gc + (8 * PORT_INDEX(PIN)) + PIN_INDEX(PIN))
diff --git a/src/avr/src/pwm.c b/src/avr/src/pwm.c
new file mode 100644
index 0000000..1659964
--- /dev/null
+++ b/src/avr/src/pwm.c
@@ -0,0 +1,221 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "pwm.h"
+
+#include "config.h"
+#include "estop.h"
+#include "outputs.h"
+
+#include
+
+
+typedef struct {
+ bool initialized;
+ float freq; // base frequency for PWM driver, in Hz
+ float min_duty;
+ float max_duty;
+ float power;
+} pwm_t;
+
+
+static pwm_t pwm = {0};
+
+
+static void _set_enable(bool enable) {
+ outputs_set_active(TOOL_ENABLE_PIN, enable);
+}
+
+
+static void _set_dir(bool clockwise) {
+ outputs_set_active(TOOL_DIR_PIN, !clockwise);
+}
+
+
+static void _update_clock(uint16_t period) {
+ if (estop_triggered()) period = 0;
+
+ // Disable
+ if (!period) {
+ TIMER_PWM.CTRLB = 0; // Disable clock control of pin
+ OUTCLR_PIN(PWM_PIN);
+ _set_enable(false);
+ return;
+ }
+ _set_enable(true);
+
+ // 100% duty
+ if (period == 0xffff) {
+ TIMER_PWM.CTRLB = 0; // Disable clock control of pin
+ OUTSET_PIN(PWM_PIN);
+ return;
+ }
+
+ // Configure clock
+ TIMER_PWM.CTRLB = TC1_CCAEN_bm | TC_WGMODE_SINGLESLOPE_gc;
+ TIMER_PWM.CCA = period;
+}
+
+
+static float _compute_duty(float power) {
+ power = fabsf(power);
+ if (!power) return 0; // 0% duty
+ if (power == 1 && pwm.max_duty == 1) return 1; // 100% duty
+ return power * (pwm.max_duty - pwm.min_duty) + pwm.min_duty;
+}
+
+
+static uint16_t _compute_period(float duty) {return TIMER_PWM.PER * duty;}
+
+
+static void _update_pwm() {
+ if (pwm.initialized)
+ _update_clock(_compute_period(_compute_duty(pwm.power)));
+}
+
+
+static void _update_freq() {
+ // Set clock period and optimal prescaler value
+ float prescale = (F_CPU >> 16) / pwm.freq;
+
+ if (prescale <= 1) {
+ TIMER_PWM.PER = F_CPU / pwm.freq;
+ TIMER_PWM.CTRLA = TC_CLKSEL_DIV1_gc;
+
+ } else if (prescale <= 2) {
+ TIMER_PWM.PER = F_CPU / 2 / pwm.freq;
+ TIMER_PWM.CTRLA = TC_CLKSEL_DIV2_gc;
+
+ } else if (prescale <= 4) {
+ TIMER_PWM.PER = F_CPU / 4 / pwm.freq;
+ TIMER_PWM.CTRLA = TC_CLKSEL_DIV4_gc;
+
+ } else if (prescale <= 8) {
+ TIMER_PWM.PER = F_CPU / 8 / pwm.freq;
+ TIMER_PWM.CTRLA = TC_CLKSEL_DIV8_gc;
+
+ } else if (prescale <= 64) {
+ TIMER_PWM.PER = F_CPU / 64 / pwm.freq;
+ TIMER_PWM.CTRLA = TC_CLKSEL_DIV64_gc;
+
+ } else TIMER_PWM.CTRLA = 0;
+
+ _update_pwm();
+}
+
+
+void pwm_init() {
+ pwm.initialized = true;
+ pwm.power = 0;
+
+ // Configure IO
+ _set_dir(true);
+ _set_enable(false);
+ _update_freq();
+
+ // PWM output
+ OUTCLR_PIN(PWM_PIN);
+ DIRSET_PIN(PWM_PIN);
+}
+
+
+float pwm_get() {return pwm.power;}
+
+
+void pwm_deinit(deinit_cb_t cb) {
+ pwm.initialized = false;
+
+ _set_enable(false);
+
+ // Float PWM output pin
+ DIRCLR_PIN(PWM_PIN);
+
+ // Disable clock
+ TIMER_PWM.CTRLA = 0;
+
+ cb();
+}
+
+
+power_update_t pwm_get_update(float power) {
+ power_update_t update = {
+ 0 <= power ? POWER_FORWARD : POWER_REVERSE,
+ power,
+ _compute_period(_compute_duty(power))
+ };
+
+ return update;
+}
+
+
+// Called from hi-priority stepper interrupt, must be very fast
+void pwm_update(const power_update_t &update) {
+ if (!pwm.initialized || update.state == POWER_IGNORE) return;
+ _update_clock(update.period);
+ if (update.period) _set_dir(update.state == POWER_FORWARD);
+ pwm.power = update.power;
+}
+
+
+// Var callbacks
+float get_pwm_min_duty() {return pwm.min_duty * 100;}
+
+
+void set_pwm_min_duty(float value) {
+ pwm.min_duty = value * 0.01;
+ _update_pwm();
+}
+
+
+float get_pwm_max_duty() {return pwm.max_duty * 100;}
+
+
+void set_pwm_max_duty(float value) {
+ pwm.max_duty = value * 0.01;
+ _update_pwm();
+}
+
+
+float get_pwm_duty() {return _compute_duty(pwm.power);}
+float get_pwm_freq() {return pwm.freq;}
+
+
+void set_pwm_freq(float value) {
+ if (value < 8) value = 8;
+ if (320000 < value) value = 320000;
+ pwm.freq = value;
+ _update_freq();
+}
+
+
+bool get_pwm_invert() {return PINCTRL_PIN(PWM_PIN) & PORT_INVEN_bm;}
+
+
+void set_pwm_invert(bool invert) {
+ if (invert) PINCTRL_PIN(PWM_PIN) |= PORT_INVEN_bm;
+ else PINCTRL_PIN(PWM_PIN) &= ~PORT_INVEN_bm;
+}
diff --git a/src/avr/src/pwm.h b/src/avr/src/pwm.h
new file mode 100644
index 0000000..23c723b
--- /dev/null
+++ b/src/avr/src/pwm.h
@@ -0,0 +1,37 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "spindle.h"
+
+
+void pwm_init();
+float pwm_get();
+void pwm_deinit(deinit_cb_t cb);
+power_update_t pwm_get_update(float power);
+void pwm_update(const power_update_t &update);
diff --git a/src/avr/src/report.c b/src/avr/src/report.c
new file mode 100644
index 0000000..5e9d032
--- /dev/null
+++ b/src/avr/src/report.c
@@ -0,0 +1,54 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "report.h"
+#include "config.h"
+#include "usart.h"
+#include "rtc.h"
+#include "vars.h"
+
+
+static bool _full = false;
+static uint32_t _last = 0;
+
+
+void report_request_full() {_full = true;}
+
+
+void report_callback() {
+ // Wait until output buffer is empty
+ if (!usart_tx_empty()) return;
+
+ // Limit frequency
+ uint32_t now = rtc_get_time();
+ if (now - _last < REPORT_RATE) return;
+ _last = now;
+
+ // Report vars
+ vars_report(_full);
+ _full = false;
+}
diff --git a/src/avr/src/report.h b/src/avr/src/report.h
new file mode 100644
index 0000000..4a7dcff
--- /dev/null
+++ b/src/avr/src/report.h
@@ -0,0 +1,34 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+
+#include "status.h"
+
+void report_request_full();
+void report_callback();
diff --git a/src/avr/src/ringbuf.def b/src/avr/src/ringbuf.def
new file mode 100644
index 0000000..1f4bad9
--- /dev/null
+++ b/src/avr/src/ringbuf.def
@@ -0,0 +1,225 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+/* This file defines an X-Macro ring buffer. It can be used like this:
+ *
+ * #define RING_BUF_NAME tx_buf
+ * #define RING_BUF_SIZE 256
+ * #include "ringbuf.def"
+ *
+ * This will define the following functions:
+ *
+ * void _init();
+ * int _empty();
+ * int _full();
+ * _peek();
+ * void _pop();
+ * void _push( data);
+ *
+ * Where is defined by RING_BUF_NAME and by RING_BUF_TYPE.
+ * RING_BUF_SIZE defines the length of the ring buffer and must be a power of 2.
+ *
+ * The data type and index type both default to uint8_t but can be changed by
+ * defining RING_BUF_TYPE and RING_BUF_INDEX_TYPE respectively.
+ *
+ * By default these functions are declared static inline but this can be changed
+ * by defining RING_BUF_FUNC.
+ */
+
+#include
+#include
+
+#include
+
+
+#ifndef RING_BUF_NAME
+#error Must define RING_BUF_NAME
+#endif
+
+#ifndef RING_BUF_SIZE
+#error Must define RING_BUF_SIZE
+#endif
+
+#ifndef RING_BUF_TYPE
+#define RING_BUF_TYPE uint8_t
+#endif
+
+#ifndef RING_BUF_INDEX_TYPE
+#define RING_BUF_INDEX_TYPE volatile uint8_t
+#endif
+
+#ifndef RING_BUF_FUNC
+#define RING_BUF_FUNC static inline
+#endif
+
+#define RING_BUF_MASK (RING_BUF_SIZE - 1)
+#if (RING_BUF_SIZE & RING_BUF_MASK)
+#error RING_BUF_SIZE is not a power of 2
+#endif
+
+#ifndef CONCAT
+#define _CONCAT(prefix, name) prefix##name
+#define CONCAT(prefix, name) _CONCAT(prefix, name)
+#endif
+
+#define RING_BUF_STRUCT CONCAT(RING_BUF_NAME, _ring_buf_t)
+#define RING_BUF RING_BUF_NAME
+
+typedef struct {
+ RING_BUF_TYPE buf[RING_BUF_SIZE];
+ RING_BUF_INDEX_TYPE head;
+ RING_BUF_INDEX_TYPE tail;
+} RING_BUF_STRUCT;
+
+static RING_BUF_STRUCT RING_BUF;
+
+
+RING_BUF_FUNC void CONCAT(RING_BUF_NAME, _init)() {
+ RING_BUF.head = RING_BUF.tail = 0;
+}
+
+
+#define RING_BUF_INC(x) (((x) + 1) & RING_BUF_MASK)
+#define RING_BUF_DEC(x) ((x) ? x - 1 : (RING_BUF_SIZE - 1))
+
+
+#ifdef RING_BUF_ATOMIC_COPY
+
+#undef RING_BUF_ATOMIC_COPY
+#define RING_BUF_ATOMIC_COPY(TO, FROM) \
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) TO = FROM
+
+
+#define RING_BUF_ATOMIC_READ_INDEX(INDEX) \
+ RING_BUF_FUNC RING_BUF_INDEX_TYPE CONCAT(RING_BUF_NAME, _read_##INDEX)() { \
+ RING_BUF_INDEX_TYPE index; \
+ RING_BUF_ATOMIC_COPY(index, RING_BUF.INDEX); \
+ return index; \
+ }
+
+
+#define RING_BUF_ATOMIC_WRITE_INDEX(INDEX) \
+ RING_BUF_FUNC void CONCAT(RING_BUF_NAME, _write_##INDEX) \
+ (RING_BUF_INDEX_TYPE value) { \
+ RING_BUF_ATOMIC_COPY(RING_BUF.INDEX, value); \
+ }
+
+
+RING_BUF_ATOMIC_READ_INDEX(head);
+RING_BUF_ATOMIC_READ_INDEX(tail);
+RING_BUF_ATOMIC_WRITE_INDEX(head);
+RING_BUF_ATOMIC_WRITE_INDEX(tail);
+
+#define RING_BUF_READ_INDEX(INDEX) CONCAT(RING_BUF_NAME, _read_##INDEX)()
+#define RING_BUF_WRITE_INDEX(INDEX, VALUE) \
+ CONCAT(RING_BUF_NAME, _write_##INDEX)(VALUE)
+
+
+#else // RING_BUF_ATOMIC_COPY
+#define RING_BUF_READ_INDEX(INDEX) RING_BUF.INDEX
+#define RING_BUF_WRITE_INDEX(INDEX, VALUE) RING_BUF.INDEX = VALUE
+#endif // RING_BUF_ATOMIC_COPY
+
+
+RING_BUF_FUNC bool CONCAT(RING_BUF_NAME, _empty)() {
+ return RING_BUF_READ_INDEX(head) == RING_BUF_READ_INDEX(tail);
+}
+
+
+RING_BUF_FUNC bool CONCAT(RING_BUF_NAME, _full)() {
+ return RING_BUF_READ_INDEX(head) == RING_BUF_INC(RING_BUF_READ_INDEX(tail));
+}
+
+
+RING_BUF_FUNC RING_BUF_INDEX_TYPE CONCAT(RING_BUF_NAME, _fill)() {
+ return
+ (RING_BUF_READ_INDEX(tail) - RING_BUF_READ_INDEX(head)) & RING_BUF_MASK;
+}
+
+
+RING_BUF_FUNC RING_BUF_INDEX_TYPE CONCAT(RING_BUF_NAME, _space)() {
+ return (RING_BUF_SIZE - 1) - CONCAT(RING_BUF_NAME, _fill)();
+}
+
+
+RING_BUF_FUNC RING_BUF_TYPE CONCAT(RING_BUF_NAME, _peek)() {
+ return RING_BUF.buf[RING_BUF_READ_INDEX(head)];
+}
+
+
+RING_BUF_FUNC RING_BUF_TYPE *CONCAT(RING_BUF_NAME, _front)() {
+ return &RING_BUF.buf[RING_BUF_READ_INDEX(head)];
+}
+
+
+RING_BUF_FUNC RING_BUF_TYPE *CONCAT(RING_BUF_NAME, _back)() {
+ return &RING_BUF.buf[RING_BUF_DEC(RING_BUF_READ_INDEX(tail))];
+}
+
+
+RING_BUF_FUNC RING_BUF_TYPE CONCAT(RING_BUF_NAME, _get)(int offset) {
+ return RING_BUF.buf[(RING_BUF_READ_INDEX(head) + offset) & RING_BUF_MASK];
+}
+
+
+RING_BUF_FUNC void CONCAT(RING_BUF_NAME, _pop)() {
+ RING_BUF_WRITE_INDEX(head, RING_BUF_INC(RING_BUF_READ_INDEX(head)));
+}
+
+
+RING_BUF_FUNC RING_BUF_TYPE CONCAT(RING_BUF_NAME, _next)() {
+ RING_BUF_TYPE x = CONCAT(RING_BUF_NAME, _peek)();
+ CONCAT(RING_BUF_NAME, _pop)();
+ return x;
+}
+
+
+RING_BUF_FUNC void CONCAT(RING_BUF_NAME, _push)(RING_BUF_TYPE data) {
+ RING_BUF.buf[RING_BUF_READ_INDEX(tail)] = data;
+ RING_BUF_WRITE_INDEX(tail, RING_BUF_INC(RING_BUF_READ_INDEX(tail)));
+}
+
+
+#undef RING_BUF
+#undef RING_BUF_STRUCT
+#undef RING_BUF_INC
+#undef RING_BUF_MASK
+
+#undef RING_BUF_NAME
+#undef RING_BUF_SIZE
+#undef RING_BUF_TYPE
+#undef RING_BUF_INDEX_TYPE
+#undef RING_BUF_FUNC
+
+#undef RING_BUF_READ_INDEX
+#undef RING_BUF_WRITE_INDEX
+
+#ifdef RING_BUF_ATOMIC_COPY
+#undef RING_BUF_ATOMIC_COPY
+#undef RING_BUF_ATOMIC_READ_INDEX
+#undef RING_BUF_ATOMIC_WRITE_INDEX
+#endif // RING_BUF_ATOMIC_COPY
diff --git a/src/avr/src/rtc.c b/src/avr/src/rtc.c
new file mode 100644
index 0000000..8020895
--- /dev/null
+++ b/src/avr/src/rtc.c
@@ -0,0 +1,78 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "rtc.h"
+
+#include "switch.h"
+#include "analog.h"
+#include "motor.h"
+#include "lcd.h"
+#include "vfd_spindle.h"
+
+#include
+#include
+#include
+
+#include
+
+
+static uint32_t ticks;
+
+
+ISR(RTC_OVF_vect) {
+ ticks++;
+
+ lcd_rtc_callback();
+ switch_rtc_callback();
+ analog_rtc_callback();
+ vfd_spindle_rtc_callback();
+ if (!(ticks & 255)) motor_rtc_callback();
+ wdt_reset();
+}
+
+
+/// Initialize and start the clock
+/// This routine follows the code in app note AVR1314.
+void rtc_init() {
+ ticks = 0;
+
+ OSC.CTRL |= OSC_RC32KEN_bm; // enable internal 32kHz.
+ while (!(OSC.STATUS & OSC_RC32KRDY_bm)); // 32kHz osc stabilize
+ while (RTC.STATUS & RTC_SYNCBUSY_bm); // wait RTC not busy
+
+ CLK.RTCCTRL = CLK_RTCSRC_RCOSC32_gc | CLK_RTCEN_bm; // 32kHz clock as RTC src
+ while (RTC.STATUS & RTC_SYNCBUSY_bm); // wait RTC not busy
+
+ // the following must be in this order or it doesn't work
+ RTC.PER = 33; // overflow period ~1ms
+ RTC.INTCTRL = RTC_OVFINTLVL_LO_gc; // overflow LO interrupt
+ RTC.CTRL = RTC_PRESCALER_DIV1_gc; // no prescale
+}
+
+
+uint32_t rtc_get_time() {return ticks;}
+bool rtc_expired(uint32_t t) {return 0 <= (int32_t)(ticks - t);}
diff --git a/src/avr/src/rtc.h b/src/avr/src/rtc.h
new file mode 100644
index 0000000..6313ae9
--- /dev/null
+++ b/src/avr/src/rtc.h
@@ -0,0 +1,37 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+
+#include
+#include
+
+void rtc_init();
+uint32_t rtc_get_time();
+int32_t rtc_diff(uint32_t t);
+bool rtc_expired(uint32_t t);
diff --git a/src/avr/src/seek.c b/src/avr/src/seek.c
new file mode 100644
index 0000000..e3faf45
--- /dev/null
+++ b/src/avr/src/seek.c
@@ -0,0 +1,139 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "seek.h"
+
+#include "command.h"
+#include "switch.h"
+#include "estop.h"
+#include "util.h"
+#include "state.h"
+
+#include
+
+#include "motor.h"
+
+enum {
+ SEEK_ACTIVE = 1 << 0,
+ SEEK_ERROR = 1 << 1,
+ SEEK_FOUND = 1 << 2,
+};
+
+
+typedef struct {
+ bool active;
+ switch_id_t sw;
+ uint8_t flags;
+} seek_t;
+
+
+static seek_t seek = {false, SW_INVALID, 0};
+
+
+switch_id_t seek_get_switch() {return seek.active ? seek.sw : SW_INVALID;}
+
+bool seek_active() {
+ return seek.active;
+}
+
+bool seek_switch_found() {
+ if (!seek.active) return false;
+
+ bool inactive = !(seek.flags & SEEK_ACTIVE);
+
+ if (switch_is_active(seek.sw) ^ inactive) {
+ seek.flags |= SEEK_FOUND;
+ return true;
+ }
+
+ return false;
+}
+
+
+void seek_end() {
+ switch_id_t seekMode;
+
+ seekMode = seek_get_switch();
+
+ if (!seek.active) return;
+
+ if (!(SEEK_FOUND & seek.flags) && (SEEK_ERROR & seek.flags))
+ estop_trigger(STAT_SEEK_NOT_FOUND);
+
+ if((seekMode == SW_STALL_0) || (seekMode == SW_STALL_1) || (seekMode ==SW_STALL_2) || (seekMode == SW_STALL_3))
+ disable_stall_microstep();
+
+ seek.active = false;
+}
+
+
+void seek_cancel() {
+ switch_id_t seekMode;
+
+ seekMode = seek_get_switch();
+
+
+ if((seekMode == SW_STALL_0) || (seekMode == SW_STALL_1) || (seekMode ==SW_STALL_2) || (seekMode == SW_STALL_3))
+ disable_stall_microstep();
+
+ seek.active = false;
+}
+
+
+// Command callbacks
+stat_t command_seek(char *cmd) {
+ switch_id_t sw = (switch_id_t)decode_hex_nibble(cmd[1]);
+ if (sw <= 0) return STAT_INVALID_ARGUMENTS; // Don't allow seek to ESTOP
+ if (!switch_is_enabled(sw)) return STAT_SEEK_NOT_ENABLED;
+
+ uint8_t flags = decode_hex_nibble(cmd[2]);
+ if (flags & 0xfc) return STAT_INVALID_ARGUMENTS;
+
+ //////////////
+ if(sw == SW_STALL_0) enable_stall_microstep(0);
+ if(sw == SW_STALL_1) enable_stall_microstep(1);
+ if(sw == SW_STALL_2) enable_stall_microstep(2);
+ if(sw == SW_STALL_3) enable_stall_microstep(3);
+
+ seek_t seek = {true, sw, flags};
+ command_push(*cmd, &seek);
+
+ return STAT_OK;
+}
+
+
+unsigned command_seek_size() {return sizeof(seek_t);}
+void command_seek_exec(void *data) {
+ //switch_id_t seekMode;
+
+ //seekMode = seek_get_switch();
+
+ //if((seekMode == SW_STALL_0) || (seekMode == SW_STALL_1) || (seekMode ==SW_STALL_2) || (seekMode == SW_STALL_3))
+ // enable_stall_microstep();
+
+ seek = *(seek_t *)data;
+}
diff --git a/src/avr/src/seek.h b/src/avr/src/seek.h
new file mode 100644
index 0000000..aa1d7fa
--- /dev/null
+++ b/src/avr/src/seek.h
@@ -0,0 +1,39 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "switch.h"
+
+#include
+
+
+switch_id_t seek_get_switch();
+bool seek_switch_found();
+void seek_end();
+void seek_cancel();
+bool seek_active();
diff --git a/src/avr/src/spindle.c b/src/avr/src/spindle.c
new file mode 100644
index 0000000..cd39a88
--- /dev/null
+++ b/src/avr/src/spindle.c
@@ -0,0 +1,334 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "spindle.h"
+#include "pwm.h"
+#include "huanyang.h"
+#include "vfd_spindle.h"
+#include "stepper.h"
+#include "config.h"
+#include "command.h"
+#include "exec.h"
+#include "util.h"
+
+#include
+
+
+typedef struct {
+ float dist;
+ float speed;
+} sync_speed_t;
+
+
+static struct {
+ spindle_type_t type;
+ float override;
+ sync_speed_t sync_speed;
+ float speed;
+ bool reversed;
+ float min_rpm;
+ float max_rpm;
+ float inv_max_rpm;
+
+ bool dynamic_power;
+ float inv_feed;
+
+ spindle_type_t next_type;
+
+} spindle = {
+ .type = SPINDLE_TYPE_DISABLED,
+ .override = 1,
+ .sync_speed = {-1, 0}
+};
+
+
+static float _get_power() {
+ switch (spindle.type) {
+ case SPINDLE_TYPE_DISABLED: return 0;
+ case SPINDLE_TYPE_PWM: return pwm_get();
+ case SPINDLE_TYPE_HUANYANG: return huanyang_get();
+ default: return vfd_spindle_get();
+ }
+}
+
+
+static float _speed_to_power(float speed) {
+ bool negative = speed < 0;
+ float power = fabs(speed * spindle.override);
+
+ if (power < spindle.min_rpm) power = 0;
+ else if (spindle.max_rpm <= power) power = 1;
+ else power *= spindle.inv_max_rpm;
+
+ return (negative ^ spindle.reversed) ? -power : power;
+}
+
+
+static void _set_speed(float speed) {
+ spindle.speed = speed;
+
+ float power = _speed_to_power(speed);
+
+ switch (spindle.type) {
+ case SPINDLE_TYPE_DISABLED: break;
+
+ case SPINDLE_TYPE_PWM: {
+ // PWM speed updates must be synchronized with stepper movement
+ spindle.sync_speed.dist = 0;
+ spindle.sync_speed.speed = speed;
+ break;
+ }
+
+ case SPINDLE_TYPE_HUANYANG: huanyang_set(power); break;
+ default: vfd_spindle_set(power); break;
+ }
+}
+
+
+static void _deinit_cb() {
+ spindle.type = spindle.next_type;
+ spindle.next_type = SPINDLE_TYPE_DISABLED;
+
+ switch (spindle.type) {
+ case SPINDLE_TYPE_DISABLED: break;
+ case SPINDLE_TYPE_PWM: pwm_init(); break;
+ case SPINDLE_TYPE_HUANYANG: huanyang_init(); break;
+ default: vfd_spindle_init(); break;
+ }
+
+ spindle_update_speed();
+}
+
+
+static void _set_type(spindle_type_t type) {
+ if (type == spindle.type) return;
+
+ spindle_type_t old_type = spindle.type;
+ spindle.next_type = type;
+ spindle.type = SPINDLE_TYPE_DISABLED;
+
+ switch (old_type) {
+ case SPINDLE_TYPE_DISABLED: _deinit_cb(); break;
+ case SPINDLE_TYPE_PWM: pwm_deinit(_deinit_cb); break;
+ case SPINDLE_TYPE_HUANYANG: huanyang_deinit(_deinit_cb); break;
+ default: vfd_spindle_deinit(_deinit_cb); break;
+ }
+}
+
+
+spindle_type_t spindle_get_type() {return spindle.type;}
+
+
+static power_update_t _get_power_update() {
+ float power = _speed_to_power(spindle.speed);
+
+ // Handle dynamic power
+ if (spindle.dynamic_power && spindle.inv_feed) {
+ float scale = spindle.inv_feed * exec_get_velocity();
+ if (scale < 1) power *= scale;
+ }
+
+ return pwm_get_update(power);
+}
+
+
+void spindle_load_power_updates(power_update_t updates[], float minD,
+ float maxD) {
+ float stepD = (maxD - minD) * (1.0 / POWER_MAX_UPDATES);
+ float d = minD + 1e-3; // Starting distance
+
+ for (unsigned i = 0; i < POWER_MAX_UPDATES; i++) {
+ bool changed = false;
+ d += stepD; // Ending distance for this power step
+
+ while (true) {
+ // Load new sync speed if needed and available
+ if (spindle.sync_speed.dist < 0 && command_peek() == COMMAND_sync_speed)
+ spindle.sync_speed = *(sync_speed_t *)(command_next() + 1);
+
+ // Exit if we don't have a speed or it's not ready to be set
+ if (spindle.sync_speed.dist == -1 || d < spindle.sync_speed.dist) break;
+
+ // Load sync speed
+ spindle.sync_speed.dist = -1; // Mark done
+ spindle.speed = spindle.sync_speed.speed;
+ changed = true;
+ }
+
+ if (spindle.type == SPINDLE_TYPE_PWM) updates[i] = _get_power_update();
+ else {
+ updates[i].state = POWER_IGNORE;
+ if (changed) spindle_update_speed();
+ }
+ }
+}
+
+
+// Called from hi-priority stepper interrupt
+void spindle_update(const power_update_t &update) {pwm_update(update);}
+void spindle_update_speed() {_set_speed(spindle.speed);}
+
+
+// Called from lo-priority stepper interrupt
+void spindle_idle() {
+ if (spindle.sync_speed.dist != -1) {
+ spindle.sync_speed.dist = -1; // Mark done
+ spindle.speed = spindle.sync_speed.speed;
+
+ if (spindle.type == SPINDLE_TYPE_PWM) spindle_update(_get_power_update());
+ else spindle_update_speed();
+ }
+}
+
+
+void spindle_stop() {_set_speed(0);} // Only called when steppers have halted
+void spindle_estop() {_set_type(SPINDLE_TYPE_DISABLED);}
+
+
+// Var callbacks
+uint8_t get_tool_type() {return spindle.type;}
+void set_tool_type(uint8_t value) {_set_type((spindle_type_t)value);}
+bool get_tool_reversed() {return spindle.reversed;}
+
+
+void set_tool_reversed(bool reversed) {
+ if (spindle.reversed == reversed) return;
+ spindle.reversed = reversed;
+ spindle_update_speed();
+}
+
+
+float get_speed() {return _get_power() * spindle.max_rpm;}
+float get_max_spin() {return spindle.max_rpm;}
+
+
+void set_max_spin(float value) {
+ if (spindle.max_rpm != value) {
+ spindle.max_rpm = value;
+ spindle.inv_max_rpm = 1 / value;
+ spindle_update_speed();
+ }
+}
+
+
+float get_min_spin() {return spindle.min_rpm;}
+
+
+void set_min_spin(float value) {
+ if (spindle.min_rpm != value) {
+ spindle.min_rpm = value;
+ spindle_update_speed();
+ }
+}
+
+
+uint16_t get_spindle_status() {
+ switch (spindle.type) {
+ case SPINDLE_TYPE_DISABLED: return 0;
+ case SPINDLE_TYPE_PWM: return 0;
+ case SPINDLE_TYPE_HUANYANG: return huanyang_get_status();
+ default: return vfd_get_status();
+ }
+}
+
+
+uint16_t get_speed_override() {return spindle.override * 1000;}
+
+
+void set_speed_override(uint16_t value) {
+ value *= 0.001;
+
+ if (spindle.override != value) {
+ spindle.override = value;
+ spindle_update_speed();
+ }
+}
+
+
+bool get_dynamic_power() {return spindle.dynamic_power;}
+
+
+void set_dynamic_power(bool enable) {
+ if (spindle.dynamic_power != enable) {
+ spindle.dynamic_power = enable;
+ spindle_update_speed();
+ }
+}
+
+
+float get_inverse_feed() {return spindle.inv_feed;}
+
+
+void set_inverse_feed(float iF) {
+ if (spindle.inv_feed != iF) {
+ spindle.inv_feed = iF;
+ spindle_update_speed();
+ }
+}
+
+
+// Command callbacks
+stat_t command_sync_speed(char *cmd) {
+ sync_speed_t s;
+
+ cmd++; // Skip command code
+
+ // Get distance and speed
+ if (!decode_float(&cmd, &s.dist) || s.dist < 0) return STAT_BAD_FLOAT;
+ if (!decode_float(&cmd, &s.speed)) return STAT_BAD_FLOAT;
+
+ // Queue
+ command_push(COMMAND_sync_speed, &s);
+
+ return STAT_OK;
+}
+
+
+unsigned command_sync_speed_size() {return sizeof(sync_speed_t);}
+
+
+void command_sync_speed_exec(void *data) {
+ _set_speed(((sync_speed_t *)data)->speed);
+}
+
+
+stat_t command_speed(char *cmd) {
+ cmd++; // Skip command code
+
+ // Get speed
+ float speed;
+ if (!decode_float(&cmd, &speed)) return STAT_BAD_FLOAT;
+
+ // Queue
+ command_push(COMMAND_speed, &speed);
+
+ return STAT_OK;
+}
+
+
+unsigned command_speed_size() {return sizeof(float);}
+void command_speed_exec(void *data) {_set_speed(*(float *)data);}
diff --git a/src/avr/src/spindle.h b/src/avr/src/spindle.h
new file mode 100644
index 0000000..4728631
--- /dev/null
+++ b/src/avr/src/spindle.h
@@ -0,0 +1,74 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include
+#include
+
+
+typedef enum {
+ POWER_IGNORE,
+ POWER_FORWARD,
+ POWER_REVERSE
+} power_state_t;
+
+
+typedef struct {
+ power_state_t state;
+ float power;
+ uint16_t period; // Used by PWM
+} power_update_t;
+
+
+typedef enum {
+ SPINDLE_TYPE_DISABLED,
+ SPINDLE_TYPE_PWM,
+ SPINDLE_TYPE_HUANYANG,
+ SPINDLE_TYPE_CUSTOM,
+ SPINDLE_TYPE_AC_TECH,
+ SPINDLE_TYPE_NOWFOREVER,
+ SPINDLE_TYPE_DELTA_VFD015M21A,
+ SPINDLE_TYPE_YL600,
+ SPINDLE_TYPE_FR_D700,
+ SPINDLE_TYPE_SUNFAR_E300,
+ SPINDLE_TYPE_OMRON_MX2,
+ SPINDLE_TYPE_V70,
+} spindle_type_t;
+
+
+typedef void (*deinit_cb_t)();
+
+
+spindle_type_t spindle_get_type();
+void spindle_stop();
+void spindle_estop();
+void spindle_load_power_updates(power_update_t updates[], float minD,
+ float maxD);
+void spindle_update(const power_update_t &update);
+void spindle_update_speed();
+void spindle_idle();
diff --git a/src/avr/src/state.c b/src/avr/src/state.c
new file mode 100644
index 0000000..e94069c
--- /dev/null
+++ b/src/avr/src/state.c
@@ -0,0 +1,259 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "state.h"
+
+#include "exec.h"
+#include "command.h"
+#include "stepper.h"
+#include "spindle.h"
+#include "outputs.h"
+#include "jog.h"
+#include "estop.h"
+#include "seek.h"
+
+#include
+
+
+static struct {
+ bool flushing;
+ bool resuming;
+ bool stop_requested;
+ bool pause_requested;
+ bool unpause_requested;
+
+ state_t state;
+ uint16_t state_count;
+ hold_reason_t hold_reason;
+} s = {
+ .flushing = true, // Start out flushing
+};
+
+
+PGM_P state_get_pgmstr(state_t state) {
+ switch (state) {
+ case STATE_READY: return PSTR("READY");
+ case STATE_ESTOPPED: return PSTR("ESTOPPED");
+ case STATE_RUNNING: return PSTR("RUNNING");
+ case STATE_JOGGING: return PSTR("JOGGING");
+ case STATE_STOPPING: return PSTR("STOPPING");
+ case STATE_HOLDING: return PSTR("HOLDING");
+ }
+
+ return PSTR("INVALID");
+}
+
+
+PGM_P state_get_hold_reason_pgmstr(hold_reason_t reason) {
+ switch (reason) {
+ case HOLD_REASON_USER_PAUSE: return PSTR("User pause");
+ case HOLD_REASON_USER_STOP: return PSTR("User stop");
+ case HOLD_REASON_PROGRAM_PAUSE: return PSTR("Program pause");
+ case HOLD_REASON_OPTIONAL_PAUSE: return PSTR("Optional pause");
+ case HOLD_REASON_SWITCH_FOUND: return PSTR("Switch found");
+ }
+
+ return PSTR("INVALID");
+}
+
+
+state_t state_get() {return s.state;}
+
+
+static void _set_state(state_t state) {
+ if (s.state == state) return; // No change
+ if (s.state == STATE_ESTOPPED) return; // Can't leave EStop state
+ s.state = state;
+ s.state_count++;
+}
+
+
+static void _set_hold_reason(hold_reason_t reason) {s.hold_reason = reason;}
+bool state_is_flushing() {return s.flushing && !s.resuming;}
+bool state_is_resuming() {return s.resuming;}
+
+
+static bool _is_idle() {
+ return (state_get() == STATE_READY || state_get() == STATE_HOLDING) &&
+ !st_is_busy();
+}
+
+
+void state_seek_hold() {
+ if (state_get() == STATE_RUNNING) {
+ _set_hold_reason(HOLD_REASON_SWITCH_FOUND);
+ _set_state(STATE_STOPPING);
+ }
+}
+
+
+static void _stop() {
+ _set_hold_reason(HOLD_REASON_USER_STOP);
+
+ switch (state_get()) {
+ case STATE_RUNNING:
+ _set_state(STATE_STOPPING);
+ break;
+
+ case STATE_JOGGING:
+ case STATE_READY:
+ case STATE_HOLDING:
+ jog_stop();
+ spindle_stop();
+ outputs_stop();
+ seek_cancel();
+ break;
+
+ case STATE_STOPPING:
+ case STATE_ESTOPPED:
+ break; // Ignore
+ }
+}
+
+
+void state_holding() {
+ _set_state(STATE_HOLDING);
+ if (s.hold_reason == HOLD_REASON_USER_STOP) _stop();
+}
+
+
+void state_running() {
+ if (state_get() == STATE_READY) _set_state(STATE_RUNNING);
+}
+
+
+void state_jogging() {
+ if (state_get() == STATE_READY || state_get() == STATE_HOLDING)
+ _set_state(STATE_JOGGING);
+}
+
+
+void state_idle() {
+ if (state_get() == STATE_RUNNING || state_get() == STATE_JOGGING)
+ _set_state(STATE_READY);
+}
+
+
+void state_estop() {_set_state(STATE_ESTOPPED);}
+
+
+void state_callback() {
+ if (estop_triggered()) return;
+
+ // Pause
+ if (s.pause_requested) {
+ if (state_get() == STATE_RUNNING) {
+ if (s.pause_requested) _set_hold_reason(HOLD_REASON_USER_PAUSE);
+ _set_state(STATE_STOPPING);
+ }
+
+ s.pause_requested = false;
+ }
+
+ // Stop
+ if (s.stop_requested) {
+ _stop();
+ s.stop_requested = false;
+ }
+
+ // Only flush queue when idle (READY or HOLDING)
+ if (s.flushing && _is_idle()) {
+ command_flush_queue();
+
+ // Resume
+ if (s.resuming) s.flushing = s.resuming = false;
+ }
+
+ // Unpause
+ if (s.unpause_requested && !s.flushing && state_get() != STATE_STOPPING) {
+ s.unpause_requested = false;
+
+ if (state_get() == STATE_HOLDING) {
+ // Check if any moves are buffered
+ if (command_get_count()) _set_state(STATE_RUNNING);
+ else _set_state(STATE_READY);
+ }
+ }
+}
+
+
+// Var callbacks
+PGM_P get_state() {return state_get_pgmstr(state_get());}
+uint16_t get_state_count() {return s.state_count;}
+PGM_P get_hold_reason() {return state_get_hold_reason_pgmstr(s.hold_reason);}
+
+
+// Command callbacks
+stat_t command_pause(char *cmd) {
+ pause_t type = (pause_t)(cmd[1] - '0');
+
+ if (type == PAUSE_USER) s.pause_requested = true;
+ else command_push(cmd[0], &type);
+
+ return STAT_OK;
+}
+
+
+unsigned command_pause_size() {return sizeof(pause_t);}
+
+
+void command_pause_exec(void *data) {
+ switch (*(pause_t *)data) {
+ case PAUSE_PROGRAM_OPTIONAL:
+ _set_hold_reason(HOLD_REASON_OPTIONAL_PAUSE);
+ break;
+
+ case PAUSE_PROGRAM: _set_hold_reason(HOLD_REASON_PROGRAM_PAUSE); break;
+ default: return;
+ }
+
+ state_holding();
+}
+
+
+stat_t command_stop(char *cmd) {
+ s.stop_requested = true;
+ return STAT_OK;
+}
+
+
+stat_t command_unpause(char *cmd) {
+ s.unpause_requested = true;
+ return STAT_OK;
+}
+
+
+stat_t command_resume(char *cmd) {
+ if (s.flushing) s.resuming = true;
+ return STAT_OK;
+}
+
+
+stat_t command_flush(char *cmd) {
+ s.flushing = true;
+ return STAT_OK;
+}
diff --git a/src/avr/src/state.h b/src/avr/src/state.h
new file mode 100644
index 0000000..d3488ab
--- /dev/null
+++ b/src/avr/src/state.h
@@ -0,0 +1,76 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "pgmspace.h"
+
+#include
+
+
+typedef enum {
+ STATE_READY,
+ STATE_ESTOPPED,
+ STATE_RUNNING,
+ STATE_JOGGING,
+ STATE_STOPPING,
+ STATE_HOLDING,
+} state_t;
+
+
+typedef enum {
+ HOLD_REASON_USER_PAUSE,
+ HOLD_REASON_USER_STOP,
+ HOLD_REASON_PROGRAM_PAUSE,
+ HOLD_REASON_OPTIONAL_PAUSE,
+ HOLD_REASON_SWITCH_FOUND,
+} hold_reason_t;
+
+
+typedef enum {
+ PAUSE_USER,
+ PAUSE_PROGRAM,
+ PAUSE_PROGRAM_OPTIONAL,
+} pause_t;
+
+
+PGM_P state_get_pgmstr(state_t state);
+PGM_P state_get_hold_reason_pgmstr(hold_reason_t reason);
+
+state_t state_get();
+
+bool state_is_flushing();
+bool state_is_resuming();
+
+void state_seek_hold();
+void state_holding();
+void state_running();
+void state_jogging();
+void state_idle();
+void state_estop();
+
+void state_callback();
diff --git a/src/avr/src/status.c b/src/avr/src/status.c
new file mode 100644
index 0000000..4279637
--- /dev/null
+++ b/src/avr/src/status.c
@@ -0,0 +1,96 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "status.h"
+#include "estop.h"
+#include "usart.h"
+
+#include
+#include
+
+
+#define STAT_MSG(NAME, TEXT) static const char stat_##NAME[] PROGMEM = TEXT;
+#include "messages.def"
+#undef STAT_MSG
+
+
+static const char *const stat_msg[] PROGMEM = {
+#define STAT_MSG(NAME, TEXT) stat_##NAME,
+#include "messages.def"
+#undef STAT_MSG
+};
+
+
+const char *status_to_pgmstr(stat_t code) {
+ return (const char *)pgm_read_ptr(&stat_msg[code]);
+}
+
+
+const char *status_level_pgmstr(status_level_t level) {
+ switch (level) {
+ case STAT_LEVEL_INFO: return PSTR("info");
+ case STAT_LEVEL_DEBUG: return PSTR("debug");
+ case STAT_LEVEL_WARNING: return PSTR("warning");
+ default: return PSTR("error");
+ }
+}
+
+
+stat_t status_message_P(const char *location, status_level_t level,
+ stat_t code, const char *msg, ...) {
+ va_list args;
+
+ // Type
+ printf_P(PSTR("\n{\"level\":\"%" PRPSTR "\",\"msg\":\""),
+ status_level_pgmstr(level));
+
+ // Message
+ printf_P(PSTR("%" PRPSTR), status_to_pgmstr(code));
+
+ if (msg && pgm_read_byte(msg)) {
+ putchar(':');
+ putchar(' ');
+
+ // TODO escape invalid chars
+ va_start(args, msg);
+ vfprintf_P(stdout, msg, args);
+ va_end(args);
+ }
+
+ putchar('"');
+
+ // Code
+ if (code) printf_P(PSTR(",\"code\":%d"), code);
+
+ // Location
+ if (location) printf_P(PSTR(",\"where\":\"%" PRPSTR "\""), location);
+
+ putchar('}');
+ putchar('\n');
+
+ return code;
+}
diff --git a/src/avr/src/status.h b/src/avr/src/status.h
new file mode 100644
index 0000000..d363a1d
--- /dev/null
+++ b/src/avr/src/status.h
@@ -0,0 +1,84 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "pgmspace.h"
+
+
+typedef enum {
+#define STAT_MSG(NAME, TEXT) STAT_##NAME,
+#include "messages.def"
+#undef STAT_MSG
+
+ STAT_MAX,
+ STAT_DO_NOT_EXCEED = 255 // Do not exceed 255
+} stat_t;
+
+
+typedef enum {
+ STAT_LEVEL_INFO,
+ STAT_LEVEL_DEBUG,
+ STAT_LEVEL_WARNING,
+ STAT_LEVEL_ERROR,
+} status_level_t;
+
+
+extern stat_t status_code;
+
+const char *status_to_pgmstr(stat_t code);
+const char *status_level_pgmstr(status_level_t level);
+stat_t status_message_P(const char *location, status_level_t level,
+ stat_t code, const char *msg, ...);
+
+#define TO_STRING(x) _TO_STRING(x)
+#define _TO_STRING(x) #x
+
+#define STATUS_LOCATION PSTR(__FILE__ ":" TO_STRING(__LINE__))
+
+#define STATUS_MESSAGE(LEVEL, CODE, MSG, ...) \
+ status_message_P(STATUS_LOCATION, LEVEL, CODE, PSTR(MSG), ##__VA_ARGS__)
+
+#define STATUS_INFO(MSG, ...) \
+ STATUS_MESSAGE(STAT_LEVEL_INFO, STAT_OK, MSG, ##__VA_ARGS__)
+
+#define STATUS_DEBUG(MSG, ...) \
+ STATUS_MESSAGE(STAT_LEVEL_DEBUG, STAT_OK, MSG, ##__VA_ARGS__)
+
+#define STATUS_WARNING(CODE, MSG, ...) \
+ STATUS_MESSAGE(STAT_LEVEL_WARNING, CODE, MSG, ##__VA_ARGS__)
+
+#define STATUS_ERROR(CODE, MSG, ...) \
+ STATUS_MESSAGE(STAT_LEVEL_ERROR, CODE, MSG, ##__VA_ARGS__)
+
+
+#ifdef DEBUG
+#define DEBUG_CALL(FMT, ...) \
+ printf_P(PSTR("%s(" FMT ")\n"), __FUNCTION__, ##__VA_ARGS__)
+#else // DEBUG
+#define DEBUG_CALL(...)
+#endif // DEBUG
diff --git a/src/avr/src/stepper.c b/src/avr/src/stepper.c
new file mode 100644
index 0000000..68453f7
--- /dev/null
+++ b/src/avr/src/stepper.c
@@ -0,0 +1,247 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "stepper.h"
+
+#include "config.h"
+#include "motor.h"
+#include "hardware.h"
+#include "estop.h"
+#include "util.h"
+#include "cpp_magic.h"
+#include "exec.h"
+#include "drv8711.h"
+
+#include
+
+#include
+#include
+
+
+typedef struct {
+ // Runtime
+ bool busy;
+ bool requesting;
+ float dwell;
+ uint8_t power_buf;
+ uint8_t power_index;
+
+ // Move prep
+ bool move_ready; // Prepped move ready for loader
+ bool move_queued; // Prepped move queued
+ float prep_dwell;
+ int8_t power_next;
+
+ power_update_t powers[2][POWER_MAX_UPDATES];
+
+ uint32_t underrun;
+} stepper_t;
+
+
+static stepper_t st = {0};
+
+
+void stepper_init() {
+ // Setup step timer
+ TIMER_STEP.CTRLB = TC_WGMODE_NORMAL_gc; // Count to TOP & rollover
+ TIMER_STEP.INTCTRLA = TC_OVFINTLVL_HI_gc; // Interrupt level
+ TIMER_STEP.PER = STEP_TIMER_POLL; // Timer rate
+ TIMER_STEP.CTRLA = TC_CLKSEL_DIV8_gc; // Start step timer
+}
+
+
+static void _end_move() {
+ for (int motor = 0; motor < MOTORS; motor++)
+ motor_end_move(motor);
+}
+
+
+static void _load_move() {
+ for (int motor = 0; motor < MOTORS; motor++)
+ motor_load_move(motor);
+}
+
+
+void st_shutdown() {
+ TIMER_STEP.CTRLA = 0; // Stop stepper clock
+ _end_move(); // Stop motor clocks
+ ADCB_CH0_INTCTRL = 0; // Disable next move interrupt
+}
+
+
+/// Return true if motors or dwell are running
+bool st_is_busy() {return st.busy;}
+
+
+/// Interrupt handler for calling move exec function.
+/// ADC channel 0 triggered by load ISR as a "software" interrupt.
+ISR(STEP_LOW_LEVEL_ISR) {
+ while (true) {
+ stat_t status = exec_next();
+
+ switch (status) {
+ case STAT_NOP: // No move executed, idle
+ if (!st.busy) {
+ if (MIN_VELOCITY < exec_get_velocity()) st.underrun++;
+ exec_set_velocity(0); // Velocity is zero if there are no moves
+
+ spindle_idle();
+ }
+ break;
+
+ case STAT_AGAIN: continue; // No command executed, try again
+
+ case STAT_OK: // Move executed
+ if (!st.move_queued)
+ estop_trigger(STAT_EXPECTED_MOVE); // No move was queued
+ st.move_queued = false;
+ st.move_ready = true;
+ break;
+
+ default: estop_trigger(status); break;
+ }
+
+ break;
+ }
+
+ ADCB_CH0_INTCTRL = 0;
+ st.requesting = false;
+}
+
+
+static void _request_exec_move() {
+ if (st.requesting) return;
+ st.requesting = true;
+
+ // Use ADC as "software" interrupt to trigger next move exec as low interrupt.
+ ADCB_CH0_INTCTRL = ADC_CH_INTLVL_LO_gc;
+ ADCB_CTRLA = ADC_ENABLE_bm | ADC_CH0START_bm;
+}
+
+
+static void _update_power() {
+ if (st.power_index < POWER_MAX_UPDATES)
+ spindle_update(st.powers[st.power_buf][st.power_index++]);
+}
+
+
+/// Step timer interrupt routine.
+/// Dwell or dequeue and load next move.
+ISR(STEP_TIMER_ISR) {
+ static uint8_t tick = 0;
+
+ // Update spindle power on every tick
+ _update_power();
+
+ // Dwell
+ if (0 < st.dwell) {
+ st.dwell -= 0.001; // 1ms
+ return;
+ }
+ st.dwell = 0;
+
+ if (tick++ & 3) return; // Proceed every 4 ticks
+
+ // If the next move is not ready try to load it
+ if (!st.move_ready) {
+ _request_exec_move();
+ _end_move();
+ tick = 0; // Try again in 1ms
+ st.busy = false;
+ return;
+ }
+
+ if (st.prep_dwell) {
+ // End last move, if any
+ _end_move();
+
+ // Start dwell
+ st.dwell = st.prep_dwell;
+ st.prep_dwell = 0;
+
+ } else {
+ // Start move
+ _load_move();
+
+ // Request next move when not in a dwell. Requesting the next move may
+ // power up motors which should not be powered up during a dwell.
+ _request_exec_move();
+ }
+
+ // Handle power updates
+ if (st.power_next != -1) {
+ st.power_index = 0;
+ st.power_buf = st.power_next;
+ st.power_next = -1;
+ _update_power();
+ }
+
+ st.busy = true; // Executing move so mark busy
+ st.move_ready = false; // We are done with this move, flip the flag back
+}
+
+
+void st_prep_power(const power_update_t powers[]) {
+ ESTOP_ASSERT(!st.move_ready, STAT_STEPPER_NOT_READY);
+ st.power_next = !st.power_buf;
+ memcpy(st.powers[st.power_next], powers,
+ sizeof(power_update_t) * POWER_MAX_UPDATES);
+}
+
+
+void st_prep_line(const float target[]) {
+ // Trap conditions that would prevent queuing the line
+ ESTOP_ASSERT(!st.move_ready, STAT_STEPPER_NOT_READY);
+
+ // Prepare motor moves
+ for (int motor = 0; motor < MOTORS; motor++)
+ motor_prep_move(motor, target[motor_get_axis(motor)]);
+
+ st.move_queued = true; // signal prep buffer ready (do this last)
+}
+
+
+/// Add a dwell to the move buffer
+void st_prep_dwell(float seconds) {
+ ESTOP_ASSERT(!st.move_ready, STAT_STEPPER_NOT_READY);
+ if (seconds <= 1e-4) seconds = 1e-4; // Min dwell
+ st.power_next = !st.power_buf;
+ spindle_load_power_updates(st.powers[st.power_next], 0, 0);
+ st.prep_dwell = seconds;
+ st.move_queued = true; // signal prep buffer ready
+}
+
+
+// Var callbacks
+uint32_t get_underrun() {return st.underrun;}
+
+
+float get_dwell_time() {
+ float dwell;
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) dwell = st.dwell;
+ return dwell;
+}
diff --git a/src/avr/src/stepper.h b/src/avr/src/stepper.h
new file mode 100644
index 0000000..d365e34
--- /dev/null
+++ b/src/avr/src/stepper.h
@@ -0,0 +1,42 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "spindle.h"
+
+#include
+#include
+
+
+void stepper_init();
+void st_shutdown();
+bool st_is_busy();
+void st_set_power_scale(float scale);
+void st_prep_power(const power_update_t powers[]);
+void st_prep_line(const float target[]);
+void st_prep_dwell(float seconds);
diff --git a/src/avr/src/switch.c b/src/avr/src/switch.c
new file mode 100644
index 0000000..6994b15
--- /dev/null
+++ b/src/avr/src/switch.c
@@ -0,0 +1,209 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "switch.h"
+#include "config.h"
+
+#include
+#include
+
+
+static struct {
+ uint16_t debounce;
+ uint16_t lockout;
+} sw = {
+ .debounce = SWITCH_DEBOUNCE,
+ .lockout = SWITCH_LOCKOUT,
+};
+
+typedef struct {
+ uint8_t pin;
+ switch_type_t type;
+
+ switch_callback_t cb;
+ bool state;
+ uint16_t debounce;
+ uint16_t lockout;
+ bool initialized;
+} switch_t;
+
+
+// Order must match indices in var functions below
+static switch_t switches[] = {
+ {.pin = ESTOP_PIN, .type = SW_DISABLED},
+ {.pin = PROBE_PIN, .type = SW_DISABLED},
+ {.pin = MIN_0_PIN, .type = SW_DISABLED},
+ {.pin = MAX_0_PIN, .type = SW_DISABLED},
+ {.pin = MIN_1_PIN, .type = SW_DISABLED},
+ {.pin = MAX_1_PIN, .type = SW_DISABLED},
+ {.pin = MIN_2_PIN, .type = SW_DISABLED},
+ {.pin = MAX_2_PIN, .type = SW_DISABLED},
+ {.pin = MIN_3_PIN, .type = SW_DISABLED},
+ {.pin = MAX_3_PIN, .type = SW_DISABLED},
+ {.pin = STALL_0_PIN, .type = SW_DISABLED},
+ {.pin = STALL_1_PIN, .type = SW_DISABLED},
+ {.pin = STALL_2_PIN, .type = SW_DISABLED},
+ {.pin = STALL_3_PIN, .type = SW_DISABLED},
+ {.pin = MOTOR_FAULT_PIN, .type = SW_DISABLED},
+};
+
+
+static const int num_switches = sizeof(switches) / sizeof (switch_t);
+
+
+void switch_init() {
+ for (int i = 0; i < num_switches; i++) {
+ switch_t *s = &switches[i];
+ PINCTRL_PIN(s->pin) = PORT_OPC_PULLUP_gc; // Pull up
+ DIRCLR_PIN(s->pin); // Input
+ }
+}
+
+
+/// Called from RTC on each tick
+void switch_rtc_callback() {
+ for (int i = 0; i < num_switches; i++) {
+ switch_t *s = &switches[i];
+
+ if (s->type == SW_DISABLED) continue;
+ if (s->lockout && --s->lockout) continue;
+
+ // Debounce switch
+ bool state = IN_PIN(s->pin);
+ if (state == s->state && s->initialized) s->debounce = 0;
+ else if (++s->debounce == sw.debounce) {
+ s->state = state;
+ s->debounce = 0;
+ s->initialized = true;
+ s->lockout = sw.lockout;
+ if (s->cb) s->cb((switch_id_t)i, switch_is_active((switch_id_t)i));
+ }
+ }
+}
+
+
+bool switch_is_active(switch_id_t sw) {
+ if (sw < 0 || num_switches <= sw || !switches[sw].initialized) return false;
+
+ // NOTE, switch inputs are active lo
+ switch (switches[sw].type) {
+ case SW_DISABLED: break; // A disabled switch cannot be active
+ case SW_NORMALLY_OPEN: return !switches[sw].state;
+ case SW_NORMALLY_CLOSED: return switches[sw].state;
+ }
+
+ return false;
+}
+
+
+bool switch_is_enabled(switch_id_t sw) {
+ return switch_get_type(sw) != SW_DISABLED;
+}
+
+
+switch_type_t switch_get_type(switch_id_t sw) {
+ return (sw < 0 || num_switches <= sw) ? SW_DISABLED : switches[sw].type;
+}
+
+
+void switch_set_type(switch_id_t sw, switch_type_t type) {
+ if (sw < 0 || num_switches <= sw) return;
+ switch_t *s = &switches[sw];
+
+ if (s->type != type) {
+ bool wasActive = switch_is_active(sw);
+ s->type = type;
+ bool isActive = switch_is_active(sw);
+ if (wasActive != isActive && s->cb) s->cb(sw, isActive);
+ }
+}
+
+
+void switch_set_callback(switch_id_t sw, switch_callback_t cb) {
+ switches[sw].cb = cb;
+}
+
+
+// Var callbacks
+uint8_t get_min_sw_mode(int index) {return switch_get_type(MIN_SWITCH(index));}
+
+
+void set_min_sw_mode(int index, uint8_t value) {
+ switch_set_type(MIN_SWITCH(index), (switch_type_t)value);
+}
+
+
+uint8_t get_max_sw_mode(int index) {return switch_get_type(MAX_SWITCH(index));}
+
+
+void set_max_sw_mode(int index, uint8_t value) {
+ switch_set_type(MAX_SWITCH(index), (switch_type_t)value);
+}
+
+
+uint8_t get_estop_mode() {return switch_get_type(SW_ESTOP);}
+
+
+void set_estop_mode(uint8_t value) {
+ switch_set_type(SW_ESTOP, (switch_type_t)value);
+}
+
+
+uint8_t get_probe_mode() {return switch_get_type(SW_PROBE);}
+
+
+void set_probe_mode(uint8_t value) {
+ switch_set_type(SW_PROBE, (switch_type_t)value);
+}
+
+
+static uint8_t _get_state(int index) {
+ if (!switch_is_enabled((switch_id_t)index)) return 2; // Disabled
+ return switches[index].state;
+}
+
+
+uint8_t get_min_switch(int index) {return _get_state(MIN_SWITCH(index));}
+uint8_t get_max_switch(int index) {return _get_state(MAX_SWITCH(index));}
+uint8_t get_estop_switch() {return _get_state(SW_ESTOP);}
+uint8_t get_probe_switch() {return _get_state(SW_PROBE);}
+
+
+void set_switch_debounce(uint16_t debounce) {
+ sw.debounce = SWITCH_MAX_DEBOUNCE < debounce ? SWITCH_DEBOUNCE : debounce;
+}
+
+
+uint16_t get_switch_debounce() {return sw.debounce;}
+
+
+void set_switch_lockout(uint16_t lockout) {
+ sw.lockout = SWITCH_MAX_LOCKOUT < lockout ? SWITCH_LOCKOUT : lockout;
+}
+
+
+uint16_t get_switch_lockout() {return sw.lockout;}
diff --git a/src/avr/src/switch.h b/src/avr/src/switch.h
new file mode 100644
index 0000000..fb3a9d7
--- /dev/null
+++ b/src/avr/src/switch.h
@@ -0,0 +1,72 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+
+#include "config.h"
+
+#include
+#include
+
+
+// macros for finding the index into the switch table give the axis number
+#define MIN_SWITCH(axis) ((switch_id_t)(2 + axis * 2))
+#define MAX_SWITCH(axis) ((switch_id_t)(2 + axis * 2 + 1))
+
+
+typedef enum {
+ SW_DISABLED,
+ SW_NORMALLY_OPEN,
+ SW_NORMALLY_CLOSED,
+} switch_type_t;
+
+
+/// Switch IDs
+typedef enum {
+ SW_INVALID = -1,
+ SW_ESTOP, SW_PROBE,
+ SW_MIN_0, SW_MAX_0,
+ SW_MIN_1, SW_MAX_1,
+ SW_MIN_2, SW_MAX_2,
+ SW_MIN_3, SW_MAX_3,
+ SW_STALL_0, SW_STALL_1,
+ SW_STALL_2, SW_STALL_3,
+ SW_MOTOR_FAULT,
+} switch_id_t;
+
+
+typedef void (*switch_callback_t)(switch_id_t sw, bool active);
+
+
+void switch_init();
+void switch_rtc_callback();
+bool switch_is_active(switch_id_t sw);
+bool switch_is_enabled(switch_id_t sw);
+switch_type_t switch_get_type(switch_id_t sw);
+void switch_set_type(switch_id_t sw, switch_type_t type);
+void switch_set_callback(switch_id_t sw, switch_callback_t cb);
diff --git a/src/avr/src/type.c b/src/avr/src/type.c
new file mode 100644
index 0000000..272e1f6
--- /dev/null
+++ b/src/avr/src/type.c
@@ -0,0 +1,216 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "type.h"
+#include "base64.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#define TYPEDEF(TYPE, DEF) \
+ static const char TYPE##_name [] PROGMEM = "<" #TYPE ">"; \
+ pstr type_get_##TYPE##_name_pgm() {return TYPE##_name;}
+
+#include "type.def"
+#undef TYPEDEF
+
+
+// String
+bool type_eq_str(str a, str b) {return a == b;}
+void type_print_str(str s) {printf_P(PSTR("\"%s\""), s);}
+str type_parse_str(const char *s, stat_t *) {return s;}
+
+// Program string
+bool type_eq_pstr(pstr a, pstr b) {return a == b;}
+void type_print_pstr(pstr s) {printf_P(PSTR("\"%" PRPSTR "\""), s);}
+const char *type_parse_pstr(const char *value, stat_t *) {return value;}
+
+
+// Float
+bool type_eq_f32(float a, float b) {return a == b || (isnan(a) && isnan(b));}
+
+
+void type_print_f32(float x) {
+ if (isnan(x)) printf_P(PSTR("\"nan\""));
+ else if (isinf(x)) printf_P(PSTR("\"%cinf\""), x < 0 ? '-' : '+');
+
+ else {
+ char buf[20];
+
+ int len = sprintf_P(buf, PSTR("%.3f"), x);
+
+ // Remove trailing zeros
+ for (int i = len; 0 < i; i--) {
+ if (buf[i - 1] == '.') buf[i - 1] = 0;
+ else if (buf[i - 1] == '0') {
+ buf[i - 1] = 0;
+ continue;
+ }
+
+ break;
+ }
+
+ printf(buf);
+ }
+}
+
+
+float type_parse_f32(const char *value, stat_t *status) {
+ while (*value && isspace(*value)) value++;
+
+ if (*value == ':') {
+ value++;
+ if (strnlen(value, 6) != 6) {
+ if (status) *status = STAT_INVALID_VALUE;
+ return NAN;
+ }
+
+ float f;
+ if (b64_decode_float(value, &f)) return f;
+ else {
+ if (status) *status = STAT_BAD_FLOAT;
+ return NAN;
+ }
+ }
+
+ char *endptr = 0;
+ float x = strtod(value, &endptr);
+
+ if (endptr == value) {
+ if (status) *status = STAT_BAD_FLOAT;
+ return NAN;
+ }
+
+ return x;
+}
+
+
+// bool
+bool type_eq_b8(bool a, bool b) {return a == b;}
+void type_print_b8(bool x) {printf_P(x ? PSTR("true") : PSTR("false"));}
+
+
+bool type_parse_b8(const char *value, stat_t *status) {
+ return !strcasecmp(value, "true") || type_parse_f32(value, status);
+}
+
+
+// s8
+bool type_eq_s8(s8 a, s8 b) {return a == b;}
+void type_print_s8(s8 x) {printf_P(PSTR("%" PRIi8), x);}
+
+
+s8 type_parse_s8(const char *value, stat_t *status) {
+ char *endptr = 0;
+ s8 x = strtol(value, &endptr, 0);
+ if (endptr == value && status) *status = STAT_BAD_INT;
+ return x;
+}
+
+
+// u8
+bool type_eq_u8(u8 a, u8 b) {return a == b;}
+void type_print_u8(u8 x) {printf_P(PSTR("%" PRIu8), x);}
+
+
+u8 type_parse_u8(const char *value, stat_t *status) {
+ char *endptr = 0;
+ u8 x = strtoul(value, &endptr, 0);
+ if (endptr == value && status) *status = STAT_BAD_INT;
+ return x;
+}
+
+
+// u16
+bool type_eq_u16(u16 a, u16 b) {return a == b;}
+void type_print_u16(u16 x) {printf_P(PSTR("%" PRIu16), x);}
+
+
+u16 type_parse_u16(const char *value, stat_t *status) {
+ char *endptr = 0;
+ u16 x = strtoul(value, &endptr, 0);
+ if (endptr == value && status) *status = STAT_BAD_INT;
+ return x;
+}
+
+
+// s32
+bool type_eq_s32(s32 a, s32 b) {return a == b;}
+void type_print_s32(s32 x) {printf_P(PSTR("%" PRIi32), x);}
+
+
+s32 type_parse_s32(const char *value, stat_t *status) {
+ char *endptr = 0;
+ s32 x = strtol(value, &endptr, 0);
+ if (endptr == value && status) *status = STAT_BAD_INT;
+ return x;
+}
+
+
+// u32
+bool type_eq_u32(u32 a, u32 b) {return a == b;}
+void type_print_u32(u32 x) {printf_P(PSTR("%" PRIu32), x);}
+
+
+u32 type_parse_u32(const char *value, stat_t *status) {
+ char *endptr = 0;
+ u32 x = strtoul(value, &endptr, 0);
+ if (endptr == value && status) *status = STAT_BAD_INT;
+ return x;
+}
+
+
+type_u type_parse(type_t type, const char *s, stat_t *status) {
+ type_u value;
+
+ if (status) *status = STAT_OK;
+
+ switch (type) {
+#define TYPEDEF(TYPE, ...) \
+ case TYPE_##TYPE: value._##TYPE = type_parse_##TYPE(s, status); break;
+#include "type.def"
+#undef TYPEDEF
+ default: if (status) *status = STAT_INVALID_TYPE;
+ }
+
+ return value;
+}
+
+
+void type_print(type_t type, type_u value) {
+ switch (type) {
+#define TYPEDEF(TYPE, ...) \
+ case TYPE_##TYPE: type_print_##TYPE(value._##TYPE); break;
+#include "type.def"
+#undef TYPEDEF
+ }
+}
diff --git a/src/avr/src/type.def b/src/avr/src/type.def
new file mode 100644
index 0000000..5f350fa
--- /dev/null
+++ b/src/avr/src/type.def
@@ -0,0 +1,37 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+// TYPE DEF
+TYPEDEF(str, const char *)
+TYPEDEF(pstr, PGM_P)
+TYPEDEF(f32, float)
+TYPEDEF(u8, uint8_t)
+TYPEDEF(s8, int8_t)
+TYPEDEF(u16, uint16_t)
+TYPEDEF(s32, int32_t)
+TYPEDEF(u32, uint32_t)
+TYPEDEF(b8, bool)
diff --git a/src/avr/src/type.h b/src/avr/src/type.h
new file mode 100644
index 0000000..322ebd6
--- /dev/null
+++ b/src/avr/src/type.h
@@ -0,0 +1,67 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include "pgmspace.h"
+#include "status.h"
+
+#include
+#include
+
+
+// Define types
+#define TYPEDEF(TYPE, DEF) typedef DEF TYPE;
+#include "type.def"
+#undef TYPEDEF
+
+typedef enum {
+#define TYPEDEF(TYPE, ...) TYPE_##TYPE,
+#include "type.def"
+#undef TYPEDEF
+} type_t;
+
+
+typedef union {
+#define TYPEDEF(TYPE, ...) TYPE _##TYPE;
+#include "type.def"
+#undef TYPEDEF
+} type_u;
+
+
+// Define functions
+#define TYPEDEF(TYPE, DEF) \
+ pstr type_get_##TYPE##_name_pgm(); \
+ bool type_eq_##TYPE(TYPE a, TYPE b); \
+ TYPE type_parse_##TYPE(const char *s, stat_t *status); \
+ void type_print_##TYPE(TYPE x);
+#include "type.def"
+#undef TYPEDEF
+
+
+type_u type_parse(type_t type, const char *s, stat_t *status);
+void type_print(type_t type, type_u value);
diff --git a/src/avr/src/usart.c b/src/avr/src/usart.c
new file mode 100644
index 0000000..d035c0e
--- /dev/null
+++ b/src/avr/src/usart.c
@@ -0,0 +1,285 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "usart.h"
+#include "cpp_magic.h"
+#include "config.h"
+
+#include
+#include
+
+#include
+#include
+#include
+
+
+// Ring buffers
+#define RING_BUF_INDEX_TYPE volatile uint16_t
+#define RING_BUF_NAME tx_buf
+#define RING_BUF_SIZE USART_TX_RING_BUF_SIZE
+#define RING_BUF_ATOMIC_COPY 1
+#include "ringbuf.def"
+
+#define RING_BUF_INDEX_TYPE volatile uint16_t
+#define RING_BUF_NAME rx_buf
+#define RING_BUF_SIZE USART_RX_RING_BUF_SIZE
+#define RING_BUF_ATOMIC_COPY 1
+#include "ringbuf.def"
+
+static bool _flush = false;
+
+
+static void _set_dre_interrupt(bool enable) {
+ if (enable) SERIAL_PORT.CTRLA |= USART_DREINTLVL_MED_gc;
+ else SERIAL_PORT.CTRLA &= ~USART_DREINTLVL_MED_gc;
+}
+
+
+static void _set_rxc_interrupt(bool enable) {
+ if (enable) {
+ if (SERIAL_CTS_THRESH <= rx_buf_space())
+ OUTCLR_PIN(SERIAL_CTS_PIN); // CTS Lo (enable)
+
+ SERIAL_PORT.CTRLA |= USART_RXCINTLVL_HI_gc;
+
+ } else SERIAL_PORT.CTRLA &= ~USART_RXCINTLVL_HI_gc;
+}
+
+
+// Data register empty interrupt vector
+ISR(SERIAL_DRE_vect) {
+ if (tx_buf_empty()) _set_dre_interrupt(false); // Disable interrupt
+
+ else {
+ SERIAL_PORT.DATA = tx_buf_peek();
+ tx_buf_pop();
+ }
+}
+
+
+// Data received interrupt vector
+ISR(SERIAL_RXC_vect) {
+ if (rx_buf_full()) _set_rxc_interrupt(false); // Disable interrupt
+ else rx_buf_push(SERIAL_PORT.DATA);
+
+ if (rx_buf_space() < SERIAL_CTS_THRESH)
+ OUTSET_PIN(SERIAL_CTS_PIN); // CTS Hi (disable)
+}
+
+
+#ifdef __AVR__
+static int _usart_putchar(char c, FILE *f) {
+ usart_putc(c);
+ return 0;
+}
+#endif // __AVR__
+
+
+static void _set_baud(USART_t *port, uint16_t bsel, uint8_t bscale) {
+ port->BAUDCTRLB = (uint8_t)((bscale << 4) | (bsel >> 8));
+ port->BAUDCTRLA = bsel;
+ port->CTRLB |= USART_CLK2X_bm;
+}
+
+
+void usart_set_baud(USART_t *port, baud_t baud) {
+ // The BSEL / BSCALE values provided below assume a 32 Mhz clock
+ // With CTRLB CLK2X is set
+ // See http://www.avrcalc.elektronik-projekt.de/xmega/baud_rate_calculator
+
+ switch (baud) {
+ case USART_BAUD_9600: _set_baud(port, 3325, 0b1101); break;
+ case USART_BAUD_19200: _set_baud(port, 3317, 0b1100); break;
+ case USART_BAUD_38400: _set_baud(port, 3301, 0b1011); break;
+ case USART_BAUD_57600: _set_baud(port, 1095, 0b1100); break;
+ case USART_BAUD_115200: _set_baud(port, 1079, 0b1011); break;
+ case USART_BAUD_230400: _set_baud(port, 1047, 0b1010); break;
+ case USART_BAUD_460800: _set_baud(port, 983, 0b1001); break;
+ case USART_BAUD_921600: _set_baud(port, 107, 0b1011); break;
+ case USART_BAUD_500000: _set_baud(port, 1, 0b0010); break;
+ case USART_BAUD_1000000: _set_baud(port, 1, 0b0001); break;
+ }
+}
+
+
+void usart_set_parity(USART_t *port, parity_t parity) {
+ uint8_t reg = port->CTRLC & ~USART_PMODE_gm;
+
+ switch (parity) {
+ case USART_NONE: reg |= USART_PMODE_DISABLED_gc; break;
+ case USART_EVEN: reg |= USART_PMODE_EVEN_gc; break;
+ case USART_ODD: reg |= USART_PMODE_ODD_gc; break;
+ }
+
+ port->CTRLC = reg;
+}
+
+
+void usart_set_stop(USART_t *port, stop_t stop) {
+ switch (stop) {
+ case USART_1STOP: port->CTRLC &= ~USART_SBMODE_bm; break;
+ case USART_2STOP: port->CTRLC |= USART_SBMODE_bm; break;
+ }
+}
+
+
+void usart_set_bits(USART_t *port, bits_t bits) {
+ uint8_t reg = port->CTRLC & ~USART_CHSIZE_gm;
+
+ switch (bits) {
+ case USART_5BITS: reg |= USART_CHSIZE_5BIT_gc; break;
+ case USART_6BITS: reg |= USART_CHSIZE_6BIT_gc; break;
+ case USART_7BITS: reg |= USART_CHSIZE_7BIT_gc; break;
+ case USART_8BITS: reg |= USART_CHSIZE_8BIT_gc; break;
+ case USART_9BITS: reg |= USART_CHSIZE_9BIT_gc; break;
+ }
+
+ port->CTRLC = reg;
+}
+
+
+void usart_init_port(USART_t *port, baud_t baud, parity_t parity, bits_t bits,
+ stop_t stop) {
+ // Set baud rate
+ usart_set_baud(port, baud);
+
+ // Async, no parity, 8 data bits, 1 stop bit
+ port->CTRLC = USART_CMODE_ASYNCHRONOUS_gc;
+ usart_set_parity(port, parity);
+ usart_set_bits(port, bits);
+ usart_set_stop(port, stop);
+
+ // Configure receiver and transmitter
+ port->CTRLB |= USART_RXEN_bm | USART_TXEN_bm;
+}
+
+
+void usart_init() {
+ // Setup ring buffer
+ tx_buf_init();
+ rx_buf_init();
+
+ PR.PRPC &= ~PR_USART0_bm; // Disable power reduction
+
+ // Setup pins
+ OUTSET_PIN(SERIAL_CTS_PIN); // CTS Hi (disable)
+ DIRSET_PIN(SERIAL_CTS_PIN); // CTS Output
+ OUTSET_PIN(SERIAL_TX_PIN); // Tx High
+ DIRSET_PIN(SERIAL_TX_PIN); // Tx Output
+ DIRCLR_PIN(SERIAL_RX_PIN); // Rx Input
+
+ // Configure port
+ usart_init_port(&SERIAL_PORT, SERIAL_BAUD, USART_NONE, USART_8BITS,
+ USART_1STOP);
+
+ PMIC.CTRL |= PMIC_HILVLEN_bm; // Interrupt level on
+
+#ifdef __AVR__
+ // Connect IO
+ static FILE _stdout;
+ memset(&_stdout, 0, sizeof(FILE));
+ _stdout.put = _usart_putchar;
+ _stdout.flags = _FDEV_SETUP_WRITE;
+
+ stdout = &_stdout;
+ stderr = &_stdout;
+#endif // __AVR__
+
+ // Enable Rx
+ _set_rxc_interrupt(true);
+}
+
+
+
+void usart_putc(char c) {
+ while (tx_buf_full() || _flush) continue;
+ tx_buf_push(c);
+ _set_dre_interrupt(true); // Enable interrupt
+}
+
+
+void usart_puts(const char *s) {while (*s) usart_putc(*s++);}
+
+
+int8_t usart_getc() {
+ while (rx_buf_empty()) continue;
+ uint8_t data = rx_buf_next();
+ _set_rxc_interrupt(true); // Enable interrupt
+ return data;
+}
+
+
+/*** Line editing features:
+ *
+ * ENTER Submit current command line.
+ * BS Backspace, delete last character.
+ * CTRL-X Cancel current line entry.
+ */
+char *usart_readline() {
+ static char line[INPUT_BUFFER_LEN];
+ static int i = 0;
+ bool eol = false;
+
+ while (!rx_buf_empty()) {
+ char data = usart_getc();
+
+ switch (data) {
+ case '\r': case '\n': eol = true; break;
+ case '\b': if (i) i--; break; // BS - backspace
+ case 0x18: i = 0; break; // CAN - Cancel or CTRL-X
+
+ default:
+ line[i++] = data;
+ if (i == INPUT_BUFFER_LEN - 1) eol = true; // Line buffer full
+ break;
+ }
+
+ if (eol) {
+ line[i] = 0;
+ i = 0;
+ return line;
+ }
+ }
+
+ return 0;
+}
+
+
+void usart_flush() {
+ _flush = true;
+
+ while (!tx_buf_empty() || !(SERIAL_PORT.STATUS & USART_DREIF_bm) ||
+ !(SERIAL_PORT.STATUS & USART_TXCIF_bm))
+ continue;
+}
+
+
+void usart_rx_flush() {rx_buf_init();}
+int16_t usart_rx_space() {return rx_buf_space();}
+int16_t usart_rx_fill() {return rx_buf_fill();}
+int16_t usart_tx_space() {return tx_buf_space();}
+int16_t usart_tx_fill() {return tx_buf_fill();}
diff --git a/src/avr/src/usart.h b/src/avr/src/usart.h
new file mode 100644
index 0000000..b59f4ed
--- /dev/null
+++ b/src/avr/src/usart.h
@@ -0,0 +1,100 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#pragma once
+
+#include
+
+#include
+#include
+
+
+// NOTE, RING_BUF_INDEX_TYPE must be be large enough to cover the buffer
+#define USART_TX_RING_BUF_SIZE 1024
+#define USART_RX_RING_BUF_SIZE 1024
+
+
+typedef enum {
+ USART_BAUD_9600,
+ USART_BAUD_19200,
+ USART_BAUD_38400,
+ USART_BAUD_57600,
+ USART_BAUD_115200,
+ USART_BAUD_230400,
+ USART_BAUD_460800,
+ USART_BAUD_921600,
+ USART_BAUD_500000,
+ USART_BAUD_1000000
+} baud_t;
+
+
+typedef enum {
+ USART_NONE,
+ USART_EVEN,
+ USART_ODD,
+} parity_t;
+
+
+typedef enum {
+ USART_1STOP,
+ USART_2STOP,
+} stop_t;
+
+
+typedef enum {
+ USART_5BITS,
+ USART_6BITS,
+ USART_7BITS,
+ USART_8BITS,
+ USART_9BITS,
+} bits_t;
+
+
+void usart_set_baud(USART_t *port, baud_t baud);
+void usart_set_parity(USART_t *port, parity_t parity);
+void usart_set_stop(USART_t *port, stop_t stop);
+void usart_set_bits(USART_t *port, bits_t bits);
+void usart_init_port(USART_t *port, baud_t baud, parity_t parity, bits_t bits,
+ stop_t stop);
+
+void usart_init();
+void usart_putc(char c);
+void usart_puts(const char *s);
+int8_t usart_getc();
+char *usart_readline();
+void usart_flush();
+
+void usart_rx_flush();
+int16_t usart_rx_fill();
+int16_t usart_rx_space();
+inline bool usart_rx_empty() {return !usart_rx_fill();}
+inline bool usart_rx_full() {return !usart_rx_space();}
+
+int16_t usart_tx_fill();
+int16_t usart_tx_space();
+inline bool usart_tx_empty() {return !usart_tx_fill();}
+inline bool usart_tx_full() {return !usart_tx_space();}
diff --git a/src/avr/src/util.c b/src/avr/src/util.c
new file mode 100644
index 0000000..61137fe
--- /dev/null
+++ b/src/avr/src/util.c
@@ -0,0 +1,95 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see .
+
+ The software 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 the software. If not, see
+ .
+
+ For information regarding this software email:
+ "Joseph Coffland"
+
+\******************************************************************************/
+
+#include "util.h"
+
+#include "base64.h"
+
+#include
+#include
+#include
+#include
+
+
+/// Fast inverse square root originally from Quake III Arena code. Original
+/// comments left intact.
+/// See: https://en.wikipedia.org/wiki/Fast_inverse_square_root
+float invsqrt(float x) {
+ // evil floating point bit level hacking
+ union {
+ float f;
+ int32_t i;
+ } u;
+
+ const float xhalf = x * 0.5f;
+ u.f = x;
+ u.i = 0x5f3759df - (u.i >> 1); // what the fuck?
+ u.f = u.f * (1.5f - xhalf * u.f * u.f); // 1st iteration
+ u.f = u.f * (1.5f - xhalf * u.f * u.f); // 2nd iteration, can be removed
+
+ return u.f;
+}
+
+
+int8_t decode_hex_nibble(char c) {
+ if ('0' <= c && c <= '9') return c - '0';
+ if ('a' <= c && c <= 'f') return c - 'a' + 10;
+ if ('A' <= c && c <= 'F') return c - 'A' + 10;
+ return -1;
+}
+
+
+bool decode_float(char **s, float *f) {
+ bool ok = b64_decode_float(*s, f) && isfinite(*f);
+ *s += 6;
+ return ok;
+}
+
+
+stat_t decode_axes(char **cmd, float axes[AXES]) {
+ while (**cmd) {
+ const char *names = "xyzabc";
+ const char *match = strchr(names, **cmd);
+ if (!match) break;
+ char *s = *cmd + 1;
+ if (!decode_float(&s, &axes[match - names])) return STAT_BAD_FLOAT;
+ *cmd = s;
+ }
+
+ return STAT_OK;
+}
+
+
+// Assumes the caller provide format buffer length is @param len * 2 + 1.
+void format_hex_buf(char *buf, const uint8_t *data, unsigned len) {
+ uint8_t i;
+
+ for (i = 0; i < len; i++)
+ sprintf(buf + i * 2, "%02x", data[i]);
+
+ buf[i * 2] = 0;
+}
diff --git a/src/avr/src/util.h b/src/avr/src/util.h
new file mode 100644
index 0000000..300fb1a
--- /dev/null
+++ b/src/avr/src/util.h
@@ -0,0 +1,85 @@
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2018, Buildbotics LLC
+ All rights reserved.
+
+ This file ("the software") is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License,
+ version 2 as published by the Free Software Foundation. You should
+ have received a copy of the GNU General Public License, version 2
+ along with the software. If not, see