mbed library sources

Fork of mbed-src by mbed official

targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/adc/adc.h

Committer:
mbed_official
Date:
2015-07-17
Revision:
592:a274ee790e56
Parent:
579:53297373a894

File content as of revision 592:a274ee790e56:

#ifndef ADC_H_INCLUDED
#define ADC_H_INCLUDED

/**
 * \defgroup asfdoc_sam0_adc_group SAM Analog to Digital Converter Driver (ADC)
 *
 * This driver for Atmel庐 | SMART SAM devices 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 API modes are covered by this manual:
 * - Polled APIs
 * \if ADC_CALLBACK_MODE
 * - Callback APIs
 * \endif
 *
 * The following peripherals are used by this module:
 *  - ADC (Analog to Digital Converter)
 *
 * The following devices can use this module:
 * \if DEVICE_SAML21_SUPPORT
 *  - Atmel | SMART SAM L21
 * \else
 *  - Atmel | SMART SAM D20/D21
 *  - Atmel | SMART SAM R21
 *  - Atmel | SMART SAM D10/D11
 * \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 (1 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-bit, 10-bit, 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鈥檚 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 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
 * compares 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 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)

/** @} */

/**
 * \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);
/** @} */

/**
 * \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
    system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_ADC);
#endif

    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
    system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_ADC);
#endif

    while (adc_is_syncing(module_inst)) {
        /* Wait for synchronization */
    }

    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 "here" 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 "here" 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;

    while (adc_is_syncing(module_inst)) {
        /* Wait for synchronization */
    }

    /* 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 restart 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 SAMR21</td>
 *	</tr>
 *	<tr>
 *		<td>Added support for SAMD21 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 QSGs 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.</td>
 *		<th>Date</td>
 *		<th>Comments</td>
 *	</tr>
 * \if DEVICE_SAML21_SUPPORT
 *  <tr>
 *      <td>A</td>
 *      <td>11/2014</td>
 *      <td>Initial release.</td>
 * </tr>
 * \else
 *	<tr>
 *		<td>D</td>
 *		<td>12/2014</td>
 *		<td>Added support for SAMR21 and SAMD10/D11.</td>
 *	</tr>
 *	<tr>
 *		<td>C</td>
 *		<td>01/2014</td>
 *		<td>Added support for SAMD21.</td>
 *	</tr>
 *	<tr>
 *		<td>B</td>
 *		<td>06/2013</td>
 *		<td>Added additional documentation on the event system. Corrected
 *          documentation typos.</td>
 *	</tr>
 *	<tr>
 *		<td>A</td>
 *		<td>06/2013</td>
 *		<td>Initial release</td>
 *	</tr>
 * \endif
 * </table>
 */

#endif /* ADC_H_INCLUDED */