Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_Atmel/TARGET_SAM_CortexM4/drivers/adc/adc2.c@188:60408c49b6d4, 2018-09-20 (annotated)
- Committer:
- WaleedElmughrabi
- Date:
- Thu Sep 20 16:11:23 2018 +0000
- Revision:
- 188:60408c49b6d4
- Parent:
- 149:156823d33999
Fork modified for BG96 error
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| mbed_official | 107:414e9c822e99 | 1 | /** |
| mbed_official | 107:414e9c822e99 | 2 | * \file |
| mbed_official | 107:414e9c822e99 | 3 | * |
| mbed_official | 107:414e9c822e99 | 4 | * \brief ADC Controller driver. |
| mbed_official | 107:414e9c822e99 | 5 | * |
| mbed_official | 107:414e9c822e99 | 6 | * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved. |
| mbed_official | 107:414e9c822e99 | 7 | * |
| mbed_official | 107:414e9c822e99 | 8 | * \asf_license_start |
| mbed_official | 107:414e9c822e99 | 9 | * |
| mbed_official | 107:414e9c822e99 | 10 | * \page License |
| mbed_official | 107:414e9c822e99 | 11 | * |
| mbed_official | 107:414e9c822e99 | 12 | * Redistribution and use in source and binary forms, with or without |
| mbed_official | 107:414e9c822e99 | 13 | * modification, are permitted provided that the following conditions are met: |
| mbed_official | 107:414e9c822e99 | 14 | * |
| mbed_official | 107:414e9c822e99 | 15 | * 1. Redistributions of source code must retain the above copyright notice, |
| mbed_official | 107:414e9c822e99 | 16 | * this list of conditions and the following disclaimer. |
| mbed_official | 107:414e9c822e99 | 17 | * |
| mbed_official | 107:414e9c822e99 | 18 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
| mbed_official | 107:414e9c822e99 | 19 | * this list of conditions and the following disclaimer in the documentation |
| mbed_official | 107:414e9c822e99 | 20 | * and/or other materials provided with the distribution. |
| mbed_official | 107:414e9c822e99 | 21 | * |
| mbed_official | 107:414e9c822e99 | 22 | * 3. The name of Atmel may not be used to endorse or promote products derived |
| mbed_official | 107:414e9c822e99 | 23 | * from this software without specific prior written permission. |
| mbed_official | 107:414e9c822e99 | 24 | * |
| mbed_official | 107:414e9c822e99 | 25 | * 4. This software may only be redistributed and used in connection with an |
| mbed_official | 107:414e9c822e99 | 26 | * Atmel microcontroller product. |
| mbed_official | 107:414e9c822e99 | 27 | * |
| mbed_official | 107:414e9c822e99 | 28 | * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED |
| mbed_official | 107:414e9c822e99 | 29 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| mbed_official | 107:414e9c822e99 | 30 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE |
| mbed_official | 107:414e9c822e99 | 31 | * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR |
| mbed_official | 107:414e9c822e99 | 32 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| mbed_official | 107:414e9c822e99 | 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| mbed_official | 107:414e9c822e99 | 34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| mbed_official | 107:414e9c822e99 | 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| mbed_official | 107:414e9c822e99 | 36 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| mbed_official | 107:414e9c822e99 | 37 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| mbed_official | 107:414e9c822e99 | 38 | * POSSIBILITY OF SUCH DAMAGE. |
| mbed_official | 107:414e9c822e99 | 39 | * |
| mbed_official | 107:414e9c822e99 | 40 | * \asf_license_stop |
| mbed_official | 107:414e9c822e99 | 41 | * |
| mbed_official | 107:414e9c822e99 | 42 | */ |
| mbed_official | 107:414e9c822e99 | 43 | /* |
| mbed_official | 107:414e9c822e99 | 44 | * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> |
| mbed_official | 107:414e9c822e99 | 45 | */ |
| mbed_official | 107:414e9c822e99 | 46 | |
| mbed_official | 107:414e9c822e99 | 47 | #include "adc2.h" |
| mbed_official | 107:414e9c822e99 | 48 | #include "sleepmgr.h" |
| mbed_official | 107:414e9c822e99 | 49 | #include "status_codes.h" |
| mbed_official | 107:414e9c822e99 | 50 | #include "sysclk.h" |
| mbed_official | 107:414e9c822e99 | 51 | #include "pmc.h" |
| mbed_official | 107:414e9c822e99 | 52 | |
| mbed_official | 107:414e9c822e99 | 53 | /** |
| mbed_official | 107:414e9c822e99 | 54 | * \defgroup sam_drivers_adc2_group Analog-to-Digital Controller |
| mbed_official | 107:414e9c822e99 | 55 | * |
| mbed_official | 107:414e9c822e99 | 56 | * See \ref sam_adc2_quickstart. |
| mbed_official | 107:414e9c822e99 | 57 | * |
| mbed_official | 107:414e9c822e99 | 58 | * Driver for the Analog-to-Digital Controller. This driver provides access to |
| mbed_official | 107:414e9c822e99 | 59 | * the main features of the ADC controller. |
| mbed_official | 107:414e9c822e99 | 60 | * |
| mbed_official | 107:414e9c822e99 | 61 | * @{ |
| mbed_official | 107:414e9c822e99 | 62 | */ |
| mbed_official | 107:414e9c822e99 | 63 | |
| mbed_official | 107:414e9c822e99 | 64 | /* The number of channel in channel sequence1 register */ |
| mbed_official | 107:414e9c822e99 | 65 | #define ADC_SEQ1_CHANNEL_NUM (8UL) |
| mbed_official | 107:414e9c822e99 | 66 | |
| mbed_official | 107:414e9c822e99 | 67 | /* The number of ADC interrupt source */ |
| mbed_official | 107:414e9c822e99 | 68 | #define ADC_NUM_OF_INTERRUPT_SOURCE (24UL) |
| mbed_official | 107:414e9c822e99 | 69 | |
| mbed_official | 107:414e9c822e99 | 70 | |
| mbed_official | 107:414e9c822e99 | 71 | const uint32_t adc_interrupt_mask[ADC_NUM_OF_INTERRUPT_SOURCE] = { |
| mbed_official | 107:414e9c822e99 | 72 | ADC_ISR_EOC0, ADC_ISR_EOC1, ADC_ISR_EOC2, ADC_ISR_EOC3, |
| mbed_official | 107:414e9c822e99 | 73 | ADC_ISR_EOC4, ADC_ISR_EOC5, ADC_ISR_EOC6, ADC_ISR_EOC7, |
| mbed_official | 107:414e9c822e99 | 74 | #if (SAM4N) |
| mbed_official | 107:414e9c822e99 | 75 | ADC_ISR_EOC8, ADC_ISR_EOC9, ADC_ISR_EOC10, ADC_ISR_EOC11, |
| mbed_official | 107:414e9c822e99 | 76 | ADC_ISR_EOC12, ADC_ISR_EOC13, ADC_ISR_EOC14, ADC_ISR_EOC15, |
| mbed_official | 107:414e9c822e99 | 77 | ADC_ISR_EOC16, |
| mbed_official | 107:414e9c822e99 | 78 | #endif |
| mbed_official | 107:414e9c822e99 | 79 | #ifdef TEMP_SENSOR |
| mbed_official | 107:414e9c822e99 | 80 | ADC_ISR_TEMPCHG, |
| mbed_official | 107:414e9c822e99 | 81 | #endif |
| mbed_official | 107:414e9c822e99 | 82 | ADC_ISR_EOCAL, ADC_ISR_DRDY, |
| mbed_official | 107:414e9c822e99 | 83 | ADC_ISR_GOVRE, ADC_ISR_COMPE, ADC_ISR_ENDRX, ADC_ISR_RXBUFF, |
| mbed_official | 107:414e9c822e99 | 84 | }; |
| mbed_official | 107:414e9c822e99 | 85 | |
| mbed_official | 107:414e9c822e99 | 86 | adc_callback_t adc_callback_pointer[ADC_NUM_OF_INTERRUPT_SOURCE]; |
| mbed_official | 107:414e9c822e99 | 87 | |
| mbed_official | 107:414e9c822e99 | 88 | /** |
| mbed_official | 107:414e9c822e99 | 89 | * \brief Get the ADC default configurations. |
| mbed_official | 107:414e9c822e99 | 90 | * |
| mbed_official | 107:414e9c822e99 | 91 | * Use to initialize the configuration structure to known default values. This |
| mbed_official | 107:414e9c822e99 | 92 | * function should be called at the start of any ADC initiation. |
| mbed_official | 107:414e9c822e99 | 93 | * |
| mbed_official | 107:414e9c822e99 | 94 | * The default configuration is as follows: |
| mbed_official | 107:414e9c822e99 | 95 | * - 10-bit resolution |
| mbed_official | 107:414e9c822e99 | 96 | * - ADC clock frequency is 6MHz |
| mbed_official | 107:414e9c822e99 | 97 | * - Start Up Time is 64 periods ADC clock |
| mbed_official | 107:414e9c822e99 | 98 | * - Tracking Time is 3 periods of ADC clock |
| mbed_official | 107:414e9c822e99 | 99 | * - Transfer Period field shall be programmed with 2 as datasheet said |
| mbed_official | 107:414e9c822e99 | 100 | * - The controller converts channels in a simple numeric order |
| mbed_official | 107:414e9c822e99 | 101 | * - Appends the channel number to the conversion result in ADC_LCDR register |
| mbed_official | 107:414e9c822e99 | 102 | * - Only a Single Trigger is required to get an averaged value |
| mbed_official | 107:414e9c822e99 | 103 | * |
| mbed_official | 107:414e9c822e99 | 104 | * \param cfg Pointer to configuration structure to be initiated. |
| mbed_official | 107:414e9c822e99 | 105 | */ |
| mbed_official | 107:414e9c822e99 | 106 | void adc_get_config_defaults(struct adc_config *const cfg) |
| mbed_official | 107:414e9c822e99 | 107 | { |
| mbed_official | 107:414e9c822e99 | 108 | /* Sanity check argument. */ |
| mbed_official | 107:414e9c822e99 | 109 | Assert(cfg); |
| mbed_official | 107:414e9c822e99 | 110 | |
| mbed_official | 107:414e9c822e99 | 111 | #if SAMG55 |
| mbed_official | 107:414e9c822e99 | 112 | cfg->resolution = ADC_12_BITS; |
| mbed_official | 107:414e9c822e99 | 113 | #else |
| mbed_official | 107:414e9c822e99 | 114 | cfg->resolution = ADC_10_BITS; |
| mbed_official | 107:414e9c822e99 | 115 | #endif |
| mbed_official | 107:414e9c822e99 | 116 | cfg->mck = sysclk_get_cpu_hz(); |
| mbed_official | 107:414e9c822e99 | 117 | cfg->adc_clock = 6000000UL; |
| mbed_official | 107:414e9c822e99 | 118 | cfg->startup_time = ADC_STARTUP_TIME_4; |
| mbed_official | 107:414e9c822e99 | 119 | cfg->tracktim = 2; |
| mbed_official | 107:414e9c822e99 | 120 | cfg->transfer = 2; |
| mbed_official | 107:414e9c822e99 | 121 | cfg->useq = false; |
| mbed_official | 107:414e9c822e99 | 122 | cfg->tag = false; |
| mbed_official | 107:414e9c822e99 | 123 | cfg->aste = false; |
| mbed_official | 107:414e9c822e99 | 124 | } |
| mbed_official | 107:414e9c822e99 | 125 | |
| mbed_official | 107:414e9c822e99 | 126 | /** |
| mbed_official | 107:414e9c822e99 | 127 | * \internal |
| mbed_official | 107:414e9c822e99 | 128 | * \brief Configure the ADC Module. |
| mbed_official | 107:414e9c822e99 | 129 | * |
| mbed_official | 107:414e9c822e99 | 130 | * \param adc Base address of the ADC |
| mbed_official | 107:414e9c822e99 | 131 | * \param config Configuration for the ADC |
| mbed_official | 107:414e9c822e99 | 132 | */ |
| mbed_official | 107:414e9c822e99 | 133 | static void adc_set_config(Adc *const adc, struct adc_config *config) |
| mbed_official | 107:414e9c822e99 | 134 | { |
| mbed_official | 107:414e9c822e99 | 135 | uint32_t reg = 0; |
| mbed_official | 107:414e9c822e99 | 136 | |
| mbed_official | 107:414e9c822e99 | 137 | reg = (config->useq ? ADC_MR_USEQ_REG_ORDER : 0) | |
| mbed_official | 107:414e9c822e99 | 138 | ADC_MR_PRESCAL(config->mck / |
| mbed_official | 107:414e9c822e99 | 139 | (2 * config->adc_clock) - 1) | |
| mbed_official | 107:414e9c822e99 | 140 | ADC_MR_TRACKTIM(config->tracktim) | |
| mbed_official | 107:414e9c822e99 | 141 | ADC_MR_TRANSFER(config->transfer) | |
| mbed_official | 107:414e9c822e99 | 142 | (config->startup_time); |
| mbed_official | 107:414e9c822e99 | 143 | |
| mbed_official | 107:414e9c822e99 | 144 | adc->ADC_MR = reg; |
| mbed_official | 107:414e9c822e99 | 145 | |
| mbed_official | 107:414e9c822e99 | 146 | adc->ADC_EMR = (config->tag ? ADC_EMR_TAG : 0) | |
| mbed_official | 107:414e9c822e99 | 147 | (config->aste ? ADC_EMR_ASTE_SINGLE_TRIG_AVERAGE : 0); |
| mbed_official | 107:414e9c822e99 | 148 | |
| mbed_official | 107:414e9c822e99 | 149 | adc_set_resolution(adc, config->resolution); |
| mbed_official | 107:414e9c822e99 | 150 | } |
| mbed_official | 107:414e9c822e99 | 151 | |
| mbed_official | 107:414e9c822e99 | 152 | #ifdef TEMP_SENSOR |
| mbed_official | 107:414e9c822e99 | 153 | /** |
| mbed_official | 107:414e9c822e99 | 154 | * \brief Get the ADC Temperature Sensor default configurations. |
| mbed_official | 107:414e9c822e99 | 155 | * |
| mbed_official | 107:414e9c822e99 | 156 | * Use to initialize the configuration structure to known default values. |
| mbed_official | 107:414e9c822e99 | 157 | * |
| mbed_official | 107:414e9c822e99 | 158 | * The default configuration is as follows: |
| mbed_official | 107:414e9c822e99 | 159 | * - Generates an event when the converted data is in the comparison window |
| mbed_official | 107:414e9c822e99 | 160 | * - The window range is 0xFF ~ 0xFFF |
| mbed_official | 107:414e9c822e99 | 161 | * |
| mbed_official | 107:414e9c822e99 | 162 | * \param cfg Pointer to temperature sensor configuration structure |
| mbed_official | 107:414e9c822e99 | 163 | * to be initiated. |
| mbed_official | 107:414e9c822e99 | 164 | */ |
| mbed_official | 107:414e9c822e99 | 165 | void adc_temp_sensor_get_config_defaults( |
| mbed_official | 107:414e9c822e99 | 166 | struct adc_temp_sensor_config *const cfg) |
| mbed_official | 107:414e9c822e99 | 167 | { |
| mbed_official | 107:414e9c822e99 | 168 | /*Sanity check argument. */ |
| mbed_official | 107:414e9c822e99 | 169 | Assert(cfg); |
| mbed_official | 107:414e9c822e99 | 170 | |
| mbed_official | 107:414e9c822e99 | 171 | cfg->tempon = true; |
| mbed_official | 107:414e9c822e99 | 172 | cfg->mode = ADC_TEMP_CMP_MODE_2; |
| mbed_official | 107:414e9c822e99 | 173 | cfg->low_threshold = 0xFF; |
| mbed_official | 107:414e9c822e99 | 174 | cfg->high_threshold = 0xFFF; |
| mbed_official | 107:414e9c822e99 | 175 | } |
| mbed_official | 107:414e9c822e99 | 176 | |
| mbed_official | 107:414e9c822e99 | 177 | /** |
| mbed_official | 107:414e9c822e99 | 178 | * \brief Configure the ADC temperature sensor. |
| mbed_official | 107:414e9c822e99 | 179 | * |
| mbed_official | 107:414e9c822e99 | 180 | * \param adc Base address of the ADC |
| mbed_official | 107:414e9c822e99 | 181 | * \param config Configuration for the ADC temperature sensor |
| mbed_official | 107:414e9c822e99 | 182 | */ |
| mbed_official | 107:414e9c822e99 | 183 | void adc_temp_sensor_set_config(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 184 | struct adc_temp_sensor_config *config) |
| mbed_official | 107:414e9c822e99 | 185 | { |
| mbed_official | 107:414e9c822e99 | 186 | uint32_t reg = 0; |
| mbed_official | 107:414e9c822e99 | 187 | |
| mbed_official | 107:414e9c822e99 | 188 | reg = ((config->tempon) ? ADC_TEMPMR_TEMPON : 0) | (config->mode); |
| mbed_official | 107:414e9c822e99 | 189 | adc->ADC_TEMPMR = reg; |
| mbed_official | 107:414e9c822e99 | 190 | |
| mbed_official | 107:414e9c822e99 | 191 | adc->ADC_TEMPCWR = ADC_TEMPCWR_TLOWTHRES(config->low_threshold) | |
| mbed_official | 107:414e9c822e99 | 192 | ADC_TEMPCWR_THIGHTHRES(config->high_threshold); |
| mbed_official | 107:414e9c822e99 | 193 | } |
| mbed_official | 107:414e9c822e99 | 194 | #endif |
| mbed_official | 107:414e9c822e99 | 195 | |
| mbed_official | 107:414e9c822e99 | 196 | #if (SAMG) |
| mbed_official | 107:414e9c822e99 | 197 | /** |
| mbed_official | 107:414e9c822e99 | 198 | * \brief Get the Last Channel Specific Measurement default configurations. |
| mbed_official | 107:414e9c822e99 | 199 | * |
| mbed_official | 107:414e9c822e99 | 200 | * Use to initialize the configuration structure to known default values. |
| mbed_official | 107:414e9c822e99 | 201 | * |
| mbed_official | 107:414e9c822e99 | 202 | * The default configuration is as follows: |
| mbed_official | 107:414e9c822e99 | 203 | * - Generates an event when the converted data is in the comparison window |
| mbed_official | 107:414e9c822e99 | 204 | * - The window range is 0xFF ~ 0xFFF |
| mbed_official | 107:414e9c822e99 | 205 | * |
| mbed_official | 107:414e9c822e99 | 206 | * \param cfg Pointer to last channel configuration structure |
| mbed_official | 107:414e9c822e99 | 207 | * to be initiated. |
| mbed_official | 107:414e9c822e99 | 208 | */ |
| mbed_official | 107:414e9c822e99 | 209 | void adc_last_channel_get_config_defaults( |
| mbed_official | 107:414e9c822e99 | 210 | struct adc_last_channel_config *const cfg) |
| mbed_official | 107:414e9c822e99 | 211 | { |
| mbed_official | 107:414e9c822e99 | 212 | /*Sanity check argument. */ |
| mbed_official | 107:414e9c822e99 | 213 | Assert(cfg); |
| mbed_official | 107:414e9c822e99 | 214 | |
| mbed_official | 107:414e9c822e99 | 215 | cfg->dual_trig_on = true; |
| mbed_official | 107:414e9c822e99 | 216 | cfg->mode = ADC_LAST_CHANNEL_CMP_MODE_2; |
| mbed_official | 107:414e9c822e99 | 217 | cfg->low_threshold = 0xFF; |
| mbed_official | 107:414e9c822e99 | 218 | cfg->high_threshold = 0xFFF; |
| mbed_official | 107:414e9c822e99 | 219 | } |
| mbed_official | 107:414e9c822e99 | 220 | |
| mbed_official | 107:414e9c822e99 | 221 | /** |
| mbed_official | 107:414e9c822e99 | 222 | * \brief Configure the ADC Last Channel Specific Measurement. |
| mbed_official | 107:414e9c822e99 | 223 | * |
| mbed_official | 107:414e9c822e99 | 224 | * \param adc Base address of the ADC |
| mbed_official | 107:414e9c822e99 | 225 | * \param config Configuration for the last channel |
| mbed_official | 107:414e9c822e99 | 226 | */ |
| mbed_official | 107:414e9c822e99 | 227 | void adc_last_channel_set_config(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 228 | struct adc_last_channel_config *config) |
| mbed_official | 107:414e9c822e99 | 229 | { |
| mbed_official | 107:414e9c822e99 | 230 | uint32_t reg = 0; |
| mbed_official | 107:414e9c822e99 | 231 | |
| mbed_official | 107:414e9c822e99 | 232 | reg = ((config->dual_trig_on) ? ADC_LCTMR_DUALTRIG : 0) | (config->mode); |
| mbed_official | 107:414e9c822e99 | 233 | adc->ADC_LCTMR = reg; |
| mbed_official | 107:414e9c822e99 | 234 | |
| mbed_official | 107:414e9c822e99 | 235 | adc->ADC_LCCWR = ADC_LCCWR_LOWTHRES(config->low_threshold) | |
| mbed_official | 107:414e9c822e99 | 236 | ADC_LCCWR_HIGHTHRES(config->high_threshold); |
| mbed_official | 107:414e9c822e99 | 237 | } |
| mbed_official | 107:414e9c822e99 | 238 | #endif |
| mbed_official | 107:414e9c822e99 | 239 | |
| mbed_official | 107:414e9c822e99 | 240 | /** |
| mbed_official | 107:414e9c822e99 | 241 | * \brief Initialize the ADC Module. |
| mbed_official | 107:414e9c822e99 | 242 | * |
| mbed_official | 107:414e9c822e99 | 243 | * \param adc Base address of the ADC |
| mbed_official | 107:414e9c822e99 | 244 | * \param config Configuration for the ADC |
| mbed_official | 107:414e9c822e99 | 245 | * |
| mbed_official | 107:414e9c822e99 | 246 | * \retval STATUS_OK Initialization is finished. |
| mbed_official | 107:414e9c822e99 | 247 | * \retval STATUS_ERR_BUSY Initialization failed. |
| mbed_official | 107:414e9c822e99 | 248 | */ |
| mbed_official | 107:414e9c822e99 | 249 | enum status_code adc_init(Adc *const adc, struct adc_config *config) |
| mbed_official | 107:414e9c822e99 | 250 | { |
| mbed_official | 107:414e9c822e99 | 251 | Assert(adc); |
| mbed_official | 107:414e9c822e99 | 252 | Assert(config); |
| mbed_official | 107:414e9c822e99 | 253 | |
| mbed_official | 107:414e9c822e99 | 254 | if ((adc_get_interrupt_status(adc) & ADC_ISR_DRDY) == ADC_ISR_DRDY) { |
| mbed_official | 107:414e9c822e99 | 255 | return STATUS_ERR_BUSY; |
| mbed_official | 107:414e9c822e99 | 256 | } |
| mbed_official | 107:414e9c822e99 | 257 | |
| mbed_official | 107:414e9c822e99 | 258 | /* Reset and configure the ADC module */ |
| mbed_official | 107:414e9c822e99 | 259 | adc->ADC_CR = ADC_CR_SWRST; |
| mbed_official | 107:414e9c822e99 | 260 | adc_set_config(adc, config); |
| mbed_official | 107:414e9c822e99 | 261 | |
| mbed_official | 107:414e9c822e99 | 262 | uint32_t i; |
| mbed_official | 107:414e9c822e99 | 263 | for (i = 0; i < ADC_NUM_OF_INTERRUPT_SOURCE; i++) { |
| mbed_official | 107:414e9c822e99 | 264 | adc_callback_pointer[i] = 0; |
| mbed_official | 107:414e9c822e99 | 265 | } |
| mbed_official | 107:414e9c822e99 | 266 | |
| mbed_official | 107:414e9c822e99 | 267 | return STATUS_OK; |
| mbed_official | 107:414e9c822e99 | 268 | } |
| mbed_official | 107:414e9c822e99 | 269 | |
| mbed_official | 107:414e9c822e99 | 270 | /** |
| mbed_official | 107:414e9c822e99 | 271 | * \brief Configure conversion resolution. |
| mbed_official | 107:414e9c822e99 | 272 | * |
| mbed_official | 107:414e9c822e99 | 273 | * \param adc Base address of the ADC. |
| mbed_official | 107:414e9c822e99 | 274 | * \param res Conversion resolution. |
| mbed_official | 107:414e9c822e99 | 275 | * |
| mbed_official | 107:414e9c822e99 | 276 | */ |
| mbed_official | 107:414e9c822e99 | 277 | void adc_set_resolution(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 278 | const enum adc_resolution res) |
| mbed_official | 107:414e9c822e99 | 279 | { |
| mbed_official | 107:414e9c822e99 | 280 | #if SAMG55 |
| mbed_official | 107:414e9c822e99 | 281 | adc->ADC_EMR |= res; |
| mbed_official | 107:414e9c822e99 | 282 | #else |
| mbed_official | 107:414e9c822e99 | 283 | if (res == ADC_11_BITS || res == ADC_12_BITS) { |
| mbed_official | 107:414e9c822e99 | 284 | adc->ADC_MR &= ~ADC_MR_LOWRES; |
| mbed_official | 107:414e9c822e99 | 285 | adc->ADC_EMR |= res; |
| mbed_official | 107:414e9c822e99 | 286 | } else { |
| mbed_official | 107:414e9c822e99 | 287 | adc->ADC_MR |= res; |
| mbed_official | 107:414e9c822e99 | 288 | adc->ADC_EMR &= ~ADC_EMR_OSR_Msk; |
| mbed_official | 107:414e9c822e99 | 289 | } |
| mbed_official | 107:414e9c822e99 | 290 | #endif |
| mbed_official | 107:414e9c822e99 | 291 | } |
| mbed_official | 107:414e9c822e99 | 292 | |
| mbed_official | 107:414e9c822e99 | 293 | /** |
| mbed_official | 107:414e9c822e99 | 294 | * \brief Configure comparison mode. |
| mbed_official | 107:414e9c822e99 | 295 | * |
| mbed_official | 107:414e9c822e99 | 296 | * \param adc Base address of the ADC. |
| mbed_official | 107:414e9c822e99 | 297 | * \param mode Comparison mode. |
| mbed_official | 107:414e9c822e99 | 298 | * \param channel Comparison Selected Channel. |
| mbed_official | 107:414e9c822e99 | 299 | * \param cmp_filter Compare Event Filtering. |
| mbed_official | 107:414e9c822e99 | 300 | */ |
| mbed_official | 107:414e9c822e99 | 301 | void adc_set_comparison_mode(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 302 | const enum adc_cmp_mode mode, |
| mbed_official | 107:414e9c822e99 | 303 | const enum adc_channel_num channel, uint8_t cmp_filter) |
| mbed_official | 107:414e9c822e99 | 304 | { |
| mbed_official | 107:414e9c822e99 | 305 | if (channel != ADC_CHANNEL_ALL) { |
| mbed_official | 107:414e9c822e99 | 306 | adc_ch_sanity_check(adc, channel); |
| mbed_official | 107:414e9c822e99 | 307 | } |
| mbed_official | 107:414e9c822e99 | 308 | |
| mbed_official | 107:414e9c822e99 | 309 | uint32_t reg; |
| mbed_official | 107:414e9c822e99 | 310 | |
| mbed_official | 107:414e9c822e99 | 311 | reg = adc->ADC_EMR; |
| mbed_official | 107:414e9c822e99 | 312 | |
| mbed_official | 107:414e9c822e99 | 313 | reg &= ~(ADC_EMR_CMPSEL_Msk | |
| mbed_official | 107:414e9c822e99 | 314 | ADC_EMR_CMPMODE_Msk | |
| mbed_official | 107:414e9c822e99 | 315 | ADC_EMR_CMPFILTER_Msk); |
| mbed_official | 107:414e9c822e99 | 316 | reg |= mode | |
| mbed_official | 107:414e9c822e99 | 317 | ((channel == ADC_CHANNEL_ALL) ? ADC_EMR_CMPALL |
| mbed_official | 107:414e9c822e99 | 318 | : ADC_EMR_CMPSEL(channel)) | |
| mbed_official | 107:414e9c822e99 | 319 | ADC_EMR_CMPFILTER(cmp_filter); |
| mbed_official | 107:414e9c822e99 | 320 | |
| mbed_official | 107:414e9c822e99 | 321 | adc->ADC_EMR = reg; |
| mbed_official | 107:414e9c822e99 | 322 | } |
| mbed_official | 107:414e9c822e99 | 323 | |
| mbed_official | 107:414e9c822e99 | 324 | /** |
| mbed_official | 107:414e9c822e99 | 325 | * \brief Configure ADC power mode. |
| mbed_official | 107:414e9c822e99 | 326 | * |
| mbed_official | 107:414e9c822e99 | 327 | * \param adc Base address of the ADC. |
| mbed_official | 107:414e9c822e99 | 328 | * \param mode ADC power mode value. |
| mbed_official | 107:414e9c822e99 | 329 | */ |
| mbed_official | 107:414e9c822e99 | 330 | void adc_set_power_mode(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 331 | const enum adc_power_mode mode) |
| mbed_official | 107:414e9c822e99 | 332 | { |
| mbed_official | 107:414e9c822e99 | 333 | uint32_t reg; |
| mbed_official | 107:414e9c822e99 | 334 | |
| mbed_official | 107:414e9c822e99 | 335 | reg = adc->ADC_MR; |
| mbed_official | 107:414e9c822e99 | 336 | |
| mbed_official | 107:414e9c822e99 | 337 | switch (mode) { |
| mbed_official | 107:414e9c822e99 | 338 | case ADC_POWER_MODE_0: |
| mbed_official | 107:414e9c822e99 | 339 | reg |= ADC_MR_SLEEP_NORMAL; |
| mbed_official | 107:414e9c822e99 | 340 | break; |
| mbed_official | 107:414e9c822e99 | 341 | |
| mbed_official | 107:414e9c822e99 | 342 | case ADC_POWER_MODE_1: |
| mbed_official | 107:414e9c822e99 | 343 | reg |= ADC_MR_SLEEP_SLEEP; |
| mbed_official | 107:414e9c822e99 | 344 | break; |
| mbed_official | 107:414e9c822e99 | 345 | } |
| mbed_official | 107:414e9c822e99 | 346 | |
| mbed_official | 107:414e9c822e99 | 347 | adc->ADC_MR = reg; |
| mbed_official | 107:414e9c822e99 | 348 | } |
| mbed_official | 107:414e9c822e99 | 349 | |
| mbed_official | 107:414e9c822e99 | 350 | /** |
| mbed_official | 107:414e9c822e99 | 351 | * \brief Set callback for ADC |
| mbed_official | 107:414e9c822e99 | 352 | * |
| mbed_official | 107:414e9c822e99 | 353 | * \param adc Base address of the ADC |
| mbed_official | 107:414e9c822e99 | 354 | * \param source Interrupt source |
| mbed_official | 107:414e9c822e99 | 355 | * \param callback Callback function pointer |
| mbed_official | 107:414e9c822e99 | 356 | * \param irq_level Interrupt level |
| mbed_official | 107:414e9c822e99 | 357 | */ |
| mbed_official | 107:414e9c822e99 | 358 | void adc_set_callback(Adc *const adc, enum adc_interrupt_source source, |
| mbed_official | 107:414e9c822e99 | 359 | adc_callback_t callback, uint8_t irq_level) |
| mbed_official | 107:414e9c822e99 | 360 | { |
| mbed_official | 107:414e9c822e99 | 361 | Assert(adc); |
| mbed_official | 107:414e9c822e99 | 362 | Assert(callback); |
| mbed_official | 107:414e9c822e99 | 363 | |
| mbed_official | 107:414e9c822e99 | 364 | adc_callback_pointer[source] = callback; |
| mbed_official | 107:414e9c822e99 | 365 | irq_register_handler(ADC_IRQn, irq_level); |
| mbed_official | 107:414e9c822e99 | 366 | |
| mbed_official | 107:414e9c822e99 | 367 | /* Enable the specified interrupt source */ |
| mbed_official | 107:414e9c822e99 | 368 | adc_enable_interrupt(adc, source); |
| mbed_official | 107:414e9c822e99 | 369 | } |
| mbed_official | 107:414e9c822e99 | 370 | |
| mbed_official | 107:414e9c822e99 | 371 | /** |
| mbed_official | 107:414e9c822e99 | 372 | * \brief Enable ADC interrupts. |
| mbed_official | 107:414e9c822e99 | 373 | * |
| mbed_official | 107:414e9c822e99 | 374 | * \param adc Base address of the ADC. |
| mbed_official | 107:414e9c822e99 | 375 | * \param interrupt_source Interrupts to be enabled. |
| mbed_official | 107:414e9c822e99 | 376 | */ |
| mbed_official | 107:414e9c822e99 | 377 | void adc_enable_interrupt(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 378 | enum adc_interrupt_source interrupt_source) |
| mbed_official | 107:414e9c822e99 | 379 | { |
| mbed_official | 107:414e9c822e99 | 380 | if (interrupt_source == ADC_INTERRUPT_ALL) { |
| mbed_official | 107:414e9c822e99 | 381 | adc->ADC_IER = ADC_INTERRUPT_ALL; |
| mbed_official | 107:414e9c822e99 | 382 | return; |
| mbed_official | 107:414e9c822e99 | 383 | } else { |
| mbed_official | 107:414e9c822e99 | 384 | adc->ADC_IER = adc_interrupt_mask[interrupt_source]; |
| mbed_official | 107:414e9c822e99 | 385 | } |
| mbed_official | 107:414e9c822e99 | 386 | } |
| mbed_official | 107:414e9c822e99 | 387 | |
| mbed_official | 107:414e9c822e99 | 388 | /** |
| mbed_official | 107:414e9c822e99 | 389 | * \brief Disable ADC interrupts. |
| mbed_official | 107:414e9c822e99 | 390 | * |
| mbed_official | 107:414e9c822e99 | 391 | * \param adc Base address of the ADC. |
| mbed_official | 107:414e9c822e99 | 392 | * \param interrupt_source Interrupts to be disabled. |
| mbed_official | 107:414e9c822e99 | 393 | */ |
| mbed_official | 107:414e9c822e99 | 394 | void adc_disable_interrupt(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 395 | enum adc_interrupt_source interrupt_source) |
| mbed_official | 107:414e9c822e99 | 396 | { |
| mbed_official | 107:414e9c822e99 | 397 | if (interrupt_source == ADC_INTERRUPT_ALL) { |
| mbed_official | 107:414e9c822e99 | 398 | adc->ADC_IDR = ADC_INTERRUPT_ALL; |
| mbed_official | 107:414e9c822e99 | 399 | return; |
| mbed_official | 107:414e9c822e99 | 400 | } else { |
| mbed_official | 107:414e9c822e99 | 401 | adc->ADC_IDR = adc_interrupt_mask[interrupt_source]; |
| mbed_official | 107:414e9c822e99 | 402 | } |
| mbed_official | 107:414e9c822e99 | 403 | } |
| mbed_official | 107:414e9c822e99 | 404 | |
| mbed_official | 107:414e9c822e99 | 405 | /** |
| mbed_official | 107:414e9c822e99 | 406 | * \internal |
| mbed_official | 107:414e9c822e99 | 407 | * \brief Common ADC interrupt handler |
| mbed_official | 107:414e9c822e99 | 408 | * |
| mbed_official | 107:414e9c822e99 | 409 | * The optional callback used by the interrupt handler is set by the |
| mbed_official | 107:414e9c822e99 | 410 | * adc_set_callback() function. |
| mbed_official | 107:414e9c822e99 | 411 | * |
| mbed_official | 107:414e9c822e99 | 412 | * \param inst_num ADC instance number to handle interrupt for |
| mbed_official | 107:414e9c822e99 | 413 | * \param source Interrupt source number |
| mbed_official | 107:414e9c822e99 | 414 | */ |
| mbed_official | 107:414e9c822e99 | 415 | static void adc_interrupt(enum adc_interrupt_source source) |
| mbed_official | 107:414e9c822e99 | 416 | { |
| mbed_official | 107:414e9c822e99 | 417 | if (adc_callback_pointer[source]) { |
| mbed_official | 107:414e9c822e99 | 418 | adc_callback_pointer[source](); |
| mbed_official | 107:414e9c822e99 | 419 | } |
| mbed_official | 107:414e9c822e99 | 420 | } |
| mbed_official | 107:414e9c822e99 | 421 | |
| mbed_official | 107:414e9c822e99 | 422 | /** |
| mbed_official | 107:414e9c822e99 | 423 | * \internal |
| mbed_official | 107:414e9c822e99 | 424 | * \brief Call the callback function if the corresponding interrupt is asserted |
| mbed_official | 107:414e9c822e99 | 425 | * |
| mbed_official | 107:414e9c822e99 | 426 | * \param adc Base address of the ADC. |
| mbed_official | 107:414e9c822e99 | 427 | */ |
| mbed_official | 107:414e9c822e99 | 428 | static void adc_process_callback(Adc *const adc) |
| mbed_official | 107:414e9c822e99 | 429 | { |
| mbed_official | 107:414e9c822e99 | 430 | volatile uint32_t status; |
| mbed_official | 107:414e9c822e99 | 431 | uint32_t cnt; |
| mbed_official | 107:414e9c822e99 | 432 | |
| mbed_official | 107:414e9c822e99 | 433 | status = adc_get_interrupt_status(adc); |
| mbed_official | 107:414e9c822e99 | 434 | |
| mbed_official | 107:414e9c822e99 | 435 | for (cnt = 0; cnt < ADC_NUM_OF_INTERRUPT_SOURCE; cnt++) { |
| mbed_official | 107:414e9c822e99 | 436 | if (status & adc_interrupt_mask[cnt]) { |
| mbed_official | 107:414e9c822e99 | 437 | adc_interrupt((enum adc_interrupt_source)cnt); |
| mbed_official | 107:414e9c822e99 | 438 | } |
| mbed_official | 107:414e9c822e99 | 439 | } |
| mbed_official | 107:414e9c822e99 | 440 | } |
| mbed_official | 107:414e9c822e99 | 441 | |
| mbed_official | 107:414e9c822e99 | 442 | /** |
| mbed_official | 107:414e9c822e99 | 443 | * \brief Interrupt handler for ADC. |
| mbed_official | 107:414e9c822e99 | 444 | */ |
| mbed_official | 107:414e9c822e99 | 445 | void ADC_Handler(void) |
| mbed_official | 107:414e9c822e99 | 446 | { |
| mbed_official | 107:414e9c822e99 | 447 | adc_process_callback(ADC); |
| mbed_official | 107:414e9c822e99 | 448 | } |
| mbed_official | 107:414e9c822e99 | 449 | |
| mbed_official | 107:414e9c822e99 | 450 | /** |
| mbed_official | 107:414e9c822e99 | 451 | * \brief Enable ADC Module. |
| mbed_official | 107:414e9c822e99 | 452 | * |
| mbed_official | 107:414e9c822e99 | 453 | */ |
| mbed_official | 107:414e9c822e99 | 454 | void adc_enable(void) |
| mbed_official | 107:414e9c822e99 | 455 | { |
| mbed_official | 107:414e9c822e99 | 456 | /* Enable peripheral clock. */ |
| mbed_official | 107:414e9c822e99 | 457 | pmc_enable_periph_clk(ID_ADC); |
| mbed_official | 107:414e9c822e99 | 458 | sleepmgr_lock_mode(SLEEP_MODE_ADC); |
| mbed_official | 107:414e9c822e99 | 459 | } |
| mbed_official | 107:414e9c822e99 | 460 | |
| mbed_official | 107:414e9c822e99 | 461 | /** |
| mbed_official | 107:414e9c822e99 | 462 | * \brief Disable ADC Module. |
| mbed_official | 107:414e9c822e99 | 463 | * |
| mbed_official | 107:414e9c822e99 | 464 | */ |
| mbed_official | 107:414e9c822e99 | 465 | void adc_disable(void) |
| mbed_official | 107:414e9c822e99 | 466 | { |
| mbed_official | 107:414e9c822e99 | 467 | /* Disable peripheral clock. */ |
| mbed_official | 107:414e9c822e99 | 468 | pmc_disable_periph_clk(ID_ADC); |
| mbed_official | 107:414e9c822e99 | 469 | sleepmgr_unlock_mode(SLEEP_MODE_ADC); |
| mbed_official | 107:414e9c822e99 | 470 | } |
| mbed_official | 107:414e9c822e99 | 471 | |
| mbed_official | 107:414e9c822e99 | 472 | /** |
| mbed_official | 107:414e9c822e99 | 473 | * \brief Configure conversion sequence. |
| mbed_official | 107:414e9c822e99 | 474 | * |
| mbed_official | 107:414e9c822e99 | 475 | * \param adc Base address of the ADC. |
| mbed_official | 107:414e9c822e99 | 476 | * \param ch_list Channel sequence list. |
| mbed_official | 107:414e9c822e99 | 477 | * \param uc_num Number of channels in the list. |
| mbed_official | 107:414e9c822e99 | 478 | */ |
| mbed_official | 107:414e9c822e99 | 479 | void adc_configure_sequence(Adc *const adc, |
| mbed_official | 107:414e9c822e99 | 480 | const enum adc_channel_num ch_list[], uint8_t uc_num) |
| mbed_official | 107:414e9c822e99 | 481 | { |
| mbed_official | 107:414e9c822e99 | 482 | uint8_t uc_counter; |
| mbed_official | 107:414e9c822e99 | 483 | |
| mbed_official | 107:414e9c822e99 | 484 | /* Set user sequence mode */ |
| mbed_official | 107:414e9c822e99 | 485 | adc->ADC_MR |= ADC_MR_USEQ_REG_ORDER; |
| mbed_official | 107:414e9c822e99 | 486 | #if (SAM4N) |
| mbed_official | 107:414e9c822e99 | 487 | adc->ADC_SEQR1 = 0; |
| mbed_official | 107:414e9c822e99 | 488 | adc->ADC_SEQR2 = 0; |
| mbed_official | 107:414e9c822e99 | 489 | #endif |
| mbed_official | 107:414e9c822e99 | 490 | #if (SAMG) |
| mbed_official | 107:414e9c822e99 | 491 | adc->ADC_SEQR1 = 0; |
| mbed_official | 107:414e9c822e99 | 492 | #endif |
| mbed_official | 107:414e9c822e99 | 493 | |
| mbed_official | 107:414e9c822e99 | 494 | if (uc_num <= ADC_SEQ1_CHANNEL_NUM) { |
| mbed_official | 107:414e9c822e99 | 495 | for (uc_counter = 0; uc_counter < uc_num; uc_counter++) { |
| mbed_official | 107:414e9c822e99 | 496 | #if (SAM4N || SAMG) |
| mbed_official | 107:414e9c822e99 | 497 | adc->ADC_SEQR1 |
| mbed_official | 107:414e9c822e99 | 498 | #endif |
| mbed_official | 107:414e9c822e99 | 499 | |= ch_list[uc_counter] << (4 * uc_counter); |
| mbed_official | 107:414e9c822e99 | 500 | } |
| mbed_official | 107:414e9c822e99 | 501 | } else { |
| mbed_official | 107:414e9c822e99 | 502 | for (uc_counter = 0; uc_counter <= ADC_SEQ1_CHANNEL_NUM; |
| mbed_official | 107:414e9c822e99 | 503 | uc_counter++) { |
| mbed_official | 107:414e9c822e99 | 504 | #if (SAM4N || SAMG) |
| mbed_official | 107:414e9c822e99 | 505 | adc->ADC_SEQR1 |
| mbed_official | 107:414e9c822e99 | 506 | #endif |
| mbed_official | 107:414e9c822e99 | 507 | |= ch_list[uc_counter] << (4 * uc_counter); |
| mbed_official | 107:414e9c822e99 | 508 | } |
| mbed_official | 107:414e9c822e99 | 509 | for (uc_counter = 0; uc_counter < uc_num - ADC_SEQ1_CHANNEL_NUM; |
| mbed_official | 107:414e9c822e99 | 510 | uc_counter++) { |
| mbed_official | 107:414e9c822e99 | 511 | #if (SAM4N) |
| mbed_official | 107:414e9c822e99 | 512 | adc->ADC_SEQR2 |= ch_list[8 + uc_counter] << (4 * uc_counter); |
| mbed_official | 107:414e9c822e99 | 513 | #endif |
| mbed_official | 107:414e9c822e99 | 514 | } |
| mbed_official | 107:414e9c822e99 | 515 | } |
| mbed_official | 107:414e9c822e99 | 516 | } |
| mbed_official | 107:414e9c822e99 | 517 | |
| mbed_official | 107:414e9c822e99 | 518 | //@} |
