Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sahilmgandhi 18:6a4db94011d3 1 /**
sahilmgandhi 18:6a4db94011d3 2 * \file
sahilmgandhi 18:6a4db94011d3 3 *
sahilmgandhi 18:6a4db94011d3 4 * \brief SAM Peripheral Analog-to-Digital Converter Driver
sahilmgandhi 18:6a4db94011d3 5 *
sahilmgandhi 18:6a4db94011d3 6 * Copyright (C) 2012-2015 Atmel Corporation. All rights reserved.
sahilmgandhi 18:6a4db94011d3 7 *
sahilmgandhi 18:6a4db94011d3 8 * \asf_license_start
sahilmgandhi 18:6a4db94011d3 9 *
sahilmgandhi 18:6a4db94011d3 10 * \page License
sahilmgandhi 18:6a4db94011d3 11 *
sahilmgandhi 18:6a4db94011d3 12 * Redistribution and use in source and binary forms, with or without
sahilmgandhi 18:6a4db94011d3 13 * modification, are permitted provided that the following conditions are met:
sahilmgandhi 18:6a4db94011d3 14 *
sahilmgandhi 18:6a4db94011d3 15 * 1. Redistributions of source code must retain the above copyright notice,
sahilmgandhi 18:6a4db94011d3 16 * this list of conditions and the following disclaimer.
sahilmgandhi 18:6a4db94011d3 17 *
sahilmgandhi 18:6a4db94011d3 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
sahilmgandhi 18:6a4db94011d3 19 * this list of conditions and the following disclaimer in the documentation
sahilmgandhi 18:6a4db94011d3 20 * and/or other materials provided with the distribution.
sahilmgandhi 18:6a4db94011d3 21 *
sahilmgandhi 18:6a4db94011d3 22 * 3. The name of Atmel may not be used to endorse or promote products derived
sahilmgandhi 18:6a4db94011d3 23 * from this software without specific prior written permission.
sahilmgandhi 18:6a4db94011d3 24 *
sahilmgandhi 18:6a4db94011d3 25 * 4. This software may only be redistributed and used in connection with an
sahilmgandhi 18:6a4db94011d3 26 * Atmel microcontroller product.
sahilmgandhi 18:6a4db94011d3 27 *
sahilmgandhi 18:6a4db94011d3 28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
sahilmgandhi 18:6a4db94011d3 29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
sahilmgandhi 18:6a4db94011d3 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
sahilmgandhi 18:6a4db94011d3 31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
sahilmgandhi 18:6a4db94011d3 32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sahilmgandhi 18:6a4db94011d3 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sahilmgandhi 18:6a4db94011d3 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sahilmgandhi 18:6a4db94011d3 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sahilmgandhi 18:6a4db94011d3 36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
sahilmgandhi 18:6a4db94011d3 37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
sahilmgandhi 18:6a4db94011d3 38 * POSSIBILITY OF SUCH DAMAGE.
sahilmgandhi 18:6a4db94011d3 39 *
sahilmgandhi 18:6a4db94011d3 40 * \asf_license_stop
sahilmgandhi 18:6a4db94011d3 41 *
sahilmgandhi 18:6a4db94011d3 42 */
sahilmgandhi 18:6a4db94011d3 43 /*
sahilmgandhi 18:6a4db94011d3 44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
sahilmgandhi 18:6a4db94011d3 45 */
sahilmgandhi 18:6a4db94011d3 46
sahilmgandhi 18:6a4db94011d3 47 #include "adc.h"
sahilmgandhi 18:6a4db94011d3 48
sahilmgandhi 18:6a4db94011d3 49 #if SAMD20
sahilmgandhi 18:6a4db94011d3 50 /* The Die revision D number */
sahilmgandhi 18:6a4db94011d3 51 #define REVISON_D_NUM 3
sahilmgandhi 18:6a4db94011d3 52 #endif
sahilmgandhi 18:6a4db94011d3 53
sahilmgandhi 18:6a4db94011d3 54 /**
sahilmgandhi 18:6a4db94011d3 55 * \brief Initializes an ADC configuration structure to defaults
sahilmgandhi 18:6a4db94011d3 56 *
sahilmgandhi 18:6a4db94011d3 57 * Initializes a given ADC configuration struct to a set of known default
sahilmgandhi 18:6a4db94011d3 58 * values. This function should be called on any new instance of the
sahilmgandhi 18:6a4db94011d3 59 * configuration struct before being modified by the user application.
sahilmgandhi 18:6a4db94011d3 60 *
sahilmgandhi 18:6a4db94011d3 61 * The default configuration is as follows:
sahilmgandhi 18:6a4db94011d3 62 * \li GCLK generator 0 (GCLK main) clock source
sahilmgandhi 18:6a4db94011d3 63 * \li 1V from internal bandgap reference
sahilmgandhi 18:6a4db94011d3 64 * \li Div 4 clock prescaler
sahilmgandhi 18:6a4db94011d3 65 * \li 12-bit resolution
sahilmgandhi 18:6a4db94011d3 66 * \li Window monitor disabled
sahilmgandhi 18:6a4db94011d3 67 * \li No gain
sahilmgandhi 18:6a4db94011d3 68 * \li Positive input on ADC PIN 0
sahilmgandhi 18:6a4db94011d3 69 * \li Negative input on ADC PIN 1
sahilmgandhi 18:6a4db94011d3 70 * \li Averaging disabled
sahilmgandhi 18:6a4db94011d3 71 * \li Oversampling disabled
sahilmgandhi 18:6a4db94011d3 72 * \li Right adjust data
sahilmgandhi 18:6a4db94011d3 73 * \li Single-ended mode
sahilmgandhi 18:6a4db94011d3 74 * \li Free running disabled
sahilmgandhi 18:6a4db94011d3 75 * \li All events (input and generation) disabled
sahilmgandhi 18:6a4db94011d3 76 * \li Sleep operation disabled
sahilmgandhi 18:6a4db94011d3 77 * \li No reference compensation
sahilmgandhi 18:6a4db94011d3 78 * \li No gain/offset correction
sahilmgandhi 18:6a4db94011d3 79 * \li No added sampling time
sahilmgandhi 18:6a4db94011d3 80 * \li Pin scan mode disabled
sahilmgandhi 18:6a4db94011d3 81 *
sahilmgandhi 18:6a4db94011d3 82 * \param[out] config Pointer to configuration struct to initialize to
sahilmgandhi 18:6a4db94011d3 83 * default values
sahilmgandhi 18:6a4db94011d3 84 */
sahilmgandhi 18:6a4db94011d3 85 void adc_get_config_defaults(struct adc_config *const config)
sahilmgandhi 18:6a4db94011d3 86 {
sahilmgandhi 18:6a4db94011d3 87 Assert(config);
sahilmgandhi 18:6a4db94011d3 88 config->clock_source = GCLK_GENERATOR_0;
sahilmgandhi 18:6a4db94011d3 89 config->reference = ADC_REFERENCE_INT1V;
sahilmgandhi 18:6a4db94011d3 90 config->clock_prescaler = ADC_CLOCK_PRESCALER_DIV4;
sahilmgandhi 18:6a4db94011d3 91 config->resolution = ADC_RESOLUTION_12BIT;
sahilmgandhi 18:6a4db94011d3 92 config->window.window_mode = ADC_WINDOW_MODE_DISABLE;
sahilmgandhi 18:6a4db94011d3 93 config->window.window_upper_value = 0;
sahilmgandhi 18:6a4db94011d3 94 config->window.window_lower_value = 0;
sahilmgandhi 18:6a4db94011d3 95 config->gain_factor = ADC_GAIN_FACTOR_1X;
sahilmgandhi 18:6a4db94011d3 96 #if SAMR21
sahilmgandhi 18:6a4db94011d3 97 config->positive_input = ADC_POSITIVE_INPUT_PIN6 ;
sahilmgandhi 18:6a4db94011d3 98 #else
sahilmgandhi 18:6a4db94011d3 99 config->positive_input = ADC_POSITIVE_INPUT_PIN0 ;
sahilmgandhi 18:6a4db94011d3 100 #endif
sahilmgandhi 18:6a4db94011d3 101 config->negative_input = ADC_NEGATIVE_INPUT_GND ;
sahilmgandhi 18:6a4db94011d3 102 config->accumulate_samples = ADC_ACCUMULATE_DISABLE;
sahilmgandhi 18:6a4db94011d3 103 config->divide_result = ADC_DIVIDE_RESULT_DISABLE;
sahilmgandhi 18:6a4db94011d3 104 config->left_adjust = false;
sahilmgandhi 18:6a4db94011d3 105 config->differential_mode = false;
sahilmgandhi 18:6a4db94011d3 106 config->freerunning = false;
sahilmgandhi 18:6a4db94011d3 107 config->event_action = ADC_EVENT_ACTION_DISABLED;
sahilmgandhi 18:6a4db94011d3 108 config->run_in_standby = false;
sahilmgandhi 18:6a4db94011d3 109 config->reference_compensation_enable = false;
sahilmgandhi 18:6a4db94011d3 110 config->correction.correction_enable = false;
sahilmgandhi 18:6a4db94011d3 111 config->correction.gain_correction = ADC_GAINCORR_RESETVALUE;
sahilmgandhi 18:6a4db94011d3 112 config->correction.offset_correction = ADC_OFFSETCORR_RESETVALUE;
sahilmgandhi 18:6a4db94011d3 113 config->sample_length = 0;
sahilmgandhi 18:6a4db94011d3 114 config->pin_scan.offset_start_scan = 0;
sahilmgandhi 18:6a4db94011d3 115 config->pin_scan.inputs_to_scan = 0;
sahilmgandhi 18:6a4db94011d3 116 }
sahilmgandhi 18:6a4db94011d3 117
sahilmgandhi 18:6a4db94011d3 118 /**
sahilmgandhi 18:6a4db94011d3 119 * \brief Sets the ADC window mode
sahilmgandhi 18:6a4db94011d3 120 *
sahilmgandhi 18:6a4db94011d3 121 * Sets the ADC window mode to a given mode and value range.
sahilmgandhi 18:6a4db94011d3 122 *
sahilmgandhi 18:6a4db94011d3 123 * \param[in] module_inst Pointer to the ADC software instance struct
sahilmgandhi 18:6a4db94011d3 124 * \param[in] window_mode Window monitor mode to set
sahilmgandhi 18:6a4db94011d3 125 * \param[in] window_lower_value Lower window monitor threshold value
sahilmgandhi 18:6a4db94011d3 126 * \param[in] window_upper_value Upper window monitor threshold value
sahilmgandhi 18:6a4db94011d3 127 */
sahilmgandhi 18:6a4db94011d3 128 void adc_set_window_mode(
sahilmgandhi 18:6a4db94011d3 129 struct adc_module *const module_inst,
sahilmgandhi 18:6a4db94011d3 130 const enum adc_window_mode window_mode,
sahilmgandhi 18:6a4db94011d3 131 const int16_t window_lower_value,
sahilmgandhi 18:6a4db94011d3 132 const int16_t window_upper_value)
sahilmgandhi 18:6a4db94011d3 133 {
sahilmgandhi 18:6a4db94011d3 134 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 135 Assert(module_inst);
sahilmgandhi 18:6a4db94011d3 136 Assert(module_inst->hw);
sahilmgandhi 18:6a4db94011d3 137
sahilmgandhi 18:6a4db94011d3 138 Adc *const adc_module = module_inst->hw;
sahilmgandhi 18:6a4db94011d3 139
sahilmgandhi 18:6a4db94011d3 140 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 141 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 142 }
sahilmgandhi 18:6a4db94011d3 143
sahilmgandhi 18:6a4db94011d3 144 /* Set window mode */
sahilmgandhi 18:6a4db94011d3 145 adc_module->WINCTRL.reg = window_mode << ADC_WINCTRL_WINMODE_Pos;
sahilmgandhi 18:6a4db94011d3 146
sahilmgandhi 18:6a4db94011d3 147 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 148 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 149 }
sahilmgandhi 18:6a4db94011d3 150
sahilmgandhi 18:6a4db94011d3 151 /* Set lower window monitor threshold value */
sahilmgandhi 18:6a4db94011d3 152 adc_module->WINLT.reg = window_lower_value << ADC_WINLT_WINLT_Pos;
sahilmgandhi 18:6a4db94011d3 153
sahilmgandhi 18:6a4db94011d3 154 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 155 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 156 }
sahilmgandhi 18:6a4db94011d3 157
sahilmgandhi 18:6a4db94011d3 158 /* Set upper window monitor threshold value */
sahilmgandhi 18:6a4db94011d3 159 adc_module->WINUT.reg = window_upper_value << ADC_WINUT_WINUT_Pos;
sahilmgandhi 18:6a4db94011d3 160 }
sahilmgandhi 18:6a4db94011d3 161
sahilmgandhi 18:6a4db94011d3 162 /**
sahilmgandhi 18:6a4db94011d3 163 * \internal Configure MUX settings for the analog pins
sahilmgandhi 18:6a4db94011d3 164 *
sahilmgandhi 18:6a4db94011d3 165 * This function will set the given ADC input pins
sahilmgandhi 18:6a4db94011d3 166 * to the analog function in the pinmux, giving
sahilmgandhi 18:6a4db94011d3 167 * the ADC access to the analog signal
sahilmgandhi 18:6a4db94011d3 168 *
sahilmgandhi 18:6a4db94011d3 169 * \param [in] pin AINxx pin to configure
sahilmgandhi 18:6a4db94011d3 170 */
sahilmgandhi 18:6a4db94011d3 171 static inline void _adc_configure_ain_pin(uint32_t pin)
sahilmgandhi 18:6a4db94011d3 172 {
sahilmgandhi 18:6a4db94011d3 173 #define PIN_INVALID_ADC_AIN 0xFFFFUL
sahilmgandhi 18:6a4db94011d3 174
sahilmgandhi 18:6a4db94011d3 175 /* Pinmapping table for AINxx -> GPIO pin number */
sahilmgandhi 18:6a4db94011d3 176 const uint32_t pinmapping[] = {
sahilmgandhi 18:6a4db94011d3 177 #if (SAMD20E) || (SAMD21E)|| (SAMDA1E)
sahilmgandhi 18:6a4db94011d3 178 PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1,
sahilmgandhi 18:6a4db94011d3 179 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 180 PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5,
sahilmgandhi 18:6a4db94011d3 181 PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 182 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 183 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 184 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 185 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 186 PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
sahilmgandhi 18:6a4db94011d3 187 PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19,
sahilmgandhi 18:6a4db94011d3 188 #elif (SAMD20G) || (SAMD21G)|| (SAMDA1G)
sahilmgandhi 18:6a4db94011d3 189 PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1,
sahilmgandhi 18:6a4db94011d3 190 PIN_PB08B_ADC_AIN2, PIN_PB09B_ADC_AIN3,
sahilmgandhi 18:6a4db94011d3 191 PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5,
sahilmgandhi 18:6a4db94011d3 192 PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 193 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 194 PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11,
sahilmgandhi 18:6a4db94011d3 195 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 196 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 197 PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
sahilmgandhi 18:6a4db94011d3 198 PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19,
sahilmgandhi 18:6a4db94011d3 199 #elif (SAMD20J) || (SAMD21J)|| (SAMDA1J)
sahilmgandhi 18:6a4db94011d3 200 PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1,
sahilmgandhi 18:6a4db94011d3 201 PIN_PB08B_ADC_AIN2, PIN_PB09B_ADC_AIN3,
sahilmgandhi 18:6a4db94011d3 202 PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5,
sahilmgandhi 18:6a4db94011d3 203 PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 204 PIN_PB00B_ADC_AIN8, PIN_PB01B_ADC_AIN9,
sahilmgandhi 18:6a4db94011d3 205 PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11,
sahilmgandhi 18:6a4db94011d3 206 PIN_PB04B_ADC_AIN12, PIN_PB05B_ADC_AIN13,
sahilmgandhi 18:6a4db94011d3 207 PIN_PB06B_ADC_AIN14, PIN_PB07B_ADC_AIN15,
sahilmgandhi 18:6a4db94011d3 208 PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
sahilmgandhi 18:6a4db94011d3 209 PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19,
sahilmgandhi 18:6a4db94011d3 210 #elif SAMR21E
sahilmgandhi 18:6a4db94011d3 211 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 212 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 213 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 214 PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 215 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 216 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 217 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 218 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 219 PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
sahilmgandhi 18:6a4db94011d3 220 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 221 #elif SAMR21G
sahilmgandhi 18:6a4db94011d3 222 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 223 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 224 PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5,
sahilmgandhi 18:6a4db94011d3 225 PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 226 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 227 PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11,
sahilmgandhi 18:6a4db94011d3 228 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 229 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 230 PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17,
sahilmgandhi 18:6a4db94011d3 231 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 232 #elif (SAMD10C) || (SAMD11C)
sahilmgandhi 18:6a4db94011d3 233 PIN_PA02B_ADC_AIN0, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 234 PIN_PA04B_ADC_AIN2, PIN_PA05B_ADC_AIN3,
sahilmgandhi 18:6a4db94011d3 235 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 236 PIN_PA14B_ADC_AIN6, PIN_PA15B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 237 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 238 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 239 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 240 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 241 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 242 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 243 #elif (SAMD10DS) || (SAMD11DS)
sahilmgandhi 18:6a4db94011d3 244 PIN_PA02B_ADC_AIN0, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 245 PIN_PA04B_ADC_AIN2, PIN_PA05B_ADC_AIN3,
sahilmgandhi 18:6a4db94011d3 246 PIN_PA06B_ADC_AIN4, PIN_PA07B_ADC_AIN5,
sahilmgandhi 18:6a4db94011d3 247 PIN_PA14B_ADC_AIN6, PIN_PA15B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 248 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 249 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 250 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 251 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 252 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 253 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 254 #elif (SAMD10DM) || (SAMD11DM)
sahilmgandhi 18:6a4db94011d3 255 PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1,
sahilmgandhi 18:6a4db94011d3 256 PIN_PA04B_ADC_AIN2, PIN_PA05B_ADC_AIN3,
sahilmgandhi 18:6a4db94011d3 257 PIN_PA06B_ADC_AIN4, PIN_PA07B_ADC_AIN5,
sahilmgandhi 18:6a4db94011d3 258 PIN_PA14B_ADC_AIN6, PIN_PA15B_ADC_AIN7,
sahilmgandhi 18:6a4db94011d3 259 PIN_PA10B_ADC_AIN8, PIN_PA11B_ADC_AIN9,
sahilmgandhi 18:6a4db94011d3 260 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 261 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 262 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 263 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 264 PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN,
sahilmgandhi 18:6a4db94011d3 265 #else
sahilmgandhi 18:6a4db94011d3 266 # error ADC pin mappings are not defined for this device.
sahilmgandhi 18:6a4db94011d3 267 #endif
sahilmgandhi 18:6a4db94011d3 268 };
sahilmgandhi 18:6a4db94011d3 269
sahilmgandhi 18:6a4db94011d3 270 uint32_t pin_map_result = PIN_INVALID_ADC_AIN;
sahilmgandhi 18:6a4db94011d3 271
sahilmgandhi 18:6a4db94011d3 272 if (pin <= ADC_EXTCHANNEL_MSB) {
sahilmgandhi 18:6a4db94011d3 273 pin_map_result = pinmapping[pin >> ADC_INPUTCTRL_MUXPOS_Pos];
sahilmgandhi 18:6a4db94011d3 274
sahilmgandhi 18:6a4db94011d3 275 Assert(pin_map_result != PIN_INVALID_ADC_AIN);
sahilmgandhi 18:6a4db94011d3 276
sahilmgandhi 18:6a4db94011d3 277 struct system_pinmux_config config;
sahilmgandhi 18:6a4db94011d3 278 system_pinmux_get_config_defaults(&config);
sahilmgandhi 18:6a4db94011d3 279
sahilmgandhi 18:6a4db94011d3 280 /* Analog functions are all on MUX setting B */
sahilmgandhi 18:6a4db94011d3 281 config.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
sahilmgandhi 18:6a4db94011d3 282 config.mux_position = 1;
sahilmgandhi 18:6a4db94011d3 283
sahilmgandhi 18:6a4db94011d3 284 system_pinmux_pin_set_config(pin_map_result, &config);
sahilmgandhi 18:6a4db94011d3 285 }
sahilmgandhi 18:6a4db94011d3 286 }
sahilmgandhi 18:6a4db94011d3 287
sahilmgandhi 18:6a4db94011d3 288 /**
sahilmgandhi 18:6a4db94011d3 289 * \internal Writes an ADC configuration to the hardware module
sahilmgandhi 18:6a4db94011d3 290 *
sahilmgandhi 18:6a4db94011d3 291 * Writes out a given ADC module configuration to the hardware module.
sahilmgandhi 18:6a4db94011d3 292 *
sahilmgandhi 18:6a4db94011d3 293 * \param[out] module_inst Pointer to the ADC software instance struct
sahilmgandhi 18:6a4db94011d3 294 * \param[in] config Pointer to configuration struct
sahilmgandhi 18:6a4db94011d3 295 *
sahilmgandhi 18:6a4db94011d3 296 * \return Status of the configuration procedure
sahilmgandhi 18:6a4db94011d3 297 * \retval STATUS_OK The configuration was successful
sahilmgandhi 18:6a4db94011d3 298 * \retval STATUS_ERR_INVALID_ARG Invalid argument(s) were provided
sahilmgandhi 18:6a4db94011d3 299 */
sahilmgandhi 18:6a4db94011d3 300 static enum status_code _adc_set_config(
sahilmgandhi 18:6a4db94011d3 301 struct adc_module *const module_inst,
sahilmgandhi 18:6a4db94011d3 302 struct adc_config *const config)
sahilmgandhi 18:6a4db94011d3 303 {
sahilmgandhi 18:6a4db94011d3 304 uint8_t adjres = 0;
sahilmgandhi 18:6a4db94011d3 305 uint32_t resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 306 enum adc_accumulate_samples accumulate = ADC_ACCUMULATE_DISABLE;
sahilmgandhi 18:6a4db94011d3 307 #if SAMD20
sahilmgandhi 18:6a4db94011d3 308 uint8_t revision_num = ((REG_DSU_DID & DSU_DID_DIE_Msk) >> DSU_DID_DIE_Pos);
sahilmgandhi 18:6a4db94011d3 309 #endif
sahilmgandhi 18:6a4db94011d3 310
sahilmgandhi 18:6a4db94011d3 311 /* Get the hardware module pointer */
sahilmgandhi 18:6a4db94011d3 312 Adc *const adc_module = module_inst->hw;
sahilmgandhi 18:6a4db94011d3 313
sahilmgandhi 18:6a4db94011d3 314 /* Configure GCLK channel and enable clock */
sahilmgandhi 18:6a4db94011d3 315 struct system_gclk_chan_config gclk_chan_conf;
sahilmgandhi 18:6a4db94011d3 316 system_gclk_chan_get_config_defaults(&gclk_chan_conf);
sahilmgandhi 18:6a4db94011d3 317 gclk_chan_conf.source_generator = config->clock_source;
sahilmgandhi 18:6a4db94011d3 318 system_gclk_chan_set_config(ADC_GCLK_ID, &gclk_chan_conf);
sahilmgandhi 18:6a4db94011d3 319 system_gclk_chan_enable(ADC_GCLK_ID);
sahilmgandhi 18:6a4db94011d3 320
sahilmgandhi 18:6a4db94011d3 321 /* Setup pinmuxing for analog inputs */
sahilmgandhi 18:6a4db94011d3 322 if (config->pin_scan.inputs_to_scan != 0) {
sahilmgandhi 18:6a4db94011d3 323 uint8_t offset = config->pin_scan.offset_start_scan;
sahilmgandhi 18:6a4db94011d3 324 uint8_t start_pin =
sahilmgandhi 18:6a4db94011d3 325 offset +(uint8_t)config->positive_input;
sahilmgandhi 18:6a4db94011d3 326 uint8_t end_pin =
sahilmgandhi 18:6a4db94011d3 327 start_pin + config->pin_scan.inputs_to_scan;
sahilmgandhi 18:6a4db94011d3 328
sahilmgandhi 18:6a4db94011d3 329 while (start_pin < end_pin) {
sahilmgandhi 18:6a4db94011d3 330 _adc_configure_ain_pin((offset % 16)+(uint8_t)config->positive_input);
sahilmgandhi 18:6a4db94011d3 331 start_pin++;
sahilmgandhi 18:6a4db94011d3 332 offset++;
sahilmgandhi 18:6a4db94011d3 333 }
sahilmgandhi 18:6a4db94011d3 334 _adc_configure_ain_pin(config->negative_input);
sahilmgandhi 18:6a4db94011d3 335 } else {
sahilmgandhi 18:6a4db94011d3 336 _adc_configure_ain_pin(config->positive_input);
sahilmgandhi 18:6a4db94011d3 337 _adc_configure_ain_pin(config->negative_input);
sahilmgandhi 18:6a4db94011d3 338 }
sahilmgandhi 18:6a4db94011d3 339
sahilmgandhi 18:6a4db94011d3 340 /* Configure run in standby */
sahilmgandhi 18:6a4db94011d3 341 adc_module->CTRLA.reg = (config->run_in_standby << ADC_CTRLA_RUNSTDBY_Pos);
sahilmgandhi 18:6a4db94011d3 342
sahilmgandhi 18:6a4db94011d3 343 /* Configure reference */
sahilmgandhi 18:6a4db94011d3 344 adc_module->REFCTRL.reg =
sahilmgandhi 18:6a4db94011d3 345 (config->reference_compensation_enable << ADC_REFCTRL_REFCOMP_Pos) |
sahilmgandhi 18:6a4db94011d3 346 (config->reference);
sahilmgandhi 18:6a4db94011d3 347
sahilmgandhi 18:6a4db94011d3 348 /* Set adjusting result and number of samples */
sahilmgandhi 18:6a4db94011d3 349 switch (config->resolution) {
sahilmgandhi 18:6a4db94011d3 350
sahilmgandhi 18:6a4db94011d3 351 case ADC_RESOLUTION_CUSTOM:
sahilmgandhi 18:6a4db94011d3 352 adjres = config->divide_result;
sahilmgandhi 18:6a4db94011d3 353 accumulate = config->accumulate_samples;
sahilmgandhi 18:6a4db94011d3 354 /* 16-bit result register */
sahilmgandhi 18:6a4db94011d3 355 resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 356 break;
sahilmgandhi 18:6a4db94011d3 357
sahilmgandhi 18:6a4db94011d3 358 case ADC_RESOLUTION_13BIT:
sahilmgandhi 18:6a4db94011d3 359 /* Increase resolution by 1 bit */
sahilmgandhi 18:6a4db94011d3 360 adjres = ADC_DIVIDE_RESULT_2;
sahilmgandhi 18:6a4db94011d3 361 accumulate = ADC_ACCUMULATE_SAMPLES_4;
sahilmgandhi 18:6a4db94011d3 362 /* 16-bit result register */
sahilmgandhi 18:6a4db94011d3 363 resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 364 break;
sahilmgandhi 18:6a4db94011d3 365
sahilmgandhi 18:6a4db94011d3 366 case ADC_RESOLUTION_14BIT:
sahilmgandhi 18:6a4db94011d3 367 /* Increase resolution by 2 bit */
sahilmgandhi 18:6a4db94011d3 368 adjres = ADC_DIVIDE_RESULT_4;
sahilmgandhi 18:6a4db94011d3 369 accumulate = ADC_ACCUMULATE_SAMPLES_16;
sahilmgandhi 18:6a4db94011d3 370 /* 16-bit result register */
sahilmgandhi 18:6a4db94011d3 371 resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 372 break;
sahilmgandhi 18:6a4db94011d3 373 #if SAMD20
sahilmgandhi 18:6a4db94011d3 374 /* See $35.1.8 for ADC errata of SAM D20.
sahilmgandhi 18:6a4db94011d3 375 The revisions before D have this issue.*/
sahilmgandhi 18:6a4db94011d3 376 case ADC_RESOLUTION_15BIT:
sahilmgandhi 18:6a4db94011d3 377 /* Increase resolution by 3 bit */
sahilmgandhi 18:6a4db94011d3 378 if(revision_num < REVISON_D_NUM) {
sahilmgandhi 18:6a4db94011d3 379 adjres = ADC_DIVIDE_RESULT_8;
sahilmgandhi 18:6a4db94011d3 380 } else {
sahilmgandhi 18:6a4db94011d3 381 adjres = ADC_DIVIDE_RESULT_2;
sahilmgandhi 18:6a4db94011d3 382 }
sahilmgandhi 18:6a4db94011d3 383 accumulate = ADC_ACCUMULATE_SAMPLES_64;
sahilmgandhi 18:6a4db94011d3 384 /* 16-bit result register */
sahilmgandhi 18:6a4db94011d3 385 resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 386 break;
sahilmgandhi 18:6a4db94011d3 387
sahilmgandhi 18:6a4db94011d3 388 case ADC_RESOLUTION_16BIT:
sahilmgandhi 18:6a4db94011d3 389 if(revision_num < REVISON_D_NUM) {
sahilmgandhi 18:6a4db94011d3 390 /* Increase resolution by 4 bit */
sahilmgandhi 18:6a4db94011d3 391 adjres = ADC_DIVIDE_RESULT_16;
sahilmgandhi 18:6a4db94011d3 392 } else {
sahilmgandhi 18:6a4db94011d3 393 adjres = ADC_DIVIDE_RESULT_DISABLE;
sahilmgandhi 18:6a4db94011d3 394 }
sahilmgandhi 18:6a4db94011d3 395 accumulate = ADC_ACCUMULATE_SAMPLES_256;
sahilmgandhi 18:6a4db94011d3 396 /* 16-bit result register */
sahilmgandhi 18:6a4db94011d3 397 resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 398 break;
sahilmgandhi 18:6a4db94011d3 399 #else
sahilmgandhi 18:6a4db94011d3 400 case ADC_RESOLUTION_15BIT:
sahilmgandhi 18:6a4db94011d3 401 /* Increase resolution by 3 bit */
sahilmgandhi 18:6a4db94011d3 402 adjres = ADC_DIVIDE_RESULT_2;
sahilmgandhi 18:6a4db94011d3 403 accumulate = ADC_ACCUMULATE_SAMPLES_64;
sahilmgandhi 18:6a4db94011d3 404 /* 16-bit result register */
sahilmgandhi 18:6a4db94011d3 405 resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 406 break;
sahilmgandhi 18:6a4db94011d3 407
sahilmgandhi 18:6a4db94011d3 408 case ADC_RESOLUTION_16BIT:
sahilmgandhi 18:6a4db94011d3 409 /* Increase resolution by 4 bit */
sahilmgandhi 18:6a4db94011d3 410 adjres = ADC_DIVIDE_RESULT_DISABLE;
sahilmgandhi 18:6a4db94011d3 411 accumulate = ADC_ACCUMULATE_SAMPLES_256;
sahilmgandhi 18:6a4db94011d3 412 /* 16-bit result register */
sahilmgandhi 18:6a4db94011d3 413 resolution = ADC_RESOLUTION_16BIT;
sahilmgandhi 18:6a4db94011d3 414 break;
sahilmgandhi 18:6a4db94011d3 415 #endif
sahilmgandhi 18:6a4db94011d3 416 case ADC_RESOLUTION_8BIT:
sahilmgandhi 18:6a4db94011d3 417 /* 8-bit result register */
sahilmgandhi 18:6a4db94011d3 418 resolution = ADC_RESOLUTION_8BIT;
sahilmgandhi 18:6a4db94011d3 419 break;
sahilmgandhi 18:6a4db94011d3 420 case ADC_RESOLUTION_10BIT:
sahilmgandhi 18:6a4db94011d3 421 /* 10-bit result register */
sahilmgandhi 18:6a4db94011d3 422 resolution = ADC_RESOLUTION_10BIT;
sahilmgandhi 18:6a4db94011d3 423 break;
sahilmgandhi 18:6a4db94011d3 424 case ADC_RESOLUTION_12BIT:
sahilmgandhi 18:6a4db94011d3 425 /* 12-bit result register */
sahilmgandhi 18:6a4db94011d3 426 resolution = ADC_RESOLUTION_12BIT;
sahilmgandhi 18:6a4db94011d3 427 break;
sahilmgandhi 18:6a4db94011d3 428
sahilmgandhi 18:6a4db94011d3 429 default:
sahilmgandhi 18:6a4db94011d3 430 /* Unknown. Abort. */
sahilmgandhi 18:6a4db94011d3 431 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 432 }
sahilmgandhi 18:6a4db94011d3 433
sahilmgandhi 18:6a4db94011d3 434 adc_module->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(adjres) | accumulate;
sahilmgandhi 18:6a4db94011d3 435
sahilmgandhi 18:6a4db94011d3 436 /* Check validity of sample length value */
sahilmgandhi 18:6a4db94011d3 437 if (config->sample_length > 63) {
sahilmgandhi 18:6a4db94011d3 438 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 439 } else {
sahilmgandhi 18:6a4db94011d3 440 /* Configure sample length */
sahilmgandhi 18:6a4db94011d3 441 adc_module->SAMPCTRL.reg =
sahilmgandhi 18:6a4db94011d3 442 (config->sample_length << ADC_SAMPCTRL_SAMPLEN_Pos);
sahilmgandhi 18:6a4db94011d3 443 }
sahilmgandhi 18:6a4db94011d3 444
sahilmgandhi 18:6a4db94011d3 445 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 446 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 447 }
sahilmgandhi 18:6a4db94011d3 448
sahilmgandhi 18:6a4db94011d3 449 /* Configure CTRLB */
sahilmgandhi 18:6a4db94011d3 450 adc_module->CTRLB.reg =
sahilmgandhi 18:6a4db94011d3 451 config->clock_prescaler |
sahilmgandhi 18:6a4db94011d3 452 resolution |
sahilmgandhi 18:6a4db94011d3 453 (config->correction.correction_enable << ADC_CTRLB_CORREN_Pos) |
sahilmgandhi 18:6a4db94011d3 454 (config->freerunning << ADC_CTRLB_FREERUN_Pos) |
sahilmgandhi 18:6a4db94011d3 455 (config->left_adjust << ADC_CTRLB_LEFTADJ_Pos) |
sahilmgandhi 18:6a4db94011d3 456 (config->differential_mode << ADC_CTRLB_DIFFMODE_Pos);
sahilmgandhi 18:6a4db94011d3 457
sahilmgandhi 18:6a4db94011d3 458 /* Check validity of window thresholds */
sahilmgandhi 18:6a4db94011d3 459 if (config->window.window_mode != ADC_WINDOW_MODE_DISABLE) {
sahilmgandhi 18:6a4db94011d3 460 switch (resolution) {
sahilmgandhi 18:6a4db94011d3 461 case ADC_RESOLUTION_8BIT:
sahilmgandhi 18:6a4db94011d3 462 if (config->differential_mode &&
sahilmgandhi 18:6a4db94011d3 463 (config->window.window_lower_value > 127 ||
sahilmgandhi 18:6a4db94011d3 464 config->window.window_lower_value < -128 ||
sahilmgandhi 18:6a4db94011d3 465 config->window.window_upper_value > 127 ||
sahilmgandhi 18:6a4db94011d3 466 config->window.window_upper_value < -128)) {
sahilmgandhi 18:6a4db94011d3 467 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 468 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 469 } else if (config->window.window_lower_value > 255 ||
sahilmgandhi 18:6a4db94011d3 470 config->window.window_upper_value > 255) {
sahilmgandhi 18:6a4db94011d3 471 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 472 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 473 }
sahilmgandhi 18:6a4db94011d3 474 break;
sahilmgandhi 18:6a4db94011d3 475 case ADC_RESOLUTION_10BIT:
sahilmgandhi 18:6a4db94011d3 476 if (config->differential_mode &&
sahilmgandhi 18:6a4db94011d3 477 (config->window.window_lower_value > 511 ||
sahilmgandhi 18:6a4db94011d3 478 config->window.window_lower_value < -512 ||
sahilmgandhi 18:6a4db94011d3 479 config->window.window_upper_value > 511 ||
sahilmgandhi 18:6a4db94011d3 480 config->window.window_upper_value < -512)) {
sahilmgandhi 18:6a4db94011d3 481 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 482 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 483 } else if (config->window.window_lower_value > 1023 ||
sahilmgandhi 18:6a4db94011d3 484 config->window.window_upper_value > 1023) {
sahilmgandhi 18:6a4db94011d3 485 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 486 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 487 }
sahilmgandhi 18:6a4db94011d3 488 break;
sahilmgandhi 18:6a4db94011d3 489 case ADC_RESOLUTION_12BIT:
sahilmgandhi 18:6a4db94011d3 490 if (config->differential_mode &&
sahilmgandhi 18:6a4db94011d3 491 (config->window.window_lower_value > 2047 ||
sahilmgandhi 18:6a4db94011d3 492 config->window.window_lower_value < -2048 ||
sahilmgandhi 18:6a4db94011d3 493 config->window.window_upper_value > 2047 ||
sahilmgandhi 18:6a4db94011d3 494 config->window.window_upper_value < -2048)) {
sahilmgandhi 18:6a4db94011d3 495 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 496 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 497 } else if (config->window.window_lower_value > 4095 ||
sahilmgandhi 18:6a4db94011d3 498 config->window.window_upper_value > 4095) {
sahilmgandhi 18:6a4db94011d3 499 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 500 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 501 }
sahilmgandhi 18:6a4db94011d3 502 break;
sahilmgandhi 18:6a4db94011d3 503 case ADC_RESOLUTION_16BIT:
sahilmgandhi 18:6a4db94011d3 504 if (config->differential_mode &&
sahilmgandhi 18:6a4db94011d3 505 (config->window.window_lower_value > 32767 ||
sahilmgandhi 18:6a4db94011d3 506 config->window.window_lower_value < -32768 ||
sahilmgandhi 18:6a4db94011d3 507 config->window.window_upper_value > 32767 ||
sahilmgandhi 18:6a4db94011d3 508 config->window.window_upper_value < -32768)) {
sahilmgandhi 18:6a4db94011d3 509 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 510 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 511 } else if (config->window.window_lower_value > 65535 ||
sahilmgandhi 18:6a4db94011d3 512 config->window.window_upper_value > 65535) {
sahilmgandhi 18:6a4db94011d3 513 /* Invalid value */
sahilmgandhi 18:6a4db94011d3 514 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 515 }
sahilmgandhi 18:6a4db94011d3 516 break;
sahilmgandhi 18:6a4db94011d3 517 }
sahilmgandhi 18:6a4db94011d3 518 }
sahilmgandhi 18:6a4db94011d3 519
sahilmgandhi 18:6a4db94011d3 520 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 521 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 522 }
sahilmgandhi 18:6a4db94011d3 523
sahilmgandhi 18:6a4db94011d3 524 /* Configure window mode */
sahilmgandhi 18:6a4db94011d3 525 adc_module->WINCTRL.reg = config->window.window_mode;
sahilmgandhi 18:6a4db94011d3 526
sahilmgandhi 18:6a4db94011d3 527 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 528 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 529 }
sahilmgandhi 18:6a4db94011d3 530
sahilmgandhi 18:6a4db94011d3 531 /* Configure lower threshold */
sahilmgandhi 18:6a4db94011d3 532 adc_module->WINLT.reg =
sahilmgandhi 18:6a4db94011d3 533 config->window.window_lower_value << ADC_WINLT_WINLT_Pos;
sahilmgandhi 18:6a4db94011d3 534
sahilmgandhi 18:6a4db94011d3 535 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 536 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 537 }
sahilmgandhi 18:6a4db94011d3 538
sahilmgandhi 18:6a4db94011d3 539 /* Configure lower threshold */
sahilmgandhi 18:6a4db94011d3 540 adc_module->WINUT.reg = config->window.window_upper_value <<
sahilmgandhi 18:6a4db94011d3 541 ADC_WINUT_WINUT_Pos;
sahilmgandhi 18:6a4db94011d3 542
sahilmgandhi 18:6a4db94011d3 543 uint8_t inputs_to_scan = config->pin_scan.inputs_to_scan;
sahilmgandhi 18:6a4db94011d3 544 if (inputs_to_scan > 0) {
sahilmgandhi 18:6a4db94011d3 545 /*
sahilmgandhi 18:6a4db94011d3 546 * Number of input sources included is the value written to INPUTSCAN
sahilmgandhi 18:6a4db94011d3 547 * plus 1.
sahilmgandhi 18:6a4db94011d3 548 */
sahilmgandhi 18:6a4db94011d3 549 inputs_to_scan--;
sahilmgandhi 18:6a4db94011d3 550 }
sahilmgandhi 18:6a4db94011d3 551
sahilmgandhi 18:6a4db94011d3 552 if (inputs_to_scan > (ADC_INPUTCTRL_INPUTSCAN_Msk >> ADC_INPUTCTRL_INPUTSCAN_Pos) ||
sahilmgandhi 18:6a4db94011d3 553 config->pin_scan.offset_start_scan > (ADC_INPUTCTRL_INPUTOFFSET_Msk >> ADC_INPUTCTRL_INPUTOFFSET_Pos)) {
sahilmgandhi 18:6a4db94011d3 554 /* Invalid number of input pins or input offset */
sahilmgandhi 18:6a4db94011d3 555 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 556 }
sahilmgandhi 18:6a4db94011d3 557
sahilmgandhi 18:6a4db94011d3 558 while (adc_is_syncing(module_inst)) {
sahilmgandhi 18:6a4db94011d3 559 /* Wait for synchronization */
sahilmgandhi 18:6a4db94011d3 560 }
sahilmgandhi 18:6a4db94011d3 561
sahilmgandhi 18:6a4db94011d3 562 /* Configure pin scan mode and positive and negative input pins */
sahilmgandhi 18:6a4db94011d3 563 adc_module->INPUTCTRL.reg =
sahilmgandhi 18:6a4db94011d3 564 config->gain_factor |
sahilmgandhi 18:6a4db94011d3 565 (config->pin_scan.offset_start_scan <<
sahilmgandhi 18:6a4db94011d3 566 ADC_INPUTCTRL_INPUTOFFSET_Pos) |
sahilmgandhi 18:6a4db94011d3 567 (inputs_to_scan << ADC_INPUTCTRL_INPUTSCAN_Pos) |
sahilmgandhi 18:6a4db94011d3 568 config->negative_input |
sahilmgandhi 18:6a4db94011d3 569 config->positive_input;
sahilmgandhi 18:6a4db94011d3 570
sahilmgandhi 18:6a4db94011d3 571 /* Configure events */
sahilmgandhi 18:6a4db94011d3 572 adc_module->EVCTRL.reg = config->event_action;
sahilmgandhi 18:6a4db94011d3 573
sahilmgandhi 18:6a4db94011d3 574 /* Disable all interrupts */
sahilmgandhi 18:6a4db94011d3 575 adc_module->INTENCLR.reg =
sahilmgandhi 18:6a4db94011d3 576 (1 << ADC_INTENCLR_SYNCRDY_Pos) | (1 << ADC_INTENCLR_WINMON_Pos) |
sahilmgandhi 18:6a4db94011d3 577 (1 << ADC_INTENCLR_OVERRUN_Pos) | (1 << ADC_INTENCLR_RESRDY_Pos);
sahilmgandhi 18:6a4db94011d3 578
sahilmgandhi 18:6a4db94011d3 579 if (config->correction.correction_enable) {
sahilmgandhi 18:6a4db94011d3 580 /* Make sure gain_correction value is valid */
sahilmgandhi 18:6a4db94011d3 581 if (config->correction.gain_correction > ADC_GAINCORR_GAINCORR_Msk) {
sahilmgandhi 18:6a4db94011d3 582 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 583 } else {
sahilmgandhi 18:6a4db94011d3 584 /* Set gain correction value */
sahilmgandhi 18:6a4db94011d3 585 adc_module->GAINCORR.reg = config->correction.gain_correction <<
sahilmgandhi 18:6a4db94011d3 586 ADC_GAINCORR_GAINCORR_Pos;
sahilmgandhi 18:6a4db94011d3 587 }
sahilmgandhi 18:6a4db94011d3 588
sahilmgandhi 18:6a4db94011d3 589 /* Make sure offset correction value is valid */
sahilmgandhi 18:6a4db94011d3 590 if (config->correction.offset_correction > 2047 ||
sahilmgandhi 18:6a4db94011d3 591 config->correction.offset_correction < -2048) {
sahilmgandhi 18:6a4db94011d3 592 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 593 } else {
sahilmgandhi 18:6a4db94011d3 594 /* Set offset correction value */
sahilmgandhi 18:6a4db94011d3 595 adc_module->OFFSETCORR.reg = config->correction.offset_correction <<
sahilmgandhi 18:6a4db94011d3 596 ADC_OFFSETCORR_OFFSETCORR_Pos;
sahilmgandhi 18:6a4db94011d3 597 }
sahilmgandhi 18:6a4db94011d3 598 }
sahilmgandhi 18:6a4db94011d3 599
sahilmgandhi 18:6a4db94011d3 600 /* Load in the fixed device ADC calibration constants */
sahilmgandhi 18:6a4db94011d3 601 adc_module->CALIB.reg =
sahilmgandhi 18:6a4db94011d3 602 ADC_CALIB_BIAS_CAL(
sahilmgandhi 18:6a4db94011d3 603 (*(uint32_t *)ADC_FUSES_BIASCAL_ADDR >> ADC_FUSES_BIASCAL_Pos)
sahilmgandhi 18:6a4db94011d3 604 ) |
sahilmgandhi 18:6a4db94011d3 605 ADC_CALIB_LINEARITY_CAL(
sahilmgandhi 18:6a4db94011d3 606 (*(uint64_t *)ADC_FUSES_LINEARITY_0_ADDR >> ADC_FUSES_LINEARITY_0_Pos)
sahilmgandhi 18:6a4db94011d3 607 );
sahilmgandhi 18:6a4db94011d3 608
sahilmgandhi 18:6a4db94011d3 609 return STATUS_OK;
sahilmgandhi 18:6a4db94011d3 610 }
sahilmgandhi 18:6a4db94011d3 611
sahilmgandhi 18:6a4db94011d3 612 /**
sahilmgandhi 18:6a4db94011d3 613 * \brief Initializes the ADC channel sequence
sahilmgandhi 18:6a4db94011d3 614 *
sahilmgandhi 18:6a4db94011d3 615 * Like SAMD and SAMR21 the INPUTOFFSET register will be incremented one
sahilmgandhi 18:6a4db94011d3 616 * automatically after a conversion done, causing the next conversion
sahilmgandhi 18:6a4db94011d3 617 * to be done with the positive input equal to MUXPOS + INPUTOFFSET,
sahilmgandhi 18:6a4db94011d3 618 * it is scanning continuously one by one even ADC channels are not continuous.
sahilmgandhi 18:6a4db94011d3 619 *
sahilmgandhi 18:6a4db94011d3 620 * Initializes the ADC channel sequence by the sequence of pin_array.
sahilmgandhi 18:6a4db94011d3 621 *
sahilmgandhi 18:6a4db94011d3 622 * \param[in] pin_array The array of the Mux selection for the positive ADC input
sahilmgandhi 18:6a4db94011d3 623 * \param[in] size The size of pin_array
sahilmgandhi 18:6a4db94011d3 624 */
sahilmgandhi 18:6a4db94011d3 625 void adc_regular_ain_channel(uint32_t *pin_array, uint8_t size)
sahilmgandhi 18:6a4db94011d3 626 {
sahilmgandhi 18:6a4db94011d3 627 for (int i = 0; i < size; i++) {
sahilmgandhi 18:6a4db94011d3 628 _adc_configure_ain_pin(pin_array[i]);
sahilmgandhi 18:6a4db94011d3 629 }
sahilmgandhi 18:6a4db94011d3 630 }
sahilmgandhi 18:6a4db94011d3 631
sahilmgandhi 18:6a4db94011d3 632 /**
sahilmgandhi 18:6a4db94011d3 633 * \brief Initializes the ADC
sahilmgandhi 18:6a4db94011d3 634 *
sahilmgandhi 18:6a4db94011d3 635 * Initializes the ADC device struct and the hardware module based on the
sahilmgandhi 18:6a4db94011d3 636 * given configuration struct values.
sahilmgandhi 18:6a4db94011d3 637 *
sahilmgandhi 18:6a4db94011d3 638 * \param[out] module_inst Pointer to the ADC software instance struct
sahilmgandhi 18:6a4db94011d3 639 * \param[in] hw Pointer to the ADC module instance
sahilmgandhi 18:6a4db94011d3 640 * \param[in] config Pointer to the configuration struct
sahilmgandhi 18:6a4db94011d3 641 *
sahilmgandhi 18:6a4db94011d3 642 * \return Status of the initialization procedure.
sahilmgandhi 18:6a4db94011d3 643 * \retval STATUS_OK The initialization was successful
sahilmgandhi 18:6a4db94011d3 644 * \retval STATUS_ERR_INVALID_ARG Invalid argument(s) were provided
sahilmgandhi 18:6a4db94011d3 645 * \retval STATUS_BUSY The module is busy with a reset operation
sahilmgandhi 18:6a4db94011d3 646 * \retval STATUS_ERR_DENIED The module is enabled
sahilmgandhi 18:6a4db94011d3 647 */
sahilmgandhi 18:6a4db94011d3 648 enum status_code adc_init(
sahilmgandhi 18:6a4db94011d3 649 struct adc_module *const module_inst,
sahilmgandhi 18:6a4db94011d3 650 Adc *hw,
sahilmgandhi 18:6a4db94011d3 651 struct adc_config *config)
sahilmgandhi 18:6a4db94011d3 652 {
sahilmgandhi 18:6a4db94011d3 653 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 654 Assert(module_inst);
sahilmgandhi 18:6a4db94011d3 655 Assert(hw);
sahilmgandhi 18:6a4db94011d3 656 Assert(config);
sahilmgandhi 18:6a4db94011d3 657
sahilmgandhi 18:6a4db94011d3 658 /* Associate the software module instance with the hardware module */
sahilmgandhi 18:6a4db94011d3 659 module_inst->hw = hw;
sahilmgandhi 18:6a4db94011d3 660
sahilmgandhi 18:6a4db94011d3 661 /* Turn on the digital interface clock */
sahilmgandhi 18:6a4db94011d3 662 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_ADC);
sahilmgandhi 18:6a4db94011d3 663
sahilmgandhi 18:6a4db94011d3 664 if (hw->CTRLA.reg & ADC_CTRLA_SWRST) {
sahilmgandhi 18:6a4db94011d3 665 /* We are in the middle of a reset. Abort. */
sahilmgandhi 18:6a4db94011d3 666 return STATUS_BUSY;
sahilmgandhi 18:6a4db94011d3 667 }
sahilmgandhi 18:6a4db94011d3 668
sahilmgandhi 18:6a4db94011d3 669 if (hw->CTRLA.reg & ADC_CTRLA_ENABLE) {
sahilmgandhi 18:6a4db94011d3 670 /* Module must be disabled before initialization. Abort. */
sahilmgandhi 18:6a4db94011d3 671 return STATUS_ERR_DENIED;
sahilmgandhi 18:6a4db94011d3 672 }
sahilmgandhi 18:6a4db94011d3 673
sahilmgandhi 18:6a4db94011d3 674 /* Store the selected reference for later use */
sahilmgandhi 18:6a4db94011d3 675 module_inst->reference = config->reference;
sahilmgandhi 18:6a4db94011d3 676
sahilmgandhi 18:6a4db94011d3 677 /* Make sure bandgap is enabled if requested by the config */
sahilmgandhi 18:6a4db94011d3 678 if (module_inst->reference == ADC_REFERENCE_INT1V) {
sahilmgandhi 18:6a4db94011d3 679 system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_BANDGAP);
sahilmgandhi 18:6a4db94011d3 680 }
sahilmgandhi 18:6a4db94011d3 681
sahilmgandhi 18:6a4db94011d3 682 #if ADC_CALLBACK_MODE == true
sahilmgandhi 18:6a4db94011d3 683 for (uint8_t i = 0; i < ADC_CALLBACK_N; i++) {
sahilmgandhi 18:6a4db94011d3 684 module_inst->callback[i] = NULL;
sahilmgandhi 18:6a4db94011d3 685 };
sahilmgandhi 18:6a4db94011d3 686
sahilmgandhi 18:6a4db94011d3 687 module_inst->registered_callback_mask = 0;
sahilmgandhi 18:6a4db94011d3 688 module_inst->enabled_callback_mask = 0;
sahilmgandhi 18:6a4db94011d3 689 module_inst->remaining_conversions = 0;
sahilmgandhi 18:6a4db94011d3 690 module_inst->job_status = STATUS_OK;
sahilmgandhi 18:6a4db94011d3 691
sahilmgandhi 18:6a4db94011d3 692 _adc_instances[0] = module_inst;
sahilmgandhi 18:6a4db94011d3 693
sahilmgandhi 18:6a4db94011d3 694 if (config->event_action == ADC_EVENT_ACTION_DISABLED &&
sahilmgandhi 18:6a4db94011d3 695 !config->freerunning) {
sahilmgandhi 18:6a4db94011d3 696 module_inst->software_trigger = true;
sahilmgandhi 18:6a4db94011d3 697 } else {
sahilmgandhi 18:6a4db94011d3 698 module_inst->software_trigger = false;
sahilmgandhi 18:6a4db94011d3 699 }
sahilmgandhi 18:6a4db94011d3 700 #endif
sahilmgandhi 18:6a4db94011d3 701
sahilmgandhi 18:6a4db94011d3 702 /* Write configuration to module */
sahilmgandhi 18:6a4db94011d3 703 return _adc_set_config(module_inst, config);
sahilmgandhi 18:6a4db94011d3 704 }