added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
bogdanm
Date:
Thu Oct 01 15:25:22 2015 +0300
Revision:
0:9b334a45a8ff
Child:
50:a417edff4437
Initial commit on mbed-dev

Replaces mbed-src (now inactive)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 0:9b334a45a8ff 1 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 2 * @file em_adc.c
bogdanm 0:9b334a45a8ff 3 * @brief Analog to Digital Converter (ADC) Peripheral API
bogdanm 0:9b334a45a8ff 4 * @version 3.20.12
bogdanm 0:9b334a45a8ff 5 *******************************************************************************
bogdanm 0:9b334a45a8ff 6 * @section License
bogdanm 0:9b334a45a8ff 7 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
bogdanm 0:9b334a45a8ff 8 *******************************************************************************
bogdanm 0:9b334a45a8ff 9 *
bogdanm 0:9b334a45a8ff 10 * Permission is granted to anyone to use this software for any purpose,
bogdanm 0:9b334a45a8ff 11 * including commercial applications, and to alter it and redistribute it
bogdanm 0:9b334a45a8ff 12 * freely, subject to the following restrictions:
bogdanm 0:9b334a45a8ff 13 *
bogdanm 0:9b334a45a8ff 14 * 1. The origin of this software must not be misrepresented; you must not
bogdanm 0:9b334a45a8ff 15 * claim that you wrote the original software.
bogdanm 0:9b334a45a8ff 16 * 2. Altered source versions must be plainly marked as such, and must not be
bogdanm 0:9b334a45a8ff 17 * misrepresented as being the original software.
bogdanm 0:9b334a45a8ff 18 * 3. This notice may not be removed or altered from any source distribution.
bogdanm 0:9b334a45a8ff 19 *
bogdanm 0:9b334a45a8ff 20 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
bogdanm 0:9b334a45a8ff 21 * obligation to support this Software. Silicon Labs is providing the
bogdanm 0:9b334a45a8ff 22 * Software "AS IS", with no express or implied warranties of any kind,
bogdanm 0:9b334a45a8ff 23 * including, but not limited to, any implied warranties of merchantability
bogdanm 0:9b334a45a8ff 24 * or fitness for any particular purpose or warranties against infringement
bogdanm 0:9b334a45a8ff 25 * of any proprietary rights of a third party.
bogdanm 0:9b334a45a8ff 26 *
bogdanm 0:9b334a45a8ff 27 * Silicon Labs will not be liable for any consequential, incidental, or
bogdanm 0:9b334a45a8ff 28 * special damages, or any other relief, or for any claim by any third party,
bogdanm 0:9b334a45a8ff 29 * arising from your use of this Software.
bogdanm 0:9b334a45a8ff 30 *
bogdanm 0:9b334a45a8ff 31 ******************************************************************************/
bogdanm 0:9b334a45a8ff 32
bogdanm 0:9b334a45a8ff 33
bogdanm 0:9b334a45a8ff 34 #include "em_adc.h"
bogdanm 0:9b334a45a8ff 35 #if defined(ADC_COUNT) && (ADC_COUNT > 0)
bogdanm 0:9b334a45a8ff 36
bogdanm 0:9b334a45a8ff 37 #include "em_cmu.h"
bogdanm 0:9b334a45a8ff 38 #include "em_assert.h"
bogdanm 0:9b334a45a8ff 39
bogdanm 0:9b334a45a8ff 40 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 41 * @addtogroup EM_Library
bogdanm 0:9b334a45a8ff 42 * @{
bogdanm 0:9b334a45a8ff 43 ******************************************************************************/
bogdanm 0:9b334a45a8ff 44
bogdanm 0:9b334a45a8ff 45 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 46 * @addtogroup ADC
bogdanm 0:9b334a45a8ff 47 * @brief Analog to Digital Converter (ADC) Peripheral API
bogdanm 0:9b334a45a8ff 48 * @{
bogdanm 0:9b334a45a8ff 49 ******************************************************************************/
bogdanm 0:9b334a45a8ff 50
bogdanm 0:9b334a45a8ff 51 /*******************************************************************************
bogdanm 0:9b334a45a8ff 52 ******************************* DEFINES ***********************************
bogdanm 0:9b334a45a8ff 53 ******************************************************************************/
bogdanm 0:9b334a45a8ff 54
bogdanm 0:9b334a45a8ff 55 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
bogdanm 0:9b334a45a8ff 56
bogdanm 0:9b334a45a8ff 57 /** Validation of ADC register block pointer reference for assert statements. */
bogdanm 0:9b334a45a8ff 58 #define ADC_REF_VALID(ref) ((ref) == ADC0)
bogdanm 0:9b334a45a8ff 59
bogdanm 0:9b334a45a8ff 60 /** Max ADC clock */
bogdanm 0:9b334a45a8ff 61 #define ADC_MAX_CLOCK 13000000
bogdanm 0:9b334a45a8ff 62
bogdanm 0:9b334a45a8ff 63 /** Min ADC clock */
bogdanm 0:9b334a45a8ff 64 #define ADC_MIN_CLOCK 32000
bogdanm 0:9b334a45a8ff 65
bogdanm 0:9b334a45a8ff 66 /** @endcond */
bogdanm 0:9b334a45a8ff 67
bogdanm 0:9b334a45a8ff 68
bogdanm 0:9b334a45a8ff 69 /*******************************************************************************
bogdanm 0:9b334a45a8ff 70 *************************** LOCAL FUNCTIONS *******************************
bogdanm 0:9b334a45a8ff 71 ******************************************************************************/
bogdanm 0:9b334a45a8ff 72
bogdanm 0:9b334a45a8ff 73 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
bogdanm 0:9b334a45a8ff 74
bogdanm 0:9b334a45a8ff 75 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 76 * @brief
bogdanm 0:9b334a45a8ff 77 * Load SCAN calibrate register with predefined values for a certain
bogdanm 0:9b334a45a8ff 78 * reference.
bogdanm 0:9b334a45a8ff 79 *
bogdanm 0:9b334a45a8ff 80 * @details
bogdanm 0:9b334a45a8ff 81 * During production, calibration values are made and stored in the device
bogdanm 0:9b334a45a8ff 82 * information page for known references. Notice that for external references,
bogdanm 0:9b334a45a8ff 83 * calibration values must be determined explicitly, and this function
bogdanm 0:9b334a45a8ff 84 * will not modify the calibration register.
bogdanm 0:9b334a45a8ff 85 *
bogdanm 0:9b334a45a8ff 86 * @param[in] adc
bogdanm 0:9b334a45a8ff 87 * Pointer to ADC peripheral register block.
bogdanm 0:9b334a45a8ff 88 *
bogdanm 0:9b334a45a8ff 89 * @param[in] ref
bogdanm 0:9b334a45a8ff 90 * Reference to load calibrated values for. No values are loaded for
bogdanm 0:9b334a45a8ff 91 * external references.
bogdanm 0:9b334a45a8ff 92 ******************************************************************************/
bogdanm 0:9b334a45a8ff 93 static void ADC_CalibrateLoadScan(ADC_TypeDef *adc, ADC_Ref_TypeDef ref)
bogdanm 0:9b334a45a8ff 94 {
bogdanm 0:9b334a45a8ff 95 uint32_t cal;
bogdanm 0:9b334a45a8ff 96
bogdanm 0:9b334a45a8ff 97 /* Load proper calibration data depending on selected reference */
bogdanm 0:9b334a45a8ff 98 /* NOTE: We use ...SCAN... defines below, they are the same as */
bogdanm 0:9b334a45a8ff 99 /* similar ...SINGLE... defines. */
bogdanm 0:9b334a45a8ff 100 switch (ref)
bogdanm 0:9b334a45a8ff 101 {
bogdanm 0:9b334a45a8ff 102 case adcRef1V25:
bogdanm 0:9b334a45a8ff 103 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
bogdanm 0:9b334a45a8ff 104 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 105 _DEVINFO_ADC0CAL0_1V25_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 106 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 107 _DEVINFO_ADC0CAL0_1V25_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 108 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 109 break;
bogdanm 0:9b334a45a8ff 110
bogdanm 0:9b334a45a8ff 111 case adcRef2V5:
bogdanm 0:9b334a45a8ff 112 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
bogdanm 0:9b334a45a8ff 113 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 114 _DEVINFO_ADC0CAL0_2V5_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 115 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 116 _DEVINFO_ADC0CAL0_2V5_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 117 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 118 break;
bogdanm 0:9b334a45a8ff 119
bogdanm 0:9b334a45a8ff 120 case adcRefVDD:
bogdanm 0:9b334a45a8ff 121 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
bogdanm 0:9b334a45a8ff 122 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 123 _DEVINFO_ADC0CAL1_VDD_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 124 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 125 _DEVINFO_ADC0CAL1_VDD_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 126 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 127 break;
bogdanm 0:9b334a45a8ff 128
bogdanm 0:9b334a45a8ff 129 case adcRef5VDIFF:
bogdanm 0:9b334a45a8ff 130 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
bogdanm 0:9b334a45a8ff 131 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 132 _DEVINFO_ADC0CAL1_5VDIFF_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 133 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 134 _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 135 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 136 break;
bogdanm 0:9b334a45a8ff 137
bogdanm 0:9b334a45a8ff 138 case adcRef2xVDD:
bogdanm 0:9b334a45a8ff 139 /* Gain value not of relevance for this reference, leave as is */
bogdanm 0:9b334a45a8ff 140 cal = adc->CAL & ~_ADC_CAL_SCANOFFSET_MASK;
bogdanm 0:9b334a45a8ff 141 cal |= ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 142 _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 143 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 144 break;
bogdanm 0:9b334a45a8ff 145
bogdanm 0:9b334a45a8ff 146 /* For external references, the calibration must be determined for the */
bogdanm 0:9b334a45a8ff 147 /* specific application and set explicitly. */
bogdanm 0:9b334a45a8ff 148 default:
bogdanm 0:9b334a45a8ff 149 break;
bogdanm 0:9b334a45a8ff 150 }
bogdanm 0:9b334a45a8ff 151 }
bogdanm 0:9b334a45a8ff 152
bogdanm 0:9b334a45a8ff 153 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 154 * @brief
bogdanm 0:9b334a45a8ff 155 * Load SINGLE calibrate register with predefined values for a certain
bogdanm 0:9b334a45a8ff 156 * reference.
bogdanm 0:9b334a45a8ff 157 *
bogdanm 0:9b334a45a8ff 158 * @details
bogdanm 0:9b334a45a8ff 159 * During production, calibration values are made and stored in the device
bogdanm 0:9b334a45a8ff 160 * information page for known references. Notice that for external references,
bogdanm 0:9b334a45a8ff 161 * calibration values must be determined explicitly, and this function
bogdanm 0:9b334a45a8ff 162 * will not modify the calibration register.
bogdanm 0:9b334a45a8ff 163 *
bogdanm 0:9b334a45a8ff 164 * @param[in] adc
bogdanm 0:9b334a45a8ff 165 * Pointer to ADC peripheral register block.
bogdanm 0:9b334a45a8ff 166 *
bogdanm 0:9b334a45a8ff 167 * @param[in] ref
bogdanm 0:9b334a45a8ff 168 * Reference to load calibrated values for. No values are loaded for
bogdanm 0:9b334a45a8ff 169 * external references.
bogdanm 0:9b334a45a8ff 170 ******************************************************************************/
bogdanm 0:9b334a45a8ff 171 static void ADC_CalibrateLoadSingle(ADC_TypeDef *adc, ADC_Ref_TypeDef ref)
bogdanm 0:9b334a45a8ff 172 {
bogdanm 0:9b334a45a8ff 173 uint32_t cal;
bogdanm 0:9b334a45a8ff 174
bogdanm 0:9b334a45a8ff 175 /* Load proper calibration data depending on selected reference */
bogdanm 0:9b334a45a8ff 176 /* NOTE: We use ...SCAN... defines below, they are the same as */
bogdanm 0:9b334a45a8ff 177 /* similar ...SINGLE... defines. */
bogdanm 0:9b334a45a8ff 178 switch (ref)
bogdanm 0:9b334a45a8ff 179 {
bogdanm 0:9b334a45a8ff 180 case adcRef1V25:
bogdanm 0:9b334a45a8ff 181 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
bogdanm 0:9b334a45a8ff 182 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 183 _DEVINFO_ADC0CAL0_1V25_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 184 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 185 _DEVINFO_ADC0CAL0_1V25_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 186 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 187 break;
bogdanm 0:9b334a45a8ff 188
bogdanm 0:9b334a45a8ff 189 case adcRef2V5:
bogdanm 0:9b334a45a8ff 190 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
bogdanm 0:9b334a45a8ff 191 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 192 _DEVINFO_ADC0CAL0_2V5_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 193 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 194 _DEVINFO_ADC0CAL0_2V5_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 195 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 196 break;
bogdanm 0:9b334a45a8ff 197
bogdanm 0:9b334a45a8ff 198 case adcRefVDD:
bogdanm 0:9b334a45a8ff 199 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
bogdanm 0:9b334a45a8ff 200 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 201 _DEVINFO_ADC0CAL1_VDD_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 202 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 203 _DEVINFO_ADC0CAL1_VDD_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 204 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 205 break;
bogdanm 0:9b334a45a8ff 206
bogdanm 0:9b334a45a8ff 207 case adcRef5VDIFF:
bogdanm 0:9b334a45a8ff 208 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
bogdanm 0:9b334a45a8ff 209 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_GAIN_MASK) >>
bogdanm 0:9b334a45a8ff 210 _DEVINFO_ADC0CAL1_5VDIFF_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
bogdanm 0:9b334a45a8ff 211 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 212 _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 213 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 214 break;
bogdanm 0:9b334a45a8ff 215
bogdanm 0:9b334a45a8ff 216 case adcRef2xVDD:
bogdanm 0:9b334a45a8ff 217 /* Gain value not of relevance for this reference, leave as is */
bogdanm 0:9b334a45a8ff 218 cal = adc->CAL & ~_ADC_CAL_SINGLEOFFSET_MASK;
bogdanm 0:9b334a45a8ff 219 cal |= ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_MASK) >>
bogdanm 0:9b334a45a8ff 220 _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
bogdanm 0:9b334a45a8ff 221 adc->CAL = cal;
bogdanm 0:9b334a45a8ff 222 break;
bogdanm 0:9b334a45a8ff 223
bogdanm 0:9b334a45a8ff 224 /* For external references, the calibration must be determined for the */
bogdanm 0:9b334a45a8ff 225 /* specific application and set explicitly. */
bogdanm 0:9b334a45a8ff 226 default:
bogdanm 0:9b334a45a8ff 227 break;
bogdanm 0:9b334a45a8ff 228 }
bogdanm 0:9b334a45a8ff 229 }
bogdanm 0:9b334a45a8ff 230
bogdanm 0:9b334a45a8ff 231 /** @endcond */
bogdanm 0:9b334a45a8ff 232
bogdanm 0:9b334a45a8ff 233 /*******************************************************************************
bogdanm 0:9b334a45a8ff 234 ************************** GLOBAL FUNCTIONS *******************************
bogdanm 0:9b334a45a8ff 235 ******************************************************************************/
bogdanm 0:9b334a45a8ff 236
bogdanm 0:9b334a45a8ff 237 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 238 * @brief
bogdanm 0:9b334a45a8ff 239 * Initialize ADC.
bogdanm 0:9b334a45a8ff 240 *
bogdanm 0:9b334a45a8ff 241 * @details
bogdanm 0:9b334a45a8ff 242 * Initializes common parts for both single conversion and scan sequence.
bogdanm 0:9b334a45a8ff 243 * In addition, single and/or scan control configuration must be done, please
bogdanm 0:9b334a45a8ff 244 * refer to ADC_InitSingle() and ADC_InitScan() respectively.
bogdanm 0:9b334a45a8ff 245 *
bogdanm 0:9b334a45a8ff 246 * @note
bogdanm 0:9b334a45a8ff 247 * This function will stop any ongoing conversion.
bogdanm 0:9b334a45a8ff 248 *
bogdanm 0:9b334a45a8ff 249 * @param[in] adc
bogdanm 0:9b334a45a8ff 250 * Pointer to ADC peripheral register block.
bogdanm 0:9b334a45a8ff 251 *
bogdanm 0:9b334a45a8ff 252 * @param[in] init
bogdanm 0:9b334a45a8ff 253 * Pointer to ADC initialization structure.
bogdanm 0:9b334a45a8ff 254 ******************************************************************************/
bogdanm 0:9b334a45a8ff 255 void ADC_Init(ADC_TypeDef *adc, const ADC_Init_TypeDef *init)
bogdanm 0:9b334a45a8ff 256 {
bogdanm 0:9b334a45a8ff 257 uint32_t tmp;
bogdanm 0:9b334a45a8ff 258
bogdanm 0:9b334a45a8ff 259 EFM_ASSERT(ADC_REF_VALID(adc));
bogdanm 0:9b334a45a8ff 260
bogdanm 0:9b334a45a8ff 261 /* Make sure conversion is not in progress */
bogdanm 0:9b334a45a8ff 262 adc->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP;
bogdanm 0:9b334a45a8ff 263
bogdanm 0:9b334a45a8ff 264 tmp = ((uint32_t)(init->ovsRateSel) << _ADC_CTRL_OVSRSEL_SHIFT) |
bogdanm 0:9b334a45a8ff 265 (((uint32_t)(init->timebase) << _ADC_CTRL_TIMEBASE_SHIFT) & _ADC_CTRL_TIMEBASE_MASK) |
bogdanm 0:9b334a45a8ff 266 (((uint32_t)(init->prescale) << _ADC_CTRL_PRESC_SHIFT) & _ADC_CTRL_PRESC_MASK) |
bogdanm 0:9b334a45a8ff 267 ((uint32_t)(init->lpfMode) << _ADC_CTRL_LPFMODE_SHIFT) |
bogdanm 0:9b334a45a8ff 268 ((uint32_t)(init->warmUpMode) << _ADC_CTRL_WARMUPMODE_SHIFT);
bogdanm 0:9b334a45a8ff 269
bogdanm 0:9b334a45a8ff 270 if (init->tailgate)
bogdanm 0:9b334a45a8ff 271 {
bogdanm 0:9b334a45a8ff 272 tmp |= ADC_CTRL_TAILGATE;
bogdanm 0:9b334a45a8ff 273 }
bogdanm 0:9b334a45a8ff 274
bogdanm 0:9b334a45a8ff 275 adc->CTRL = tmp;
bogdanm 0:9b334a45a8ff 276 }
bogdanm 0:9b334a45a8ff 277
bogdanm 0:9b334a45a8ff 278
bogdanm 0:9b334a45a8ff 279 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 280 * @brief
bogdanm 0:9b334a45a8ff 281 * Initialize ADC scan sequence.
bogdanm 0:9b334a45a8ff 282 *
bogdanm 0:9b334a45a8ff 283 * @details
bogdanm 0:9b334a45a8ff 284 * Please refer to ADC_Start() for starting scan sequence.
bogdanm 0:9b334a45a8ff 285 *
bogdanm 0:9b334a45a8ff 286 * When selecting an external reference, the gain and offset calibration
bogdanm 0:9b334a45a8ff 287 * must be set explicitly (CAL register). For other references, the
bogdanm 0:9b334a45a8ff 288 * calibration is updated with values defined during manufacturing.
bogdanm 0:9b334a45a8ff 289 *
bogdanm 0:9b334a45a8ff 290 * @note
bogdanm 0:9b334a45a8ff 291 * This function will stop any ongoing scan sequence.
bogdanm 0:9b334a45a8ff 292 *
bogdanm 0:9b334a45a8ff 293 * @param[in] adc
bogdanm 0:9b334a45a8ff 294 * Pointer to ADC peripheral register block.
bogdanm 0:9b334a45a8ff 295 *
bogdanm 0:9b334a45a8ff 296 * @param[in] init
bogdanm 0:9b334a45a8ff 297 * Pointer to ADC initialization structure.
bogdanm 0:9b334a45a8ff 298 ******************************************************************************/
bogdanm 0:9b334a45a8ff 299 void ADC_InitScan(ADC_TypeDef *adc, const ADC_InitScan_TypeDef *init)
bogdanm 0:9b334a45a8ff 300 {
bogdanm 0:9b334a45a8ff 301 uint32_t tmp;
bogdanm 0:9b334a45a8ff 302
bogdanm 0:9b334a45a8ff 303 EFM_ASSERT(ADC_REF_VALID(adc));
bogdanm 0:9b334a45a8ff 304
bogdanm 0:9b334a45a8ff 305 /* Make sure scan sequence is not in progress */
bogdanm 0:9b334a45a8ff 306 adc->CMD = ADC_CMD_SCANSTOP;
bogdanm 0:9b334a45a8ff 307
bogdanm 0:9b334a45a8ff 308 /* Load proper calibration data depending on selected reference */
bogdanm 0:9b334a45a8ff 309 ADC_CalibrateLoadScan(adc, init->reference);
bogdanm 0:9b334a45a8ff 310
bogdanm 0:9b334a45a8ff 311 tmp = ((uint32_t)(init->prsSel) << _ADC_SCANCTRL_PRSSEL_SHIFT) |
bogdanm 0:9b334a45a8ff 312 ((uint32_t)(init->acqTime) << _ADC_SCANCTRL_AT_SHIFT) |
bogdanm 0:9b334a45a8ff 313 ((uint32_t)(init->reference) << _ADC_SCANCTRL_REF_SHIFT) |
bogdanm 0:9b334a45a8ff 314 init->input |
bogdanm 0:9b334a45a8ff 315 ((uint32_t)(init->resolution) << _ADC_SCANCTRL_RES_SHIFT);
bogdanm 0:9b334a45a8ff 316
bogdanm 0:9b334a45a8ff 317 if (init->prsEnable)
bogdanm 0:9b334a45a8ff 318 {
bogdanm 0:9b334a45a8ff 319 tmp |= ADC_SCANCTRL_PRSEN;
bogdanm 0:9b334a45a8ff 320 }
bogdanm 0:9b334a45a8ff 321
bogdanm 0:9b334a45a8ff 322 if (init->leftAdjust)
bogdanm 0:9b334a45a8ff 323 {
bogdanm 0:9b334a45a8ff 324 tmp |= ADC_SCANCTRL_ADJ_LEFT;
bogdanm 0:9b334a45a8ff 325 }
bogdanm 0:9b334a45a8ff 326
bogdanm 0:9b334a45a8ff 327 if (init->diff)
bogdanm 0:9b334a45a8ff 328 {
bogdanm 0:9b334a45a8ff 329 tmp |= ADC_SCANCTRL_DIFF;
bogdanm 0:9b334a45a8ff 330 }
bogdanm 0:9b334a45a8ff 331
bogdanm 0:9b334a45a8ff 332 if (init->rep)
bogdanm 0:9b334a45a8ff 333 {
bogdanm 0:9b334a45a8ff 334 tmp |= ADC_SCANCTRL_REP;
bogdanm 0:9b334a45a8ff 335 }
bogdanm 0:9b334a45a8ff 336
bogdanm 0:9b334a45a8ff 337 adc->SCANCTRL = tmp;
bogdanm 0:9b334a45a8ff 338 }
bogdanm 0:9b334a45a8ff 339
bogdanm 0:9b334a45a8ff 340
bogdanm 0:9b334a45a8ff 341 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 342 * @brief
bogdanm 0:9b334a45a8ff 343 * Initialize single ADC sample conversion.
bogdanm 0:9b334a45a8ff 344 *
bogdanm 0:9b334a45a8ff 345 * @details
bogdanm 0:9b334a45a8ff 346 * Please refer to ADC_Start() for starting single conversion.
bogdanm 0:9b334a45a8ff 347 *
bogdanm 0:9b334a45a8ff 348 * When selecting an external reference, the gain and offset calibration
bogdanm 0:9b334a45a8ff 349 * must be set explicitly (CAL register). For other references, the
bogdanm 0:9b334a45a8ff 350 * calibration is updated with values defined during manufacturing.
bogdanm 0:9b334a45a8ff 351 *
bogdanm 0:9b334a45a8ff 352 * @note
bogdanm 0:9b334a45a8ff 353 * This function will stop any ongoing single conversion.
bogdanm 0:9b334a45a8ff 354 *
bogdanm 0:9b334a45a8ff 355 * @param[in] adc
bogdanm 0:9b334a45a8ff 356 * Pointer to ADC peripheral register block.
bogdanm 0:9b334a45a8ff 357 *
bogdanm 0:9b334a45a8ff 358 * @param[in] init
bogdanm 0:9b334a45a8ff 359 * Pointer to ADC initialization structure.
bogdanm 0:9b334a45a8ff 360 ******************************************************************************/
bogdanm 0:9b334a45a8ff 361 void ADC_InitSingle(ADC_TypeDef *adc, const ADC_InitSingle_TypeDef *init)
bogdanm 0:9b334a45a8ff 362 {
bogdanm 0:9b334a45a8ff 363 uint32_t tmp;
bogdanm 0:9b334a45a8ff 364
bogdanm 0:9b334a45a8ff 365 EFM_ASSERT(ADC_REF_VALID(adc));
bogdanm 0:9b334a45a8ff 366
bogdanm 0:9b334a45a8ff 367 /* Make sure single conversion is not in progress */
bogdanm 0:9b334a45a8ff 368 adc->CMD = ADC_CMD_SINGLESTOP;
bogdanm 0:9b334a45a8ff 369
bogdanm 0:9b334a45a8ff 370 /* Load proper calibration data depending on selected reference */
bogdanm 0:9b334a45a8ff 371 ADC_CalibrateLoadSingle(adc, init->reference);
bogdanm 0:9b334a45a8ff 372
bogdanm 0:9b334a45a8ff 373 tmp = ((uint32_t)(init->prsSel) << _ADC_SINGLECTRL_PRSSEL_SHIFT) |
bogdanm 0:9b334a45a8ff 374 ((uint32_t)(init->acqTime) << _ADC_SINGLECTRL_AT_SHIFT) |
bogdanm 0:9b334a45a8ff 375 ((uint32_t)(init->reference) << _ADC_SINGLECTRL_REF_SHIFT) |
bogdanm 0:9b334a45a8ff 376 ((uint32_t)(init->input) << _ADC_SINGLECTRL_INPUTSEL_SHIFT) |
bogdanm 0:9b334a45a8ff 377 ((uint32_t)(init->resolution) << _ADC_SINGLECTRL_RES_SHIFT);
bogdanm 0:9b334a45a8ff 378
bogdanm 0:9b334a45a8ff 379 if (init->prsEnable)
bogdanm 0:9b334a45a8ff 380 {
bogdanm 0:9b334a45a8ff 381 tmp |= ADC_SINGLECTRL_PRSEN;
bogdanm 0:9b334a45a8ff 382 }
bogdanm 0:9b334a45a8ff 383
bogdanm 0:9b334a45a8ff 384 if (init->leftAdjust)
bogdanm 0:9b334a45a8ff 385 {
bogdanm 0:9b334a45a8ff 386 tmp |= ADC_SINGLECTRL_ADJ_LEFT;
bogdanm 0:9b334a45a8ff 387 }
bogdanm 0:9b334a45a8ff 388
bogdanm 0:9b334a45a8ff 389 if (init->diff)
bogdanm 0:9b334a45a8ff 390 {
bogdanm 0:9b334a45a8ff 391 tmp |= ADC_SINGLECTRL_DIFF;
bogdanm 0:9b334a45a8ff 392 }
bogdanm 0:9b334a45a8ff 393
bogdanm 0:9b334a45a8ff 394 if (init->rep)
bogdanm 0:9b334a45a8ff 395 {
bogdanm 0:9b334a45a8ff 396 tmp |= ADC_SINGLECTRL_REP;
bogdanm 0:9b334a45a8ff 397 }
bogdanm 0:9b334a45a8ff 398
bogdanm 0:9b334a45a8ff 399 adc->SINGLECTRL = tmp;
bogdanm 0:9b334a45a8ff 400 }
bogdanm 0:9b334a45a8ff 401
bogdanm 0:9b334a45a8ff 402
bogdanm 0:9b334a45a8ff 403 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 404 * @brief
bogdanm 0:9b334a45a8ff 405 * Calculate prescaler value used to determine ADC clock.
bogdanm 0:9b334a45a8ff 406 *
bogdanm 0:9b334a45a8ff 407 * @details
bogdanm 0:9b334a45a8ff 408 * The ADC clock is given by: HFPERCLK / (prescale + 1).
bogdanm 0:9b334a45a8ff 409 *
bogdanm 0:9b334a45a8ff 410 * @param[in] adcFreq ADC frequency wanted. The frequency will automatically
bogdanm 0:9b334a45a8ff 411 * be adjusted to be within valid range according to reference manual.
bogdanm 0:9b334a45a8ff 412 *
bogdanm 0:9b334a45a8ff 413 * @param[in] hfperFreq Frequency in Hz of reference HFPER clock. Set to 0 to
bogdanm 0:9b334a45a8ff 414 * use currently defined HFPER clock setting.
bogdanm 0:9b334a45a8ff 415 *
bogdanm 0:9b334a45a8ff 416 * @return
bogdanm 0:9b334a45a8ff 417 * Prescaler value to use for ADC in order to achieve a clock value
bogdanm 0:9b334a45a8ff 418 * <= @p adcFreq.
bogdanm 0:9b334a45a8ff 419 ******************************************************************************/
bogdanm 0:9b334a45a8ff 420 uint8_t ADC_PrescaleCalc(uint32_t adcFreq, uint32_t hfperFreq)
bogdanm 0:9b334a45a8ff 421 {
bogdanm 0:9b334a45a8ff 422 uint32_t ret;
bogdanm 0:9b334a45a8ff 423
bogdanm 0:9b334a45a8ff 424 /* Make sure selected ADC clock is within valid range */
bogdanm 0:9b334a45a8ff 425 if (adcFreq > ADC_MAX_CLOCK)
bogdanm 0:9b334a45a8ff 426 {
bogdanm 0:9b334a45a8ff 427 adcFreq = ADC_MAX_CLOCK;
bogdanm 0:9b334a45a8ff 428 }
bogdanm 0:9b334a45a8ff 429 else if (adcFreq < ADC_MIN_CLOCK)
bogdanm 0:9b334a45a8ff 430 {
bogdanm 0:9b334a45a8ff 431 adcFreq = ADC_MIN_CLOCK;
bogdanm 0:9b334a45a8ff 432 }
bogdanm 0:9b334a45a8ff 433
bogdanm 0:9b334a45a8ff 434 /* Use current HFPER frequency? */
bogdanm 0:9b334a45a8ff 435 if (!hfperFreq)
bogdanm 0:9b334a45a8ff 436 {
bogdanm 0:9b334a45a8ff 437 hfperFreq = CMU_ClockFreqGet(cmuClock_HFPER);
bogdanm 0:9b334a45a8ff 438 }
bogdanm 0:9b334a45a8ff 439
bogdanm 0:9b334a45a8ff 440 ret = (hfperFreq + adcFreq - 1) / adcFreq;
bogdanm 0:9b334a45a8ff 441 if (ret)
bogdanm 0:9b334a45a8ff 442 {
bogdanm 0:9b334a45a8ff 443 ret--;
bogdanm 0:9b334a45a8ff 444 }
bogdanm 0:9b334a45a8ff 445
bogdanm 0:9b334a45a8ff 446 return (uint8_t)ret;
bogdanm 0:9b334a45a8ff 447 }
bogdanm 0:9b334a45a8ff 448
bogdanm 0:9b334a45a8ff 449
bogdanm 0:9b334a45a8ff 450 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 451 * @brief
bogdanm 0:9b334a45a8ff 452 * Reset ADC to same state as after a HW reset.
bogdanm 0:9b334a45a8ff 453 *
bogdanm 0:9b334a45a8ff 454 * @note
bogdanm 0:9b334a45a8ff 455 * The ROUTE register is NOT reset by this function, in order to allow for
bogdanm 0:9b334a45a8ff 456 * centralized setup of this feature.
bogdanm 0:9b334a45a8ff 457 *
bogdanm 0:9b334a45a8ff 458 * @param[in] adc
bogdanm 0:9b334a45a8ff 459 * Pointer to ADC peripheral register block.
bogdanm 0:9b334a45a8ff 460 ******************************************************************************/
bogdanm 0:9b334a45a8ff 461 void ADC_Reset(ADC_TypeDef *adc)
bogdanm 0:9b334a45a8ff 462 {
bogdanm 0:9b334a45a8ff 463 /* Stop conversions, before resetting other registers. */
bogdanm 0:9b334a45a8ff 464 adc->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP;
bogdanm 0:9b334a45a8ff 465 adc->SINGLECTRL = _ADC_SINGLECTRL_RESETVALUE;
bogdanm 0:9b334a45a8ff 466 adc->SCANCTRL = _ADC_SCANCTRL_RESETVALUE;
bogdanm 0:9b334a45a8ff 467 adc->CTRL = _ADC_CTRL_RESETVALUE;
bogdanm 0:9b334a45a8ff 468 adc->IEN = _ADC_IEN_RESETVALUE;
bogdanm 0:9b334a45a8ff 469 adc->IFC = _ADC_IFC_MASK;
bogdanm 0:9b334a45a8ff 470 adc->BIASPROG = _ADC_BIASPROG_RESETVALUE;
bogdanm 0:9b334a45a8ff 471
bogdanm 0:9b334a45a8ff 472 /* Load calibration values for the 1V25 internal reference. */
bogdanm 0:9b334a45a8ff 473 ADC_CalibrateLoadSingle(adc, adcRef1V25);
bogdanm 0:9b334a45a8ff 474 ADC_CalibrateLoadScan(adc, adcRef1V25);
bogdanm 0:9b334a45a8ff 475
bogdanm 0:9b334a45a8ff 476 /* Do not reset route register, setting should be done independently */
bogdanm 0:9b334a45a8ff 477 }
bogdanm 0:9b334a45a8ff 478
bogdanm 0:9b334a45a8ff 479
bogdanm 0:9b334a45a8ff 480 /***************************************************************************//**
bogdanm 0:9b334a45a8ff 481 * @brief
bogdanm 0:9b334a45a8ff 482 * Calculate timebase value in order to get a timebase providing at least 1us.
bogdanm 0:9b334a45a8ff 483 *
bogdanm 0:9b334a45a8ff 484 * @param[in] hfperFreq Frequency in Hz of reference HFPER clock. Set to 0 to
bogdanm 0:9b334a45a8ff 485 * use currently defined HFPER clock setting.
bogdanm 0:9b334a45a8ff 486 *
bogdanm 0:9b334a45a8ff 487 * @return
bogdanm 0:9b334a45a8ff 488 * Timebase value to use for ADC in order to achieve at least 1 us.
bogdanm 0:9b334a45a8ff 489 ******************************************************************************/
bogdanm 0:9b334a45a8ff 490 uint8_t ADC_TimebaseCalc(uint32_t hfperFreq)
bogdanm 0:9b334a45a8ff 491 {
bogdanm 0:9b334a45a8ff 492 if (!hfperFreq)
bogdanm 0:9b334a45a8ff 493 {
bogdanm 0:9b334a45a8ff 494 hfperFreq = CMU_ClockFreqGet(cmuClock_HFPER);
bogdanm 0:9b334a45a8ff 495
bogdanm 0:9b334a45a8ff 496 /* Just in case, make sure we get non-zero freq for below calculation */
bogdanm 0:9b334a45a8ff 497 if (!hfperFreq)
bogdanm 0:9b334a45a8ff 498 {
bogdanm 0:9b334a45a8ff 499 hfperFreq = 1;
bogdanm 0:9b334a45a8ff 500 }
bogdanm 0:9b334a45a8ff 501 }
bogdanm 0:9b334a45a8ff 502 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
bogdanm 0:9b334a45a8ff 503 /* Handle errata on Giant Gecko, max TIMEBASE is 5 bits wide or max 0x1F */
bogdanm 0:9b334a45a8ff 504 /* cycles. This will give a warmp up time of e.g. 0.645us, not the */
bogdanm 0:9b334a45a8ff 505 /* required 1us when operating at 48MHz. One must also increase acqTime */
bogdanm 0:9b334a45a8ff 506 /* to compensate for the missing clock cycles, adding up to 1us in total.*/
bogdanm 0:9b334a45a8ff 507 /* See reference manual for details. */
bogdanm 0:9b334a45a8ff 508 if( hfperFreq > 32000000 )
bogdanm 0:9b334a45a8ff 509 {
bogdanm 0:9b334a45a8ff 510 hfperFreq = 32000000;
bogdanm 0:9b334a45a8ff 511 }
bogdanm 0:9b334a45a8ff 512 #endif
bogdanm 0:9b334a45a8ff 513 /* Determine number of HFPERCLK cycle >= 1us */
bogdanm 0:9b334a45a8ff 514 hfperFreq += 999999;
bogdanm 0:9b334a45a8ff 515 hfperFreq /= 1000000;
bogdanm 0:9b334a45a8ff 516
bogdanm 0:9b334a45a8ff 517 /* Return timebase value (N+1 format) */
bogdanm 0:9b334a45a8ff 518 return (uint8_t)(hfperFreq - 1);
bogdanm 0:9b334a45a8ff 519 }
bogdanm 0:9b334a45a8ff 520
bogdanm 0:9b334a45a8ff 521
bogdanm 0:9b334a45a8ff 522 /** @} (end addtogroup ADC) */
bogdanm 0:9b334a45a8ff 523 /** @} (end addtogroup EM_Library) */
bogdanm 0:9b334a45a8ff 524 #endif /* defined(ADC_COUNT) && (ADC_COUNT > 0) */