diff --git a/cpu/lpc11u34/include/periph_cpu.h b/cpu/lpc11u34/include/periph_cpu.h index 84c6864fae..29d988398c 100644 --- a/cpu/lpc11u34/include/periph_cpu.h +++ b/cpu/lpc11u34/include/periph_cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Freie Universität Berlin + * Copyright (C) 2015-2016 Freie Universität Berlin * * 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 @@ -14,6 +14,7 @@ * @brief CPU specific definitions for internal peripheral handling * * @author Paul RATHGEB + * @author Hauke Petersen */ #ifndef PERIPH_CPU_H_ @@ -39,6 +40,28 @@ extern "C" { */ #define CPUID_LEN (16U) +/** + * @brief Define number of available ADC lines + * + * TODO: check this value + */ +#define ADC_NUMOF (10U) + +/** + * @brief Override the ADC resolution settings + * @{ + */ +#define HAVE_ADC_RES_T +typedef enum { + ADC_RES_6BIT = 0, /**< ADC resolution: 6 bit */ + ADC_RES_8BIT, /**< ADC resolution: 8 bit */ + ADC_RES_10BIT, /**< ADC resolution: 10 bit */ + ADC_RES_12BIT, /**< ADC resolution: 12 bit */ + ADC_RES_14BIT, /**< ADC resolution: 14 bit */ + ADC_RES_16BIT, /**< ADC resolution: 16 bit */ +} adc_res_t; +/** @} */ + #ifdef __cplusplus } #endif diff --git a/cpu/lpc11u34/periph/adc.c b/cpu/lpc11u34/periph/adc.c index 6bd3ec4b3d..4144f5c0b5 100644 --- a/cpu/lpc11u34/periph/adc.c +++ b/cpu/lpc11u34/periph/adc.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2015 Freie Universität Berlin + * Copyright (C) 2015-2016 Freie Universität Berlin * - * 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. + * 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. */ /** @@ -13,114 +13,91 @@ * @file * @brief Low-level ADC driver implementation * - * @author Paul RATHGEB + * @author Paul Rathgeb + * @author Hauke Petersen * * @} */ #include -#include #include "cpu.h" +#include "mutex.h" #include "periph/adc.h" -#include "periph_conf.h" -/* guard in case that no ADC device is defined */ -#if ADC_NUMOF +/** + * @brief Mutex to synchronize ADC access from different threads + */ +static mutex_t lock = MUTEX_INIT; -static inline uint32_t *_adc_channel_to_pin(int channel) +static inline uint32_t *pincfg_reg(adc_t line) { - return (channel < 6) ? ((uint32_t*)(LPC_IOCON) + (11 + channel)) - : ((uint32_t*)(LPC_IOCON) + (16 + channel)); + int offset = (line < 6) ? (11 + line) : (16 + line); + return ((uint32_t *)(LPC_IOCON) + offset); } -int adc_init(adc_t dev, adc_precision_t precision) +static inline void prep(void) { - adc_poweron(dev); + mutex_lock(&lock); + LPC_SYSCON->PDRUNCFG &= ~(1 << 4); + LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 13); +} - /* Set resolution */ - switch (precision) { - case ADC_RES_6BIT: - LPC_ADC->CR |= (0x04 << 17); - break; - case ADC_RES_8BIT: - LPC_ADC->CR |= (0x02 << 17); - break; - case ADC_RES_10BIT: - LPC_ADC->CR |= (0x0 << 17); - break; - case ADC_RES_12BIT: - case ADC_RES_14BIT: - case ADC_RES_16BIT: - /* Resolution > 10 bits unsupported */ - adc_poweroff(dev); - return -1; - break; - } +static inline void done(void) +{ + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 13); + LPC_SYSCON->PDRUNCFG |= (1 << 4); + mutex_unlock(&lock); +} + +int adc_init(adc_t line) +{ + uint32_t *pincfg; + + prep(); /* ADC frequency : 3MHz */ - LPC_ADC->CR |= (15 << 8); + LPC_ADC->CR = (15 << 8); + /* configure the connected pin */ + pincfg = pincfg_reg(line); + /* Put the pin in its ADC alternate function */ + if (line < 5) { + *pincfg |= 2; + } + else { + *pincfg |= 1; + } + /* Configure ADMODE in analog input */ + *pincfg &= ~(1 << 7); + + done(); return 0; } -int adc_sample(adc_t dev, int channel) +int adc_sample(adc_t line, adc_res_t res) { - if (channel > ADC_MAX_CHANNELS) { + int sample; + + /* check if resolution is valid */ + if (res < 0xff) { return -1; } - /* Compute the IOCON register for the channel */ - uint32_t *cfg = _adc_channel_to_pin(channel); - /* Put the pin in its ADC alternate function */ - if (channel < 5) { - *cfg |= 2; - } - else { - *cfg |= 1; - } - /* Configure ADMODE in analog input */ - *cfg &= ~(1 << 7); + /* prepare the device */ + prep(); + + /* set resolution */ + LPC_ADC->CR &= ~(0x7 << 17); + LPC_ADC->CR |= res; /* Start a conversion */ - LPC_ADC->CR |= (1 << channel) | (1 << 24); + LPC_ADC->CR |= (1 << line) | (1 << 24); /* Wait for the end of the conversion */ - while (!(LPC_ADC->DR[channel] & (1 << 31))); + while (!(LPC_ADC->DR[line] & (1 << 31))) {} /* Read and return result */ - return (LPC_ADC->DR[channel] >> 6); -} + sample = (LPC_ADC->DR[line] >> 6); -void adc_poweron(adc_t dev) -{ - switch (dev) { -#if ADC_0_EN - case ADC_0: - LPC_SYSCON->PDRUNCFG &= ~(1 << 4); - LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 13); - break; -#endif - } -} + done(); -void adc_poweroff(adc_t dev) -{ - switch (dev) { -#if ADC_0_EN - case ADC_0: - LPC_SYSCON->PDRUNCFG |= (1 << 4); - LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 13); - break; -#endif - } + return sample; } - -int adc_map(adc_t dev, int value, int min, int max) -{ - return 0; -} - -float adc_mapf(adc_t dev, int value, float min, float max) -{ - return 0.0; -} - -#endif /* ADC_NUMOF */