diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 7567b1a78300ceab6231aa6cef4356ed5bfbab7c..ee9c6d12d849edb92883b187c9fcb5670b219d29 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -19,6 +19,8 @@ PSEUDOMODULES += newlib PSEUDOMODULES += pktqueue PSEUDOMODULES += schedstatistics PSEUDOMODULES += netif +PSEUDOMODULES += saul_default +PSEUDOMODULES += saul_gpio # include variants of the AT86RF2xx drivers as pseudo modules PSEUDOMODULES += at86rf23% diff --git a/drivers/include/saul.h b/drivers/include/saul.h new file mode 100644 index 0000000000000000000000000000000000000000..f6a9dcc47a7f75b156fe90356406ae6fa40371d5 --- /dev/null +++ b/drivers/include/saul.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015 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. + */ + +/** + * @defgroup drivers_saul [S]ensor [A]ctuator [U]ber [L]ayer + * @ingroup drivers + * @brief Generic sensor/actuator abstraction layer for RIOT + * + * SAUL is a generic actuator/sensor interface in RIOT. Its purpose is to + * enable unified interaction with a wide range of sensors and actuators through + * a set of defined access functions and a common data structure. + * + * Each device driver implementing this interface has to expose a set of + * predefined functions and it has to register itself to the central SAUL + * registry. From here devices can be found, listed, and accessed. + * + * Each device has further to expose a name and its type. This information can + * be used for automated searching and matching of devices (e.g. connect light + * sensor automatically with the color of an RGB LED...). + * + * The SAUL module enables further the automated initialization of preconfigured + * actuators/sensor via auto_init and the access to all available devices via + * one unified shell command. + * + * @todo So far, the interface only supports simple read and set + * operations. It probably needs to be extended to handling events, + * thresholds, and so on. + * + * @{ + * + * @file + * @brief Definition of the generic [S]ensor [A]ctuator [U]ber [L]ayer + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + */ + +#ifndef SAUL_H +#define SAUL_H + +#include <stdint.h> + +#include "phydat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Definition of device classes + * + * This list contains a collections of available device classes. Each device + * must be part of one, but can be part of multiple of these classes. When + * belonging to more than one class, a device must however expose one driver + * for each class it belongs to, and it has to register each driver with a + * separate entry at the SAUL registry. + * + * Classes are identified by 8-bit unsigned integers. + * + * For searching and filtering purposes, the device classes are further split + * into two top-level classes: sensors and actuators. For identification, all + * actuator classes start with 0b01xxxxxx, all sensor classes start with + * 0b10xxxxxx. + * + * This list is not exhaustive, extend to your needs! + */ +enum { + SAUL_CLASS_UNDEF = 0x00, /**< device class undefined */ + SAUL_ACT_ANY = 0x40, /**< any actuator - wildcard */ + SAUL_ACT_LED_RGB = 0x42, /**< actuator: RGB LED */ + SAUL_ACT_SERVO = 0x43, /**< actuator: servo motor */ + SAUL_ACT_MOTOR = 0x44, /**< actuator: motor */ + SAUL_ACT_SWITCH = 0x45, /**< actuator: simple on/off switch */ + SAUL_ACT_DIMMER = 0x46, /**< actuator: dimmable switch */ + SAUL_SENSE_ANY = 0x80, /**< any sensor - wildcart */ + SAUL_SENSE_BTN = 0x81, /**< sensor: simple button */ + SAUL_SENSE_TEMP = 0x82, /**< sensor: temperature */ + SAUL_SENSE_HUM = 0x83, /**< sensor: humidity */ + SAUL_SENSE_LIGHT = 0x84, /**< sensor: light */ + SAUL_SENSE_ACCEL = 0x85, /**< sensor: accelerometer */ + SAUL_SENSE_MAG = 0x86, /**< sensor: magnetometer */ + SAUL_SENSE_GYRO = 0x87, /**< sensor: gyroscope */ + SAUL_SENSE_COLOR = 0x88, /**< sensor: (light) color */ + SAUL_SENSE_PRESS = 0x89, /**< sensor: pressure */ + SAUL_SENSE_ANALOG = 0x8a, /**< sensor: raw analog value */ + SAUL_CLASS_ANY = 0xff /**< any device - wildcard */ + /* extend this list as needed... */ +}; + +/** + * @brief Read a value (a set of values) from a device + * + * Simple sensors, as e.g. a temperature sensor, will return exactly one value + * together with the values scale and unit. Some sensors might return a touple + * or triple of data (e.g. a 3-axis accelerometer). + * + * Actuators can chose to either just return -ENOTSUP or to return their current + * set value (e.g. useful for reading back the current state of a switch) + * + * @param[in] dev device descriptor of the target device + * @param[out] res data read from the device + * + * @return number of values written into to result data structure [1-3] + * @return -ENOTSUP if the device does not support this operation + * @return -ECANCELED on other errors + */ +typedef int(*saul_read_t)(void *dev, phydat_t *res); + +/** + * @brief Write a value (a set of values) to a device + * + * Most sensors will probably just return -ENOTSUP, as writing values to a + * sensor is often without purpose. The interface can however be used to + * configure sensors, e.g. to switch a sensor's unit type by writing the + * newly selected type to it. + * + * For actuators this function is used to influence the actuators state, e.g. + * switching a switch or setting the speed of a motor. + * + * @param[in] dev device descriptor of the target device + * @param[in] data data to write to the device + * + * @return number of values actually processed by the device [1-3] + * @return -ENOTSUP if the device does not support this operation + * @return -ECANCELED on other errors + */ +typedef int(*saul_write_t)(void *dev, phydat_t *data); + +/** + * @brief Definition of the RIOT actuator/sensor interface + */ +typedef struct { + saul_read_t read; /**< read function pointer */ + saul_write_t write; /**< write function pointer */ + uint8_t type; /**< device class the device belongs to */ +} saul_driver_t; + +/** + * @brief Helper function converts a class ID to a string + * + * @param[in] class_id device class ID + * + * @return string representation of the device class + * @return NULL if class ID is not known + */ +const char *saul_class_to_str(uint8_t class_id); + +#ifdef __cplusplus +} +#endif + +#endif /* SAUL_H */ +/** @} */ diff --git a/drivers/include/saul/periph.h b/drivers/include/saul/periph.h new file mode 100644 index 0000000000000000000000000000000000000000..963c3fdfa83ab1fd10e55824f8c4e50c2813c2cb --- /dev/null +++ b/drivers/include/saul/periph.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 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. + */ + +/** + * @ingroup drivers_saul + * @{ + * + * @file + * @brief Parameter definitions for mapping peripherals directly to SAUL + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + */ + +#ifndef SAUL_PERIPH_H +#define SAUL_PERIPH_H + +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Direct mapped GPIO configuration values + */ +typedef struct { + const char *name; /**< name of the device connected to this pin */ + gpio_t pin; /**< GPIO pin to initialize and expose */ + gpio_dir_t dir; /**< use GPIO as input or output */ +} saul_gpio_params_t; + +#ifdef __cplusplus +} +#endif + +#endif /* SAUL_PERIPH_H */ +/** @} */ diff --git a/drivers/saul/Makefile b/drivers/saul/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3247d1d8ac934e641bd50572232dc3cf4b789270 --- /dev/null +++ b/drivers/saul/Makefile @@ -0,0 +1,7 @@ +SRC = saul_str.c + +ifneq (,$(filter saul_gpio,$(USEMODULE))) + SRC += gpio_saul.c +endif + +include $(RIOTBASE)/Makefile.base diff --git a/drivers/saul/gpio_saul.c b/drivers/saul/gpio_saul.c new file mode 100644 index 0000000000000000000000000000000000000000..62217e7290eb7a0a54a7226bbf84cd6cc171be47 --- /dev/null +++ b/drivers/saul/gpio_saul.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 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. + */ + +/* + * @ingroup drivers_saul + * @{ + * + * @file + * @brief SAUL wrapper for direct access to GPIO pins + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * + * @} + */ + +#include <string.h> + +#include "saul.h" +#include "phydat.h" +#include "periph/gpio.h" + + +static int read(void *dev, phydat_t *res) +{ + gpio_t pin = *((gpio_t *)dev); + res->val[0] = (gpio_read(pin)) ? 1 : 0; + memset(&(res->val[1]), 0, 2 * sizeof(int16_t)); + res->unit = UNIT_BOOL; + res->scale = 0; + return 1; +} + +static int write(void *dev, phydat_t *state) +{ + gpio_t pin = *((gpio_t *)dev); + gpio_write(pin, state->val[0]); + return 1; +} + +const saul_driver_t gpio_saul_driver = { + .read = read, + .write = write, + .type = SAUL_ACT_SWITCH, +}; diff --git a/drivers/saul/saul_str.c b/drivers/saul/saul_str.c new file mode 100644 index 0000000000000000000000000000000000000000..fb9b5d9ce7d5144773de33ef409a435ccc913613 --- /dev/null +++ b/drivers/saul/saul_str.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 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. + */ + +/** + * @ingroup drivers_saul + * @{ + * + * @file + * @brief SAUL string functions + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * + * @} + */ + +#include <stdint.h> + +#include "saul.h" + +/* + * This is surely not the most beautiful implementation of a stringification + * function, but works... + */ +const char *saul_class_to_str(uint8_t class_id) +{ + switch (class_id) { + case SAUL_CLASS_UNDEF: return "CLASS_UNDEF"; + case SAUL_ACT_ANY: return "ACT_ANY"; + case SAUL_ACT_LED_RGB: return "ACT_LED_RGB"; + case SAUL_ACT_SERVO: return "ACT_SERVO"; + case SAUL_ACT_MOTOR: return "ACT_MOTOR"; + case SAUL_ACT_SWITCH: return "ACT_SWITCH"; + case SAUL_ACT_DIMMER: return "ACT_DIMMER"; + case SAUL_SENSE_ANY: return "SENSE_ANY"; + case SAUL_SENSE_BTN: return "SENSE_BTN"; + case SAUL_SENSE_TEMP: return "SENSE_TEMP"; + case SAUL_SENSE_HUM: return "SENSE_HUM"; + case SAUL_SENSE_LIGHT: return "SENSE_LIGHT"; + case SAUL_SENSE_ACCEL: return "SENSE_ACCEL"; + case SAUL_SENSE_MAG: return "SENSE_MAG"; + case SAUL_SENSE_GYRO: return "SENSE_GYRO"; + case SAUL_SENSE_COLOR: return "SENSE_COLOR"; + case SAUL_SENSE_PRESS: return "SENSE_PRESS"; + case SAUL_CLASS_ANY: return "CLASS_ANY"; + default: return "CLASS_UNKNOWN"; + } +}