mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
134 lines
3.4 KiB
C
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];
|
|
}
|