1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge pull request #7883 from Hyungsin/hamilton-pushbutton

pulse counter driver: initial SAUL-compatible implementation
This commit is contained in:
Gaëtan Harter 2018-01-30 19:35:44 +01:00 committed by GitHub
commit 934b075f76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 433 additions and 0 deletions

View File

@ -131,6 +131,11 @@ ifneq (,$(filter hdc1000,$(USEMODULE)))
FEATURES_REQUIRED += periph_i2c
endif
ifneq (,$(filter pulse_counter,$(USEMODULE)))
USEMODULE += xtimer
FEATURES_REQUIRED += periph_gpio
endif
ifneq (,$(filter hih6130,$(USEMODULE)))
USEMODULE += xtimer
endif

View File

@ -58,6 +58,9 @@ endif
ifneq (,$(filter my9221,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/my9221/include
endif
ifneq (,$(filter pulse_counter,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/pulse_counter/include
endif
ifneq (,$(filter ina220,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ina220/include
endif

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2017 UC Berkeley
*
* 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_pulse_counter extra sensor
* @ingroup drivers_sensors
*
* The connection between the MCU and the PULSE_COUNTER is based on the
* GPIO-interface.
*
* @{
*
* @file
* @brief Driver for the PULSE_COUNTER extra sensor
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*/
#ifndef PULSE_COUNTER_H
#define PULSE_COUNTER_H
#include <stdint.h>
#include "periph/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Parameters needed for device initialization
*/
typedef struct {
gpio_t gpio; /**< GPIO pin that sensor is connected to */
gpio_flank_t gpio_flank; /**< GPIO flank option */
} pulse_counter_params_t;
/**
* @brief Device descriptor for a PULSE_COUNTER device
*/
typedef struct {
int16_t pulse_count; /**< pulse counter */
} pulse_counter_t;
/**
* @brief Initialize an PULSE_COUNTER device
*
* @param[out] dev device descriptor
* @param[in] params configuration parameters
*
* @return 0 on success
* @return -1 on error
*/
int pulse_counter_init(pulse_counter_t *dev, const pulse_counter_params_t *params);
/**
* @brief Read and reset PULSE_COUNTER value
*
* @param[in] dev device descriptor of sensor
*
* @return Accumulated pulse counts
*/
int16_t pulse_counter_read_with_reset(const void *dev);
/**
* @brief Read PULSE_COUNTER value
*
* @param[in] dev device descriptor of sensor
*
* @return Accumulated pulse counts
*/
int16_t pulse_counter_read_without_reset(const void *dev);
/**
* @brief Reset PULSE_COUNTER value
*
* @param[in] dev device descriptor of sensor
*/
void pulse_counter_reset(const void *dev);
#ifdef __cplusplus
}
#endif
#endif /* PULSE_COUNTER_H */
/** @} */

View File

@ -92,6 +92,7 @@ enum {
SAUL_SENSE_ANALOG = 0x8a, /**< sensor: raw analog value */
SAUL_SENSE_UV = 0x8b, /**< sensor: UV index */
SAUL_SENSE_OBJTEMP = 0x8c, /**< sensor: object temperature */
SAUL_SENSE_COUNT = 0x8d, /**< sensor: pulse counter */
SAUL_CLASS_ANY = 0xff /**< any device - wildcard */
/* extend this list as needed... */
};

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2017 UC Berkeley
*
* 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_pulse_counter
*
* @{
* @file
* @brief Default configuration for PULSE_COUNTER devices
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*/
#ifndef PULSE_COUNTER_PARAMS_H
#define PULSE_COUNTER_PARAMS_H
#include "board.h"
#include "pulse_counter.h"
#include "saul_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef PULSE_COUNTER_GPIO
#define PULSE_COUNTER_GPIO GPIO_PIN(0,18)
#endif
#ifndef PULSE_COUNTER_GPIO_FLANK
#define PULSE_COUNTER_GPIO_FLANK GPIO_FALLING
#endif
#ifndef PULSE_COUNTER_PARAMS
#define PULSE_COUNTER_PARAMS { .gpio = PULSE_COUNTER_GPIO, \
.gpio_flank = PULSE_COUNTER_GPIO_FLANK }
#endif
#ifndef PULSE_COUNTER_SAUL_INFO
#define PULSE_COUNTER_SAUL_INFO { .name = "pulse counter" }
#endif
/**
* @brief PULSE_COUNTER configuration
*/
static const pulse_counter_params_t pulse_counter_params[] =
{
PULSE_COUNTER_PARAMS,
};
/**
* @brief Additional meta information to keep in the SAUL registry
*/
static const saul_reg_info_t pulse_counter_saul_info[] =
{
PULSE_COUNTER_SAUL_INFO
};
#ifdef __cplusplus
}
#endif
#endif /* PULSE_COUNTER_PARAMS_H */
/** @} */

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2017 UC Berkeley
*
* 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_pulse_counter
* @{
*
* @file
* @brief Driver for the PULSE COUNTER.
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*
* @}
*/
#include <string.h>
#include "pulse_counter_params.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/* Accumulate pulse count */
static void pulse_counter_trigger(void *arg)
{
pulse_counter_t *dev = (pulse_counter_t *)arg;
/* Use atomic operations to avoid messing with IRQ flags */
__atomic_fetch_add(&(dev->pulse_count), 1, __ATOMIC_SEQ_CST);
}
/* Initialize pulse counter */
int pulse_counter_init(pulse_counter_t *dev, const pulse_counter_params_t *params)
{
if (gpio_init_int(params->gpio, GPIO_IN_PU, params->gpio_flank, pulse_counter_trigger, dev)) {
return -1;
}
dev->pulse_count = 0;
return 0;
}
/* Return the accumulated pulse counts and reset the count to zero */
int16_t pulse_counter_read_with_reset(const void *dev)
{
int16_t pulse_count_output = 0;
int16_t reset_value = 0;
/* Use atomic operations to avoid messing with IRQ flags */
__atomic_exchange(&(((pulse_counter_t *)dev)->pulse_count), &reset_value, &pulse_count_output, __ATOMIC_SEQ_CST);
return pulse_count_output;
}
/* Return the accumulated pulse counts */
int16_t pulse_counter_read_without_reset(const void *dev)
{
return ((pulse_counter_t *)dev)->pulse_count;
}
/* Reset the pulse count value to zero */
void pulse_counter_reset(const void *dev)
{
((pulse_counter_t *)dev)->pulse_count = 0;
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2017 UC Berkeley
*
* 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_pulse_counter
* @{
*
* @file
* @brief PULSE_COUNTER adaption to the RIOT actuator/sensor interface
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*
* @}
*/
#include <string.h>
#include "saul.h"
#include "pulse_counter.h"
static int read_pulse_counter(const void *dev, phydat_t *res)
{
res->val[0] = pulse_counter_read_with_reset(dev);
res->unit = UNIT_NONE;
res->scale = 0;
return 1;
}
static int write_pulse_counter(const void *dev, phydat_t *data)
{
pulse_counter_reset(dev);
(void) data;
return 1;
}
const saul_driver_t pulse_counter_saul_driver = {
.read = read_pulse_counter,
.write = write_pulse_counter,
.type = SAUL_SENSE_COUNT,
};

View File

@ -48,6 +48,7 @@ const char *saul_class_to_str(const uint8_t class_id)
case SAUL_SENSE_PRESS: return "SENSE_PRESS";
case SAUL_SENSE_ANALOG: return "SENSE_ANALOG";
case SAUL_SENSE_OBJTEMP:return "SENSE_OBJTEMP";
case SAUL_SENSE_COUNT: return "SENSE_PULSE_COUNT";
case SAUL_CLASS_ANY: return "CLASS_ANY";
default: return "CLASS_UNKNOWN";
}

View File

@ -323,6 +323,10 @@ auto_init_mpu9150();
extern void auto_init_tsl2561(void);
auto_init_tsl2561();
#endif
#ifdef MODULE_PULSE_COUNTER
extern void auto_init_pulse_counter(void);
auto_init_pulse_counter();
#endif
#ifdef MODULE_HDC1000
extern void auto_init_hdc1000(void);
auto_init_hdc1000();

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2017 UC Berkeley
*
* 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 for PULSE_COUNTER devices
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*
* @}
*/
#ifdef MODULE_PULSE_COUNTER
#include "log.h"
#include "saul_reg.h"
#include "pulse_counter_params.h"
/**
* @brief Define the number of configured sensors
*/
#define PULSE_COUNTER_NUM (sizeof(pulse_counter_params) / sizeof(pulse_counter_params[0]))
/**
* @brief Allocate memory for the device descriptors
*/
static pulse_counter_t pulse_counter_devs[PULSE_COUNTER_NUM];
/**
* @brief Memory for the SAUL registry entries
*/
static saul_reg_t saul_entries[PULSE_COUNTER_NUM];
/**
* @brief Define the number of configured sensors
*/
#define PULSE_COUNTER_INFO_NUM (sizeof(pulse_counter_saul_info) / sizeof(pulse_counter_saul_info[0]))
/**
* @brief Reference the driver struct
*/
extern saul_driver_t pulse_counter_saul_driver;
void auto_init_pulse_counter(void)
{
assert(PULSE_COUNTER_NUM == PULSE_COUNTER_INFO_NUM)
for (unsigned i = 0; i < PULSE_COUNTER_NUM; i++) {
LOG_DEBUG("[auto_init_saul] initializing pulse_counter #%u\n", i);
int res = pulse_counter_init(&pulse_counter_devs[i], &pulse_counter_params[i]);
if (res != 0) {
LOG_ERROR("[auto_init_saul] error initializing pulse_counter #%u\n", i);
}
else {
saul_entries[i].dev = &(pulse_counter_devs[i]);
saul_entries[i].name = pulse_counter_saul_info[i].name;
saul_entries[i].driver = &pulse_counter_saul_driver;
saul_reg_add(&(saul_entries[i]));
}
}
}
#else
typedef int dont_be_pedantic;
#endif /* MODULE_PULSE_COUNTER */

View File

@ -0,0 +1,7 @@
include ../Makefile.tests_common
BOARD_BLACKLIST := msb-430 msb-430h telosb wsn430-v1_3b wsn430-v1_4 z1
USEMODULE += pulse_counter
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,12 @@
# About
This is a manual test application for the PULSE_COUNTER driver.
# Usage
This test application will initialize the PULSE_COUNTER sensor with the configuration
as specified in the default `pulse_counter_params.h` file.
If you want to use this test application with different parameters, you can
simply override the default PULSE_COUNTER_PARAMS.
After initialization, the sensor reads the pulse counter values every second and
prints them to STDOUT.

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2017 UC Berkeley
*
* 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 tests
* @{
*
* @file
* @brief Test application for the PULSE_COUNTER driver
*
* @author Hyung-Sin Kim <hs.kim@cs.berkeley.edu>
*
* @}
*/
#include <stdio.h>
#include "xtimer.h"
#include "pulse_counter_params.h"
#define SLEEP US_PER_SEC
int main(void)
{
pulse_counter_t dev;
printf("PULSE_COUNTER driver test application\n");
/* Initialization */
if (pulse_counter_init(&dev, &pulse_counter_params[0])) {
printf("[Failed]");
return 1;
}
else {
printf("[OK]\n");
}
while (1) {
/* Pulse counter reading */
int16_t count = pulse_counter_read_with_reset(&dev);
printf("pulse counter: %d\n", count);
xtimer_usleep(SLEEP);
}
return 0;
}