Marco Mayer / Mbed OS Queue
Committer:
demayer
Date:
Sat Mar 28 15:28:19 2020 +0000
Revision:
0:6bf0743ece18
IMU Thread with an event-queue running parallel to handle tasks like a 5 times blinking LED. Button with interrupt detected.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
demayer 0:6bf0743ece18 1 /* mbed Microcontroller Library
demayer 0:6bf0743ece18 2 * Copyright (c) 2006-2013 ARM Limited
demayer 0:6bf0743ece18 3 *
demayer 0:6bf0743ece18 4 * Licensed under the Apache License, Version 2.0 (the "License");
demayer 0:6bf0743ece18 5 * you may not use this file except in compliance with the License.
demayer 0:6bf0743ece18 6 * You may obtain a copy of the License at
demayer 0:6bf0743ece18 7 *
demayer 0:6bf0743ece18 8 * http://www.apache.org/licenses/LICENSE-2.0
demayer 0:6bf0743ece18 9 *
demayer 0:6bf0743ece18 10 * Unless required by applicable law or agreed to in writing, software
demayer 0:6bf0743ece18 11 * distributed under the License is distributed on an "AS IS" BASIS,
demayer 0:6bf0743ece18 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
demayer 0:6bf0743ece18 13 * See the License for the specific language governing permissions and
demayer 0:6bf0743ece18 14 * limitations under the License.
demayer 0:6bf0743ece18 15 *
demayer 0:6bf0743ece18 16 * Ported to NXP LPC43XX by Micromint USA <support@micromint.com>
demayer 0:6bf0743ece18 17 */
demayer 0:6bf0743ece18 18 #include "mbed_assert.h"
demayer 0:6bf0743ece18 19 #include "analogin_api.h"
demayer 0:6bf0743ece18 20 #include "cmsis.h"
demayer 0:6bf0743ece18 21 #include "pinmap.h"
demayer 0:6bf0743ece18 22 #include "mbed_error.h"
demayer 0:6bf0743ece18 23 #include "gpio_api.h"
demayer 0:6bf0743ece18 24
demayer 0:6bf0743ece18 25 #define ANALOGIN_MEDIAN_FILTER 1
demayer 0:6bf0743ece18 26
demayer 0:6bf0743ece18 27 static inline int div_round_up(int x, int y) {
demayer 0:6bf0743ece18 28 return (x + (y - 1)) / y;
demayer 0:6bf0743ece18 29 }
demayer 0:6bf0743ece18 30
demayer 0:6bf0743ece18 31 static const PinMap PinMap_ADC[] = {
demayer 0:6bf0743ece18 32 {P4_3, ADC0_0, 0},
demayer 0:6bf0743ece18 33 {P4_1, ADC0_1, 0},
demayer 0:6bf0743ece18 34 {PF_8, ADC0_2, 0},
demayer 0:6bf0743ece18 35 {P7_5, ADC0_3, 0},
demayer 0:6bf0743ece18 36 {P7_4, ADC0_4, 0},
demayer 0:6bf0743ece18 37 {PF_10, ADC0_5, 0},
demayer 0:6bf0743ece18 38 {PB_6, ADC0_6, 0},
demayer 0:6bf0743ece18 39 {PC_3, ADC1_0, 0},
demayer 0:6bf0743ece18 40 {PC_0, ADC1_1, 0},
demayer 0:6bf0743ece18 41 {PF_9, ADC1_2, 0},
demayer 0:6bf0743ece18 42 {PF_6, ADC1_3, 0},
demayer 0:6bf0743ece18 43 {PF_5, ADC1_4, 0},
demayer 0:6bf0743ece18 44 {PF_11, ADC1_5, 0},
demayer 0:6bf0743ece18 45 {P7_7, ADC1_6, 0},
demayer 0:6bf0743ece18 46 {PF_7, ADC1_7, 0},
demayer 0:6bf0743ece18 47 {adc0_0, ADC_pin0_0, 0},
demayer 0:6bf0743ece18 48 {adc0_1, ADC_pin0_1, 0},
demayer 0:6bf0743ece18 49 {adc0_2, ADC_pin0_2, 0},
demayer 0:6bf0743ece18 50 {adc0_3, ADC_pin0_3, 0},
demayer 0:6bf0743ece18 51 {adc0_4, ADC_pin0_4, 0},
demayer 0:6bf0743ece18 52 {adc0_5, ADC_pin0_5, 0},
demayer 0:6bf0743ece18 53 {adc0_6, ADC_pin0_6, 0},
demayer 0:6bf0743ece18 54 {adc0_7, ADC_pin0_7, 0},
demayer 0:6bf0743ece18 55 {adc1_0, ADC_pin1_0, 0},
demayer 0:6bf0743ece18 56 {adc1_1, ADC_pin1_1, 0},
demayer 0:6bf0743ece18 57 {adc1_2, ADC_pin1_2, 0},
demayer 0:6bf0743ece18 58 {adc1_3, ADC_pin1_3, 0},
demayer 0:6bf0743ece18 59 {adc1_4, ADC_pin1_4, 0},
demayer 0:6bf0743ece18 60 {adc1_5, ADC_pin1_5, 0},
demayer 0:6bf0743ece18 61 {adc1_6, ADC_pin1_6, 0},
demayer 0:6bf0743ece18 62 {adc1_7, ADC_pin1_7, 0},
demayer 0:6bf0743ece18 63 {NC, NC, 0 }
demayer 0:6bf0743ece18 64 };
demayer 0:6bf0743ece18 65
demayer 0:6bf0743ece18 66 void analogin_init(analogin_t *obj, PinName pin) {
demayer 0:6bf0743ece18 67 ADCName name;
demayer 0:6bf0743ece18 68
demayer 0:6bf0743ece18 69 name = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
demayer 0:6bf0743ece18 70 MBED_ASSERT(obj->adc != (LPC_ADC_T *)NC);
demayer 0:6bf0743ece18 71
demayer 0:6bf0743ece18 72 // Set ADC number
demayer 0:6bf0743ece18 73 if(name < ADC1_0) {
demayer 0:6bf0743ece18 74 obj->num = 0;
demayer 0:6bf0743ece18 75 } else if(name < ADC_pin0_0 && name > ADC0_6) {
demayer 0:6bf0743ece18 76 obj->num = 1;
demayer 0:6bf0743ece18 77 } else if(name < ADC_pin1_1 && name > ADC1_7) {
demayer 0:6bf0743ece18 78 obj->num = 0;
demayer 0:6bf0743ece18 79 } else if(name > ADC_pin0_7) {
demayer 0:6bf0743ece18 80 obj->num = 1;
demayer 0:6bf0743ece18 81 }
demayer 0:6bf0743ece18 82
demayer 0:6bf0743ece18 83 //ADC register and channel
demayer 0:6bf0743ece18 84 obj->ch = name % (ADC0_7 + 1);
demayer 0:6bf0743ece18 85 obj->adc = (LPC_ADC_T *) (obj->num > 0) ? LPC_ADC1 : LPC_ADC0;
demayer 0:6bf0743ece18 86
demayer 0:6bf0743ece18 87 // Reset pin function to GPIO if it is a GPIO pin. for adc only pins it is not necessary
demayer 0:6bf0743ece18 88 if(name < ADC_pin0_0) {
demayer 0:6bf0743ece18 89 gpio_set(pin);
demayer 0:6bf0743ece18 90 // Select ADC on analog function select register in SCU
demayer 0:6bf0743ece18 91 LPC_SCU->ENAIO[obj->num] |= (1 << obj->ch);
demayer 0:6bf0743ece18 92 } else {
demayer 0:6bf0743ece18 93 LPC_SCU->ENAIO[obj->num] &= ~(1 << obj->ch);
demayer 0:6bf0743ece18 94 }
demayer 0:6bf0743ece18 95
demayer 0:6bf0743ece18 96 // Calculate minimum clock divider
demayer 0:6bf0743ece18 97 // clkdiv = divider - 1
demayer 0:6bf0743ece18 98 uint32_t PCLK = SystemCoreClock;
demayer 0:6bf0743ece18 99 uint32_t adcRate = 400000;
demayer 0:6bf0743ece18 100 uint32_t clkdiv = div_round_up(PCLK, adcRate) - 1;
demayer 0:6bf0743ece18 101
demayer 0:6bf0743ece18 102 // Set the generic software-controlled ADC settings
demayer 0:6bf0743ece18 103 obj->adc->CR = (0 << 0) // SEL: 0 = no channels selected
demayer 0:6bf0743ece18 104 | (clkdiv << 8) // CLKDIV:
demayer 0:6bf0743ece18 105 | (0 << 16) // BURST: 0 = software control
demayer 0:6bf0743ece18 106 | (1 << 21) // PDN: 1 = operational
demayer 0:6bf0743ece18 107 | (0 << 24) // START: 0 = no start
demayer 0:6bf0743ece18 108 | (0 << 27); // EDGE: not applicable
demayer 0:6bf0743ece18 109 }
demayer 0:6bf0743ece18 110
demayer 0:6bf0743ece18 111 static inline uint32_t adc_read(analogin_t *obj) {
demayer 0:6bf0743ece18 112 uint32_t temp;
demayer 0:6bf0743ece18 113 uint8_t channel = obj->ch;
demayer 0:6bf0743ece18 114 LPC_ADC_T *pADC = obj->adc;
demayer 0:6bf0743ece18 115
demayer 0:6bf0743ece18 116 // Select the appropriate channel and start conversion
demayer 0:6bf0743ece18 117 pADC->CR |= ADC_CR_CH_SEL(channel);
demayer 0:6bf0743ece18 118 temp = pADC->CR & ~ADC_CR_START_MASK;
demayer 0:6bf0743ece18 119 pADC->CR = temp | (ADC_CR_START_MODE_SEL(ADC_START_NOW));
demayer 0:6bf0743ece18 120
demayer 0:6bf0743ece18 121 // Wait for DONE bit and read data
demayer 0:6bf0743ece18 122 while (!(pADC->STAT & ADC_CR_CH_SEL(channel)));
demayer 0:6bf0743ece18 123 temp = pADC->DR[channel];
demayer 0:6bf0743ece18 124
demayer 0:6bf0743ece18 125 // Deselect channel and return result
demayer 0:6bf0743ece18 126 pADC->CR &= ~ADC_CR_START_MASK;
demayer 0:6bf0743ece18 127 pADC->CR &= ~ADC_CR_CH_SEL(channel);
demayer 0:6bf0743ece18 128 return ADC_DR_RESULT(temp);
demayer 0:6bf0743ece18 129 }
demayer 0:6bf0743ece18 130
demayer 0:6bf0743ece18 131 static inline void order(uint32_t *a, uint32_t *b) {
demayer 0:6bf0743ece18 132 if (*a > *b) {
demayer 0:6bf0743ece18 133 uint32_t t = *a;
demayer 0:6bf0743ece18 134 *a = *b;
demayer 0:6bf0743ece18 135 *b = t;
demayer 0:6bf0743ece18 136 }
demayer 0:6bf0743ece18 137 }
demayer 0:6bf0743ece18 138
demayer 0:6bf0743ece18 139 static inline uint32_t adc_read_u32(analogin_t *obj) {
demayer 0:6bf0743ece18 140 uint32_t value;
demayer 0:6bf0743ece18 141 #if ANALOGIN_MEDIAN_FILTER
demayer 0:6bf0743ece18 142 uint32_t v1 = adc_read(obj);
demayer 0:6bf0743ece18 143 uint32_t v2 = adc_read(obj);
demayer 0:6bf0743ece18 144 uint32_t v3 = adc_read(obj);
demayer 0:6bf0743ece18 145 order(&v1, &v2);
demayer 0:6bf0743ece18 146 order(&v2, &v3);
demayer 0:6bf0743ece18 147 order(&v1, &v2);
demayer 0:6bf0743ece18 148 value = v2;
demayer 0:6bf0743ece18 149 #else
demayer 0:6bf0743ece18 150 value = adc_read(obj);
demayer 0:6bf0743ece18 151 #endif
demayer 0:6bf0743ece18 152 return value;
demayer 0:6bf0743ece18 153 }
demayer 0:6bf0743ece18 154
demayer 0:6bf0743ece18 155 uint16_t analogin_read_u16(analogin_t *obj) {
demayer 0:6bf0743ece18 156 uint32_t value = adc_read_u32(obj);
demayer 0:6bf0743ece18 157
demayer 0:6bf0743ece18 158 return (value << 6) | ((value >> 4) & 0x003F); // 10 bit
demayer 0:6bf0743ece18 159 }
demayer 0:6bf0743ece18 160
demayer 0:6bf0743ece18 161 float analogin_read(analogin_t *obj) {
demayer 0:6bf0743ece18 162 uint32_t value = adc_read_u32(obj);
demayer 0:6bf0743ece18 163 return (float)value * (1.0f / (float)ADC_RANGE);
demayer 0:6bf0743ece18 164 }