Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Revision:
18:6a4db94011d3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-dev/targets/TARGET_Atmel/TARGET_SAM_CortexM4/drivers/adc/adc2.h	Sun May 14 23:18:57 2017 +0000
@@ -0,0 +1,813 @@
+/**
+ * \file
+ *
+ * \brief ADC Controller driver.
+ *
+ * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef ADC2_H_INCLUDED
+#define ADC2_H_INCLUDED
+
+#include "compiler.h"
+#include "status_codes.h"
+
+#if (SAM4N)
+#define TEMP_SENSOR
+#define SLEEP_MODE_ADC    SLEEPMGR_SLEEP_WFI
+#endif
+
+#if (SAMG)
+#define NO_TEMP_SENSOR
+#define SLEEP_MODE_ADC    SLEEPMGR_ACTIVE
+#endif
+
+/** Write Protect Key */
+#ifndef ADC_WPMR_WPKEY_PASSWD
+#define ADC_WPMR_WPKEY_PASSWD    (0x414443u << 8)
+#endif
+
+/** Definitions for ADC resolution */
+enum adc_resolution {
+#if SAMG55
+    ADC_12_BITS = ADC_EMR_OSR_NO_AVERAGE,     /* ADC 12-bit resolution */
+    ADC_13_BITS = ADC_EMR_OSR_OSR4,           /* ADC 13-bit resolution */
+    ADC_14_BITS = ADC_EMR_OSR_OSR16,          /* ADC 14-bit resolution */
+    ADC_15_BITS = ADC_EMR_OSR_OSR64,          /* ADC 15-bit resolution */
+    ADC_16_BITS = ADC_EMR_OSR_OSR256,         /* ADC 16-bit resolution */
+#else
+    ADC_8_BITS = ADC_MR_LOWRES_BITS_8,        /* ADC 8-bit resolution */
+    ADC_10_BITS = ADC_MR_LOWRES_BITS_10,      /* ADC 10-bit resolution */
+    ADC_11_BITS = ADC_EMR_OSR_OSR4,           /* ADC 11-bit resolution */
+    ADC_12_BITS = ADC_EMR_OSR_OSR16           /* ADC 12-bit resolution */
+#endif
+};
+
+/** Definitions for ADC power mode */
+enum adc_power_mode {
+    /* ADC core on and reference voltage circuitry on */
+    ADC_POWER_MODE_0 = 0,
+    /* ADC core off and reference voltage circuitry off */
+    ADC_POWER_MODE_1
+};
+
+/** Definitions for ADC trigger */
+enum adc_trigger {
+    /* Starting a conversion is only possible by software. */
+    ADC_TRIG_SW = ADC_MR_TRGEN_DIS,
+    /* External trigger */
+    ADC_TRIG_EXT = ADC_MR_TRGSEL_ADC_TRIG0 | ADC_MR_TRGEN,
+    /* TIO Output of the Timer Counter Channel 0 */
+    ADC_TRIG_TIO_CH_0 = ADC_MR_TRGSEL_ADC_TRIG1 | ADC_MR_TRGEN,
+    /* TIO Output of the Timer Counter Channel 1 */
+    ADC_TRIG_TIO_CH_1 = ADC_MR_TRGSEL_ADC_TRIG2 | ADC_MR_TRGEN,
+    /* TIO Output of the Timer Counter Channel 2 */
+    ADC_TRIG_TIO_CH_2 = ADC_MR_TRGSEL_ADC_TRIG3 | ADC_MR_TRGEN,
+#if (SAMG)
+    /* RTCOUT0 */
+    ADC_TRIG_RTC_0 = ADC_MR_TRGSEL_ADC_TRIG4 | ADC_MR_TRGEN,
+    /* RTTINC */
+    ADC_TRIG_RTT = ADC_MR_TRGSEL_ADC_TRIG5 | ADC_MR_TRGEN,
+#endif
+    /* Freerun mode conversion. */
+    ADC_TRIG_FREERUN = 0xFF
+};
+
+/** Definitions for ADC channel number */
+enum adc_channel_num {
+    ADC_CHANNEL_0 = 0,
+    ADC_CHANNEL_1,
+    ADC_CHANNEL_2,
+    ADC_CHANNEL_3,
+    ADC_CHANNEL_4,
+    ADC_CHANNEL_5,
+    ADC_CHANNEL_6,
+    ADC_CHANNEL_7,
+#if (SAM4N)
+    ADC_CHANNEL_8,
+    ADC_CHANNEL_9,
+    ADC_CHANNEL_10,
+    ADC_CHANNEL_11,
+    ADC_CHANNEL_12,
+    ADC_CHANNEL_13,
+    ADC_CHANNEL_14,
+    ADC_CHANNEL_15,
+#endif
+#ifdef TEMP_SENSOR
+    ADC_TEMPERATURE_SENSOR,
+#endif
+    ADC_CHANNEL_ALL = 0xFFFF
+};
+
+/** Definitions for ADC Start Up Time */
+enum adc_startup_time {
+    ADC_STARTUP_TIME_0 = ADC_MR_STARTUP_SUT0,
+    ADC_STARTUP_TIME_1 = ADC_MR_STARTUP_SUT8,
+    ADC_STARTUP_TIME_2 = ADC_MR_STARTUP_SUT16,
+    ADC_STARTUP_TIME_3 = ADC_MR_STARTUP_SUT24,
+    ADC_STARTUP_TIME_4 = ADC_MR_STARTUP_SUT64,
+    ADC_STARTUP_TIME_5 = ADC_MR_STARTUP_SUT80,
+    ADC_STARTUP_TIME_6 = ADC_MR_STARTUP_SUT96,
+    ADC_STARTUP_TIME_7 = ADC_MR_STARTUP_SUT112,
+    ADC_STARTUP_TIME_8 = ADC_MR_STARTUP_SUT512,
+    ADC_STARTUP_TIME_9 = ADC_MR_STARTUP_SUT576,
+    ADC_STARTUP_TIME_10 = ADC_MR_STARTUP_SUT640,
+    ADC_STARTUP_TIME_11 = ADC_MR_STARTUP_SUT704,
+    ADC_STARTUP_TIME_12 = ADC_MR_STARTUP_SUT768,
+    ADC_STARTUP_TIME_13 = ADC_MR_STARTUP_SUT832,
+    ADC_STARTUP_TIME_14 = ADC_MR_STARTUP_SUT896,
+    ADC_STARTUP_TIME_15 = ADC_MR_STARTUP_SUT960
+};
+
+/** Definitions for Comparison Mode */
+enum adc_cmp_mode {
+    ADC_CMP_MODE_0 = ADC_EMR_CMPMODE_LOW,
+    ADC_CMP_MODE_1 = ADC_EMR_CMPMODE_HIGH,
+    ADC_CMP_MODE_2 = ADC_EMR_CMPMODE_IN,
+    ADC_CMP_MODE_3 = ADC_EMR_CMPMODE_OUT
+};
+
+#ifdef TEMP_SENSOR
+/** Definitions for Temperature Comparison Mode */
+enum adc_temp_cmp_mode {
+    ADC_TEMP_CMP_MODE_0 = ADC_TEMPMR_TEMPCMPMOD_LOW,
+    ADC_TEMP_CMP_MODE_1 = ADC_TEMPMR_TEMPCMPMOD_HIGH,
+    ADC_TEMP_CMP_MODE_2 = ADC_TEMPMR_TEMPCMPMOD_IN,
+    ADC_TEMP_CMP_MODE_3 = ADC_TEMPMR_TEMPCMPMOD_OUT
+};
+#endif
+#if (SAMG)
+/** Definitions for Last Channel Specific Measurement Comparison Mode */
+enum adc_last_channel_cmp_mode {
+    ADC_LAST_CHANNEL_CMP_MODE_0 = ADC_LCTMR_CMPMOD_LOW,
+    ADC_LAST_CHANNEL_CMP_MODE_1 = ADC_LCTMR_CMPMOD_HIGH,
+    ADC_LAST_CHANNEL_CMP_MODE_2 = ADC_LCTMR_CMPMOD_IN,
+    ADC_LAST_CHANNEL_CMP_MODE_3 = ADC_LCTMR_CMPMOD_OUT
+};
+#endif
+
+/** Definitions for Reference Voltage Selection */
+enum adc_refer_voltage_source {
+    ADC_REFER_VOL_EXTERNAL = 0,
+    ADC_REFER_VOL_STUCK_AT_MIN,
+    ADC_REFER_VOL_VDDANA,
+    ADC_REFER_VOL_IRVS
+};
+
+/**
+ * \brief ADC Enhanced configuration structure.
+ *
+ * Configuration structure for a ADC Enhanced instance.
+ * This structure could be initialized by the \ref ADC_get_config_defaults()
+ * function before being modified by the user application.
+ */
+struct adc_config {
+    /** Resolution */
+    enum adc_resolution resolution;
+    /** Master Clock */
+    uint32_t mck;
+    /** ADC Clock */
+    uint32_t adc_clock;
+    /** Start Up Time */
+    enum adc_startup_time startup_time;
+    /** Tracking Time = (tracktim+1) / ADC clock */
+    uint8_t tracktim;
+    /** Transfer Period */
+    uint8_t transfer;
+    /** Use Sequence Enable */
+    bool useq;
+    /** TAG of ADC_LDCR register */
+    bool tag;
+    /** Averaging on Single Trigger Event */
+    bool aste;
+};
+
+#ifdef TEMP_SENSOR
+/** ADC Temperature Sensor configuration structure.*/
+struct adc_temp_sensor_config {
+    /** Temperature Sensor On */
+    bool tempon;
+    /** Temperature Comparison Mode */
+    enum adc_temp_cmp_mode mode;
+    /** Temperature Low Threshold */
+    uint16_t low_threshold;
+    /** Temperature High Threshold */
+    uint16_t high_threshold;
+};
+#endif
+
+#if (SAMG)
+/** ADC Last Channel Specific Measurement configuration structure.*/
+struct adc_last_channel_config {
+    /** Specific Measurement On */
+    bool dual_trig_on;
+    /** Specific Measurement Comparison Mode */
+    enum adc_last_channel_cmp_mode mode;
+    /** Specific Measurement Low Threshold */
+    uint16_t low_threshold;
+    /** Specific Measurement High Threshold */
+    uint16_t high_threshold;
+};
+#endif
+
+/** ADC interrupt source type */
+enum adc_interrupt_source {
+    ADC_INTERRUPT_EOC_0 = 0,
+    ADC_INTERRUPT_EOC_1,
+    ADC_INTERRUPT_EOC_2,
+    ADC_INTERRUPT_EOC_3,
+    ADC_INTERRUPT_EOC_4,
+    ADC_INTERRUPT_EOC_5,
+    ADC_INTERRUPT_EOC_6,
+    ADC_INTERRUPT_EOC_7,
+#if (SAM4N)
+    ADC_INTERRUPT_EOC_8,
+    ADC_INTERRUPT_EOC_9,
+    ADC_INTERRUPT_EOC_10,
+    ADC_INTERRUPT_EOC_11,
+    ADC_INTERRUPT_EOC_12,
+    ADC_INTERRUPT_EOC_13,
+    ADC_INTERRUPT_EOC_14,
+    ADC_INTERRUPT_EOC_15,
+    ADC_INTERRUPT_EOC_16,
+#endif
+#ifdef TEMP_SENSOR
+    ADC_INTERRUPT_TEMP_CHANGE,
+#endif
+    ADC_INTERRUPT_END_CAL,
+    ADC_INTERRUPT_DATA_READY,
+    ADC_INTERRUPT_OVERRUN_ERROR,
+    ADC_INTERRUPT_COMP_ERROR,
+    ADC_INTERRUPT_END_RXBUF,
+    ADC_INTERRUPT_RXBUF_FULL,
+    ADC_INTERRUPT_ALL = 0xFFFFFFFF
+};
+
+typedef void (*adc_callback_t)(void);
+
+void adc_get_config_defaults(struct adc_config *const cfg);
+enum status_code adc_init(Adc *const adc, struct adc_config *const config);
+
+#ifdef TEMP_SENSOR
+void adc_temp_sensor_get_config_defaults(
+    struct adc_temp_sensor_config *const cfg);
+void adc_temp_sensor_set_config(Adc *const adc,
+                                struct adc_temp_sensor_config *config);
+#endif
+#if (SAMG)
+void adc_last_channel_get_config_defaults(
+    struct adc_last_channel_config *const cfg);
+void adc_last_channel_set_config(Adc *const adc,
+                                 struct adc_last_channel_config *config);
+#endif
+
+void adc_configure_sequence(Adc *const adc,
+                            const enum adc_channel_num ch_list[], const uint8_t uc_num);
+void adc_enable(void);
+void adc_disable(void);
+void adc_set_callback(Adc *const adc, enum adc_interrupt_source source,
+                      adc_callback_t callback, uint8_t irq_level);
+
+/**
+ * \internal
+ * \brief ADC channel sanity check
+ *
+ * \param adc  Base address of the ADC.
+ * \param channel  Adc channel number.
+ *
+ */
+static inline void adc_ch_sanity_check(Adc *const adc,
+                                       const enum adc_channel_num channel)
+{
+    if (adc == ADC) {
+        Assert((channel < NB_CH_ADC)
+#ifdef TEMP_SENSOR
+               ||(channel == ADC_TEMPERATURE_SENSOR)
+#endif
+              );
+    }
+
+    UNUSED(channel);
+}
+
+#if (SAMG)
+#if SAMG55
+/**
+ * \brief Configure ADC clock to mck.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ */
+static inline void adc_select_clock_source_mck(Adc *const adc)
+{
+    uint32_t reg;
+
+    reg = adc->ADC_EMR;
+
+    reg &= ~ADC_EMR_SRCCLK_PMC_PCK;
+
+    adc->ADC_EMR = reg;
+}
+
+/**
+ * \brief Configure ADC clock to pck.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ */
+static inline void adc_select_clock_source_pck(Adc *const adc)
+{
+    uint32_t reg;
+
+    reg = adc->ADC_EMR;
+
+    reg |= ADC_EMR_SRCCLK_PMC_PCK;
+
+    adc->ADC_EMR = reg;
+}
+
+#else
+/**
+ * \brief Configure ADC clock to MCK.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ */
+static inline void adc_set_clock_mck(Adc *const adc)
+{
+    uint32_t reg;
+
+    reg = adc->ADC_EMR;
+
+    reg |= ADC_MR_DIV1;
+
+    adc->ADC_MR = reg;
+}
+
+/**
+ * \brief Configure ADC clock to MCK/3.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ */
+static inline void adc_set_clock_mck_div3(Adc *const adc)
+{
+    uint32_t reg;
+
+    reg = adc->ADC_MR;
+
+    reg &= ~ADC_MR_DIV1;
+    reg |= ADC_MR_DIV3;
+
+    adc->ADC_MR = reg;
+}
+#endif
+#endif
+
+/**
+ * \brief Configure conversion trigger and free run mode.
+ *
+ * \param adc  Base address of the ADC.
+ * \param trigger Conversion trigger.
+ *
+ */
+static inline void adc_set_trigger(Adc *const adc,
+                                   const enum adc_trigger trigger)
+{
+    uint32_t reg;
+
+    reg = adc->ADC_MR;
+
+    if (trigger == ADC_TRIG_FREERUN) {
+        reg |= ADC_MR_FREERUN_ON;
+    } else {
+        reg &= ~(ADC_MR_TRGSEL_Msk | ADC_MR_TRGEN | ADC_MR_FREERUN_ON);
+        reg |= trigger;
+    }
+
+    adc->ADC_MR = reg;
+}
+
+void adc_set_resolution(Adc *const adc,
+                        const enum adc_resolution res);
+
+void adc_set_comparison_mode(Adc *const adc,
+                             const enum adc_cmp_mode mode,
+                             const enum adc_channel_num channel,
+                             uint8_t cmp_filter);
+
+/**
+ * \brief Get comparison mode.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \retval Compare mode value.
+ */
+static inline enum adc_cmp_mode adc_get_comparison_mode(Adc *const adc)
+{
+    return (enum adc_cmp_mode)(adc->ADC_EMR & ADC_EMR_CMPMODE_Msk);
+}
+
+/**
+ * \brief Configure ADC compare window.
+ *
+ * \param adc  Base address of the ADC.
+ * \param us_low_threshold Low threshold of compare window.
+ * \param us_high_threshold High threshold of compare window.
+ */
+static inline void adc_set_comparison_window(Adc *const adc,
+        const uint16_t us_low_threshold,
+        const uint16_t us_high_threshold)
+{
+    adc->ADC_CWR = ADC_CWR_LOWTHRES(us_low_threshold) |
+                   ADC_CWR_HIGHTHRES(us_high_threshold);
+}
+
+/**
+ * \brief Enable or disable write protection of ADC registers.
+ *
+ * \param adc  Base address of the ADC.
+ * \param is_enable 1 to enable, 0 to disable.
+ */
+static inline void adc_set_writeprotect(Adc *const adc,
+                                        const bool is_enable)
+{
+    if (is_enable) {
+        adc->ADC_WPMR = ADC_WPMR_WPEN | ADC_WPMR_WPKEY_PASSWD;
+    } else {
+        adc->ADC_WPMR = ADC_WPMR_WPKEY_PASSWD;
+    }
+}
+
+/**
+ * \brief Indicate write protect status.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \return 0 if no write protect violation occurred, or 16-bit write protect
+ * violation source.
+ */
+static inline uint32_t adc_get_writeprotect_status(Adc *const adc)
+{
+    uint32_t reg_value;
+
+    reg_value = adc->ADC_WPSR;
+    if (reg_value & ADC_WPSR_WPVS) {
+        return (reg_value & ADC_WPSR_WPVSRC_Msk) >> ADC_WPSR_WPVSRC_Pos;
+    } else {
+        return 0;
+    }
+}
+
+/**
+ * \brief Get ADC overrun error status.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \return ADC overrun error status.
+ */
+static inline uint32_t adc_get_overrun_status(Adc *const adc)
+{
+    return adc->ADC_OVER;
+}
+
+/**
+ * \brief Set ADC averaging on single trigger event
+ *
+ * \param adc Base address of the ADC.
+ */
+static inline void adc_average_on_single_trigger(Adc *const adc)
+{
+    adc->ADC_EMR |= ADC_EMR_ASTE_SINGLE_TRIG_AVERAGE;
+}
+
+/**
+ * \brief Set ADC averaging on serval trigger events
+ *
+ * \param adc Base address of the ADC.
+ */
+static inline void adc_average_on_multi_trigger(Adc *const adc)
+{
+    adc->ADC_EMR &= ~ADC_EMR_ASTE_SINGLE_TRIG_AVERAGE;
+}
+
+/**
+ * \brief Start analog-to-digital conversion.
+ *
+ * \note If one of the hardware event is selected as ADC trigger,
+ * this function can NOT start analog to digital conversion.
+ *
+ * \param adc  Base address of the ADC.
+ */
+static inline void adc_start_software_conversion(Adc *const adc)
+{
+    adc->ADC_CR = ADC_CR_START;
+}
+
+void adc_set_power_mode(Adc *const adc,
+                        const enum adc_power_mode mode);
+
+/**
+ * \brief Enable the specified ADC channel.
+ *
+ * \param adc  Base address of the ADC.
+ * \param adc_ch Adc channel number.
+ */
+static inline void adc_channel_enable(Adc *const adc,
+                                      const enum adc_channel_num adc_ch)
+{
+    if (adc_ch != ADC_CHANNEL_ALL) {
+        adc_ch_sanity_check(adc, adc_ch);
+    }
+
+    adc->ADC_CHER = (adc_ch == ADC_CHANNEL_ALL) ?
+                    ADC_CHANNEL_ALL : 1 << adc_ch;
+}
+
+/**
+ * \brief Disable the specified ADC channel.
+ *
+ * \param adc  Base address of the ADC.
+ * \param adc_ch Adc channel number.
+ */
+static inline void adc_channel_disable(Adc *const adc,
+                                       const enum adc_channel_num adc_ch)
+{
+    if (adc_ch != ADC_CHANNEL_ALL) {
+        adc_ch_sanity_check(adc, adc_ch);
+    }
+
+    adc->ADC_CHDR = (adc_ch == ADC_CHANNEL_ALL) ?
+                    ADC_CHANNEL_ALL : 1 << adc_ch;
+}
+
+/**
+ * \brief Get the ADC channel status.
+ *
+ * \param adc  Base address of the ADC.
+ * \param adc_ch Adc channel number.
+ *
+ * \retval 1 if channel is enabled.
+ * \retval 0 if channel is disabled.
+ */
+static inline uint32_t adc_channel_get_status(Adc *const adc,
+        const enum adc_channel_num adc_ch)
+{
+    adc_ch_sanity_check(adc, adc_ch);
+
+    return adc->ADC_CHSR & (1 << adc_ch);
+}
+
+/**
+ * \brief Read the Converted Data of the selected channel.
+ *
+ * \param adc  Base address of the ADC.
+ * \param adc_ch Adc channel number.
+ *
+ * \return ADC converted value of the selected channel.
+ */
+static inline uint32_t adc_channel_get_value(Adc *const adc,
+        enum adc_channel_num adc_ch)
+{
+    adc_ch_sanity_check(adc, adc_ch);
+
+    return adc->ADC_CDR[adc_ch];
+}
+
+/**
+ * \brief Get the Last Data Converted.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \return ADC latest converted value.
+ */
+static inline uint32_t adc_get_latest_value(Adc *const adc)
+{
+    return adc->ADC_LCDR & ADC_LCDR_LDATA_Msk;
+}
+
+/**
+ * \brief Get the Last Converted Channel Number.
+ *
+ * \param adc Base address of the ADC.
+ *
+ * \return ADC Last Converted Channel Number.
+ */
+static inline uint32_t adc_get_latest_chan_num(Adc *const adc)
+{
+#if SAMG55
+    return (adc->ADC_LCDR & ADC_LCDR_CHNBOSR_Msk) >> ADC_LCDR_CHNBOSR_Pos;
+#else
+    return (adc->ADC_LCDR & ADC_LCDR_CHNB_Msk) >> ADC_LCDR_CHNB_Pos;
+#endif
+}
+
+void adc_enable_interrupt(Adc *const adc,
+                          enum adc_interrupt_source interrupt_source);
+
+void adc_disable_interrupt(Adc *const adc,
+                           enum adc_interrupt_source interrupt_source);
+
+/**
+ * \brief Get ADC interrupt status.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \return The interrupt status value.
+ */
+static inline uint32_t adc_get_interrupt_status(Adc *const adc)
+{
+    return adc->ADC_ISR;
+}
+
+/**
+ * \brief Get ADC interrupt mask.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \return The interrupt mask value.
+ */
+static inline uint32_t adc_get_interrupt_mask(Adc *const adc)
+{
+    return adc->ADC_IMR;
+}
+
+/**
+ * \brief Get PDC registers base address.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \return Adc Pdc register base address.
+ */
+static inline Pdc *adc_get_pdc_base(Adc *const adc)
+{
+    Pdc *p_pdc_base = NULL;
+
+    if (adc == ADC) {
+        p_pdc_base = PDC_ADC;
+    }
+
+    return p_pdc_base;
+}
+
+/**
+ * \brief Launch an automatic calibration of the ADC on next sequence.
+ *
+ * \param adc  Base address of the ADC.
+ *
+ * \retval STATUS_OK  An automatic calibration is launched.
+ * \retval STATUS_ERR_BUSY  Automatic calibration can not be launched because
+ *         the ADC is in freerun mode.
+ */
+static inline enum status_code adc_start_calibration(Adc *const adc)
+{
+    if ((adc->ADC_MR & ADC_MR_FREERUN) == ADC_MR_FREERUN_ON) {
+        return STATUS_ERR_BUSY;
+    }
+
+    adc->ADC_CR = ADC_CR_AUTOCAL;
+    return STATUS_OK;
+}
+
+#if (SAM4N)
+/**
+ * \brief ADC Reference Voltage Selection
+ *
+ * \param  adc  Base address of the ADC.
+ * \param  adc_ref_src The source selection for ADC reference voltage,
+ * ADC_REFER_VOL_EXTERNAL - the external pin ADVREF defines the voltage reference.
+ * ADC_REFER_VOL_STUCK_AT_MIN - the internal reference voltage is stuck at the minimum value
+ * ADC_REFER_VOL_VDDANA - the internal voltage reference is forced to VDDANA. Effective only if ONREF is 1.
+ * ADC_REFER_VOL_IRVS - the internal reference voltage is defined by field IRVS
+ * See the product electrical characteristics for further details.
+ * \param  irvs Internal reference volatage selection, only be effective when
+ *         adc_ref_src equals to ADC_REFER_VOL_IRVS
+ */
+static inline void adc_ref_vol_sel(Adc *const adc,
+                                   enum adc_refer_voltage_source adc_ref_src,
+                                   uint8_t irvs)
+{
+    if (ADC_REFER_VOL_EXTERNAL == adc_ref_src) {
+        adc->ADC_ACR &= ~ADC_ACR_ONREF_EN;
+    } else if (ADC_REFER_VOL_STUCK_AT_MIN == adc_ref_src) {
+        adc->ADC_ACR |= ADC_ACR_ONREF_EN;
+        adc->ADC_ACR &= ~(ADC_ACR_IRVCE_EN | ADC_ACR_FORCEREF_EN);
+    } else if (ADC_REFER_VOL_VDDANA == adc_ref_src) {
+        adc->ADC_ACR |= ADC_ACR_ONREF_EN | ADC_ACR_FORCEREF_EN;
+    } else if (ADC_REFER_VOL_IRVS == adc_ref_src) {
+        adc->ADC_ACR &= ~ADC_ACR_FORCEREF_EN;
+        adc->ADC_ACR |= ADC_ACR_ONREF_EN | ADC_ACR_IRVCE_EN |
+                        (irvs << ADC_ACR_IRVS_Pos);
+    }
+}
+#endif
+
+/**
+ * \page sam_adc2_quickstart Quickstart guide for ADC driver
+ *
+ * This is the quickstart guide for the \ref sam_drivers_adc2_group
+ * "ADC2 driver" with step-by-step instructions on how to configure and use
+ * the driver in a selection of use cases.
+ *
+ * The use cases contain several code fragments. The code fragments in the
+ * steps for setup can be copied into a custom initialization function, while
+ * the steps for usage can be copied into, e.g., the main application function.
+ *
+ * \section adc_basic_use_case Basic use case
+ * In this basic use case, the ADC module and single channel are configured for:
+ * - 10 -bit resolution
+ * - ADC clock frequency is 6MHz
+ * - Start Up Time is 64 periods ADC clock
+ * - Tracking Time is 3 periods of ADC clock
+ * - Transfer Period field shall be programmed with 2 as datasheet said
+ * - The controller converts channels in a simple numeric order
+ * - Appends the channel number to the conversion result in AFE_LDCR register
+ * - Single Trigger is optional to get an averaged value
+ * - Software triggering of conversions
+ * - Single channel measurement
+ * - ADC_CHANNEL_1 of ADC as input
+ *
+ * \subsection sam_adc2_quickstart_prereq Prerequisites
+ * -# \ref sysclk_group "System Clock Management (Sysclock)"
+ *
+ * \section adc_basic_use_case_setup Setup steps
+ * \subsection adc_basic_use_case_setup_code Example code
+ * Add to application C-file:
+ * \code
+	adc_enable();
+	adc_get_config_defaults(&adc_cfg);
+	adc_init(ADC, &adc_cfg);
+	adc_set_trigger(ADC, ADC_TRIG_SW);
+	adc_channel_enable(ADC, ADC_CHANNEL_1);
+\endcode
+ *
+ * \subsection adc_basic_use_case_setup_flow Workflow
+ * -# Enable ADC Module:
+ *   - \code adc_enable(); \endcode
+ * -# Get the ADC default configurations:
+ *   - \code adc_get_config_defaults(&adc_cfg); \endcode
+ * -# Initialize the ADC Module:
+ *   - \code adc_init(ADC, &adc_cfg); \endcode
+ * -# Configure conversion trigger and free run mode:
+ *   - \code adc_set_trigger(ADC, ADC_TRIG_SW); \endcode
+ * -# Enable Channel:
+ *   - \code adc_channel_enable(ADC, ADC_CHANNEL_1); \endcode
+ *
+ * \section adc_basic_use_case_usage Usage steps
+ * \subsection adc_basic_use_case_usage_code Example code
+ * Add to, e.g., main loop in application C-file:
+ * \code
+	adc_start_software_conversion(ADC);
+	while (adc_get_interrupt_status(ADC) & (1 << ADC_CHANNEL_1));
+	uint32_t result = adc_channel_get_value(ADC, ADC_CHANNEL_1);
+\endcode
+ *
+ * \subsection adc_basic_use_case_usage_flow Workflow
+ * -# Start ADC conversion on channel:
+ *   - \code adc_start_software_conversion(ADC); \endcode
+ * -# Wait for the conversion over:
+ *   - \code while (adc_get_interrupt_status(ADC) & (1 << ADC_CHANNEL_1));
+\endcode
+ * -# Get the conversion result:
+ *   - \code uint32_t result = adc_channel_get_value(ADC, ADC_CHANNEL_1);
+\endcode
+ */
+#endif /* ADC2_H_INCLUDED */