1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/lm4f120/periph/adc.c
2020-01-10 14:13:14 +01:00

134 lines
3.4 KiB
C

/*
* 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
* @ingroup drivers_periph_adc
* @{
*
* @file
* @brief Low-level ADC driver implementation
*
* The current ADC driver implementation only supports ADC0.
*
* @author Marc Poulhiès <dkm@kataplop.net>
*
* @}
*/
#include <stdint.h>
#include <string.h>
#include "cpu.h"
#include "mutex.h"
#include "periph/adc.h"
/*
* @brief ADC sequence used by this driver and oversampling settings
* @{
*/
#define SEQ (3)
#define OVERSAMPLE (64)
/** @} */
/**
* @brief pin configuration parameters
*/
struct adc_gpio_cfg_s {
unsigned long gpio_base;
unsigned long gpio_sysctl;
unsigned short gpio_pin;
};
/**
* @brief Fixed ADC pin configuration
*/
static const struct adc_gpio_cfg_s adc0_gpio[ADC_NUMOF] = {
{ 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_PORTD_BASE, SYSCTL_PERIPH_GPIOD, GPIO_PIN_3 }, /**< AIN4 */
{ GPIO_PORTD_BASE, SYSCTL_PERIPH_GPIOD, GPIO_PIN_2 }, /**< AIN5 */
{ GPIO_PORTD_BASE, SYSCTL_PERIPH_GPIOD, GPIO_PIN_1 }, /**< AIN6 */
{ GPIO_PORTD_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_PORTB_BASE, SYSCTL_PERIPH_GPIOB, GPIO_PIN_4 }, /**< AIN10 */
{ GPIO_PORTB_BASE, SYSCTL_PERIPH_GPIOB, GPIO_PIN_5 }, /**< AIN11 */
};
/**
* @brief Lock to prevent concurrent access to the ADC
*/
static mutex_t lock = MUTEX_INIT;
static inline void prep(void)
{
mutex_lock(&lock);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
}
static inline void done(void)
{
ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC0);
mutex_unlock(&lock);
}
int adc_init(adc_t line)
{
/* make sure the given ADC line is valid */
if (line >= ADC_NUMOF) {
return -1;
}
prep();
ROM_SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS);
ROM_ADCHardwareOversampleConfigure(ADC0_BASE, OVERSAMPLE);
ROM_SysCtlPeripheralEnable(adc0_gpio[line].gpio_sysctl);
ROM_GPIOPinTypeADC(adc0_gpio[line].gpio_base, adc0_gpio[line].gpio_pin);
done();
return 0;
}
int32_t adc_sample(adc_t line, adc_res_t res)
{
int value[2];
if ((res != ADC_RES_10BIT) && (res != ADC_RES_12BIT)) {
return -1;
}
prep();
/* set channel */
ROM_ADCSequenceConfigure(ADC0_BASE, SEQ, ADC_TRIGGER_PROCESSOR, 0);
ROM_ADCSequenceStepConfigure(ADC0_BASE, SEQ, 0, line | ADC_CTL_IE | ADC_CTL_END);
/* set resolution */
ROM_ADCResolutionSet(ADC0_BASE, (unsigned long)res);
/* start conversion and wait for results */
ROM_ADCSequenceEnable(ADC0_BASE, SEQ);
ROM_ADCIntClear(ADC0_BASE, SEQ);
ROM_ADCProcessorTrigger(ADC0_BASE, SEQ);
while (!ROM_ADCIntStatus(ADC0_BASE, SEQ, false)) {}
/* get results */
ROM_ADCSequenceDataGet(ADC0_BASE, SEQ, (unsigned long *) value);
/* disable device again */
ROM_ADCSequenceDisable(ADC0_BASE, SEQ);
done();
return value[0];
}