1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156 |
- /**
- * \file
- *
- * \brief SAM Peripheral Analog-to-Digital Converter Driver
- *
- * Copyright (C) 2012-2016 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 ADC_H_INCLUDED
- #define ADC_H_INCLUDED
- /**
- * \defgroup asfdoc_sam0_adc_group SAM Analog-to-Digital Converter (ADC) Driver
- *
- * This driver for Atmel® | SMART ARM®-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
- * \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) || (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) || (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 */
|