mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
drivers: add adc driver for nrf52
This commit is contained in:
parent
4ee7d1359c
commit
6f9a5004c6
@ -54,6 +54,21 @@ typedef enum {
|
|||||||
} i2c_speed_t;
|
} i2c_speed_t;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Override ADC resolution values
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define HAVE_ADC_RES_T
|
||||||
|
typedef enum {
|
||||||
|
ADC_RES_6BIT = 0xf0, /**< ADC resolution: 6 bit */
|
||||||
|
ADC_RES_8BIT = 0x00, /**< ADC resolution: 8 bit */
|
||||||
|
ADC_RES_10BIT = 0x02, /**< ADC resolution: 10 bit */
|
||||||
|
ADC_RES_12BIT = 0xf1, /**< ADC resolution: 12 bit */
|
||||||
|
ADC_RES_14BIT = 0xf2, /**< ADC resolution: 14 bit */
|
||||||
|
ADC_RES_16BIT = 0xf3 /**< ADC resolution: 16 bit */
|
||||||
|
} adc_res_t;
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief I2C (TWI) configuration options
|
* @brief I2C (TWI) configuration options
|
||||||
*/
|
*/
|
||||||
|
@ -40,6 +40,30 @@ extern "C" {
|
|||||||
#define SPI_MISOSEL (dev(bus)->PSEL.MISO)
|
#define SPI_MISOSEL (dev(bus)->PSEL.MISO)
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Override ADC resolution values
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define HAVE_ADC_RES_T
|
||||||
|
typedef enum {
|
||||||
|
ADC_RES_6BIT = 0xf0, /**< not supported by hardware */
|
||||||
|
ADC_RES_8BIT = 0x00, /**< ADC resolution: 8 bit */
|
||||||
|
ADC_RES_10BIT = 0x01, /**< ADC resolution: 10 bit */
|
||||||
|
ADC_RES_12BIT = 0x02, /**< ADC resolution: 12 bit */
|
||||||
|
ADC_RES_14BIT = 0xf1, /**< supported with oversampling */
|
||||||
|
ADC_RES_16BIT = 0xf2 /**< not supported by hardware */
|
||||||
|
} adc_res_t;
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name ADC configuration, valid for all boards using this CPU
|
||||||
|
*
|
||||||
|
* The NRF52832 has a fixed mapping of ADC pins and a fixed number of ADC channels,
|
||||||
|
* so this ADC configuration is valid for all boards using this CPU. No need for
|
||||||
|
* any board specific configuration.
|
||||||
|
*/
|
||||||
|
#define ADC_NUMOF (8U)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
156
cpu/nrf52/periph/adc.c
Normal file
156
cpu/nrf52/periph/adc.c
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 HAW Hamburg
|
||||||
|
*
|
||||||
|
* 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_nrf52
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* Any one of the available channels can be enabled for the ADC to operate in
|
||||||
|
* one-shot mode. If more than one CH[n] is configured, the ADC enters scan mode.
|
||||||
|
*
|
||||||
|
* Example of RAM placement (RESULT.MAXCNT = 8), all channels enabled:
|
||||||
|
*
|
||||||
|
* 31 16 15 0
|
||||||
|
* RESULT.PTR = adc_val[0] | CH[1] | CH[0] |
|
||||||
|
* RESULT.PTR + 4 | CH[3] | CH[2] |
|
||||||
|
* RESULT.PTR + 8 | CH[5] | CH[4] |
|
||||||
|
* RESULT.PTR + 12 | CH[7] | CH[6] |
|
||||||
|
*
|
||||||
|
* Example of RAM placement (RESULT.MAXCNT = 4), channels 0, 3, 4 and 7 enabled:
|
||||||
|
*
|
||||||
|
* 31 16 15 0
|
||||||
|
* RESULT.PTR = adc_val[0] | CH[3] | CH[0] |
|
||||||
|
* RESULT.PTR + 4 | CH[7] | CH[4] |
|
||||||
|
* RESULT.PTR + 8 | | |
|
||||||
|
* RESULT.PTR + 12 | | |
|
||||||
|
*
|
||||||
|
* Scan mode and oversampling cannot be combined.
|
||||||
|
* -> 8/10/12-bit resolution, 14-bit resolution only with oversampling
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Low-level ADC driver implementation
|
||||||
|
*
|
||||||
|
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "periph/adc.h"
|
||||||
|
#include "periph_conf.h"
|
||||||
|
|
||||||
|
#ifdef ADC_NUMOF
|
||||||
|
|
||||||
|
static int16_t adc_val[ADC_NUMOF];
|
||||||
|
static uint8_t adc_ch_enabled = 0;
|
||||||
|
static uint8_t adc_return_idx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Lock to prevent concurrency issues when used from different threads
|
||||||
|
*/
|
||||||
|
static mutex_t lock;
|
||||||
|
|
||||||
|
static inline void prep(void)
|
||||||
|
{
|
||||||
|
mutex_lock(&lock);
|
||||||
|
NRF_SAADC->ENABLE = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void done(void)
|
||||||
|
{
|
||||||
|
NRF_SAADC->ENABLE = 0;
|
||||||
|
mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int adc_init(adc_t line)
|
||||||
|
{
|
||||||
|
if (line >= ADC_NUMOF) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((adc_ch_enabled & (1 << line)) == 0) {
|
||||||
|
/* prepare device */
|
||||||
|
prep();
|
||||||
|
|
||||||
|
/* set the number of enabled channels and the data pointer */
|
||||||
|
NRF_SAADC->RESULT.MAXCNT += 1;
|
||||||
|
NRF_SAADC->RESULT.PTR = (uint32_t)&adc_val;
|
||||||
|
|
||||||
|
/* set ADC channel and use VDD (+5V) as reference */
|
||||||
|
NRF_SAADC->CH[line].PSELP = line + 1;
|
||||||
|
NRF_SAADC->CH[line].CONFIG = (SAADC_CH_CONFIG_GAIN_Gain1_4 << SAADC_CH_CONFIG_RESN_Pos) |
|
||||||
|
(SAADC_CH_CONFIG_REFSEL_VDD1_4 << SAADC_CH_CONFIG_REFSEL_Pos);
|
||||||
|
|
||||||
|
/* calibrate the SAADC */
|
||||||
|
NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
|
||||||
|
NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
|
||||||
|
while (NRF_SAADC->EVENTS_CALIBRATEDONE == 0) {}
|
||||||
|
|
||||||
|
/* remember which ADC channel is enabled */
|
||||||
|
adc_ch_enabled |= (1 << line);
|
||||||
|
|
||||||
|
/* free device */
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adc_sample(adc_t line, adc_res_t res)
|
||||||
|
{
|
||||||
|
assert(line < ADC_NUMOF);
|
||||||
|
|
||||||
|
/* check if resolution is valid */
|
||||||
|
if (res > 2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare device */
|
||||||
|
prep();
|
||||||
|
|
||||||
|
/* set resolution */
|
||||||
|
NRF_SAADC->RESOLUTION = res;
|
||||||
|
|
||||||
|
/* start the SAADC and wait for the started event */
|
||||||
|
NRF_SAADC->EVENTS_STARTED = 0;
|
||||||
|
NRF_SAADC->TASKS_START = 1;
|
||||||
|
while (NRF_SAADC->EVENTS_STARTED == 0) {}
|
||||||
|
|
||||||
|
/* start conversions and wait for conversions to be complete */
|
||||||
|
for (uint8_t i = 0; i < NRF_SAADC->RESULT.MAXCNT; i++) {
|
||||||
|
while (NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos)) {}
|
||||||
|
NRF_SAADC->EVENTS_DONE = 0;
|
||||||
|
NRF_SAADC->TASKS_SAMPLE = 1;
|
||||||
|
while (NRF_SAADC->EVENTS_DONE == 0) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stop the SAADC */
|
||||||
|
NRF_SAADC->EVENTS_STOPPED = 0;
|
||||||
|
NRF_SAADC->TASKS_STOP = 1;
|
||||||
|
while (NRF_SAADC->EVENTS_STOPPED == 0) {}
|
||||||
|
|
||||||
|
/* free device */
|
||||||
|
done();
|
||||||
|
|
||||||
|
/* return the ADC value for the given line */
|
||||||
|
adc_return_idx = 0;
|
||||||
|
for (uint8_t i = 0; i < line; i++) {
|
||||||
|
if (adc_ch_enabled & (1 << i)) {
|
||||||
|
adc_return_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (adc_val[adc_return_idx] < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return adc_val[adc_return_idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef int dont_be_pedantic;
|
||||||
|
#endif /* ADC_CONFIG */
|
@ -109,21 +109,6 @@ typedef enum {
|
|||||||
GPIO_BOTH = 3 /**< emit interrupt on both flanks */
|
GPIO_BOTH = 3 /**< emit interrupt on both flanks */
|
||||||
} gpio_flank_t;
|
} gpio_flank_t;
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Override ADC resolution values
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
#define HAVE_ADC_RES_T
|
|
||||||
typedef enum {
|
|
||||||
ADC_RES_6BIT = 0xf0, /**< ADC resolution: 6 bit */
|
|
||||||
ADC_RES_8BIT = 0x00, /**< ADC resolution: 8 bit */
|
|
||||||
ADC_RES_10BIT = 0x02, /**< ADC resolution: 10 bit */
|
|
||||||
ADC_RES_12BIT = 0xf1, /**< ADC resolution: 12 bit */
|
|
||||||
ADC_RES_14BIT = 0xf2, /**< ADC resolution: 14 bit */
|
|
||||||
ADC_RES_16BIT = 0xf3 /**< ADC resolution: 16 bit */
|
|
||||||
} adc_res_t;
|
|
||||||
/** @} */
|
|
||||||
#endif /* ndef DOXYGEN */
|
#endif /* ndef DOXYGEN */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user