Mouse code for the MacroRat
mbed-dev/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/drivers/adc/adc.h
- Committer:
- sahilmgandhi
- Date:
- 2017-05-14
- Revision:
- 18:6a4db94011d3
File content as of revision 18:6a4db94011d3:
/** * \file * * \brief SAM Peripheral Analog-to-Digital Converter Driver * * Copyright (C) 2012-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 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 * - Atmel | SMART SAM C20/C21 * \else * - Atmel | SMART SAM D20/D21 * - Atmel | SMART SAM R21 * - Atmel | SMART SAM D10/D11 * - Atmel | SMART SAM DA0/DA1 * \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 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 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) || (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 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 */ } 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) || (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 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 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.</td> * <th>Date</td> * <th>Comments</td> * </tr> * \if DEVICE_SAML21_SUPPORT * <tr> * <td>42451A</td> * <td>07/2015</td> * <td>Initial document release</td> * </tr> * \else * <tr> * <td>42109E</td> * <td>04/2015</td> * <td>Added support for SAMDAx.</td> * </tr> * <tr> * <td>42109D</td> * <td>12/2014</td> * <td>Added support for SAMR21 and SAMD10/D11</td> * </tr> * <tr> * <td>42109C</td> * <td>01/2014</td> * <td>Added support for SAMD21</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 */