From d0fb8adf4503e3e53e54eb7836123fa943f965e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Thu, 3 Dec 2015 13:10:12 +0100 Subject: [PATCH] cpu/lm4f120: ADC support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only ADC_0 and no precision support. Signed-off-by: Marc Poulhiès --- boards/ek-lm4f120xl/Makefile.features | 1 + boards/ek-lm4f120xl/include/periph_conf.h | 8 + cpu/lm4f120/periph/adc.c | 173 ++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 cpu/lm4f120/periph/adc.c diff --git a/boards/ek-lm4f120xl/Makefile.features b/boards/ek-lm4f120xl/Makefile.features index 139370150f..aacc4f47ac 100644 --- a/boards/ek-lm4f120xl/Makefile.features +++ b/boards/ek-lm4f120xl/Makefile.features @@ -1,4 +1,5 @@ # Put defined MCU peripherals here (in alphabetical order) +FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_cpuid FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_timer diff --git a/boards/ek-lm4f120xl/include/periph_conf.h b/boards/ek-lm4f120xl/include/periph_conf.h index e2de1321cb..83e9634545 100644 --- a/boards/ek-lm4f120xl/include/periph_conf.h +++ b/boards/ek-lm4f120xl/include/periph_conf.h @@ -92,6 +92,14 @@ extern "C" { #define UART_1_ISR isr_uart1 /** @} */ +/** + * @name ADC configuration + * @{ + */ +#define ADC_NUMOF 1 +#define ADC_0_EN 1 +#define ADC_MAX_CHANNELS 12 + #ifdef __cplusplus } #endif diff --git a/cpu/lm4f120/periph/adc.c b/cpu/lm4f120/periph/adc.c new file mode 100644 index 0000000000..24b58b1bd5 --- /dev/null +++ b/cpu/lm4f120/periph/adc.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2016 Marc Poulhiès + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup cpu_lm4f120 + * @{ + * + * @file + * @brief Low-level ADC driver implementation + * + * @author Marc Poulhiès + * + * @} + */ + +#include +#include + +#include "cpu.h" +#include "periph/adc.h" +#include "periph_conf.h" + +#if ADC_NUMOF + +struct adc_gpio_cfg_s { + unsigned long gpio_base; + unsigned long gpio_sysctl; + unsigned short gpio_pin; +}; + +static const struct adc_gpio_cfg_s adc0_gpio[ADC_MAX_CHANNELS] = { + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, GPIO_PIN_3 }, // AIN0 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, GPIO_PIN_2 }, // AIN1 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, GPIO_PIN_1 }, // AIN2 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, GPIO_PIN_0 }, // AIN3 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOD, GPIO_PIN_3 }, // AIN4 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOD, GPIO_PIN_2 }, // AIN5 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOD, GPIO_PIN_1 }, // AIN6 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOD, GPIO_PIN_0 }, // AIN7 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, GPIO_PIN_5 }, // AIN8 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, GPIO_PIN_4 }, // AIN9 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOB, GPIO_PIN_4 }, // AIN10 + { GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOB, GPIO_PIN_5 }, // AIN11 +}; + +/* + * We only support ADC0 for now + */ +#define ADC_0_SYSCTL SYSCTL_PERIPH_ADC0 +#define ADC_0_GPIO adc0_gpio +#define ADC_0_BASE ADC0_BASE +#define ADC_0_SEQ 3 + +int adc_init(adc_t dev, adc_precision_t precision) +{ + unsigned long adc_base; + unsigned long adc_seq; + + switch (dev) { +#if ADC_0_EN + case ADC_0: + adc_base = ADC_0_BASE; + adc_seq = ADC_0_SEQ; + break; +#endif + } + ROM_SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS); + adc_poweron(dev); + + ROM_ADCHardwareOversampleConfigure(adc_base, 64); + ROM_ADCSequenceDisable(adc_base, adc_seq); + + return 0; +} + +int adc_sample(adc_t dev, int channel) +{ + int value[2]; + unsigned long adc_base; + unsigned long adc_seq; + unsigned long adc_gpio_port = 0; + unsigned long adc_gpio_pin = 0; + unsigned long adc_gpio_sysctl = 0; + + if (channel >= ADC_MAX_CHANNELS) { + return -1; + } + + switch (dev) { +#if ADC_0_EN + case ADC_0: + adc_base = ADC_0_BASE; + adc_seq = ADC_0_SEQ; + + adc_gpio_port = ADC_0_GPIO[channel].gpio_base; + adc_gpio_sysctl = ADC_0_GPIO[channel].gpio_sysctl; + adc_gpio_pin = ADC_0_GPIO[channel].gpio_pin; + break; +#endif + } + ROM_SysCtlPeripheralEnable(adc_gpio_sysctl); + ROM_GPIOPinTypeADC(adc_gpio_port, adc_gpio_pin); + + ROM_ADCSequenceDisable(adc_base, adc_seq); + ROM_ADCIntClear(adc_base, adc_seq); + + ROM_ADCSequenceConfigure(adc_base, adc_seq, ADC_TRIGGER_PROCESSOR, 0); + + ROM_ADCSequenceStepConfigure(adc_base, adc_seq, 0, channel | ADC_CTL_IE | ADC_CTL_END); + ROM_ADCSequenceEnable(adc_base, adc_seq); + + ROM_ADCIntClear(adc_base, adc_seq); + + ROM_ADCProcessorTrigger(adc_base, adc_seq); + while (!ROM_ADCIntStatus(adc_base, adc_seq, false)) { + } + ROM_ADCIntClear(adc_base, adc_seq); + ROM_ADCSequenceDataGet(adc_base, adc_seq, (unsigned long *) value); + + return value[0]; +} + +void adc_poweron(adc_t dev) +{ + unsigned long adc_sysctl; + + switch (dev) { +#if ADC_0_EN + case ADC_0: + adc_sysctl = ADC_0_SYSCTL; + break; +#endif + } + ROM_SysCtlPeripheralEnable(adc_sysctl); +} + +void adc_poweroff(adc_t dev) +{ + unsigned long adc_sysctl; + + switch (dev) { +#if ADC_0_EN + case ADC_0: + adc_sysctl = ADC_0_SYSCTL; + break; +#endif + } + ROM_SysCtlPeripheralDisable(adc_sysctl); +} + + +/* + * Currently not supported + */ +int adc_map(adc_t dev, int value, int min, int max) +{ + return 0; +} + +/* + * Currently not supported + */ +float adc_mapf(adc_t dev, int value, float min, float max) +{ + return 0.0; +} + +#endif /* ADC_NUMOF */