diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 6963794764..2bc202a645 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -38,6 +38,7 @@ PSEUDOMODULES += newlib PSEUDOMODULES += newlib_nano PSEUDOMODULES += pktqueue PSEUDOMODULES += printf_float +PSEUDOMODULES += saul_adc PSEUDOMODULES += saul_default PSEUDOMODULES += saul_gpio PSEUDOMODULES += schedstatistics diff --git a/drivers/include/saul/periph.h b/drivers/include/saul/periph.h index 4f49cdf83d..00a148538f 100644 --- a/drivers/include/saul/periph.h +++ b/drivers/include/saul/periph.h @@ -19,12 +19,19 @@ #ifndef SAUL_PERIPH_H #define SAUL_PERIPH_H +#ifdef MODULE_SAUL_GPIO #include "periph/gpio.h" +#endif /* MODULE_SAUL_GPIO */ + +#ifdef MODULE_SAUL_ADC +#include "periph/adc.h" +#endif /* MODULE_SAUL_ADC */ #ifdef __cplusplus extern "C" { #endif +#ifdef MODULE_SAUL_GPIO /** * @brief Direct mapped GPIO configuration values */ @@ -33,6 +40,18 @@ typedef struct { gpio_t pin; /**< GPIO pin to initialize and expose */ gpio_mode_t mode; /**< pin mode to use */ } saul_gpio_params_t; +#endif /* MODULE_SAUL_GPIO */ + +#ifdef MODULE_SAUL_ADC +/** + * @brief Direct mapped ADC configuration values + */ +typedef struct { + const char *name; /**< name of the device connected to this pin */ + adc_t line; /**< ADC line to initialize and expose */ + adc_res_t res; /**< ADC resolution */ +} saul_adc_params_t; +#endif /* MODULE_SAUL_ADC */ #ifdef __cplusplus } diff --git a/drivers/saul/Makefile b/drivers/saul/Makefile index cc5ba7234e..39dc655787 100644 --- a/drivers/saul/Makefile +++ b/drivers/saul/Makefile @@ -3,5 +3,8 @@ SRC = saul.c saul_str.c ifneq (,$(filter saul_gpio,$(USEMODULE))) SRC += gpio_saul.c endif +ifneq (,$(filter saul_adc,$(USEMODULE))) + SRC += adc_saul.c +endif include $(RIOTBASE)/Makefile.base diff --git a/drivers/saul/adc_saul.c b/drivers/saul/adc_saul.c new file mode 100644 index 0000000000..a7c81f2799 --- /dev/null +++ b/drivers/saul/adc_saul.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Eistec AB + * + * 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 drivers_saul + * @{ + * + * @file + * @brief SAUL wrapper for direct access to analog pins + * + * @author Joakim Nohlgård + * + * @} + */ + +#include + +#include "saul.h" +#include "saul/periph.h" +#include "phydat.h" +#include "periph/adc.h" + + +static int read_adc(void *dev, phydat_t *res) +{ + const saul_adc_params_t *params = *((const saul_adc_params_t **)dev); + res->val[0] = adc_sample(params->line, params->res); + memset(&(res->val[1]), 0, 2 * sizeof(res->val[1])); + /* Raw ADC reading has no unit */ + res->unit = UNIT_NONE; + res->scale = 0; + return 1; +} + +const saul_driver_t adc_saul_driver = { + .read = read_adc, + .write = saul_notsup, + .type = SAUL_SENSE_ANALOG, +}; diff --git a/drivers/saul/saul_str.c b/drivers/saul/saul_str.c index fb9b5d9ce7..3e688563d8 100644 --- a/drivers/saul/saul_str.c +++ b/drivers/saul/saul_str.c @@ -46,6 +46,7 @@ const char *saul_class_to_str(uint8_t class_id) case SAUL_SENSE_GYRO: return "SENSE_GYRO"; case SAUL_SENSE_COLOR: return "SENSE_COLOR"; case SAUL_SENSE_PRESS: return "SENSE_PRESS"; + case SAUL_SENSE_ANALOG: return "SENSE_ANALOG"; case SAUL_CLASS_ANY: return "CLASS_ANY"; default: return "CLASS_UNKNOWN"; } diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 4488675a0f..9981271385 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -221,6 +221,10 @@ void auto_init(void) extern void auto_init_gpio(void); auto_init_gpio(); #endif +#ifdef MODULE_SAUL_ADC + extern void auto_init_adc(void); + auto_init_adc(); +#endif #ifdef MODULE_LSM303DLHC extern void auto_init_lsm303dlhc(void); auto_init_lsm303dlhc(); diff --git a/sys/auto_init/saul/auto_init_adc.c b/sys/auto_init/saul/auto_init_adc.c new file mode 100644 index 0000000000..16b020d434 --- /dev/null +++ b/sys/auto_init/saul/auto_init_adc.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016 Eistec AB + * + * 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 auto_init_saul + * @{ + * + * @file + * @brief Auto initialization of ADC lines directly mapped to SAUL reg + * + * @author Joakim Nohlgård + * + * @} + */ + +#ifdef MODULE_SAUL_ADC + +#include "saul_reg.h" +#include "saul/periph.h" +#include "adc_params.h" +#include "periph/gpio.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief Define the number of configured sensors + */ +#define SAUL_ADC_NUMOF (sizeof(saul_adc_params)/sizeof(saul_adc_params[0])) + +/** + * @brief Allocate memory for pointers to the ADC parameter structs + * + * We use this extra level of indirection to be able to keep the saul_adc_params + * array const and residing in ROM. + */ +static const saul_adc_params_t *saul_adcs[SAUL_ADC_NUMOF]; + +/** + * @brief Memory for the registry entries + */ +static saul_reg_t saul_reg_entries[SAUL_ADC_NUMOF]; + +/** + * @brief Reference the driver struct + */ +extern saul_driver_t adc_saul_driver; + +void auto_init_adc(void) +{ + DEBUG("auto init SAUL ADC\n"); + for (int i = 0; i < SAUL_ADC_NUMOF; i++) { + const saul_adc_params_t *p = &saul_adc_params[i]; + saul_adcs[i] = p; + + DEBUG("[auto_init_saul] initializing direct ADC\n"); + saul_reg_entries[i].dev = &saul_adcs[i]; + saul_reg_entries[i].name = p->name; + saul_reg_entries[i].driver = &adc_saul_driver; + /* initialize the ADC line */ + adc_init(p->line); + /* add to registry */ + saul_reg_add(&(saul_reg_entries[i])); + } +} + +#else +typedef int dont_be_pedantic; +#endif /* MODULE_SAUL_ADC */