diff --git a/src/ASF/sam0/drivers/adc/adc.h b/src/ASF/sam0/drivers/adc/adc.h
new file mode 100644
index 0000000000000000000000000000000000000000..1236203e7b2f37911111231b3510ef6f084f7283
--- /dev/null
+++ b/src/ASF/sam0/drivers/adc/adc.h
@@ -0,0 +1,1147 @@
+/**
+ * \file
+ *
+ * \brief SAM Peripheral Analog-to-Digital Converter Driver
+ *
+ * Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+#ifndef ADC_H_INCLUDED
+#define ADC_H_INCLUDED
+
+/**
+ * \defgroup asfdoc_sam0_adc_group SAM Analog-to-Digital Converter (ADC) Driver
+ *
+ * This driver for Atmel&reg; | SMART ARM&reg;-based microcontrollers provides an interface for the configuration
+ * and management of the device's Analog-to-Digital Converter functionality, for
+ * the conversion of analog voltages into a corresponding digital form.
+ * The following driver Application Programming Interface (API) modes are covered by this manual:
+ * - Polled APIs
+ * \if ADC_CALLBACK_MODE
+ * - Callback APIs
+ * \endif
+ *
+ * The following peripheral is used by this module:
+ *  - ADC (Analog-to-Digital Converter)
+ *
+ * The following devices can use this module:
+ * \if DEVICE_SAML21_SUPPORT
+ *  - Atmel | SMART SAM L21/L22
+ *  - Atmel | SMART SAM C20/C21
+ *  - Atmel | SMART SAM R34/R35
+ * \else
+ *  - Atmel | SMART SAM D20/D21
+ *  - Atmel | SMART SAM R21
+ *  - Atmel | SMART SAM D09/D10/D11
+ *  - Atmel | SMART SAM DA1
+ *  - Atmel | SMART SAM HA1
+ * \endif
+ *
+ * The outline of this documentation is as follows:
+ *  - \ref asfdoc_sam0_adc_prerequisites
+ *  - \ref asfdoc_sam0_adc_module_overview
+ *  - \ref asfdoc_sam0_adc_special_considerations
+ *  - \ref asfdoc_sam0_adc_extra_info
+ *  - \ref asfdoc_sam0_adc_examples
+ *  - \ref asfdoc_sam0_adc_api_overview
+ *
+ *
+ * \section asfdoc_sam0_adc_prerequisites Prerequisites
+ *
+ * There are no prerequisites for this module.
+ *
+ *
+ * \section asfdoc_sam0_adc_module_overview Module Overview
+ *
+ * This driver provides an interface for the Analog-to-Digital conversion
+ * functions on the device, to convert analog voltages to a corresponding
+ * digital value. The ADC has up to 12-bit resolution, and is capable of
+ * \if DEVICE_SAML21_SUPPORT
+ * converting up to 1,000,000 samples per second (MSPS).
+ * \else
+ * converting up to 500K samples per second (KSPS).
+ * \endif
+ *
+ * The ADC has a compare function for accurate monitoring of user defined
+ * thresholds with minimum software intervention required.
+ * The ADC may be configured for 8-, 10-, or 12-bit result, reducing the
+ * conversion time. ADC conversion results are provided left or right adjusted
+ * which eases calculation when the result is represented as a signed integer.
+ *
+ * The input selection is flexible, and both single-ended and differential
+ * measurements can be made. For differential measurements, an optional gain
+ * stage is available to increase the dynamic range. In addition, several
+ * internal signal inputs are available. The ADC can provide both signed and
+ * unsigned results.
+ *
+ * The ADC measurements can either be started by application software or an
+ * incoming event from another peripheral in the device, and both internal and
+ * external reference voltages can be selected.
+ *
+ * \note Internal references will be enabled by the driver, but not disabled.
+ *       Any reference not used by the application should be disabled by the application.
+ *
+ * A simplified block diagram of the ADC can be seen in
+ * \ref asfdoc_sam0_adc_module_block_diagram "the figure below".
+ *
+ * \anchor asfdoc_sam0_adc_module_block_diagram
+ * \dot
+ * digraph overview {
+ * splines = false;
+ * rankdir=LR;
+ *
+ * mux1 [label="Positive input", shape=box];
+ * mux2 [label="Negative input", shape=box];
+ *
+ *
+ * mux3 [label="Reference", shape=box];
+ *
+ * adc [label="ADC", shape=polygon, sides=5, orientation=90, distortion=-0.6, style=filled, fillcolor=darkolivegreen1, height=1, width=1];
+ * prescaler [label="PRESCALER", shape=box, style=filled, fillcolor=lightblue];
+ *
+ * mux1 -> adc;
+ * mux2 -> adc;
+ * mux3 -> adc:sw;
+ * prescaler -> adc;
+ *
+ * postproc [label="Post processing", shape=box];
+ * result [label="RESULT", shape=box, style=filled, fillcolor=lightblue];
+ *
+ * adc:e -> postproc:w;
+ * postproc:e -> result:w;
+ *
+ * {rank=same; mux1 mux2}
+ * {rank=same; prescaler adc}
+ *
+ * }
+ * \enddot
+ *
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_prescaler Sample Clock Prescaler
+ * The ADC features a prescaler, which enables conversion at lower clock rates
+ * than the input Generic Clock to the ADC module. This feature can be used to
+ * lower the synchronization time of the digital interface to the ADC module
+ * via a high speed Generic Clock frequency, while still allowing the ADC
+ * sampling rate to be reduced.
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_resolution ADC Resolution
+ * The ADC supports full 8-, 10-, or 12-bit resolution. Hardware
+ * oversampling and decimation can be used to increase the
+ * effective resolution at the expense of throughput. Using oversampling and
+ * decimation mode the ADC resolution is increased from 12-bit to an effective
+ * 13-, 14-, 15-, or 16-bit. In these modes the conversion rate is reduced, as
+ * a greater number of samples is used to achieve the increased resolution. The
+ * available resolutions and effective conversion rate is listed in
+ * \ref asfdoc_sam0_adc_module_conversion_rate "the table below".
+ *
+ * \anchor asfdoc_sam0_adc_module_conversion_rate
+ * <table>
+ *	<caption>Effective ADC Conversion Speed Using Oversampling</caption>
+ *	<tr>
+ *		<th>Resolution</th>
+ *		<th>Effective conversion rate</th>
+ *	</tr>
+ *	<tr>
+ *		<td>13-bit</td>
+ *		<td>Conversion rate divided by 4</td>
+ *	</tr>
+ *	<tr>
+ *		<td>14-bit</td>
+ *		<td>Conversion rate divided by 16</td>
+ *	</tr>
+ *	<tr>
+ *		<td>15-bit</td>
+ *		<td>Conversion rate divided by 64</td>
+ *	</tr>
+ *	<tr>
+ *		<td>16-bit</td>
+ *		<td>Conversion rate divided by 256</td>
+ *	</tr>
+ * </table>
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_conversion Conversion Modes
+ * ADC conversions can be software triggered on demand by the user application,
+ * if continuous sampling is not required. It is also possible to configure the
+ * ADC in free running mode, where new conversions are started as soon as the
+ * previous conversion is completed, or configure the ADC to scan across a
+ * number of input pins (see \ref asfdoc_sam0_adc_module_overview_pin_scan).
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_diff_mode Differential and Single-ended Conversion
+ * The ADC has two conversion modes; differential and single-ended. When
+ * measuring signals where the positive input pin is always at a higher voltage
+ * than the negative input pin, the single-ended conversion mode should be used
+ * in order to achieve a full 12-bit output resolution.
+ *
+ * If however the positive input pin voltage may drop below the negative input
+ * pin the signed differential mode should be used.
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_sample_time Sample Time
+ * The sample time for each ADC conversion is configurable as a number of half
+ * prescaled ADC clock cycles (depending on the prescaler value), allowing the
+ * user application to achieve faster or slower sampling depending on the
+ * source impedance of the ADC input channels. For applications with high
+ * impedance inputs the sample time can be increased to give the ADC an adequate
+ * time to sample and convert the input channel.
+ *
+ * The resulting sampling time is given by the following equation:
+ * \f[
+ * t_{SAMPLE} = (sample\_length+1) \times \frac{ADC_{CLK}} {2}
+ * \f]
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_averaging Averaging
+ * The ADC can be configured to trade conversion speed for accuracy by averaging
+ * multiple samples in hardware. This feature is suitable when operating in
+ * noisy conditions.
+ *
+ * You can specify any number of samples to accumulate (up to 1024) and the
+ * divide ratio to use (up to divide by 128). To modify these settings the
+ * ADC_RESOLUTION_CUSTOM needs to be set as the resolution. When this is set
+ * the number of samples to accumulate and the division ratio can be set by
+ * the configuration struct members \ref adc_config.accumulate_samples and
+ * \ref adc_config.divide_result. When using this mode the ADC result register
+ * will be set to be 16-bit wide to accommodate the larger result sizes
+ * produced by the accumulator.
+ *
+ * The effective ADC conversion rate will be reduced by a factor of the number
+ * of accumulated samples;
+ * however, the effective resolution will be increased according to
+ * \ref asfdoc_sam0_adc_module_hw_av_resolution "the table below".
+ *
+ * \anchor asfdoc_sam0_adc_module_hw_av_resolution
+ * <table>
+ *   <caption>Effective ADC Resolution From Various Hardware Averaging Modes</caption>
+ *   <tr>
+ *     <th>Number of samples</tr>
+ *     <th>Final result</tr>
+ *   </tr>
+ *   <tr>
+ *     <td>1</td>
+ *     <td>12-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>2</td>
+ *      <td>13-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>4</td>
+ *      <td>14-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>8</td>
+ *      <td>15-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>16</td>
+ *      <td>16-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>32</td>
+ *      <td>16-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>64</td>
+ *      <td>16-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>128</td>
+ *      <td>16-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>256</td>
+ *      <td>16-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>512</td>
+ *      <td>16-bit</td>
+ *   </tr>
+ *   <tr>
+ *      <td>1024</td>
+ *      <td>16-bit</td>
+ *   </tr>
+ * </table>
+ *
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_offset_corr Offset and Gain Correction
+ * Inherent gain and offset errors affect the absolute accuracy of the ADC.
+ *
+ * The offset error is defined as the deviation of the ADC's actual transfer
+ * function from ideal straight line at zero input voltage.
+ *
+ * The gain error is defined as the deviation of the last output step's
+ * midpoint from the ideal straight line, after compensating for offset error.
+ *
+ * The offset correction value is subtracted from the converted data before the
+ * result is ready. The gain correction value is multiplied with the offset
+ * corrected value.
+ *
+ * The equation for both offset and gain error compensation is shown below:
+ * \f[
+ * ADC_{RESULT} = (VALUE_{CONV} + CORR_{OFFSET}) \times CORR_{GAIN}
+ * \f]
+ *
+ * When enabled, a given set of offset and gain correction values can be applied
+ * to the sampled data in hardware, giving a corrected stream of sample data to
+ * the user application at the cost of an increased sample latency.
+ *
+ * In single conversion, a latency of 13 ADC Generic Clock cycles is added for
+ * the final sample result availability. As the correction time is always less
+ * than the propagation delay, in free running mode this latency appears only
+ * during the first conversion. After the first conversion is complete, future
+ * conversion results are available at the defined sampling rate.
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_pin_scan Pin Scan
+ * In pin scan mode, the first ADC conversion will begin from the configured
+ * positive channel, plus the requested starting offset. When the first
+ * conversion is completed, the next conversion will start at the next positive
+ * input channel and so on, until all requested pins to scan have been sampled
+ * and converted.
+ * SAM L21/L22 has automatic sequences feature instead of pin scan mode. In automatic
+ * sequence mode, all of 32 positives inputs can be included in a sequence. The
+ * sequence starts from the lowest input, and go to the next enabled input
+ * automatically.
+ *
+ * Pin scanning gives a simple mechanism to sample a large number of physical
+ * input channel samples, using a single physical ADC channel.
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_window_monitor Window Monitor
+ * The ADC module window monitor function can be used to automatically compare
+ * the conversion result against a preconfigured pair of upper and lower
+ * threshold values.
+ *
+ * The threshold values are evaluated differently, depending on whether
+ * differential or single-ended mode is selected. In differential mode, the
+ * upper and lower thresholds are evaluated as signed values for the comparison,
+ * while in single-ended mode the comparisons are made as a set of unsigned
+ * values.
+ *
+ * The significant bits of the lower window monitor threshold and upper window
+ * monitor threshold values are user-configurable, and follow the overall ADC
+ * sampling bit precision set when the ADC is configured by the user application.
+ * For example, only the eight lower bits of the window threshold values will be
+ * compared to the sampled data whilst the ADC is configured in 8-bit mode.
+ * In addition, if using differential mode, the 8<SUP>th</SUP> bit will be considered as
+ * the sign bit even if bit 9 is zero.
+ *
+ * \subsection asfdoc_sam0_adc_module_overview_events Events
+ * Event generation and event actions are configurable in the ADC.
+ *
+ * The ADC has two actions that can be triggered upon event reception:
+ * \li Start conversion
+ * \li Flush pipeline and start conversion
+ *
+ * The ADC can generate two events:
+ * \li Window monitor
+ * \li Result ready
+ *
+ * If the event actions are enabled in the configuration, any incoming event
+ * will trigger the action.
+ *
+ * If the window monitor event is enabled, an event will be generated
+ * when the configured window condition is detected.
+ *
+ * If the result ready event is enabled, an event will be generated when a
+ * conversion is completed.
+ *
+ * \note The connection of events between modules requires the use of the
+ *       \ref asfdoc_sam0_events_group "SAM Event System Driver (EVENTS)"
+ *       to route output event of one module to the input event of another.
+ *       For more information on event routing, refer to the event driver
+ *       documentation.
+ *
+ *
+ * \section asfdoc_sam0_adc_special_considerations Special Considerations
+ *
+ * An integrated analog temperature sensor is available for use with the ADC.
+ * The bandgap voltage, as well as the scaled I/O and core voltages can also be
+ * measured by the ADC. For internal ADC inputs, the internal source(s) may need
+ * to be manually enabled by the user application before they can be measured.
+ *
+ *
+ * \section asfdoc_sam0_adc_extra_info Extra Information
+ *
+ * For extra information, see \ref asfdoc_sam0_adc_extra. This includes:
+ *  - \ref asfdoc_sam0_adc_extra_acronyms
+ *  - \ref asfdoc_sam0_adc_extra_dependencies
+ *  - \ref asfdoc_sam0_adc_extra_errata
+ *  - \ref asfdoc_sam0_adc_extra_history
+ *
+ *
+ * \section asfdoc_sam0_adc_examples Examples
+ *
+ * For a list of examples related to this driver, see
+ * \ref asfdoc_sam0_adc_exqsg.
+ *
+ *
+ * \section asfdoc_sam0_adc_api_overview API Overview
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <compiler.h>
+#include <system.h>
+#include <adc_feature.h>
+
+/**
+ * \name Module Status Flags
+ *
+ * ADC status flags, returned by \ref adc_get_status() and cleared by
+ * \ref adc_clear_status().
+ *
+ * @{
+ */
+
+/** ADC result ready. */
+#define ADC_STATUS_RESULT_READY  (1UL << 0)
+/** Window monitor match. */
+#define ADC_STATUS_WINDOW        (1UL << 1)
+/** ADC result overwritten before read. */
+#define ADC_STATUS_OVERRUN       (1UL << 2)
+
+/** @} */
+
+#if ADC_CALLBACK_MODE == true
+#   if (ADC_INST_NUM > 1)
+#       define _ADC_INTERRUPT_VECT_NUM(n, unused) \
+			SYSTEM_INTERRUPT_MODULE_ADC##n,
+/**
+ * \internal Get the interrupt vector for the given device instance
+ *
+ * \param[in] The ADC module instance number
+ *
+ * \return Interrupt vector for of the given ADC module instance.
+ */
+static enum system_interrupt_vector _adc_interrupt_get_interrupt_vector(
+		uint32_t inst_num)
+{
+	static uint8_t adc_interrupt_vectors[ADC_INST_NUM] = {
+		MREPEAT(ADC_INST_NUM, _ADC_INTERRUPT_VECT_NUM, 0)
+	};
+
+	return (enum system_interrupt_vector)adc_interrupt_vectors[inst_num];
+}
+#   endif
+#endif
+
+#if !defined(__DOXYGEN__)
+uint8_t _adc_get_inst_index(
+		Adc *const hw);
+#endif
+
+/**
+ * \name Driver Initialization and Configuration
+ * @{
+ */
+enum status_code adc_init(
+		struct adc_module *const module_inst,
+		Adc *hw,
+		struct adc_config *config);
+
+void adc_get_config_defaults(
+		struct adc_config *const config);
+
+#if (SAMD) || (SAMHA1) || (SAMHA0) || (SAMR21)
+void adc_regular_ain_channel(
+		uint32_t *pin_array, uint8_t size);
+#endif
+
+/** @} */
+
+/**
+ * \name Status Management
+ * @{
+ */
+
+/**
+ * \brief Retrieves the current module status.
+ *
+ * Retrieves the status of the module, giving overall state information.
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ *
+ * \return Bitmask of \c ADC_STATUS_* flags.
+ *
+ * \retval ADC_STATUS_RESULT_READY  ADC result is ready to be read
+ * \retval ADC_STATUS_WINDOW        ADC has detected a value inside the set
+ *                                  window range
+ * \retval ADC_STATUS_OVERRUN       ADC result has overrun
+ */
+static inline uint32_t adc_get_status(
+		struct adc_module *const module_inst)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	uint32_t int_flags = adc_module->INTFLAG.reg;
+
+	uint32_t status_flags = 0;
+
+	/* Check for ADC Result Ready */
+	if (int_flags & ADC_INTFLAG_RESRDY) {
+		status_flags |= ADC_STATUS_RESULT_READY;
+	}
+
+	/* Check for ADC Window Match */
+	if (int_flags & ADC_INTFLAG_WINMON) {
+		status_flags |= ADC_STATUS_WINDOW;
+	}
+
+	/* Check for ADC Overrun */
+	if (int_flags & ADC_INTFLAG_OVERRUN) {
+		status_flags |= ADC_STATUS_OVERRUN;
+	}
+
+	return status_flags;
+}
+
+/**
+ * \brief Clears a module status flag.
+ *
+ * Clears the given status flag of the module.
+ *
+ * \param[in] module_inst   Pointer to the ADC software instance struct
+ * \param[in] status_flags  Bitmask of \c ADC_STATUS_* flags to clear
+ */
+static inline void adc_clear_status(
+		struct adc_module *const module_inst,
+		const uint32_t status_flags)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	uint32_t int_flags = 0;
+
+	/* Check for ADC Result Ready */
+	if (status_flags & ADC_STATUS_RESULT_READY) {
+		int_flags |= ADC_INTFLAG_RESRDY;
+	}
+
+	/* Check for ADC Window Match */
+	if (status_flags & ADC_STATUS_WINDOW) {
+		int_flags |= ADC_INTFLAG_WINMON;
+	}
+
+	/* Check for ADC Overrun */
+	if (status_flags & ADC_STATUS_OVERRUN) {
+		int_flags |= ADC_INTFLAG_OVERRUN;
+	}
+
+	/* Clear interrupt flag */
+	adc_module->INTFLAG.reg = int_flags;
+}
+/** @} */
+
+/**
+ * \name Enable, Disable, and Reset ADC Module, Start Conversion and Read Result
+ * @{
+ */
+
+/**
+ * \brief Enables the ADC module.
+ *
+ * Enables an ADC module that has previously been configured. If any internal reference
+ * is selected it will be enabled.
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ */
+static inline enum status_code adc_enable(
+		struct adc_module *const module_inst)
+{
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+#if ADC_CALLBACK_MODE == true
+#   if (ADC_INST_NUM > 1)
+	system_interrupt_enable(_adc_interrupt_get_interrupt_vector(
+			_adc_get_inst_index(adc_module)));
+#   elif (SAMC20)
+		system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_ADC0);
+#	else
+		system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_ADC);
+#   endif
+#endif
+
+	/* Disbale interrupt */
+	adc_module->INTENCLR.reg = ADC_INTENCLR_MASK;
+	/* Clear interrupt flag */
+	adc_module->INTFLAG.reg = ADC_INTFLAG_MASK;
+
+	adc_module->CTRLA.reg |= ADC_CTRLA_ENABLE;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+	return STATUS_OK;
+}
+
+/**
+ * \brief Disables the ADC module.
+ *
+ * Disables an ADC module that was previously enabled.
+ *
+ * \param[in] module_inst Pointer to the ADC software instance struct
+ */
+static inline enum status_code adc_disable(
+		struct adc_module *const module_inst)
+{
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+#if ADC_CALLBACK_MODE == true
+#   if (ADC_INST_NUM > 1)
+	system_interrupt_disable(_adc_interrupt_get_interrupt_vector(
+			_adc_get_inst_index(adc_module)));
+#   elif (SAMC20)
+		system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_ADC0);
+#	else
+		system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_ADC);
+#   endif
+#endif
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Disbale interrupt */
+	adc_module->INTENCLR.reg = ADC_INTENCLR_MASK;
+	/* Clear interrupt flag */
+	adc_module->INTFLAG.reg = ADC_INTFLAG_MASK;
+
+	adc_module->CTRLA.reg &= ~ADC_CTRLA_ENABLE;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+	return STATUS_OK;
+}
+
+/**
+ * \brief Resets the ADC module.
+ *
+ * Resets an ADC module, clearing all module state, and registers to their
+ * default values.
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ */
+static inline enum status_code adc_reset(
+		struct adc_module *const module_inst)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	/* Disable to make sure the pipeline is flushed before reset */
+	adc_disable(module_inst);
+
+	/* Software reset the module */
+	adc_module->CTRLA.reg |= ADC_CTRLA_SWRST;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+	return STATUS_OK;
+}
+
+
+/**
+ * \brief Enables an ADC event input or output.
+ *
+ *  Enables one or more input or output events to or from the ADC module. See
+ *  \ref adc_events "Struct adc_events" for a list of events this module supports.
+ *
+ *  \note Events cannot be altered while the module is enabled.
+ *
+ *  \param[in] module_inst  Software instance for the ADC peripheral
+ *  \param[in] events       Struct containing flags of events to enable
+ */
+static inline void adc_enable_events(
+		struct adc_module *const module_inst,
+		struct adc_events *const events)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+	Assert(events);
+
+	Adc *const adc_module = module_inst->hw;
+
+	uint32_t event_mask = 0;
+
+	/* Configure Window Monitor event */
+	if (events->generate_event_on_window_monitor) {
+		event_mask |= ADC_EVCTRL_WINMONEO;
+	}
+
+	/* Configure Result Ready event */
+	if (events->generate_event_on_conversion_done) {
+		event_mask |= ADC_EVCTRL_RESRDYEO;
+	}
+
+	adc_module->EVCTRL.reg |= event_mask;
+}
+
+/**
+ * \brief Disables an ADC event input or output.
+ *
+ *  Disables one or more input or output events to or from the ADC module. See
+ *  \ref adc_events "Struct adc_events" for a list of events this module supports.
+ *
+ *  \note Events cannot be altered while the module is enabled.
+ *
+ *  \param[in] module_inst  Software instance for the ADC peripheral
+ *  \param[in] events       Struct containing flags of events to disable
+ */
+static inline void adc_disable_events(
+		struct adc_module *const module_inst,
+		struct adc_events *const events)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+	Assert(events);
+
+	Adc *const adc_module = module_inst->hw;
+
+	uint32_t event_mask = 0;
+
+	/* Configure Window Monitor event */
+	if (events->generate_event_on_window_monitor) {
+		event_mask |= ADC_EVCTRL_WINMONEO;
+	}
+
+	/* Configure Result Ready event */
+	if (events->generate_event_on_conversion_done) {
+		event_mask |= ADC_EVCTRL_RESRDYEO;
+	}
+
+	adc_module->EVCTRL.reg &= ~event_mask;
+}
+
+/**
+ * \brief Starts an ADC conversion.
+ *
+ * Starts a new ADC conversion.
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ */
+static inline void adc_start_conversion(
+		struct adc_module *const module_inst)
+{
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	adc_module->SWTRIG.reg |= ADC_SWTRIG_START;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+}
+
+/**
+ * \brief Reads the ADC result.
+ *
+ * Reads the result from an ADC conversion that was previously started.
+ *
+ * \param[in]  module_inst  Pointer to the ADC software instance struct
+ * \param[out] result       Pointer to store the result value in
+ *
+ * \return Status of the ADC read request.
+ * \retval STATUS_OK           The result was retrieved successfully
+ * \retval STATUS_BUSY         A conversion result was not ready
+ * \retval STATUS_ERR_OVERFLOW The result register has been overwritten by the
+ *                             ADC module before the result was read by the software
+ */
+static inline enum status_code adc_read(
+		struct adc_module *const module_inst,
+		uint16_t *result)
+{
+	Assert(module_inst);
+	Assert(module_inst->hw);
+	Assert(result);
+
+	if (!(adc_get_status(module_inst) & ADC_STATUS_RESULT_READY)) {
+		/* Result not ready */
+		return STATUS_BUSY;
+	}
+
+	Adc *const adc_module = module_inst->hw;
+
+#if (SAMD) || (SAMHA1) || (SAMHA0) || (SAMR21)
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+#endif
+
+	/* Get ADC result */
+	*result = adc_module->RESULT.reg;
+
+	/* Reset ready flag */
+	adc_clear_status(module_inst, ADC_STATUS_RESULT_READY);
+
+	if (adc_get_status(module_inst) & ADC_STATUS_OVERRUN) {
+		adc_clear_status(module_inst, ADC_STATUS_OVERRUN);
+		return STATUS_ERR_OVERFLOW;
+	}
+
+	return STATUS_OK;
+}
+
+/** @} */
+
+/**
+ * \name Runtime Changes of ADC Module
+ * @{
+ */
+
+/**
+ * \brief Flushes the ADC pipeline.
+ *
+ * Flushes the pipeline and restarts the ADC clock on the next peripheral clock
+ * edge. All conversions in progress will be lost. When flush is complete, the
+ * module will resume where it left off.
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ */
+static inline void adc_flush(
+		struct adc_module *const module_inst)
+{
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	adc_module->SWTRIG.reg |= ADC_SWTRIG_FLUSH;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+}
+void adc_set_window_mode(
+		struct adc_module *const module_inst,
+		const enum adc_window_mode window_mode,
+		const int16_t window_lower_value,
+		const int16_t window_upper_value);
+
+/**
+ * \brief Sets positive ADC input pin.
+ *
+ * Sets the positive ADC input pin selection.
+ *
+ * \param[in] module_inst     Pointer to the ADC software instance struct
+ * \param[in] positive_input  Positive input pin
+ */
+static inline void adc_set_positive_input(
+		struct adc_module *const module_inst,
+		const enum adc_positive_input positive_input)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Set positive input pin */
+	adc_module->INPUTCTRL.reg =
+			(adc_module->INPUTCTRL.reg & ~ADC_INPUTCTRL_MUXPOS_Msk) |
+			(positive_input);
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+}
+
+
+/**
+ * \brief Sets negative ADC input pin for differential mode.
+ *
+ * Sets the negative ADC input pin, when the ADC is configured in differential
+ * mode.
+ *
+ * \param[in] module_inst     Pointer to the ADC software instance struct
+ * \param[in] negative_input  Negative input pin
+ */
+static inline void adc_set_negative_input(
+		struct adc_module *const module_inst,
+		const enum adc_negative_input negative_input)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Set negative input pin */
+	adc_module->INPUTCTRL.reg =
+			(adc_module->INPUTCTRL.reg & ~ADC_INPUTCTRL_MUXNEG_Msk) |
+			(negative_input);
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+}
+
+/** @} */
+
+#if ADC_CALLBACK_MODE == true
+/**
+ * \name Enable and Disable Interrupts
+ * @{
+ */
+
+/**
+ * \brief Enable interrupt.
+ *
+ * Enable the given interrupt request from the ADC module.
+ *
+ * \param[in] module_inst Pointer to the ADC software instance struct
+ * \param[in] interrupt Interrupt to enable
+ */
+static inline void adc_enable_interrupt(struct adc_module *const module_inst,
+		enum adc_interrupt_flag interrupt)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+	/* Enable interrupt */
+	adc_module->INTENSET.reg = interrupt;
+}
+
+/**
+ * \brief Disable interrupt.
+ *
+ * Disable the given interrupt request from the ADC module.
+ *
+ * \param[in] module_inst Pointer to the ADC software instance struct
+ * \param[in] interrupt Interrupt to disable
+ */
+static inline void adc_disable_interrupt(struct adc_module *const module_inst,
+		enum adc_interrupt_flag interrupt)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+	/* Enable interrupt */
+	adc_module->INTENCLR.reg = interrupt;
+}
+
+/** @} */
+#endif /* ADC_CALLBACK_MODE == true */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+
+/**
+ * \page asfdoc_sam0_adc_extra Extra Information for ADC Driver
+ *
+ * \section asfdoc_sam0_adc_extra_acronyms Acronyms
+ * Below is a table listing the acronyms used in this module, along with their
+ * intended meanings.
+ *
+ * <table>
+ *	<tr>
+ *		<th>Acronym</th>
+ *		<th>Description</th>
+ *	</tr>
+ *  <tr>
+ *		<td>ADC</td>
+ *		<td>Analog-to-Digital Converter</td>
+ *	</tr>
+ *  <tr>
+ *		<td>DAC</td>
+ *		<td>Digital-to-Analog Converter</td>
+ *	</tr>
+ *	<tr>
+ *		<td>LSB</td>
+ *		<td>Least Significant Bit</td>
+ *	</tr>
+ *	<tr>
+ *		<td>MSB</td>
+ *		<td>Most Significant Bit</td>
+ *	</tr>
+ *	<tr>
+ *		<td>DMA</td>
+ *		<td>Direct Memory Access</td>
+ *	</tr>
+ * </table>
+ *
+ *
+ * \section asfdoc_sam0_adc_extra_dependencies Dependencies
+ * This driver has the following dependencies:
+ *
+ *  - \ref asfdoc_sam0_system_pinmux_group "System Pin Multiplexer Driver"
+ *
+ *
+ * \section asfdoc_sam0_adc_extra_errata Errata
+ * There are no errata related to this driver.
+ *
+ *
+ * \section asfdoc_sam0_adc_extra_history Module History
+ * An overview of the module history is presented in the table below, with
+ * details on the enhancements and fixes made to the module since its first
+ * release. The current version of this corresponds to the newest version in
+ * the table.
+ *
+ * <table>
+ *	<tr>
+ *		<th>Changelog</th>
+ *	</tr>
+ * \if DEVICE_SAML21_SUPPORT
+ *  <tr>
+ *		<td>Initial Release</td>
+ * </tr>
+ * \else
+ *	<tr>
+ *		<td>Added support for SAM R21</td>
+ *	</tr>
+ *	<tr>
+ *		<td>Added support for SAM D21 and new DMA quick start guide</td>
+ *	</tr>
+ *	<tr>
+ *		<td>Added ADC calibration constant loading from the device signature
+ *          row when the module is initialized</td>
+ *	</tr>
+ *	<tr>
+ *		<td>Initial Release</td>
+ *	</tr>
+ * \endif
+ * </table>
+ */
+
+/**
+ * \page asfdoc_sam0_adc_exqsg Examples for ADC Driver
+ *
+ * This is a list of the available Quick Start guides (QSGs) and example
+ * applications for \ref asfdoc_sam0_adc_group. QSGs are simple examples with
+ * step-by-step instructions to configure and use this driver in a selection of
+ * use cases. Note that a QSG can be compiled as a standalone application or be
+ * added to the user application.
+ *
+ *  - \subpage asfdoc_sam0_adc_basic_use_case
+ * \if ADC_CALLBACK_MODE
+ *  - \subpage asfdoc_sam0_adc_basic_use_case_callback
+ * \endif
+ *  - \subpage asfdoc_sam0_adc_dma_use_case
+ *
+ * \page asfdoc_sam0_adc_document_revision_history Document Revision History
+ *
+ * <table>
+ *	<tr>
+ *		<th>Doc. Rev.</th>
+ *		<th>Date</th>
+ *		<th>Comments</th>
+ *	</tr>
+ * \if DEVICE_SAML21_SUPPORT
+ *	<tr>
+ *		<td>42451B</td>
+ *		<td>12/2015</td>
+ *		<td>Added support for SAM L22</td>
+ *	</tr>
+ *  <tr>
+ *      <td>42451A</td>
+ *      <td>07/2015</td>
+ *      <td>Initial document release</td>
+ * </tr>
+ * \else
+ *	<tr>
+ *		<td>42109E</td>
+ *		<td>12/2015</td>
+ *		<td>Added support for SAM DA1 and SAM D09</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42109D</td>
+ *		<td>12/2014</td>
+ *		<td>Added support for SAM R21 and SAM D10/D11</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42109C</td>
+ *		<td>01/2014</td>
+ *		<td>Added support for SAM D21</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42109B</td>
+ *		<td>06/2013</td>
+ *		<td>Added additional documentation on the event system. Corrected
+ *          documentation typos.</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42109A</td>
+ *		<td>06/2013</td>
+ *		<td>Initial release</td>
+ *	</tr>
+ * \endif
+ * </table>
+ */
+
+#endif /* ADC_H_INCLUDED */
diff --git a/src/ASF/sam0/drivers/adc/adc_sam_d_r_h/adc.c b/src/ASF/sam0/drivers/adc/adc_sam_d_r_h/adc.c
new file mode 100644
index 0000000000000000000000000000000000000000..32ce661ded157b46fc1d72f88e63539e28b126b4
--- /dev/null
+++ b/src/ASF/sam0/drivers/adc/adc_sam_d_r_h/adc.c
@@ -0,0 +1,726 @@
+/**
+ * \file
+ *
+ * \brief SAM Peripheral Analog-to-Digital Converter Driver
+ *
+ * Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+#include "adc.h"
+
+#if SAMD20
+/* The Die revision D number */
+#define REVISON_D_NUM    3
+#endif
+
+/**
+ * \brief Initializes an ADC configuration structure to defaults
+ *
+ * Initializes a given ADC configuration struct to a set of known default
+ * values. This function should be called on any new instance of the
+ * configuration struct before being modified by the user application.
+ *
+ * The default configuration is as follows:
+ *  \li GCLK generator 0 (GCLK main) clock source
+ *  \li 1V from internal bandgap reference
+ *  \li Div 4 clock prescaler
+ *  \li 12-bit resolution
+ *  \li Window monitor disabled
+ *  \li No gain
+ *  \li Positive input on ADC PIN 0
+ *  \li Negative input on ADC PIN 1
+ *  \li Averaging disabled
+ *  \li Oversampling disabled
+ *  \li Right adjust data
+ *  \li Single-ended mode
+ *  \li Free running disabled
+ *  \li All events (input and generation) disabled
+ *  \li Sleep operation disabled
+ *  \li No reference compensation
+ *  \li No gain/offset correction
+ *  \li No added sampling time
+ *  \li Pin scan mode disabled
+ *
+ * \param[out] config  Pointer to configuration struct to initialize to
+ *                     default values
+ */
+void adc_get_config_defaults(struct adc_config *const config)
+{
+	Assert(config);
+	config->clock_source                  = GCLK_GENERATOR_0;
+	config->reference                     = ADC_REFERENCE_INT1V;
+	config->clock_prescaler               = ADC_CLOCK_PRESCALER_DIV4;
+	config->resolution                    = ADC_RESOLUTION_12BIT;
+	config->window.window_mode            = ADC_WINDOW_MODE_DISABLE;
+	config->window.window_upper_value     = 0;
+	config->window.window_lower_value     = 0;
+	config->gain_factor                   = ADC_GAIN_FACTOR_1X;
+#if SAMR21
+	config->positive_input                = ADC_POSITIVE_INPUT_PIN6 ;
+#else
+ 	config->positive_input                = ADC_POSITIVE_INPUT_PIN0 ;
+#endif
+	config->negative_input                = ADC_NEGATIVE_INPUT_GND ;
+	config->accumulate_samples            = ADC_ACCUMULATE_DISABLE;
+	config->divide_result                 = ADC_DIVIDE_RESULT_DISABLE;
+	config->left_adjust                   = false;
+	config->differential_mode             = false;
+	config->freerunning                   = false;
+	config->event_action                  = ADC_EVENT_ACTION_DISABLED;
+	config->run_in_standby                = false;
+	config->reference_compensation_enable = false;
+	config->correction.correction_enable  = false;
+	config->correction.gain_correction    = ADC_GAINCORR_RESETVALUE;
+	config->correction.offset_correction  = ADC_OFFSETCORR_RESETVALUE;
+	config->sample_length                 = 0;
+	config->pin_scan.offset_start_scan    = 0;
+	config->pin_scan.inputs_to_scan       = 0;
+}
+
+/**
+ * \brief Sets the ADC window mode
+ *
+ * Sets the ADC window mode to a given mode and value range.
+ *
+ * \param[in] module_inst         Pointer to the ADC software instance struct
+ * \param[in] window_mode         Window monitor mode to set
+ * \param[in] window_lower_value  Lower window monitor threshold value
+ * \param[in] window_upper_value  Upper window monitor threshold value
+  */
+void adc_set_window_mode(
+		struct adc_module *const module_inst,
+		const enum adc_window_mode window_mode,
+		const int16_t window_lower_value,
+		const int16_t window_upper_value)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Set window mode */
+	adc_module->WINCTRL.reg = window_mode << ADC_WINCTRL_WINMODE_Pos;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Set lower window monitor threshold value */
+	adc_module->WINLT.reg = window_lower_value << ADC_WINLT_WINLT_Pos;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Set upper window monitor threshold value */
+	adc_module->WINUT.reg = window_upper_value << ADC_WINUT_WINUT_Pos;
+}
+
+/**
+* \internal Configure MUX settings for the analog pins
+*
+* This function will set the given ADC input pins
+* to the analog function in the pinmux, giving
+* the ADC access to the analog signal
+*
+* \param [in] pin AINxx pin to configure
+*/
+static inline void _adc_configure_ain_pin(uint32_t pin)
+{
+#define PIN_INVALID_ADC_AIN    0xFFFFUL
+
+	/* Pinmapping table for AINxx -> GPIO pin number */
+	const uint32_t pinmapping[] = {
+#if (SAMD20E) || (SAMD21E)|| (SAMDA1E)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA04B_ADC_AIN4,  PIN_PA05B_ADC_AIN5,
+			PIN_PA06B_ADC_AIN6,  PIN_PA07B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
+			PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19,
+#elif (SAMD20G) || (SAMD21G)|| (SAMDA1G)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_PB08B_ADC_AIN2,  PIN_PB09B_ADC_AIN3,
+			PIN_PA04B_ADC_AIN4,  PIN_PA05B_ADC_AIN5,
+			PIN_PA06B_ADC_AIN6,  PIN_PA07B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
+			PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19,
+#elif (SAMD20J) || (SAMD21J)|| (SAMDA1J)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_PB08B_ADC_AIN2,  PIN_PB09B_ADC_AIN3,
+			PIN_PA04B_ADC_AIN4,  PIN_PA05B_ADC_AIN5,
+			PIN_PA06B_ADC_AIN6,  PIN_PA07B_ADC_AIN7,
+			PIN_PB00B_ADC_AIN8,  PIN_PB01B_ADC_AIN9,
+			PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11,
+			PIN_PB04B_ADC_AIN12, PIN_PB05B_ADC_AIN13,
+			PIN_PB06B_ADC_AIN14, PIN_PB07B_ADC_AIN15,
+			PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
+			PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19,
+#elif SAMR21E
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA06B_ADC_AIN6,  PIN_PA07B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+#elif SAMR21G
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA04B_ADC_AIN4,  PIN_PA05B_ADC_AIN5,
+			PIN_PA06B_ADC_AIN6,  PIN_PA07B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+#elif (SAMD09C) || (SAMD10C) || (SAMD11C)
+			PIN_PA02B_ADC_AIN0,  PIN_INVALID_ADC_AIN,
+			PIN_PA04B_ADC_AIN2,  PIN_PA05B_ADC_AIN3,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA14B_ADC_AIN6,  PIN_PA15B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+#elif (SAMD09D)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_PA04B_ADC_AIN2,  PIN_PA05B_ADC_AIN3,
+			PIN_PA06B_ADC_AIN4,  PIN_PA07B_ADC_AIN5,
+			PIN_PA14B_ADC_AIN6,  PIN_PA15B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN,  PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+#elif (SAMD10DS) || (SAMD10DU) || (SAMD11DS) || (SAMD11DU)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_PA04B_ADC_AIN2,  PIN_PA05B_ADC_AIN3,
+			PIN_PA06B_ADC_AIN4,  PIN_PA07B_ADC_AIN5,
+			PIN_PA14B_ADC_AIN6,  PIN_PA15B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+#elif (SAMD10DM) || (SAMD11DM)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_PA04B_ADC_AIN2,  PIN_PA05B_ADC_AIN3,
+			PIN_PA06B_ADC_AIN4,  PIN_PA07B_ADC_AIN5,
+			PIN_PA14B_ADC_AIN6,  PIN_PA15B_ADC_AIN7,
+			PIN_PA10B_ADC_AIN8,  PIN_PA11B_ADC_AIN9,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+#elif (SAMHA1G) || (SAMHA0G)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA04B_ADC_AIN4,  PIN_PA05B_ADC_AIN5,
+			PIN_PA06B_ADC_AIN6,  PIN_PA07B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_PB03B_ADC_AIN11,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PB06B_ADC_AIN14, PIN_PB07B_ADC_AIN15,
+			PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
+			PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19,
+#elif (SAMHA1E) || (SAMHA0E)
+			PIN_PA02B_ADC_AIN0,  PIN_PA03B_ADC_AIN1,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA06B_ADC_AIN6,  PIN_PA07B_ADC_AIN7,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
+			PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
+#else
+#  error ADC pin mappings are not defined for this device.
+#endif
+		};
+
+	uint32_t pin_map_result = PIN_INVALID_ADC_AIN;
+
+	if (pin <= ADC_EXTCHANNEL_MSB) {
+		pin_map_result = pinmapping[pin >> ADC_INPUTCTRL_MUXPOS_Pos];
+
+		Assert(pin_map_result != PIN_INVALID_ADC_AIN);
+
+		struct system_pinmux_config config;
+		system_pinmux_get_config_defaults(&config);
+
+		/* Analog functions are all on MUX setting B */
+		config.input_pull   = SYSTEM_PINMUX_PIN_PULL_NONE;
+		config.mux_position = 1;
+
+		system_pinmux_pin_set_config(pin_map_result, &config);
+	}
+}
+
+/**
+ * \internal Writes an ADC configuration to the hardware module
+ *
+ * Writes out a given ADC module configuration to the hardware module.
+ *
+ * \param[out] module_inst  Pointer to the ADC software instance struct
+ * \param[in]  config       Pointer to configuration struct
+ *
+ * \return Status of the configuration procedure
+ * \retval STATUS_OK               The configuration was successful
+ * \retval STATUS_ERR_INVALID_ARG  Invalid argument(s) were provided
+ */
+static enum status_code _adc_set_config(
+		struct adc_module *const module_inst,
+		struct adc_config *const config)
+{
+	uint8_t adjres = 0;
+	uint32_t resolution = ADC_RESOLUTION_16BIT;
+	enum adc_accumulate_samples accumulate = ADC_ACCUMULATE_DISABLE;
+#if SAMD20
+	uint8_t revision_num = ((REG_DSU_DID & DSU_DID_REVISION_Msk) >> DSU_DID_REVISION_Pos);
+#endif
+
+	/* Get the hardware module pointer */
+	Adc *const adc_module = module_inst->hw;
+
+	/* Configure GCLK channel and enable clock */
+	struct system_gclk_chan_config gclk_chan_conf;
+	system_gclk_chan_get_config_defaults(&gclk_chan_conf);
+	gclk_chan_conf.source_generator = config->clock_source;
+	system_gclk_chan_set_config(ADC_GCLK_ID, &gclk_chan_conf);
+	system_gclk_chan_enable(ADC_GCLK_ID);
+
+	/* Setup pinmuxing for analog inputs */
+	if (config->pin_scan.inputs_to_scan != 0) {
+		uint8_t offset = config->pin_scan.offset_start_scan;
+		uint8_t start_pin =
+				offset +(uint8_t)config->positive_input;
+		uint8_t end_pin =
+				start_pin + config->pin_scan.inputs_to_scan;
+
+		while (start_pin < end_pin) {
+			_adc_configure_ain_pin((offset % 16)+(uint8_t)config->positive_input);
+			start_pin++;
+			offset++;
+		}
+		_adc_configure_ain_pin(config->negative_input);
+	} else {
+		_adc_configure_ain_pin(config->positive_input);
+		_adc_configure_ain_pin(config->negative_input);
+	}
+
+	/* Configure run in standby */
+	adc_module->CTRLA.reg = (config->run_in_standby << ADC_CTRLA_RUNSTDBY_Pos);
+
+	/* Configure reference */
+	adc_module->REFCTRL.reg =
+			(config->reference_compensation_enable << ADC_REFCTRL_REFCOMP_Pos) |
+			(config->reference);
+
+	/* Set adjusting result and number of samples */
+	switch (config->resolution) {
+
+	case ADC_RESOLUTION_CUSTOM:
+		adjres = config->divide_result;
+		accumulate = config->accumulate_samples;
+		/* 16-bit result register */
+		resolution = ADC_RESOLUTION_16BIT;
+		break;
+
+	case ADC_RESOLUTION_13BIT:
+		/* Increase resolution by 1 bit */
+		adjres = ADC_DIVIDE_RESULT_2;
+		accumulate = ADC_ACCUMULATE_SAMPLES_4;
+		/* 16-bit result register */
+		resolution = ADC_RESOLUTION_16BIT;
+		break;
+
+	case ADC_RESOLUTION_14BIT:
+		/* Increase resolution by 2 bit */
+		adjres = ADC_DIVIDE_RESULT_4;
+		accumulate = ADC_ACCUMULATE_SAMPLES_16;
+		/* 16-bit result register */
+		resolution = ADC_RESOLUTION_16BIT;
+		break;
+#if SAMD20
+	/* See $35.1.8 for ADC errata of SAM D20.
+	   The revisions before D have this issue.*/
+	case ADC_RESOLUTION_15BIT:
+		/* Increase resolution by 3 bit */
+		if(revision_num < REVISON_D_NUM) {
+			adjres = ADC_DIVIDE_RESULT_8;
+		} else {
+			adjres = ADC_DIVIDE_RESULT_2;
+		}
+		accumulate = ADC_ACCUMULATE_SAMPLES_64;
+		/* 16-bit result register */
+		resolution = ADC_RESOLUTION_16BIT;
+		break;
+
+	case ADC_RESOLUTION_16BIT:
+		if(revision_num < REVISON_D_NUM) {
+			/* Increase resolution by 4 bit */
+			adjres = ADC_DIVIDE_RESULT_16;
+		} else {
+			adjres = ADC_DIVIDE_RESULT_DISABLE;
+		}
+		accumulate = ADC_ACCUMULATE_SAMPLES_256;
+		/* 16-bit result register */
+		resolution = ADC_RESOLUTION_16BIT;
+		break;
+#else
+	case ADC_RESOLUTION_15BIT:
+		/* Increase resolution by 3 bit */
+		adjres = ADC_DIVIDE_RESULT_2;
+		accumulate = ADC_ACCUMULATE_SAMPLES_64;
+		/* 16-bit result register */
+		resolution = ADC_RESOLUTION_16BIT;
+		break;
+
+	case ADC_RESOLUTION_16BIT:
+		/* Increase resolution by 4 bit */
+		adjres = ADC_DIVIDE_RESULT_DISABLE;
+		accumulate = ADC_ACCUMULATE_SAMPLES_256;
+		/* 16-bit result register */
+		resolution = ADC_RESOLUTION_16BIT;
+		break;
+#endif
+	case ADC_RESOLUTION_8BIT:
+		/* 8-bit result register */
+		resolution = ADC_RESOLUTION_8BIT;
+		break;
+	case ADC_RESOLUTION_10BIT:
+		/* 10-bit result register */
+		resolution = ADC_RESOLUTION_10BIT;
+		break;
+	case ADC_RESOLUTION_12BIT:
+		/* 12-bit result register */
+		resolution = ADC_RESOLUTION_12BIT;
+		break;
+
+	default:
+		/* Unknown. Abort. */
+		return STATUS_ERR_INVALID_ARG;
+	}
+
+	adc_module->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(adjres) | accumulate;
+
+	/* Check validity of sample length value */
+	if (config->sample_length > 63) {
+		return STATUS_ERR_INVALID_ARG;
+	} else {
+		/* Configure sample length */
+		adc_module->SAMPCTRL.reg =
+				(config->sample_length << ADC_SAMPCTRL_SAMPLEN_Pos);
+	}
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Configure CTRLB */
+	adc_module->CTRLB.reg =
+			config->clock_prescaler |
+			resolution |
+			(config->correction.correction_enable << ADC_CTRLB_CORREN_Pos) |
+			(config->freerunning << ADC_CTRLB_FREERUN_Pos) |
+			(config->left_adjust << ADC_CTRLB_LEFTADJ_Pos) |
+			(config->differential_mode << ADC_CTRLB_DIFFMODE_Pos);
+
+	/* Check validity of window thresholds */
+	if (config->window.window_mode != ADC_WINDOW_MODE_DISABLE) {
+		switch (resolution) {
+		case ADC_RESOLUTION_8BIT:
+			if (config->differential_mode &&
+					(config->window.window_lower_value > 127 ||
+					config->window.window_lower_value < -128 ||
+					config->window.window_upper_value > 127 ||
+					config->window.window_upper_value < -128)) {
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			} else if (config->window.window_lower_value > 255 ||
+					config->window.window_upper_value > 255){
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			}
+			break;
+		case ADC_RESOLUTION_10BIT:
+			if (config->differential_mode &&
+					(config->window.window_lower_value > 511 ||
+					config->window.window_lower_value < -512 ||
+					config->window.window_upper_value > 511 ||
+					config->window.window_upper_value < -512)) {
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			} else if (config->window.window_lower_value > 1023 ||
+					config->window.window_upper_value > 1023){
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			}
+			break;
+		case ADC_RESOLUTION_12BIT:
+			if (config->differential_mode &&
+					(config->window.window_lower_value > 2047 ||
+					config->window.window_lower_value < -2048 ||
+					config->window.window_upper_value > 2047 ||
+					config->window.window_upper_value < -2048)) {
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			} else if (config->window.window_lower_value > 4095 ||
+					config->window.window_upper_value > 4095){
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			}
+			break;
+		case ADC_RESOLUTION_16BIT:
+			if (config->differential_mode &&
+					(config->window.window_lower_value > 32767 ||
+					config->window.window_lower_value < -32768 ||
+					config->window.window_upper_value > 32767 ||
+					config->window.window_upper_value < -32768)) {
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			} else if (config->window.window_lower_value > 65535 ||
+					config->window.window_upper_value > 65535){
+				/* Invalid value */
+				return STATUS_ERR_INVALID_ARG;
+			}
+			break;
+		}
+	}
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Configure window mode */
+	adc_module->WINCTRL.reg = config->window.window_mode;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Configure lower threshold */
+	adc_module->WINLT.reg =
+			config->window.window_lower_value << ADC_WINLT_WINLT_Pos;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Configure lower threshold */
+	adc_module->WINUT.reg = config->window.window_upper_value <<
+			ADC_WINUT_WINUT_Pos;
+
+	uint8_t inputs_to_scan = config->pin_scan.inputs_to_scan;
+	if (inputs_to_scan > 0) {
+		/*
+		* Number of input sources included is the value written to INPUTSCAN
+		* plus 1.
+		*/
+		inputs_to_scan--;
+	}
+
+	if (inputs_to_scan > (ADC_INPUTCTRL_INPUTSCAN_Msk >> ADC_INPUTCTRL_INPUTSCAN_Pos) ||
+			config->pin_scan.offset_start_scan > (ADC_INPUTCTRL_INPUTOFFSET_Msk >> ADC_INPUTCTRL_INPUTOFFSET_Pos)) {
+		/* Invalid number of input pins or input offset */
+		return STATUS_ERR_INVALID_ARG;
+	}
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Configure pin scan mode and positive and negative input pins */
+	adc_module->INPUTCTRL.reg =
+			config->gain_factor |
+			(config->pin_scan.offset_start_scan <<
+			ADC_INPUTCTRL_INPUTOFFSET_Pos) |
+			(inputs_to_scan << ADC_INPUTCTRL_INPUTSCAN_Pos) |
+			config->negative_input |
+			config->positive_input;
+
+	/* Configure events */
+	adc_module->EVCTRL.reg = config->event_action;
+
+	/* Disable all interrupts */
+	adc_module->INTENCLR.reg =
+			(1 << ADC_INTENCLR_SYNCRDY_Pos) | (1 << ADC_INTENCLR_WINMON_Pos) |
+			(1 << ADC_INTENCLR_OVERRUN_Pos) | (1 << ADC_INTENCLR_RESRDY_Pos);
+
+	if (config->correction.correction_enable){
+		/* Make sure gain_correction value is valid */
+		if (config->correction.gain_correction > ADC_GAINCORR_GAINCORR_Msk) {
+			return STATUS_ERR_INVALID_ARG;
+		} else {
+			/* Set gain correction value */
+			adc_module->GAINCORR.reg = config->correction.gain_correction <<
+					ADC_GAINCORR_GAINCORR_Pos;
+		}
+
+		/* Make sure offset correction value is valid */
+		if (config->correction.offset_correction > 2047 ||
+				config->correction.offset_correction < -2048) {
+			return STATUS_ERR_INVALID_ARG;
+		} else {
+			/* Set offset correction value */
+			adc_module->OFFSETCORR.reg = config->correction.offset_correction <<
+					ADC_OFFSETCORR_OFFSETCORR_Pos;
+		}
+	}
+
+	/* Load in the fixed device ADC calibration constants */
+	adc_module->CALIB.reg =
+			ADC_CALIB_BIAS_CAL(
+				(*(uint32_t *)ADC_FUSES_BIASCAL_ADDR >> ADC_FUSES_BIASCAL_Pos)
+			) |
+			ADC_CALIB_LINEARITY_CAL(
+				(*(uint64_t *)ADC_FUSES_LINEARITY_0_ADDR >> ADC_FUSES_LINEARITY_0_Pos)
+			);
+
+	return STATUS_OK;
+}
+
+/**
+ * \brief Initializes the ADC channel sequence
+ *
+ * Like SAMD and SAMR21 the INPUTOFFSET register will be incremented one
+ * automatically after a conversion done, causing the next conversion
+ * to be done with the positive input equal to MUXPOS + INPUTOFFSET,
+ * it is scanning continuously one by one even ADC channels are not continuous.
+ *
+ * Initializes the ADC channel sequence by the sequence of pin_array.
+ *
+ * \param[in]  pin_array   The array of the Mux selection for the positive ADC input
+ * \param[in]  size        The size of pin_array
+ */
+void adc_regular_ain_channel(uint32_t *pin_array, uint8_t size)
+{
+	for (int i = 0; i < size; i++) {
+		_adc_configure_ain_pin(pin_array[i]);
+  	}
+}
+
+/**
+ * \brief Initializes the ADC
+ *
+ * Initializes the ADC device struct and the hardware module based on the
+ * given configuration struct values.
+ *
+ * \param[out] module_inst Pointer to the ADC software instance struct
+ * \param[in]  hw          Pointer to the ADC module instance
+ * \param[in]  config      Pointer to the configuration struct
+ *
+ * \return Status of the initialization procedure.
+ * \retval STATUS_OK                The initialization was successful
+ * \retval STATUS_ERR_INVALID_ARG   Invalid argument(s) were provided
+ * \retval STATUS_BUSY          The module is busy with a reset operation
+ * \retval STATUS_ERR_DENIED        The module is enabled
+ */
+enum status_code adc_init(
+		struct adc_module *const module_inst,
+		Adc *hw,
+		struct adc_config *config)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(hw);
+	Assert(config);
+
+	/* Associate the software module instance with the hardware module */
+	module_inst->hw = hw;
+
+	/* Turn on the digital interface clock */
+	system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_ADC);
+
+	if (hw->CTRLA.reg & ADC_CTRLA_SWRST) {
+		/* We are in the middle of a reset. Abort. */
+		return STATUS_BUSY;
+	}
+
+	if (hw->CTRLA.reg & ADC_CTRLA_ENABLE) {
+		/* Module must be disabled before initialization. Abort. */
+		return STATUS_ERR_DENIED;
+	}
+
+	/* Store the selected reference for later use */
+	module_inst->reference = config->reference;
+
+	/* Make sure bandgap is enabled if requested by the config */
+	if (module_inst->reference == ADC_REFERENCE_INT1V) {
+		system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_BANDGAP);
+	}
+
+#if ADC_CALLBACK_MODE == true
+	for (uint8_t i = 0; i < ADC_CALLBACK_N; i++) {
+		module_inst->callback[i] = NULL;
+	};
+
+	module_inst->registered_callback_mask = 0;
+	module_inst->enabled_callback_mask = 0;
+	module_inst->remaining_conversions = 0;
+	module_inst->job_status = STATUS_OK;
+
+	_adc_instances[0] = module_inst;
+
+	if (config->event_action == ADC_EVENT_ACTION_DISABLED &&
+			!config->freerunning) {
+		module_inst->software_trigger = true;
+	} else {
+		module_inst->software_trigger = false;
+	}
+#endif
+
+	/* Write configuration to module */
+	return _adc_set_config(module_inst, config);
+}
diff --git a/src/ASF/sam0/drivers/adc/adc_sam_d_r_h/adc_feature.h b/src/ASF/sam0/drivers/adc/adc_sam_d_r_h/adc_feature.h
new file mode 100644
index 0000000000000000000000000000000000000000..d715b9d11642168e2ff9bf767234f290715ab15f
--- /dev/null
+++ b/src/ASF/sam0/drivers/adc/adc_sam_d_r_h/adc_feature.h
@@ -0,0 +1,718 @@
+/**
+ * \file
+ *
+ * \brief SAM ADC functionality
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+#ifndef ADC_FEATURE_H_INCLUDED
+#define ADC_FEATURE_H_INCLUDED
+
+/**
+ * \addtogroup asfdoc_sam0_adc_group
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if ADC_CALLBACK_MODE == true
+#  include <system_interrupt.h>
+
+#if !defined(__DOXYGEN__)
+extern struct adc_module *_adc_instances[ADC_INST_NUM];
+#endif
+
+/** Forward definition of the device instance. */
+struct adc_module;
+
+/** Type of the callback functions. */
+typedef void (*adc_callback_t)(struct adc_module *const module);
+
+/**
+ * \brief ADC Callback enum
+ *
+ * Callback types for ADC callback driver.
+ *
+ */
+enum adc_callback {
+	/** Callback for buffer received */
+	ADC_CALLBACK_READ_BUFFER,
+	/** Callback when window is hit */
+	ADC_CALLBACK_WINDOW,
+	/** Callback for error */
+	ADC_CALLBACK_ERROR,
+#  if !defined(__DOXYGEN__)
+	/** Number of available callbacks */
+	ADC_CALLBACK_N,
+#  endif
+};
+
+#endif
+
+/**
+ * \brief ADC reference voltage enum
+ *
+ * Enum for the possible reference voltages for the ADC.
+ *
+ */
+enum adc_reference {
+	/** 1.0V voltage reference */
+	ADC_REFERENCE_INT1V   = ADC_REFCTRL_REFSEL_INT1V,
+	/** 1/1.48V<SUB>CC</SUB> reference */
+	ADC_REFERENCE_INTVCC0 = ADC_REFCTRL_REFSEL_INTVCC0,
+	/** 1/2V<SUB>CC</SUB> (only for internal V<SUB>CC</SUB> > 2.1V) */
+	ADC_REFERENCE_INTVCC1 = ADC_REFCTRL_REFSEL_INTVCC1,
+	/** External reference A */
+	ADC_REFERENCE_AREFA   = ADC_REFCTRL_REFSEL_AREFA,
+	/** External reference B */
+	ADC_REFERENCE_AREFB   = ADC_REFCTRL_REFSEL_AREFB,
+};
+
+/**
+ * \brief ADC clock prescaler enum
+ *
+ * Enum for the possible clock prescaler values for the ADC.
+ *
+ */
+enum adc_clock_prescaler {
+	/** ADC clock division factor 4 */
+	ADC_CLOCK_PRESCALER_DIV4   = ADC_CTRLB_PRESCALER_DIV4,
+	/** ADC clock division factor 8 */
+	ADC_CLOCK_PRESCALER_DIV8   = ADC_CTRLB_PRESCALER_DIV8,
+	/** ADC clock division factor 16 */
+	ADC_CLOCK_PRESCALER_DIV16  = ADC_CTRLB_PRESCALER_DIV16,
+	/** ADC clock division factor 32 */
+	ADC_CLOCK_PRESCALER_DIV32  = ADC_CTRLB_PRESCALER_DIV32,
+	/** ADC clock division factor 64 */
+	ADC_CLOCK_PRESCALER_DIV64  = ADC_CTRLB_PRESCALER_DIV64,
+	/** ADC clock division factor 128 */
+	ADC_CLOCK_PRESCALER_DIV128 = ADC_CTRLB_PRESCALER_DIV128,
+	/** ADC clock division factor 256 */
+	ADC_CLOCK_PRESCALER_DIV256 = ADC_CTRLB_PRESCALER_DIV256,
+	/** ADC clock division factor 512 */
+	ADC_CLOCK_PRESCALER_DIV512 = ADC_CTRLB_PRESCALER_DIV512,
+};
+
+/**
+ * \brief ADC resolution enum
+ *
+ * Enum for the possible resolution values for the ADC.
+ *
+ */
+enum adc_resolution {
+	/** ADC 12-bit resolution */
+	ADC_RESOLUTION_12BIT = ADC_CTRLB_RESSEL_12BIT,
+	/** ADC 16-bit resolution using oversampling and decimation */
+	ADC_RESOLUTION_16BIT = ADC_CTRLB_RESSEL_16BIT,
+	/** ADC 10-bit resolution */
+	ADC_RESOLUTION_10BIT = ADC_CTRLB_RESSEL_10BIT,
+	/** ADC 8-bit resolution */
+	ADC_RESOLUTION_8BIT  = ADC_CTRLB_RESSEL_8BIT,
+	/** ADC 13-bit resolution using oversampling and decimation */
+	ADC_RESOLUTION_13BIT,
+	/** ADC 14-bit resolution using oversampling and decimation */
+	ADC_RESOLUTION_14BIT,
+	/** ADC 15-bit resolution using oversampling and decimation */
+	ADC_RESOLUTION_15BIT,
+	/** ADC 16-bit result register for use with averaging. When using this mode
+	  * the ADC result register will be set to 16-bit wide, and the number of
+	  * samples to accumulate and the division factor is configured by the
+	  * \ref adc_config.accumulate_samples and \ref adc_config.divide_result
+	  * members in the configuration struct.
+	  */
+	ADC_RESOLUTION_CUSTOM,
+};
+
+/**
+ * \brief ADC window monitor mode enum
+ *
+ * Enum for the possible window monitor modes for the ADC.
+ *
+ */
+enum adc_window_mode {
+	/** No window mode */
+	ADC_WINDOW_MODE_DISABLE          = ADC_WINCTRL_WINMODE_DISABLE,
+	/** RESULT > WINLT */
+	ADC_WINDOW_MODE_ABOVE_LOWER      = ADC_WINCTRL_WINMODE_MODE1,
+	/** RESULT < WINUT */
+	ADC_WINDOW_MODE_BELOW_UPPER      = ADC_WINCTRL_WINMODE_MODE2,
+	/** WINLT < RESULT < WINUT */
+	ADC_WINDOW_MODE_BETWEEN          = ADC_WINCTRL_WINMODE_MODE3,
+	/** !(WINLT < RESULT < WINUT) */
+	ADC_WINDOW_MODE_BETWEEN_INVERTED = ADC_WINCTRL_WINMODE_MODE4,
+};
+
+/**
+ * \brief ADC gain factor selection enum
+ *
+ * Enum for the possible gain factor values for the ADC.
+ *
+ */
+enum adc_gain_factor {
+	/** 1x gain */
+	ADC_GAIN_FACTOR_1X   = ADC_INPUTCTRL_GAIN_1X,
+	/** 2x gain */
+	ADC_GAIN_FACTOR_2X   = ADC_INPUTCTRL_GAIN_2X,
+	/** 4x gain */
+	ADC_GAIN_FACTOR_4X   = ADC_INPUTCTRL_GAIN_4X,
+	/** 8x gain */
+	ADC_GAIN_FACTOR_8X   = ADC_INPUTCTRL_GAIN_8X,
+	/** 16x gain */
+	ADC_GAIN_FACTOR_16X  = ADC_INPUTCTRL_GAIN_16X,
+	/** 1/2x gain */
+	ADC_GAIN_FACTOR_DIV2 = ADC_INPUTCTRL_GAIN_DIV2,
+};
+
+/**
+ * \brief ADC event action enum
+ *
+ * Enum for the possible actions to take on an incoming event.
+ *
+ */
+enum adc_event_action {
+	/** Event action disabled */
+	ADC_EVENT_ACTION_DISABLED         = 0,
+	/** Flush ADC and start conversion */
+	ADC_EVENT_ACTION_FLUSH_START_CONV = ADC_EVCTRL_SYNCEI,
+	/** Start conversion */
+	ADC_EVENT_ACTION_START_CONV       = ADC_EVCTRL_STARTEI,
+};
+
+/**
+ * \brief ADC positive MUX input selection enum
+ *
+ * Enum for the possible positive MUX input selections for the ADC.
+ *
+ */
+enum adc_positive_input {
+	/** ADC0 pin */
+	ADC_POSITIVE_INPUT_PIN0          = ADC_INPUTCTRL_MUXPOS_PIN0,
+	/** ADC1 pin */
+	ADC_POSITIVE_INPUT_PIN1          = ADC_INPUTCTRL_MUXPOS_PIN1,
+	/** ADC2 pin */
+	ADC_POSITIVE_INPUT_PIN2          = ADC_INPUTCTRL_MUXPOS_PIN2,
+	/** ADC3 pin */
+	ADC_POSITIVE_INPUT_PIN3          = ADC_INPUTCTRL_MUXPOS_PIN3,
+	/** ADC4 pin */
+	ADC_POSITIVE_INPUT_PIN4          = ADC_INPUTCTRL_MUXPOS_PIN4,
+	/** ADC5 pin */
+	ADC_POSITIVE_INPUT_PIN5          = ADC_INPUTCTRL_MUXPOS_PIN5,
+	/** ADC6 pin */
+	ADC_POSITIVE_INPUT_PIN6          = ADC_INPUTCTRL_MUXPOS_PIN6,
+	/** ADC7 pin */
+	ADC_POSITIVE_INPUT_PIN7          = ADC_INPUTCTRL_MUXPOS_PIN7,
+	/** ADC8 pin */
+	ADC_POSITIVE_INPUT_PIN8          = ADC_INPUTCTRL_MUXPOS_PIN8,
+	/** ADC9 pin */
+	ADC_POSITIVE_INPUT_PIN9          = ADC_INPUTCTRL_MUXPOS_PIN9,
+	/** ADC10 pin */
+	ADC_POSITIVE_INPUT_PIN10         = ADC_INPUTCTRL_MUXPOS_PIN10,
+	/** ADC11 pin */
+	ADC_POSITIVE_INPUT_PIN11         = ADC_INPUTCTRL_MUXPOS_PIN11,
+	/** ADC12 pin */
+	ADC_POSITIVE_INPUT_PIN12         = ADC_INPUTCTRL_MUXPOS_PIN12,
+	/** ADC13 pin */
+	ADC_POSITIVE_INPUT_PIN13         = ADC_INPUTCTRL_MUXPOS_PIN13,
+	/** ADC14 pin */
+	ADC_POSITIVE_INPUT_PIN14         = ADC_INPUTCTRL_MUXPOS_PIN14,
+	/** ADC15 pin */
+	ADC_POSITIVE_INPUT_PIN15         = ADC_INPUTCTRL_MUXPOS_PIN15,
+	/** ADC16 pin */
+	ADC_POSITIVE_INPUT_PIN16         = ADC_INPUTCTRL_MUXPOS_PIN16,
+	/** ADC17 pin */
+	ADC_POSITIVE_INPUT_PIN17         = ADC_INPUTCTRL_MUXPOS_PIN17,
+	/** ADC18 pin */
+	ADC_POSITIVE_INPUT_PIN18         = ADC_INPUTCTRL_MUXPOS_PIN18,
+	/** ADC19 pin */
+	ADC_POSITIVE_INPUT_PIN19         = ADC_INPUTCTRL_MUXPOS_PIN19,
+	/** Temperature reference */
+	ADC_POSITIVE_INPUT_TEMP          = ADC_INPUTCTRL_MUXPOS_TEMP,
+	/** Bandgap voltage */
+	ADC_POSITIVE_INPUT_BANDGAP       = ADC_INPUTCTRL_MUXPOS_BANDGAP,
+	/** 1/4 scaled core supply */
+	ADC_POSITIVE_INPUT_SCALEDCOREVCC = ADC_INPUTCTRL_MUXPOS_SCALEDCOREVCC,
+	/** 1/4 scaled I/O supply */
+	ADC_POSITIVE_INPUT_SCALEDIOVCC   = ADC_INPUTCTRL_MUXPOS_SCALEDIOVCC,
+	/** DAC input */
+	ADC_POSITIVE_INPUT_DAC           = ADC_INPUTCTRL_MUXPOS_DAC,
+};
+
+/**
+ * \brief ADC negative Multiplexer(MUX) input selection enum
+ *
+ * Enum for the possible negative Multiplexer(MUX) input selections for the ADC.
+ *
+ */
+enum adc_negative_input {
+	/** ADC0 pin */
+	ADC_NEGATIVE_INPUT_PIN0          = ADC_INPUTCTRL_MUXNEG_PIN0,
+	/** ADC1 pin */
+	ADC_NEGATIVE_INPUT_PIN1          = ADC_INPUTCTRL_MUXNEG_PIN1,
+	/** ADC2 pin */
+	ADC_NEGATIVE_INPUT_PIN2          = ADC_INPUTCTRL_MUXNEG_PIN2,
+	/** ADC3 pin */
+	ADC_NEGATIVE_INPUT_PIN3          = ADC_INPUTCTRL_MUXNEG_PIN3,
+	/** ADC4 pin */
+	ADC_NEGATIVE_INPUT_PIN4          = ADC_INPUTCTRL_MUXNEG_PIN4,
+	/** ADC5 pin */
+	ADC_NEGATIVE_INPUT_PIN5          = ADC_INPUTCTRL_MUXNEG_PIN5,
+	/** ADC6 pin */
+	ADC_NEGATIVE_INPUT_PIN6          = ADC_INPUTCTRL_MUXNEG_PIN6,
+	/** ADC7 pin */
+	ADC_NEGATIVE_INPUT_PIN7          = ADC_INPUTCTRL_MUXNEG_PIN7,
+	/** Internal ground */
+	ADC_NEGATIVE_INPUT_GND           = ADC_INPUTCTRL_MUXNEG_GND,
+	/** I/O ground */
+	ADC_NEGATIVE_INPUT_IOGND         = ADC_INPUTCTRL_MUXNEG_IOGND,
+};
+
+/**
+ * \brief ADC number of accumulated samples enum
+ *
+ * Enum for the possible numbers of ADC samples to accumulate.
+ * This setting is only used when the \ref ADC_RESOLUTION_CUSTOM
+ * resolution setting is used.
+ *
+ */
+enum adc_accumulate_samples {
+	/** No averaging */
+	ADC_ACCUMULATE_DISABLE      = ADC_AVGCTRL_SAMPLENUM_1,
+	/** Average 2 samples */
+	ADC_ACCUMULATE_SAMPLES_2    = ADC_AVGCTRL_SAMPLENUM_2,
+	/** Average 4 samples */
+	ADC_ACCUMULATE_SAMPLES_4    = ADC_AVGCTRL_SAMPLENUM_4,
+	/** Average 8 samples */
+	ADC_ACCUMULATE_SAMPLES_8    = ADC_AVGCTRL_SAMPLENUM_8,
+	/** Average 16 samples */
+	ADC_ACCUMULATE_SAMPLES_16   = ADC_AVGCTRL_SAMPLENUM_16,
+	/** Average 32 samples */
+	ADC_ACCUMULATE_SAMPLES_32   = ADC_AVGCTRL_SAMPLENUM_32,
+	/** Average 64 samples */
+	ADC_ACCUMULATE_SAMPLES_64   = ADC_AVGCTRL_SAMPLENUM_64,
+	/** Average 128 samples */
+	ADC_ACCUMULATE_SAMPLES_128  = ADC_AVGCTRL_SAMPLENUM_128,
+	/** Average 256 samples */
+	ADC_ACCUMULATE_SAMPLES_256  = ADC_AVGCTRL_SAMPLENUM_256,
+	/** Average 512 samples */
+	ADC_ACCUMULATE_SAMPLES_512  = ADC_AVGCTRL_SAMPLENUM_512,
+	/** Average 1024 samples */
+	ADC_ACCUMULATE_SAMPLES_1024 = ADC_AVGCTRL_SAMPLENUM_1024,
+};
+
+/**
+ * \brief ADC possible dividers for the result register
+ *
+ * Enum for the possible division factors to use when accumulating
+ * multiple samples. To keep the same resolution for the averaged
+ * result and the actual input value, the division factor must
+ * be equal to the number of samples accumulated. This setting is only
+ * used when the \ref ADC_RESOLUTION_CUSTOM resolution setting is used.
+ */
+enum adc_divide_result {
+	/** Don't divide result register after accumulation */
+	ADC_DIVIDE_RESULT_DISABLE = 0,
+	/** Divide result register by 2 after accumulation */
+	ADC_DIVIDE_RESULT_2       = 1,
+	/** Divide result register by 4 after accumulation */
+	ADC_DIVIDE_RESULT_4       = 2,
+	/** Divide result register by 8 after accumulation */
+	ADC_DIVIDE_RESULT_8       = 3,
+	/** Divide result register by 16 after accumulation */
+	ADC_DIVIDE_RESULT_16      = 4,
+	/** Divide result register by 32 after accumulation */
+	ADC_DIVIDE_RESULT_32      = 5,
+	/** Divide result register by 64 after accumulation */
+	ADC_DIVIDE_RESULT_64      = 6,
+	/** Divide result register by 128 after accumulation */
+	ADC_DIVIDE_RESULT_128     = 7,
+};
+
+#if ADC_CALLBACK_MODE == true
+/**
+ * Enum for the possible ADC interrupt flags.
+ */
+enum adc_interrupt_flag {
+	/** ADC result ready */
+	ADC_INTERRUPT_RESULT_READY = ADC_INTFLAG_RESRDY,
+	/** Window monitor match */
+	ADC_INTERRUPT_WINDOW       = ADC_INTFLAG_WINMON,
+	/** ADC result overwritten before read */
+	ADC_INTERRUPT_OVERRUN      = ADC_INTFLAG_OVERRUN,
+};
+#endif
+
+/**
+ * \brief ADC oversampling and decimation enum
+ *
+ * Enum for the possible numbers of bits resolution can be increased by when
+ * using oversampling and decimation.
+ *
+ */
+enum adc_oversampling_and_decimation {
+	/** Don't use oversampling and decimation mode */
+	ADC_OVERSAMPLING_AND_DECIMATION_DISABLE = 0,
+	/** 1-bit resolution increase */
+	ADC_OVERSAMPLING_AND_DECIMATION_1BIT,
+	/** 2-bit resolution increase */
+	ADC_OVERSAMPLING_AND_DECIMATION_2BIT,
+	/** 3-bit resolution increase */
+	ADC_OVERSAMPLING_AND_DECIMATION_3BIT,
+	/** 4-bit resolution increase */
+	ADC_OVERSAMPLING_AND_DECIMATION_4BIT
+};
+
+/**
+ * \brief Window monitor configuration structure
+ *
+ * Window monitor configuration structure.
+ */
+struct adc_window_config {
+	/** Selected window mode */
+	enum adc_window_mode window_mode;
+	/** Lower window value */
+	int32_t window_lower_value;
+	/** Upper window value */
+	int32_t window_upper_value;
+};
+
+/**
+ * \brief ADC event enable/disable structure.
+ *
+ * Event flags for the ADC module. This is used to enable and
+ * disable events via \ref adc_enable_events() and \ref adc_disable_events().
+ */
+struct adc_events {
+	/** Enable event generation on conversion done */
+	bool generate_event_on_conversion_done;
+	/** Enable event generation on window monitor */
+	bool generate_event_on_window_monitor;
+};
+
+/**
+ * \brief Gain and offset correction configuration structure
+ *
+ * Gain and offset correction configuration structure.
+ * Part of the \ref adc_config struct and will  be initialized by
+ * \ref adc_get_config_defaults.
+ */
+struct adc_correction_config {
+	/**
+	 * Enables correction for gain and offset based on values of gain_correction and
+	 * offset_correction if set to true
+	 */
+	bool correction_enable;
+	/**
+	 * This value defines how the ADC conversion result is compensated for gain
+	 * error before written to the result register. This is a fractional value,
+	 * 1-bit integer plus an 11-bit fraction, therefore
+	 * 1/2 <= gain_correction < 2. Valid \c gain_correction values ranges from
+	 * \c 0b010000000000 to \c 0b111111111111.
+	 */
+	uint16_t gain_correction;
+	/**
+	 * This value defines how the ADC conversion result is compensated for
+	 * offset error before written to the result register. This is a 12-bit
+	 * value in two's complement format.
+	 */
+	int16_t offset_correction;
+};
+
+/**
+ * \brief Pin scan configuration structure
+ *
+ * Pin scan configuration structure. Part of the \ref adc_config struct and will
+ * be initialized by \ref adc_get_config_defaults.
+ */
+struct adc_pin_scan_config {
+	/**
+	 * Offset (relative to selected positive input) of the first input pin to be
+	 * used in pin scan mode
+	 */
+	uint8_t offset_start_scan;
+	/**
+	 * Number of input pins to scan in pin scan mode. A value below two will
+	 * disable pin scan mode.
+	 */
+	uint8_t inputs_to_scan;
+};
+
+/**
+ * \brief ADC configuration structure
+ *
+ * Configuration structure for an ADC instance. This structure should be
+ * initialized by the \ref adc_get_config_defaults()
+ * function before being modified by the user application.
+ */
+struct adc_config {
+	/** GCLK generator used to clock the peripheral */
+	enum gclk_generator clock_source;
+	/** Voltage reference */
+	enum adc_reference reference;
+	/** Clock prescaler */
+	enum adc_clock_prescaler clock_prescaler;
+	/** Result resolution */
+	enum adc_resolution resolution;
+	/** Gain factor */
+	enum adc_gain_factor gain_factor;
+	/** Positive Multiplexer (MUX) input */
+	enum adc_positive_input positive_input;
+	/** Negative MUX input. For singled-ended conversion mode, the negative
+	 * input must be connected to ground. This ground could be the internal
+	 * GND, IOGND or an external ground connected to a pin. */
+	enum adc_negative_input negative_input;
+	/** Number of ADC samples to accumulate when using the
+	 *  \c ADC_RESOLUTION_CUSTOM mode. Note: if the result width increases,
+	 *  result resolution will be changed accordingly.
+	 */
+	enum adc_accumulate_samples accumulate_samples;
+	/** Division ration when using the ADC_RESOLUTION_CUSTOM mode */
+	enum adc_divide_result divide_result;
+	/** Left adjusted result */
+	bool left_adjust;
+	/** Enables differential mode if true. 
+	 * if false, ADC will run in singled-ended mode. */
+	bool differential_mode;
+	/** Enables free running mode if true */
+	bool freerunning;
+	/** Enables ADC in standby sleep mode if true */
+	bool run_in_standby;
+	/**
+	 * Enables reference buffer offset compensation if true.
+	 * This will increase the accuracy of the gain stage, but decreases the input
+	 * impedance; therefore the startup time of the reference must be increased.
+	 */
+	bool reference_compensation_enable;
+	/**
+	 * This value (0-63) control the ADC sampling time in number of half ADC
+	 * prescaled clock cycles (depends of \c ADC_PRESCALER value), thus
+	 * controlling the ADC input impedance. Sampling time is set according to
+	 * the formula:
+	 * Sample time = (sample_length+1) * (ADCclk / 2).
+	 */
+	uint8_t sample_length;
+	/** Window monitor configuration structure */
+	struct adc_window_config window;
+	/** Gain and offset correction configuration structure */
+	struct adc_correction_config correction;
+	/** Event action to take on incoming event */
+	enum adc_event_action event_action;
+	/** Pin scan configuration structure */
+	struct adc_pin_scan_config pin_scan;
+};
+
+/**
+ * \brief ADC software device instance structure.
+ *
+ * ADC software instance structure, used to retain software state information
+ * of an associated hardware module instance.
+ *
+ * \note The fields of this structure should not be altered by the user
+ *       application; they are reserved for module-internal use only.
+ */
+struct adc_module {
+#if !defined(__DOXYGEN__)
+	/** Pointer to ADC hardware module */
+	Adc *hw;
+	/** Keep reference configuration so we know when enable is called */
+	enum adc_reference reference;
+#  if ADC_CALLBACK_MODE == true
+	/** Array to store callback functions */
+	adc_callback_t callback[ADC_CALLBACK_N];
+	/** Pointer to buffer used for ADC results */
+	volatile uint16_t *job_buffer;
+	/** Remaining number of conversions in current job */
+	volatile uint16_t remaining_conversions;
+	/** Bit mask for callbacks registered */
+	uint8_t registered_callback_mask;
+	/** Bit mask for callbacks enabled */
+	uint8_t enabled_callback_mask;
+	/** Holds the status of the ongoing or last conversion job */
+	volatile enum status_code job_status;
+	/** If software triggering is needed */
+	bool software_trigger;
+#  endif
+#endif
+};
+
+#if !defined(__DOXYGEN__)
+
+/**
+ * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
+ *
+ * Checks to see if the underlying hardware peripheral module(s) are currently
+ * synchronizing across multiple clock domains to the hardware bus. This
+ * function can be used to delay further operations on a module until such time
+ * that it is ready, to prevent blocking delays for synchronization in the
+ * user application.
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ *
+ * \return Synchronization status of the underlying hardware module(s).
+ *
+ * \retval true if the module synchronization is ongoing
+ * \retval false if the module has completed synchronization
+ */
+static inline bool adc_is_syncing(
+	struct adc_module *const module_inst)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+
+	Adc *const adc_module = module_inst->hw;
+
+	if (adc_module->STATUS.reg & ADC_STATUS_SYNCBUSY) {
+		return true;
+	}
+
+	return false;
+}
+#endif
+
+/**
+ * \name ADC Gain and Pin Scan Mode
+ * @{
+ */
+
+/**
+ * \brief Sets ADC gain factor
+ *
+ * Sets the ADC gain factor to a specified gain setting.
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ * \param[in] gain_factor  Gain factor value to set
+ */
+static inline void adc_set_gain(
+		struct adc_module *const module_inst,
+		const enum adc_gain_factor gain_factor)
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Set new gain factor */
+	adc_module->INPUTCTRL.reg =
+			(adc_module->INPUTCTRL.reg & ~ADC_INPUTCTRL_GAIN_Msk) |
+			(gain_factor);
+}
+
+/**
+ * \brief Sets the ADC pin scan mode
+ *
+ * Configures the pin scan mode of the ADC module. In pin scan mode, the first
+ * conversion will start at the configured positive input + start_offset. When
+ * a conversion is done, a conversion will start on the next input, until
+ * \c inputs_to_scan number of conversions are made.
+ *
+ * \param[in] module_inst     Pointer to the ADC software instance struct
+ * \param[in] inputs_to_scan  Number of input pins to perform a conversion on
+ *                            (must be two or more)
+ * \param[in] start_offset    Offset of first pin to scan (relative to
+ *                            configured positive input)
+ *
+ * \return Status of the pin scan configuration set request.
+ *
+ * \retval STATUS_OK               Pin scan mode has been set successfully
+ * \retval STATUS_ERR_INVALID_ARG  Number of input pins to scan or offset has
+ *                                 an invalid value
+ */
+static inline enum status_code adc_set_pin_scan_mode(
+		struct adc_module *const module_inst,
+		uint8_t inputs_to_scan,
+		const uint8_t start_offset)
+
+{
+	/* Sanity check arguments */
+	Assert(module_inst);
+	Assert(module_inst->hw);
+
+	Adc *const adc_module = module_inst->hw;
+
+	if (inputs_to_scan > 0) {
+		/*
+		* Number of input sources included is the value written to INPUTSCAN
+		* plus 1.
+		*/
+		inputs_to_scan--;
+	}
+
+	if (inputs_to_scan > (ADC_INPUTCTRL_INPUTSCAN_Msk >> ADC_INPUTCTRL_INPUTSCAN_Pos) ||
+			start_offset > (ADC_INPUTCTRL_INPUTOFFSET_Msk >> ADC_INPUTCTRL_INPUTOFFSET_Pos)) {
+		/* Invalid number of input pins */
+		return STATUS_ERR_INVALID_ARG;
+	}
+
+	while (adc_is_syncing(module_inst)) {
+		/* Wait for synchronization */
+	}
+
+	/* Set pin scan mode */
+	adc_module->INPUTCTRL.reg =
+			(adc_module->INPUTCTRL.reg &
+			~(ADC_INPUTCTRL_INPUTSCAN_Msk | ADC_INPUTCTRL_INPUTOFFSET_Msk)) |
+			(start_offset   << ADC_INPUTCTRL_INPUTOFFSET_Pos) |
+			(inputs_to_scan << ADC_INPUTCTRL_INPUTSCAN_Pos);
+
+	return STATUS_OK;
+}
+
+/**
+ * \brief Disables pin scan mode
+ *
+ * Disables pin scan mode. The next conversion will be made on only one pin
+ * (the configured positive input pin).
+ *
+ * \param[in] module_inst  Pointer to the ADC software instance struct
+ */
+static inline void adc_disable_pin_scan_mode(
+		struct adc_module *const module_inst)
+{
+	/* Disable pin scan mode */
+	adc_set_pin_scan_mode(module_inst, 0, 0);
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* ADC_FEATURE_H_INCLUDED */
+
diff --git a/src/ASF/sam0/drivers/wdt/quick_start/qs_wdt_basic.h b/src/ASF/sam0/drivers/wdt/quick_start/qs_wdt_basic.h
new file mode 100644
index 0000000000000000000000000000000000000000..c363d37cae7614d9df62b29ffd5347b8d68bf249
--- /dev/null
+++ b/src/ASF/sam0/drivers/wdt/quick_start/qs_wdt_basic.h
@@ -0,0 +1,98 @@
+/**
+ * \file
+ *
+ * \brief SAM Watchdog Driver Quick Start
+ *
+ * Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+/**
+ * \page asfdoc_sam0_wdt_basic_use_case Quick Start Guide for WDT - Basic
+ *
+ * In this use case, the Watchdog module is configured for:
+ *  \li System reset after 2048 clocks of the Watchdog generic clock
+ *  \li Always on mode disabled
+ *  \li Basic mode, with no window or early warning periods
+ *
+ * This use case sets up the Watchdog to force a system reset after every 2048
+ * clocks of the Watchdog's Generic Clock channel, unless the user periodically
+ * resets the Watchdog counter via a button before the timer expires. If the
+ * Watchdog resets the device, a LED on the board is turned off.
+ *
+ * \section asfdoc_sam0_wdt_basic_use_case_setup Setup
+ *
+ * \subsection asfdoc_sam0_wdt_basic_use_case_setup_prereq Prerequisites
+ * There are no special setup requirements for this use-case.
+ *
+ * \subsection asfdoc_sam0_wdt_basic_use_case_setup_code Code
+ * Copy-paste the following setup code to your user application:
+ * \snippet qs_wdt_basic.c setup
+ *
+ * Add to user application initialization (typically the start of \c main()):
+ * \snippet qs_wdt_basic.c setup_init
+ *
+ * \subsection asfdoc_sam0_wdt_basic_use_case_setup_flow Workflow
+ * -# Create a Watchdog module configuration struct, which can be filled out to
+ *    adjust the configuration of the Watchdog.
+ *    \snippet qs_wdt_basic.c setup_1
+ * -# Initialize the Watchdog configuration struct with the module's default
+ *    values.
+ *    \snippet qs_wdt_basic.c setup_2
+ *    \note This should always be performed before using the configuration
+ *          struct to ensure that all values are initialized to known default
+ *          settings.
+ *
+ * -# Adjust the configuration struct to set the timeout period and lock mode
+ *    of the Watchdog.
+ *    \snippet qs_wdt_basic.c setup_3
+ * -# Setups the WDT hardware module with the requested settings.
+ *    \snippet qs_wdt_basic.c setup_4
+ *
+ * \section asfdoc_sam0_wdt_basic_use_case Use Case
+ *
+ * \subsection asfdoc_sam0_wdt_basic_use_case_code Code
+ * Copy-paste the following code to your user application:
+ * \snippet qs_wdt_basic.c main
+ *
+ * \subsection asfdoc_sam0_wdt_basic_use_case_main Workflow
+ * -# Retrieve the cause of the system reset to determine if the Watchdog module
+ *    was the cause of the last reset.
+ *    \snippet qs_wdt_basic.c main_1
+ * -# Turn on or off the board LED based on whether the Watchdog reset the device.
+ *    \snippet qs_wdt_basic.c main_2
+ * -# Enter an infinite loop to hold the main program logic.
+ *    \snippet qs_wdt_basic.c main_3
+ * -# Test to see if the board button is currently being pressed.
+ *    \snippet qs_wdt_basic.c main_4
+ * -# If the button is pressed, turn on the board LED and reset the Watchdog
+ *    timer.
+ *    \snippet qs_wdt_basic.c main_5
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
diff --git a/src/ASF/sam0/drivers/wdt/wdt.c b/src/ASF/sam0/drivers/wdt/wdt.c
new file mode 100644
index 0000000000000000000000000000000000000000..3fae4d3c90ca0af2cebda1d4af516637e4feef35
--- /dev/null
+++ b/src/ASF/sam0/drivers/wdt/wdt.c
@@ -0,0 +1,254 @@
+/**
+ * \file
+ *
+ * \brief SAM Watchdog Driver
+ *
+ * Copyright (c) 2012-2020 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+#include "wdt.h"
+#include <system.h>
+
+/**
+ * \brief Sets up the WDT hardware module based on the configuration.
+ *
+ * Writes a given configuration of a WDT configuration to the
+ * hardware module, and initializes the internal device struct.
+ *
+ * \param[in]  config  Pointer to the configuration struct
+ *
+ * \return Status of the configuration procedure.
+ *
+ * \retval STATUS_OK     If the module was configured correctly
+ * \retval STATUS_ERR_INVALID_ARG   If invalid argument(s) were supplied
+ * \retval STATUS_ERR_IO  If the Watchdog module is locked to be always on
+ */
+#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || (SAMR30) || (SAMR34) || (SAMR35) || (WLR089)
+enum status_code wdt_set_config(
+		const struct wdt_conf *const config)
+{
+	/* Sanity check arguments */
+	Assert(config);
+
+	Wdt *const WDT_module = WDT;
+
+	/* Turn on the digital interface clock */
+	system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, MCLK_APBAMASK_WDT);
+
+	/* Check of the Watchdog has been locked to be always on, if so, abort */
+	if (wdt_is_locked()) {
+		return STATUS_ERR_IO;
+	}
+
+	/* Check for an invalid timeout period, abort if found */
+	if (config->timeout_period == WDT_PERIOD_NONE) {
+		return STATUS_ERR_INVALID_ARG;
+	}
+
+	/* Make sure the Window and Early Warning periods are not more than the
+	 * reset period, abort if either is invalid */
+	if ((config->timeout_period < config->window_period) ||
+			(config->timeout_period < config->early_warning_period)) {
+		return STATUS_ERR_INVALID_ARG;
+	}
+
+	/* Disable the Watchdog module */
+	WDT_module->CTRLA.reg &= ~WDT_CTRLA_ENABLE;
+
+	while (wdt_is_syncing()) {
+		/* Wait for all hardware modules to complete synchronization */
+	}
+
+	if(config->enable == false) {
+		return STATUS_OK;
+	}
+
+	uint32_t new_config = 0;
+
+	/* Update the timeout period value with the requested period */
+	new_config |= (config->timeout_period - 1) << WDT_CONFIG_PER_Pos;
+
+	/* Check if the user has requested a reset window period */
+	if (config->window_period != WDT_PERIOD_NONE) {
+		WDT_module->CTRLA.reg |= WDT_CTRLA_WEN;
+
+		/* Update and enable the timeout period value */
+		new_config |= (config->window_period - 1) << WDT_CONFIG_WINDOW_Pos;
+	} else {
+		/* Ensure the window enable control flag is cleared */
+		WDT_module->CTRLA.reg &= ~WDT_CTRLA_WEN;
+	}
+
+	while (wdt_is_syncing()) {
+		/* Wait for all hardware modules to complete synchronization */
+	}
+
+	/* Write the new Watchdog configuration */
+	WDT_module->CONFIG.reg = new_config;
+
+	/* Check if the user has requested an early warning period */
+	if (config->early_warning_period != WDT_PERIOD_NONE) {
+		/* Set the Early Warning period */
+		WDT_module->EWCTRL.reg
+			= (config->early_warning_period - 1) << WDT_EWCTRL_EWOFFSET_Pos;
+	}
+
+	/* Either enable or lock-enable the Watchdog timer depending on the user
+	 * settings */
+	if (config->always_on) {
+		WDT_module->CTRLA.reg |= WDT_CTRLA_ALWAYSON;
+	} else {
+		WDT_module->CTRLA.reg |= WDT_CTRLA_ENABLE;
+	}
+
+	while (wdt_is_syncing()) {
+		/* Wait for all hardware modules to complete synchronization */
+	}
+
+	return STATUS_OK;
+}
+#else
+enum status_code wdt_set_config(
+		const struct wdt_conf *const config)
+{
+	/* Sanity check arguments */
+	Assert(config);
+
+	Wdt *const WDT_module = WDT;
+
+	/* Turn on the digital interface clock */
+	system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, PM_APBAMASK_WDT);
+
+	/* Check of the Watchdog has been locked to be always on, if so, abort */
+	if (wdt_is_locked()) {
+		return STATUS_ERR_IO;
+	}
+
+	/* Check for an invalid timeout period, abort if found */
+	if (config->timeout_period == WDT_PERIOD_NONE) {
+		return STATUS_ERR_INVALID_ARG;
+	}
+
+	/* Make sure the Window and Early Warning periods are not more than the
+	 * reset period, abort if either is invalid */
+	if ((config->timeout_period < config->window_period) ||
+			(config->timeout_period < config->early_warning_period)) {
+		return STATUS_ERR_INVALID_ARG;
+	}
+
+	/* Disable the Watchdog module */
+	WDT_module->CTRL.reg &= ~WDT_CTRL_ENABLE;
+
+	while (wdt_is_syncing()) {
+		/* Wait for all hardware modules to complete synchronization */
+	}
+
+	if(config->enable == false) {
+		return STATUS_OK;
+	}
+
+	/* Configure GCLK channel and enable clock */
+	struct system_gclk_chan_config gclk_chan_conf;
+	gclk_chan_conf.source_generator = config->clock_source;
+	system_gclk_chan_set_config(WDT_GCLK_ID, &gclk_chan_conf);
+	system_gclk_chan_enable(WDT_GCLK_ID);
+	if (config->always_on) {
+		system_gclk_chan_lock(WDT_GCLK_ID);
+	}
+
+	uint32_t new_config = 0;
+
+	/* Update the timeout period value with the requested period */
+	new_config |= (config->timeout_period - 1) << WDT_CONFIG_PER_Pos;
+
+	/* Check if the user has requested a reset window period */
+	if (config->window_period != WDT_PERIOD_NONE) {
+		WDT_module->CTRL.reg |= WDT_CTRL_WEN;
+
+		/* Update and enable the timeout period value */
+		new_config |= (config->window_period - 1) << WDT_CONFIG_WINDOW_Pos;
+	} else {
+		/* Ensure the window enable control flag is cleared */
+		WDT_module->CTRL.reg &= ~WDT_CTRL_WEN;
+	}
+
+	while (wdt_is_syncing()) {
+		/* Wait for all hardware modules to complete synchronization */
+	}
+
+	/* Write the new Watchdog configuration */
+	WDT_module->CONFIG.reg = new_config;
+
+	/* Check if the user has requested an early warning period */
+	if (config->early_warning_period != WDT_PERIOD_NONE) {
+		while (wdt_is_syncing()) {
+			/* Wait for all hardware modules to complete synchronization */
+		}
+
+		/* Set the Early Warning period */
+		WDT_module->EWCTRL.reg
+			= (config->early_warning_period - 1) << WDT_EWCTRL_EWOFFSET_Pos;
+	}
+
+	/* Either enable or lock-enable the Watchdog timer depending on the user
+	 * settings */
+	if (config->always_on) {
+		WDT_module->CTRL.reg |= WDT_CTRL_ALWAYSON;
+	} else {
+		WDT_module->CTRL.reg |= WDT_CTRL_ENABLE;
+	}
+
+	while (wdt_is_syncing()) {
+		/* Wait for all hardware modules to complete synchronization */
+	}
+
+	return STATUS_OK;
+}
+#endif
+
+/**
+ * \brief Resets the count of the running Watchdog Timer that was previously enabled.
+ *
+ * Resets the current count of the Watchdog Timer, restarting the timeout
+ * period count elapsed. This function should be called after the window
+ * period (if one was set in the module configuration) but before the timeout
+ * period to prevent a reset of the system.
+ */
+void wdt_reset_count(void)
+{
+	Wdt *const WDT_module = WDT;
+
+	/* Disable the Watchdog module */
+	WDT_module->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
+
+	while (wdt_is_syncing()) {
+		/* Wait for all hardware modules to complete synchronization */
+	}
+}
diff --git a/src/ASF/sam0/drivers/wdt/wdt.h b/src/ASF/sam0/drivers/wdt/wdt.h
new file mode 100644
index 0000000000000000000000000000000000000000..088f5891d25e85e74ceab66be5d68a4ad5a6308f
--- /dev/null
+++ b/src/ASF/sam0/drivers/wdt/wdt.h
@@ -0,0 +1,495 @@
+/**
+ * \file
+ *
+ * \brief SAM Watchdog Driver
+ *
+ * Copyright (c) 2012-2020 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+#ifndef WDT_H_INCLUDED
+#define WDT_H_INCLUDED
+
+/**
+ * \defgroup asfdoc_sam0_wdt_group SAM Watchdog (WDT) Driver
+ *
+ * This driver for Atmel&reg; | SMART ARM&reg;-based microcontrollers provides
+ * an interface for the configuration and management of the device's Watchdog
+ * Timer module, including the enabling, disabling, and kicking within the device.
+ * The following driver API modes are covered by this manual:
+ *
+ *  - Polled APIs
+ * \if WDT_CALLBACK_MODE
+ *  - Callback APIs
+ * \endif
+ *
+ * The following peripherals are used by this module:
+ *  - WDT (Watchdog Timer)
+ *
+ * The following devices can use this module:
+ *  - Atmel | SMART SAM D20/D21
+ *  - Atmel | SMART SAM R21
+ *  - Atmel | SMART SAM D09/D10/D11
+ *  - Atmel | SMART SAM L21/L22
+ *  - Atmel | SMART SAM DA1
+ *  - Atmel | SMART SAM C20/C21
+ *  - Atmel | SMART SAM HA1
+ *  - Atmel | SMART SAM R30
+ *  - Atmel | SMART SAM R34
+ *  - Atmel | SMART SAM R35
+ *
+ * The outline of this documentation is as follows:
+ *  - \ref asfdoc_sam0_wdt_prerequisites
+ *  - \ref asfdoc_sam0_wdt_module_overview
+ *  - \ref asfdoc_sam0_wdt_special_considerations
+ *  - \ref asfdoc_sam0_wdt_extra_info
+ *  - \ref asfdoc_sam0_wdt_examples
+ *  - \ref asfdoc_sam0_wdt_api_overview
+ *
+ *
+ * \section asfdoc_sam0_wdt_prerequisites Prerequisites
+ *
+ * There are no prerequisites for this module.
+ *
+ *
+ * \section asfdoc_sam0_wdt_module_overview Module Overview
+ *
+ * The Watchdog module (WDT) is designed to give an added level of safety in
+ * critical systems, to ensure a system reset is triggered in the case of a
+ * deadlock or other software malfunction that prevents normal device operation.
+ *
+ * At a basic level, the Watchdog is a system timer with a fixed period; once
+ * enabled, it will continue to count ticks of its asynchronous clock until
+ * it is periodically reset, or the timeout period is reached. In the event of a
+ * Watchdog timeout, the module will trigger a system reset identical to a pulse
+ * of the device's reset pin, resetting all peripherals to their power-on
+ * default states and restarting the application software from the reset vector.
+ *
+ * In many systems, there is an obvious upper bound to the amount of time each
+ * iteration of the main application loop can be expected to run, before a
+ * malfunction can be assumed (either due to a deadlock waiting on hardware or
+ * software, or due to other means). When the Watchdog is configured with a
+ * timeout period equal to this upper bound, a malfunction in the system will
+ * force a full system reset to allow for a graceful recovery.
+ *
+ * \subsection asfdoc_sam0_wdt_module_locked_mode Locked Mode
+ * The Watchdog configuration can be set in the device fuses and locked in
+ * hardware, so that no software changes can be made to the Watchdog
+ * configuration. Additionally, the Watchdog can be locked on in software if it
+ * is not already locked, so that the module configuration cannot be modified
+ * until a power on reset of the device.
+ *
+ * The locked configuration can be used to ensure that faulty software does not
+ * cause the Watchdog configuration to be changed, preserving the level of
+ * safety given by the module.
+ *
+ * \subsection asfdoc_sam0_wdt_module_window_mode Window Mode
+ * Just as there is a reasonable upper bound to the time the main program loop
+ * should take for each iteration, there is also in many applications a lower
+ * bound, i.e. a \a minimum time for which each loop iteration should run for
+ * under normal circumstances. To guard against a system failure resetting the
+ * Watchdog in a tight loop (or a failure in the system application causing the
+ * main loop to run faster than expected) a "Window" mode can be enabled to
+ * disallow resetting of the Watchdog counter before a certain period of time.
+ * If the Watchdog is not reset \a after the window opens but not \a before the
+ * Watchdog expires, the system will reset.
+ *
+ * \subsection asfdoc_sam0_wdt_module_early_warning Early Warning
+ * In some cases it is desirable to receive an early warning that the Watchdog is
+ * about to expire, so that some system action (such as saving any system
+ * configuration data for failure analysis purposes) can be performed before the
+ * system reset occurs. The Early Warning feature of the Watchdog module allows
+ * such a notification to be requested; after the configured early warning time
+ * (but before the expiry of the Watchdog counter) the Early Warning flag will
+ * become set, so that the user application can take an appropriate action.
+ *
+ * \note It is important to note that the purpose of the Early Warning feature
+ *       is \a not to allow the user application to reset the Watchdog; doing
+ *       so will defeat the safety the module gives to the user application.
+ *       Instead, this feature should be used purely to perform any tasks that
+ *       need to be undertaken before the system reset occurs.
+ *
+ * \subsection asfdoc_sam0_wdt_module_overview_physical Physical Connection
+ *
+ * \ref asfdoc_sam0_wdt_module_int_connections "The figure below" shows how
+ * this module is interconnected within the device.
+ *
+ * \anchor asfdoc_sam0_wdt_module_int_connections
+ * \dot
+ * digraph overview {
+ *   rankdir=LR;
+ *   node [label="GCLK*\nGeneric Clock" shape=square] wdt_clock;
+ *
+ *   subgraph driver {
+ *     node [label="<f0> WDT | <f1> Watchdog Counter" shape=record] wdt_module;
+ *     node [label="System Reset Logic" shape=ellipse style=filled fillcolor=lightgray] sys_reset;
+ *   }
+ *
+ *   wdt_clock     -> wdt_module:f1;
+ *   wdt_module:f1 -> sys_reset;
+ * }
+ * \enddot
+ *
+ * \note Watchdog Counter of SAM L21/L22/R30/R34/R35 is \a not provided by GCLK, but it uses an
+ *       internal 1KHz OSCULP32K output clock.
+ *
+ * \section asfdoc_sam0_wdt_special_considerations Special Considerations
+ *
+ * On some devices the Watchdog configuration can be fused to be always on in
+ * a particular configuration; if this mode is enabled the Watchdog is not
+ * software configurable and can have its count reset and early warning state
+ * checked/cleared only.
+ *
+ * \section asfdoc_sam0_wdt_extra_info Extra Information
+ *
+ * For extra information, see \ref asfdoc_sam0_wdt_extra. This includes:
+ *  - \ref asfdoc_sam0_wdt_extra_acronyms
+ *  - \ref asfdoc_sam0_wdt_extra_dependencies
+ *  - \ref asfdoc_sam0_wdt_extra_errata
+ *  - \ref asfdoc_sam0_wdt_extra_history
+ *
+ *
+ * \section asfdoc_sam0_wdt_examples Examples
+ *
+ * For a list of examples related to this driver, see
+ * \ref asfdoc_sam0_wdt_exqsg.
+ *
+ * \section asfdoc_sam0_wdt_api_overview API Overview
+ * @{
+ */
+
+#include <compiler.h>
+#include <clock.h>
+#include <gclk.h>
+
+#if WDT_CALLBACK_MODE == true
+#  include "wdt_callback.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Watchdog Timer period configuration enum.
+ *
+ * Enum for the possible period settings of the Watchdog timer module, for
+ * values requiring a period as a number of Watchdog timer clock ticks.
+ */
+enum wdt_period {
+	/** No Watchdog period. This value can only be used when setting the
+	 *  Window and Early Warning periods; its use as the Watchdog Reset
+	 *  Period is invalid. */
+	WDT_PERIOD_NONE     = 0,
+	/** Watchdog period of 8 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_8CLK     = 1,
+	/** Watchdog period of 16 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_16CLK    = 2,
+	/** Watchdog period of 32 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_32CLK    = 3,
+	/** Watchdog period of 64 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_64CLK    = 4,
+	/** Watchdog period of 128 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_128CLK   = 5,
+	/** Watchdog period of 256 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_256CLK   = 6,
+	/** Watchdog period of 512 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_512CLK   = 7,
+	/** Watchdog period of 1024 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_1024CLK  = 8,
+	/** Watchdog period of 2048 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_2048CLK  = 9,
+	/** Watchdog period of 4096 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_4096CLK  = 10,
+	/** Watchdog period of 8192 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_8192CLK  = 11,
+	/** Watchdog period of 16384 clocks of the Watchdog Timer Generic Clock */
+	WDT_PERIOD_16384CLK = 12,
+};
+
+/**
+ * \brief Watchdog Timer configuration structure.
+ *
+ *  Configuration structure for a Watchdog Timer instance. This
+ *  structure should be initialized by the \ref wdt_get_config_defaults()
+ *  function before being modified by the user application.
+ */
+struct wdt_conf {
+	/** If \c true, the Watchdog will be locked to the current configuration
+	 *  settings when the Watchdog is enabled */
+	bool always_on;
+	/** Enable/Disable the Watchdog Timer */
+	bool enable;
+#if !(SAML21) && !(SAML22) && !(SAMC20) && !(SAMC21) && !(SAMR30) && !(SAMR34) && !(SAMR35) && !(WLR089)
+	/** GCLK generator used to clock the peripheral except SAM L21/L22/C21/C20/R30*/
+	enum gclk_generator clock_source;
+#endif
+	/** Number of Watchdog timer clock ticks until the Watchdog expires */
+	enum wdt_period timeout_period;
+	/** Number of Watchdog timer clock ticks until the reset window opens */
+	enum wdt_period window_period;
+	/** Number of Watchdog timer clock ticks until the early warning flag is
+	 *  set */
+	enum wdt_period early_warning_period;
+};
+
+/** \name Configuration and Initialization
+ * @{
+ */
+
+/**
+ * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
+ *
+ * Checks to see if the underlying hardware peripheral module(s) are currently
+ * synchronizing across multiple clock domains to the hardware bus. This
+ * function can be used to delay further operations on a module until such time
+ * that it is ready, to prevent blocking delays for synchronization in the
+ * user application.
+ *
+ * \return Synchronization status of the underlying hardware module(s).
+ *
+ * \retval false If the module has completed synchronization
+ * \retval true If the module synchronization is ongoing
+ */
+static inline bool wdt_is_syncing(void)
+{
+	Wdt *const WDT_module = WDT;
+
+#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || (SAMR30) || (SAMR34) || (SAMR35) || (WLR089)
+	if (WDT_module->SYNCBUSY.reg) {
+#else
+	if (WDT_module->STATUS.reg & WDT_STATUS_SYNCBUSY) {
+#endif
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * \brief Initializes a Watchdog Timer configuration structure to defaults.
+ *
+ *  Initializes a given Watchdog Timer configuration structure to a set of
+ *  known default values. This function should be called on all new
+ *  instances of these configuration structures before being modified by the
+ *  user application.
+ *
+ *  The default configuration is as follows:
+ *   \li Not locked, to allow for further (re-)configuration
+ *   \li Enable WDT
+ *   \li Watchdog timer sourced from Generic Clock Channel 4
+ *   \li A timeout period of 16384 clocks of the Watchdog module clock
+ *   \li No window period, so that the Watchdog count can be reset at any time
+ *   \li No early warning period to indicate the Watchdog will soon expire
+ *
+ *  \param[out] config  Configuration structure to initialize to default values
+ */
+static inline void wdt_get_config_defaults(
+		struct wdt_conf *const config)
+{
+	/* Sanity check arguments */
+	Assert(config);
+
+	/* Default configuration values */
+	config->always_on            = false;
+	config->enable               = true;
+#if !(SAML21) && !(SAML22) && !(SAMC20) && !(SAMC21) && !(SAMR30) && !(SAMR34) && !(SAMR35) && !(WLR089)
+	config->clock_source         = GCLK_GENERATOR_4;
+#endif
+	config->timeout_period       = WDT_PERIOD_16384CLK;
+	config->window_period        = WDT_PERIOD_NONE;
+	config->early_warning_period = WDT_PERIOD_NONE;
+}
+
+enum status_code wdt_set_config(
+		const struct wdt_conf *const config);
+
+/** \brief Determines if the Watchdog timer is currently locked in an enabled state.
+ *
+ *  Determines if the Watchdog timer is currently enabled and locked, so that
+ *  it cannot be disabled or otherwise reconfigured.
+ *
+ *  \return Current Watchdog lock state.
+ */
+static inline bool wdt_is_locked(void)
+{
+	Wdt *const WDT_module = WDT;
+
+#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || (SAMR30) || (SAMR34) || (SAMR35) || (WLR089)
+	return (WDT_module->CTRLA.reg & WDT_CTRLA_ALWAYSON);
+#else
+	return (WDT_module->CTRL.reg & WDT_CTRL_ALWAYSON);
+#endif
+}
+
+/** @} */
+
+/** \name Timeout and Early Warning Management
+ * @{
+ */
+
+/** \brief Clears the Watchdog timer early warning period elapsed flag.
+ *
+ *  Clears the Watchdog timer early warning period elapsed flag, so that a new
+ *  early warning period can be detected.
+ */
+static inline void wdt_clear_early_warning(void)
+{
+	Wdt *const WDT_module = WDT;
+
+	WDT_module->INTFLAG.reg = WDT_INTFLAG_EW;
+}
+
+/** \brief Determines if the Watchdog timer early warning period has elapsed.
+ *
+ *  Determines if the Watchdog timer early warning period has elapsed.
+ *
+ *  \note If no early warning period was configured, the value returned by this
+ *        function is invalid.
+ *
+ *  \return Current Watchdog Early Warning state.
+ */
+static inline bool wdt_is_early_warning(void)
+{
+	Wdt *const WDT_module = WDT;
+
+	return (WDT_module->INTFLAG.reg & WDT_INTFLAG_EW);
+}
+
+void wdt_reset_count(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+/**
+ * \page asfdoc_sam0_wdt_extra Extra Information for WDT Driver
+ *
+ * \section asfdoc_sam0_wdt_extra_acronyms Acronyms
+ * The table below presents the acronyms used in this module:
+ *
+ * <table>
+ *	<tr>
+ *		<th>Acronym</th>
+ *		<th>Description</th>
+ *	</tr>
+ *	<tr>
+ *		<td>WDT</td>
+ *		<td>Watchdog Timer</td>
+ *	</tr>
+ * </table>
+ *
+ *
+ * \section asfdoc_sam0_wdt_extra_dependencies Dependencies
+ * This driver has the following dependencies:
+ *
+ *  - \ref asfdoc_sam0_system_clock_group "System Clock Driver"
+ *
+ *
+ * \section asfdoc_sam0_wdt_extra_errata Errata
+ * There are no errata related to this driver.
+ *
+ *
+ * \section asfdoc_sam0_wdt_extra_history Module History
+ * An overview of the module history is presented in the table below, with
+ * details on the enhancements and fixes made to the module since its first
+ * release. The current version of this corresponds to the newest version in
+ * the table.
+ *
+ * <table>
+ *	<tr>
+ *		<th>Changelog</th>
+ *	</tr>
+ *	<tr>
+ *		<td>Driver updated to follow driver type convention:
+ *             \li wdt_init, wdt_enable, wdt_disable functions removed
+ *             \li wdt_set_config function added
+ *             \li WDT module enable state moved inside the configuration struct </td>
+ *	</tr>
+ *	<tr>
+ *		<td>Initial Release</td>
+ *	</tr>
+ * </table>
+ */
+
+/**
+ * \page asfdoc_sam0_wdt_exqsg Examples for WDT Driver
+ *
+ * This is a list of the available Quick Start guides (QSGs) and example
+ * applications for \ref asfdoc_sam0_wdt_group. QSGs are simple examples with
+ * step-by-step instructions to configure and use this driver in a selection of
+ * use cases. Note that a QSG can be compiled as a standalone application or be
+ * added to the user application.
+ *
+ *  - \subpage asfdoc_sam0_wdt_basic_use_case
+ * \if WDT_CALLBACK_MODE
+ *  - \subpage asfdoc_sam0_wdt_callback_use_case
+ * \endif
+ *
+ * \page asfdoc_sam0_wdt_document_revision_history Document Revision History
+ *
+ * <table>
+ *	<tr>
+ *		<th>Doc. Rev.</th>
+ *		<th>Date</th>
+ *		<th>Comments</th>
+ *	</tr>
+ *	<tr>
+ *		<td>42124E</td>
+ *		<td>12/2015</td>
+ *		<td>Added support for SAM L21/L22, SAM DA1, SAM D09, SAM R30, and SAM C20/C21</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42124D</td>
+ *		<td>12/2014</td>
+ *		<td>Added SAM R21 and SAM D10/D11 support</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42124C</td>
+ *		<td>01/2014</td>
+ *		<td>Add SAM D21 support</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42124B</td>
+ *		<td>06/2013</td>
+ *		<td>Corrected documentation typos</td>
+ *	</tr>
+ *	<tr>
+ *		<td>42124A</td>
+ *		<td>06/2013</td>
+ *		<td>Initial release</td>
+ *	</tr>
+ * </table>
+ */
+
+#endif /* WDT_H_INCLUDED */
diff --git a/src/ArduinoZeroTemplate.c b/src/ArduinoZeroTemplate.c
index 2d0e0ebd842e39f2b82dd73571e86ca9079b58cd..65169f5702727a128e0e5064e27a0df7dc541651 100644
--- a/src/ArduinoZeroTemplate.c
+++ b/src/ArduinoZeroTemplate.c
@@ -63,7 +63,7 @@ void ArduinoZeroTemplate(void)
 
 	// DAC example. All configuration needed is already done in Init. DAC is 10 bits and can convert in 350 ksps
 	dac_chan_write(&dac0_instance_struct, DAC_CHANNEL_0, 1023);	// 1023 is the value and is also maximum value.
-	
+
 	SerialUSB.begin(115200);
 
 	while (true)
diff --git a/src/sam.h b/src/sam.h
new file mode 100644
index 0000000000000000000000000000000000000000..80a1c486cda80fa9ddd3dc896e11824ae8e9a006
--- /dev/null
+++ b/src/sam.h
@@ -0,0 +1,567 @@
+/* ----------------------------------------------------------------------------
+ *         SAM Software Package License
+ * ----------------------------------------------------------------------------
+ * 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 condition is met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+#ifndef _SAM_INCLUDED_
+#define _SAM_INCLUDED_
+
+#define part_is_defined(part) (defined(__ ## part ## __))
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAMG family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAMG55 series */
+#define SAMG55J1 ( \
+    part_is_defined( SAMG55J19 ) )
+
+#define SAMG55G1 ( \
+    part_is_defined( SAMG55G19 ) )
+
+/* Entire SAMG55 series */
+#define SAMG55_SERIES (SAMG55J1 || SAMG55G1)
+
+/* SAMG54 series */
+#define SAMG54N1 ( \
+    part_is_defined( SAMG54N19 ) )
+
+#define SAMG54J1 ( \
+    part_is_defined( SAMG54J19 ) )
+
+#define SAMG54G1 ( \
+    part_is_defined( SAMG54G19 ) )
+
+/* Entire SAMG54 series */
+#define SAMG54_SERIES (SAMG54N1 || SAMG54J1 || SAMG54G1)
+
+
+
+/* Entire SAMG family */
+#define SAMG_SERIES ( SAMG55_SERIES || SAMG54_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAMD family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAMD10 series */
+#define SAMD10C14 ( \
+    part_is_defined( SAMD10C14A ) )
+
+#define SAMD10C13 ( \
+    part_is_defined( SAMD10C13A ) )
+
+#define SAMD10D13A ( \
+    part_is_defined( SAMD10D13AS ) || \
+    part_is_defined( SAMD10D13AM ) )
+
+#define SAMD10D14A ( \
+    part_is_defined( SAMD10D14AS ) || \
+    part_is_defined( SAMD10D14AM ) )
+
+/* Entire SAMD10 series */
+#define SAMD10_SERIES (SAMD10C14 || SAMD10C13 || SAMD10D13A || SAMD10D14A)
+
+/* SAMD11 series */
+#define SAMD11C14 ( \
+    part_is_defined( SAMD11C14A ) )
+
+#define SAMD11D14A ( \
+    part_is_defined( SAMD11D14AS ) || \
+    part_is_defined( SAMD11D14AM ) )
+
+/* Entire SAMD11 series */
+#define SAMD11_SERIES (SAMD11C14 || SAMD11D14A)
+
+/* SAMD21 series */
+#define SAMD21J17 ( \
+    part_is_defined( SAMD21J17A ) )
+
+#define SAMD21G17A ( \
+    part_is_defined( SAMD21G17AU ) )
+
+#define SAMD21E15B ( \
+    part_is_defined( SAMD21E15BU ) )
+
+#define SAMD21E15 ( \
+    part_is_defined( SAMD21E15A ) || \
+    part_is_defined( SAMD21E15B ) || \
+    part_is_defined( SAMD21E15L ) )
+
+#define SAMD21E16 ( \
+    part_is_defined( SAMD21E16A ) || \
+    part_is_defined( SAMD21E16B ) || \
+    part_is_defined( SAMD21E16L ) )
+
+#define SAMD21E17 ( \
+    part_is_defined( SAMD21E17A ) )
+
+#define SAMD21E18 ( \
+    part_is_defined( SAMD21E18A ) )
+
+#define SAMD21E16B ( \
+    part_is_defined( SAMD21E16BU ) )
+
+#define SAMD21J15 ( \
+    part_is_defined( SAMD21J15A ) || \
+    part_is_defined( SAMD21J15B ) )
+
+#define SAMD21J16 ( \
+    part_is_defined( SAMD21J16A ) || \
+    part_is_defined( SAMD21J16B ) )
+
+#define SAMD21G16 ( \
+    part_is_defined( SAMD21G16A ) || \
+    part_is_defined( SAMD21G16B ) )
+
+#define SAMD21G17 ( \
+    part_is_defined( SAMD21G17A ) )
+
+#define SAMD21G18A ( \
+    part_is_defined( SAMD21G18AU ) )
+
+#define SAMD21G15 ( \
+    part_is_defined( SAMD21G15A ) || \
+    part_is_defined( SAMD21G15B ) )
+
+#define SAMD21G18 ( \
+    part_is_defined( SAMD21G18A ) )
+
+#define SAMD21J18 ( \
+    part_is_defined( SAMD21J18A ) )
+	
+#define SAMD51G18A ( \
+    part_is_defined( SAMD51G18A ) )
+
+#define SAMD51G19A ( \
+    part_is_defined( SAMD51G19A ) )
+
+#define SAMD51J19A ( \
+    part_is_defined( SAMD51J19A ) )
+
+#define SAMD51J20A ( \
+    part_is_defined( SAMD51J20A ) )
+
+#define SAMD51N19A ( \
+    part_is_defined( SAMD51N19A ) )
+
+#define SAMD51N20A ( \
+    part_is_defined( SAMD51N20A ) )
+
+#define SAMD51P19A ( \
+    part_is_defined( SAMD51P19A ) )
+
+#define SAMD51P20A ( \
+    part_is_defined( SAMD51P20A ) )
+
+	
+/* Entire SAMD21 series */
+#define SAMD21_SERIES (SAMD21J17 || SAMD21G17A || SAMD21E15B || SAMD21E15 || SAMD21E16 || SAMD21E17 || SAMD21E18 || SAMD21E16B || SAMD21J15 || SAMD21J16 || SAMD21G16 || SAMD21G17 || SAMD21G18A || SAMD21G15 || SAMD21G18 || SAMD21J18)
+
+/* Entire SAMD51 series */
+#define SAMD51_SERIES (SAMD51G18A || SAMD51G19A || SAMD51J19A || SAMD51J20A || SAMD51N19A || SAMD51N20A || SAMD51P19A || SAMD51P20A)
+
+/* Entire SAMD family */
+#define SAMD_SERIES (SAMD10_SERIES || SAMD11_SERIES || SAMD21_SERIES || SAMD51_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAML family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAML21 series */
+#define SAML21E18A ( \
+    part_is_defined( SAML21E18A ) )
+#define SAML21G18A ( \
+    part_is_defined( SAML21G18A ) )
+#define SAML21J18A ( \
+    part_is_defined( SAML21J18A ) )
+
+#define SAML21E15B ( \
+    part_is_defined( SAML21E15B ) )
+#define SAML21E16B ( \
+    part_is_defined( SAML21E16B ) )
+#define SAML21E17B ( \
+    part_is_defined( SAML21E17B ) )
+#define SAML21E18B ( \
+    part_is_defined( SAML21E18B ) )
+#define SAML21G16B ( \
+    part_is_defined( SAML21G16B ) )
+#define SAML21G17B ( \
+    part_is_defined( SAML21G17B ) )
+#define SAML21G18B ( \
+    part_is_defined( SAML21G18B ) )
+#define SAML21J16B ( \
+    part_is_defined( SAML21J16B ) )
+#define SAML21J17B ( \
+    part_is_defined( SAML21J17B ) )
+#define SAML21J18B ( \
+    part_is_defined( SAML21J18B ) )
+#define SAML21J18BU ( \
+    part_is_defined( SAML21J18BU ) )
+
+/* Entire SAML21A series */
+#define SAML21_SERIES (SAML21E18A || SAML21G18A || SAML21J18A)
+
+/* Entire SAML21B series */
+#define SAML21B_SERIES (SAML21E15B || SAML21E16B || SAML21E17B || SAML21E18B || SAML21G16B || SAML21G17B || SAML21G18B || SAML21J16B || SAML21J17B || SAML21J18B || SAML21J18BU)
+
+/* Entire SAMD family */
+#define SAML_SERIES (SAML21A_SERIES || SAML21B_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAMC family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAMC21 series */
+#define SAMC21E15A ( \
+    part_is_defined( SAMC21E15A ) )
+#define SAMC21E16A ( \
+    part_is_defined( SAMC21E16A ) )
+#define SAMC21E17A ( \
+    part_is_defined( SAMC21E17A ) )
+#define SAMC21E18A ( \
+    part_is_defined( SAMC21E18A ) )
+#define SAMC21G15A ( \
+    part_is_defined( SAMC21G15A ) )
+#define SAMC21G16A ( \
+    part_is_defined( SAMC21G16A ) )
+#define SAMC21G17A ( \
+    part_is_defined( SAMC21G17A ) )
+#define SAMC21G18A ( \
+    part_is_defined( SAMC21G18A ) )
+#define SAMC21J15A ( \
+    part_is_defined( SAMC21J15A ) )
+#define SAMC21J16A ( \
+    part_is_defined( SAMC21J16A ) )
+#define SAMC21J17A ( \
+    part_is_defined( SAMC21J17A ) )
+#define SAMC21J18A ( \
+    part_is_defined( SAMC21J18A ) )
+#define SAMC21J18AU ( \
+    part_is_defined( SAMC21J18AU ) )
+
+
+/* Entire SAMC21 series */
+#define SAMC21_SERIES (SAMC21E15A || SAMC21E16A || SAMC21E17A || SAMC21E18A || SAMC21G15A || SAMC21G16A || SAMC21G17A || SAMC21G18A || SAMC21J15A || SAMC21J16A || SAMC21J17A || SAMC21J18A || SAMC21J18AU)
+
+/* Entire SAMC family */
+#define SAMC_SERIES SAMC21_SERIES
+
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAMS family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAMS70 series */
+#define SAMS70Q2 ( \
+    part_is_defined( SAMS70Q20 ) || \
+    part_is_defined( SAMS70Q21 ) )
+
+#define SAMS70Q1 ( \
+    part_is_defined( SAMS70Q19 ) )
+
+#define SAMS70N2 ( \
+    part_is_defined( SAMS70N20 ) || \
+    part_is_defined( SAMS70N21 ) )
+
+#define SAMS70N1 ( \
+    part_is_defined( SAMS70N19 ) )
+
+#define SAMS70J2 ( \
+    part_is_defined( SAMS70J20 ) || \
+    part_is_defined( SAMS70J21 ) )
+
+#define SAMS70J1 ( \
+    part_is_defined( SAMS70J19 ) )
+
+/* Entire SAMS70 series */
+#define SAMS70_SERIES (SAMS70Q2 || SAMS70Q1 || SAMS70N2 || SAMS70N1 || SAMS70J2 || SAMS70J1)
+
+/* Entire SAMS family */
+#define SAMS_SERIES (SAMS70_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAME family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAME70 series */
+#define SAME70N1 ( \
+    part_is_defined( SAME70N19 ) )
+
+#define SAME70N2 ( \
+    part_is_defined( SAME70N20 ) || \
+    part_is_defined( SAME70N21 ) )
+
+#define SAME70J1 ( \
+    part_is_defined( SAME70J19 ) )
+
+#define SAME70J2 ( \
+    part_is_defined( SAME70J20 ) || \
+    part_is_defined( SAME70J21 ) )
+
+#define SAME70Q1 ( \
+    part_is_defined( SAME70Q19 ) )
+
+#define SAME70Q2 ( \
+    part_is_defined( SAME70Q20 ) || \
+    part_is_defined( SAME70Q21 ) )
+
+/* Entire SAME70 series */
+#define SAME70_SERIES (SAME70N1 || SAME70N2 || SAME70J1 || SAME70J2 || SAME70Q1 || SAME70Q2)
+
+/* Entire SAME family */
+#define SAME_SERIES (SAME70_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAM3 family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAM3U series */
+#define SAM3U1 ( \
+    part_is_defined( SAM3U1E ) || \
+    part_is_defined( SAM3U1C ) )
+
+#define SAM3U2 ( \
+    part_is_defined( SAM3U2E ) || \
+    part_is_defined( SAM3U2C ) )
+
+#define SAM3U4 ( \
+    part_is_defined( SAM3U4E ) || \
+    part_is_defined( SAM3U4C ) )
+
+/* Entire SAM3U series */
+#define SAM3U_SERIES (SAM3U1 || SAM3U2 || SAM3U4)
+
+/* SAM3XA series */
+#define SAM3A4 ( \
+    part_is_defined( SAM3A4C ) )
+
+#define SAM3X4 ( \
+    part_is_defined( SAM3X4C ) || \
+    part_is_defined( SAM3X4E ) )
+
+#define SAM3A8 ( \
+    part_is_defined( SAM3A8C ) )
+
+#define SAM3X8 ( \
+    part_is_defined( SAM3X8C ) || \
+    part_is_defined( SAM3X8E ) || \
+    part_is_defined( SAM3X8H ) )
+
+/* Entire SAM3XA series */
+#define SAM3XA_SERIES (SAM3A4 || SAM3X4 || SAM3A8 || SAM3X8)
+
+/* Entire SAM3 family */
+#define SAM3_SERIES (SAM3U_SERIES || SAM3XA_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAMR family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAMR21 series */
+#define SAMR21E16 ( \
+    part_is_defined( SAMR21E16A ) )
+
+#define SAMR21E18 ( \
+    part_is_defined( SAMR21E18A ) )
+
+#define SAMR21G16 ( \
+    part_is_defined( SAMR21G16A ) )
+
+#define SAMR21G17 ( \
+    part_is_defined( SAMR21G17A ) )
+
+#define SAMR21G18 ( \
+    part_is_defined( SAMR21G18A ) )
+
+#define SAMR21E17 ( \
+    part_is_defined( SAMR21E17A ) )
+
+/* Entire SAMR21 series */
+#define SAMR21_SERIES (SAMR21E16 || SAMR21E18 || SAMR21G16 || SAMR21G17 || SAMR21G18 || SAMR21E17)
+
+/* Entire SAMR family */
+#define SAMR_SERIES (SAMR21_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * SAM4 family
+ * ----------------------------------------------------------------------------
+ */
+
+/* SAM4N series */
+#define SAM4N8 ( \
+    part_is_defined( SAM4N8A ) || \
+    part_is_defined( SAM4N8B ) || \
+    part_is_defined( SAM4N8C ) )
+
+#define SAM4N16 ( \
+    part_is_defined( SAM4N16B ) || \
+    part_is_defined( SAM4N16C ) )
+
+/* Entire SAM4N series */
+#define SAM4N_SERIES (SAM4N8 || SAM4N16)
+
+/* SAM4S series */
+#define SAM4S8 ( \
+    part_is_defined( SAM4S8C ) || \
+    part_is_defined( SAM4S8B ) )
+
+#define SAM4S2 ( \
+    part_is_defined( SAM4S2A ) || \
+    part_is_defined( SAM4S2B ) || \
+    part_is_defined( SAM4S2C ) )
+
+#define SAM4S4 ( \
+    part_is_defined( SAM4S4A ) || \
+    part_is_defined( SAM4S4B ) || \
+    part_is_defined( SAM4S4C ) )
+
+#define SAM4SD16 ( \
+    part_is_defined( SAM4SD16B ) || \
+    part_is_defined( SAM4SD16C ) )
+
+#define SAM4S16 ( \
+    part_is_defined( SAM4S16C ) || \
+    part_is_defined( SAM4S16B ) )
+
+#define SAM4SD32 ( \
+    part_is_defined( SAM4SD32B ) || \
+    part_is_defined( SAM4SD32C ) )
+
+#define SAM4SA16 ( \
+    part_is_defined( SAM4SA16B ) || \
+    part_is_defined( SAM4SA16C ) )
+
+/* Entire SAM4S series */
+#define SAM4S_SERIES (SAM4S8 || SAM4S2 || SAM4S4 || SAM4SD16 || SAM4S16 || SAM4SD32 || SAM4SA16)
+
+/* SAM4E series */
+#define SAM4E16 ( \
+    part_is_defined( SAM4E16E ) || \
+    part_is_defined( SAM4E16C ) )
+
+#define SAM4E8 ( \
+    part_is_defined( SAM4E8E ) || \
+    part_is_defined( SAM4E8C ) )
+
+/* Entire SAM4E series */
+#define SAM4E_SERIES (SAM4E16 || SAM4E8)
+
+/* SAM4C series */
+#define SAM4C4C_ ( \
+    part_is_defined( SAM4C4C_0 ) || \
+    part_is_defined( SAM4C4C_1 ) )
+
+#define SAM4C8C_ ( \
+    part_is_defined( SAM4C8C_0 ) || \
+    part_is_defined( SAM4C8C_1 ) )
+
+#define SAM4C16C_ ( \
+    part_is_defined( SAM4C16C_0 ) || \
+    part_is_defined( SAM4C16C_1 ) )
+
+#define SAM4C32C_ ( \
+    part_is_defined( SAM4C32C_0 ) || \
+    part_is_defined( SAM4C32C_1 ) )
+
+#define SAM4C32E_ ( \
+    part_is_defined( SAM4C32E_0 ) || \
+    part_is_defined( SAM4C32E_1 ) )
+
+/* Entire SAM4C series */
+#define SAM4C_SERIES (SAM4C4C_ || SAM4C8C_ || SAM4C16C_ || SAM4C32C_ || SAM4C32E_)
+
+/* Entire SAM4 family */
+#define SAM4_SERIES (SAM4N_SERIES || SAM4S_SERIES || SAM4E_SERIES || SAM4C_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Whole SAM product line
+ * ----------------------------------------------------------------------------
+ */
+
+#define SAM (SAM4_SERIES || SAMR_SERIES || SAM3_SERIES || SAMS_SERIES || SAME_SERIES || SAMD_SERIES || SAML_SERIES || SAMG_SERIES ||SAMC_SERIES)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Header inclusion
+ * ----------------------------------------------------------------------------
+ */
+
+#if SAMG_SERIES
+#include "samg.h"
+#endif /* SAMG_SERIES */
+
+#if SAME_SERIES
+#include "same.h"
+#endif /* SAME_SERIES */
+
+#if SAMD_SERIES
+#include "samd.h"
+#endif /* SAMD_SERIES */
+
+#if SAML_SERIES
+#include "saml.h"
+#endif /* SAML_SERIES */
+
+#if SAMC_SERIES
+#include "samc.h"
+#endif /* SAMC_SERIES */
+
+#if SAMS_SERIES
+#include "sams.h"
+#endif /* SAMS_SERIES */
+
+#if SAM3_SERIES
+#include "sam3.h"
+#endif /* SAM3_SERIES */
+
+#if SAMR_SERIES
+#include "samr.h"
+#endif /* SAMR_SERIES */
+
+#if SAM4_SERIES
+#include "sam4.h"
+#endif /* SAM4_SERIES */
+
+#endif