mbed

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Fri Feb 16 16:09:33 2018 +0000
Revision:
182:57724642e740
Parent:
175:b96e65c34a4d
mbed-dev library. Release version 159.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 175:b96e65c34a4d 1 /* mbed Microcontroller Library
AnnaBridge 175:b96e65c34a4d 2 * Copyright (c) 2015-2017 Nuvoton
AnnaBridge 175:b96e65c34a4d 3 *
AnnaBridge 175:b96e65c34a4d 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 175:b96e65c34a4d 5 * you may not use this file except in compliance with the License.
AnnaBridge 175:b96e65c34a4d 6 * You may obtain a copy of the License at
AnnaBridge 175:b96e65c34a4d 7 *
AnnaBridge 175:b96e65c34a4d 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 175:b96e65c34a4d 9 *
AnnaBridge 175:b96e65c34a4d 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 175:b96e65c34a4d 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 175:b96e65c34a4d 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 175:b96e65c34a4d 13 * See the License for the specific language governing permissions and
AnnaBridge 175:b96e65c34a4d 14 * limitations under the License.
AnnaBridge 175:b96e65c34a4d 15 */
AnnaBridge 175:b96e65c34a4d 16
AnnaBridge 175:b96e65c34a4d 17 #include "analogin_api.h"
AnnaBridge 175:b96e65c34a4d 18
AnnaBridge 175:b96e65c34a4d 19 #if DEVICE_ANALOGIN
AnnaBridge 175:b96e65c34a4d 20
AnnaBridge 175:b96e65c34a4d 21 #include "mbed_wait_api.h"
AnnaBridge 175:b96e65c34a4d 22 #include "cmsis.h"
AnnaBridge 175:b96e65c34a4d 23 #include "pinmap.h"
AnnaBridge 175:b96e65c34a4d 24 #include "PeripheralPins.h"
AnnaBridge 175:b96e65c34a4d 25 #include "nu_modutil.h"
AnnaBridge 175:b96e65c34a4d 26
AnnaBridge 175:b96e65c34a4d 27 static uint32_t adc_modinit_mask = 0;
AnnaBridge 175:b96e65c34a4d 28 volatile int adc_busy_flag = 0;
AnnaBridge 175:b96e65c34a4d 29
AnnaBridge 175:b96e65c34a4d 30 static const struct nu_modinit_s adc_modinit_tab[] = {
AnnaBridge 175:b96e65c34a4d 31 {ADC_0_0, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 32 {ADC_0_1, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 33 {ADC_0_2, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 34 {ADC_0_3, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 35 {ADC_0_4, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 36 {ADC_0_5, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 37 {ADC_0_6, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 38 {ADC_0_7, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 39 {ADC_0_8, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 40 {ADC_0_9, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 41 {ADC_0_10, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 42 {ADC_0_11, ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_ADC_CLK_DIVIDER(1), ADC_RST, ADC_IRQn, NULL},
AnnaBridge 175:b96e65c34a4d 43 };
AnnaBridge 175:b96e65c34a4d 44
AnnaBridge 175:b96e65c34a4d 45 void analogin_init(analogin_t *obj, PinName pin)
AnnaBridge 175:b96e65c34a4d 46 {
AnnaBridge 175:b96e65c34a4d 47 obj->adc = (ADCName) pinmap_peripheral(pin, PinMap_ADC);
AnnaBridge 175:b96e65c34a4d 48 MBED_ASSERT(obj->adc != (ADCName) NC);
AnnaBridge 175:b96e65c34a4d 49
AnnaBridge 175:b96e65c34a4d 50 const struct nu_modinit_s *modinit = get_modinit(obj->adc, adc_modinit_tab);
AnnaBridge 175:b96e65c34a4d 51 MBED_ASSERT(modinit != NULL);
AnnaBridge 175:b96e65c34a4d 52 MBED_ASSERT((ADCName) modinit->modname == obj->adc);
AnnaBridge 175:b96e65c34a4d 53
AnnaBridge 175:b96e65c34a4d 54 ADC_T *adc_base = (ADC_T *) NU_MODBASE(obj->adc);
AnnaBridge 175:b96e65c34a4d 55 uint32_t chn = NU_MODSUBINDEX(obj->adc);
AnnaBridge 175:b96e65c34a4d 56
AnnaBridge 175:b96e65c34a4d 57 // Wait for ADC is not busy, due to all ADC channels share the same module
AnnaBridge 175:b96e65c34a4d 58 while (adc_busy_flag != 0) {
AnnaBridge 175:b96e65c34a4d 59 wait_us(100);
AnnaBridge 175:b96e65c34a4d 60 }
AnnaBridge 175:b96e65c34a4d 61 adc_busy_flag = 1;
AnnaBridge 175:b96e65c34a4d 62
AnnaBridge 175:b96e65c34a4d 63 // NOTE: All channels (identified by ADCName) share a ADC module. This reset will also affect other channels of the same ADC module.
AnnaBridge 175:b96e65c34a4d 64 if (! adc_modinit_mask) {
AnnaBridge 175:b96e65c34a4d 65 // Reset this module if no channel enabled
AnnaBridge 175:b96e65c34a4d 66 SYS_ResetModule(modinit->rsetidx);
AnnaBridge 175:b96e65c34a4d 67
AnnaBridge 175:b96e65c34a4d 68 // Select clock source of paired channels
AnnaBridge 175:b96e65c34a4d 69 CLK_SetModuleClock(modinit->clkidx, modinit->clksrc, modinit->clkdiv);
AnnaBridge 175:b96e65c34a4d 70 // Enable clock of paired channels
AnnaBridge 175:b96e65c34a4d 71 CLK_EnableModuleClock(modinit->clkidx);
AnnaBridge 175:b96e65c34a4d 72
AnnaBridge 175:b96e65c34a4d 73 // Set operation mode and enable channel N
AnnaBridge 175:b96e65c34a4d 74 ADC_Open(ADC, ADC_INPUT_MODE_SINGLE_END, ADC_OPERATION_MODE_SINGLE_CYCLE, 1 << chn);
AnnaBridge 175:b96e65c34a4d 75
AnnaBridge 175:b96e65c34a4d 76 // Set reference voltage to AVDD
AnnaBridge 175:b96e65c34a4d 77 ADC_SET_REF_VOLTAGE(ADC, ADC_REFSEL_POWER);
AnnaBridge 175:b96e65c34a4d 78
AnnaBridge 175:b96e65c34a4d 79 // Power on ADC
AnnaBridge 175:b96e65c34a4d 80 ADC_POWER_ON(ADC);
AnnaBridge 175:b96e65c34a4d 81 } else {
AnnaBridge 175:b96e65c34a4d 82 // Just enable channel N
AnnaBridge 175:b96e65c34a4d 83 adc_base->CHEN |= 1 << chn;
AnnaBridge 175:b96e65c34a4d 84 }
AnnaBridge 175:b96e65c34a4d 85
AnnaBridge 175:b96e65c34a4d 86 adc_modinit_mask |= 1 << chn;
AnnaBridge 175:b96e65c34a4d 87
AnnaBridge 175:b96e65c34a4d 88 adc_busy_flag = 0;
AnnaBridge 175:b96e65c34a4d 89
AnnaBridge 175:b96e65c34a4d 90 // Wire pinout
AnnaBridge 175:b96e65c34a4d 91 pinmap_pinout(pin, PinMap_ADC);
AnnaBridge 175:b96e65c34a4d 92 }
AnnaBridge 175:b96e65c34a4d 93
AnnaBridge 175:b96e65c34a4d 94 void analogin_deinit(PinName pin)
AnnaBridge 175:b96e65c34a4d 95 {
AnnaBridge 175:b96e65c34a4d 96 analogin_t obj;
AnnaBridge 175:b96e65c34a4d 97 obj.adc = (ADCName) pinmap_peripheral(pin, PinMap_ADC);
AnnaBridge 175:b96e65c34a4d 98 MBED_ASSERT(obj.adc != (ADCName) NC);
AnnaBridge 175:b96e65c34a4d 99
AnnaBridge 175:b96e65c34a4d 100 const struct nu_modinit_s *modinit = get_modinit(obj.adc, adc_modinit_tab);
AnnaBridge 175:b96e65c34a4d 101 MBED_ASSERT(modinit != NULL);
AnnaBridge 175:b96e65c34a4d 102 MBED_ASSERT((ADCName) modinit->modname == obj.adc);
AnnaBridge 175:b96e65c34a4d 103
AnnaBridge 175:b96e65c34a4d 104 ADC_T *adc_base = (ADC_T *) NU_MODBASE(obj.adc);
AnnaBridge 175:b96e65c34a4d 105 uint32_t chn = NU_MODSUBINDEX(obj.adc);
AnnaBridge 175:b96e65c34a4d 106
AnnaBridge 175:b96e65c34a4d 107 // Wait for ADC is not busy, due to all ADC channels share the same module
AnnaBridge 175:b96e65c34a4d 108 while (adc_busy_flag != 0) {
AnnaBridge 175:b96e65c34a4d 109 wait_us(100);
AnnaBridge 175:b96e65c34a4d 110 }
AnnaBridge 175:b96e65c34a4d 111 adc_busy_flag = 1;
AnnaBridge 175:b96e65c34a4d 112
AnnaBridge 175:b96e65c34a4d 113 // Disable channel N
AnnaBridge 175:b96e65c34a4d 114 adc_base->CHEN &= ~(1 << chn);
AnnaBridge 175:b96e65c34a4d 115 adc_modinit_mask &= ~(1 << chn);
AnnaBridge 175:b96e65c34a4d 116
AnnaBridge 175:b96e65c34a4d 117 adc_busy_flag = 0;
AnnaBridge 175:b96e65c34a4d 118 }
AnnaBridge 175:b96e65c34a4d 119
AnnaBridge 175:b96e65c34a4d 120 uint16_t analogin_read_u16(analogin_t *obj)
AnnaBridge 175:b96e65c34a4d 121 {
AnnaBridge 175:b96e65c34a4d 122 ADC_T *adc_base = (ADC_T *) NU_MODBASE(obj->adc);
AnnaBridge 175:b96e65c34a4d 123 uint32_t chn = NU_MODSUBINDEX(obj->adc);
AnnaBridge 175:b96e65c34a4d 124
AnnaBridge 175:b96e65c34a4d 125 // Wait for ADC is not busy, due to all ADC channels share the same module
AnnaBridge 175:b96e65c34a4d 126 while (adc_busy_flag != 0) {
AnnaBridge 175:b96e65c34a4d 127 wait_us(100);
AnnaBridge 175:b96e65c34a4d 128 }
AnnaBridge 175:b96e65c34a4d 129 adc_busy_flag = 1;
AnnaBridge 175:b96e65c34a4d 130
AnnaBridge 175:b96e65c34a4d 131 // Start the A/D conversion
AnnaBridge 175:b96e65c34a4d 132 adc_base->CR |= ADC_CR_ADST_Msk;
AnnaBridge 175:b96e65c34a4d 133 // Wait for conversion finish
AnnaBridge 175:b96e65c34a4d 134 while (! ADC_GET_INT_FLAG(adc_base, ADC_ADF_INT) & ADC_ADF_INT) ;
AnnaBridge 175:b96e65c34a4d 135 ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);
AnnaBridge 175:b96e65c34a4d 136 uint16_t conv_res_12 = ADC_GET_CONVERSION_DATA(adc_base, chn);
AnnaBridge 175:b96e65c34a4d 137
AnnaBridge 175:b96e65c34a4d 138 adc_busy_flag = 0;
AnnaBridge 175:b96e65c34a4d 139
AnnaBridge 175:b96e65c34a4d 140 // Just 12 bits are effective. Convert to 16 bits.
AnnaBridge 175:b96e65c34a4d 141 // conv_res_12: 0000 b11b10b9b8 b7b6b5b4 b3b2b1b0
AnnaBridge 175:b96e65c34a4d 142 // conv_res_16: b11b10b9b8 b7b6b5b4 b3b2b1b0 b11b10b9b8
AnnaBridge 175:b96e65c34a4d 143 uint16_t conv_res_16 = (conv_res_12 << 4) | (conv_res_12 >> 8);
AnnaBridge 175:b96e65c34a4d 144
AnnaBridge 175:b96e65c34a4d 145 return conv_res_16;
AnnaBridge 175:b96e65c34a4d 146 }
AnnaBridge 175:b96e65c34a4d 147
AnnaBridge 175:b96e65c34a4d 148 float analogin_read(analogin_t *obj)
AnnaBridge 175:b96e65c34a4d 149 {
AnnaBridge 175:b96e65c34a4d 150 uint16_t value = analogin_read_u16(obj);
AnnaBridge 175:b96e65c34a4d 151 return (float) value * (1.0f / (float) 0xFFFF);
AnnaBridge 175:b96e65c34a4d 152 }
AnnaBridge 175:b96e65c34a4d 153
AnnaBridge 175:b96e65c34a4d 154 #endif