--- /dev/null
+#
+# For a description of the syntax of this configuration file,
+# see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt
+#
+
+config EXAMPLES_SENSOR_TEST
+ bool "\"Sensor Test\" example"
+ default n
+ depends on SENSOR
+ ---help---
+ Enable the \"Sensor Test\" example
+
+
+if EXAMPLES_SENSOR_TEST
+config EXAMPLES_SENSOR_TEST_PPD42NS
+ bool "PPD42NS Dust Sensor Example"
+ default n
+ ---help---
+ Enable PPD42NS Dust Sensor Example Application
+
+config EXAMPLES_SENSOR_TEST_PPD42NS_MQTT_TRANSMISSION
+ bool "Support MQTT transmission for sending sensor data"
+ default n
+ depends on EXAMPLES_SENSOR_TEST_PPD42NS
+ depends on EXAMPLES_MQTT_TEST
+ ---help---
+ Enable to dust send sensor data using MQTT transmission
+
+endif # EXAMPLES_SENSOR_TEST
+
+config USER_ENTRYPOINT
+ string
+ default "ppd42ns_test_main" if ENTRY_SENSOR_TEST
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/**
+ * @file ppd42ns_test.c
+ * @brief the program for testing ppd42ns dust sensor
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <tinyara/sensors/ppd42ns.h>
+
+#define DUST_SENSOR_DEVNAME "/dev/dust0"
+
+#if defined(CONFIG_EXAMPLES_SENSOR_TEST_PPD42NS_MQTT_TRANSMISSION)
+/**************
+ * Definitions
+ **************/
+#define MQTT_BROKER_IP_ADDRESS "192.168.1.14"
+#define MQTT_BROKER_PORT "1883"
+#define MQTT_TOPIC "/test/sensor"
+
+/**************
+ * Structure
+ **************/
+struct mqtt_pub_input {
+ int argc;
+ char **argv;
+};
+
+/**************
+ * Private Data
+ **************/
+char g_argv_buf[30][100];
+char *g_argv_cur[30];
+
+/******************
+ * function prototype
+ ******************/
+int mqtt_client_pub_task(void *arg);
+
+/******************
+ * static function
+ ******************/
+static void create_arg(struct mqtt_pub_input *arg, char **argv_cur, char(*argv)[100], char *cmd)
+{
+ int i, len, idx1, idx2;
+
+ len = (int)strlen(cmd);
+ idx1 = idx2 = 0;
+ for (i = 0; i < len; i++) {
+ if (cmd[i] == ' ') {
+ argv[idx1][idx2] = '\0';
+ idx1++;
+ idx2 = 0;
+ i++;
+ }
+ argv[idx1][idx2++] = cmd[i];
+ }
+ argv[idx1][idx2] = '\0';
+
+ arg->argc = idx1 + 1;
+ for (i = 0; i < arg->argc; i++) {
+ argv_cur[i] = argv[i];
+ }
+ arg->argv = argv_cur;
+}
+
+static int send_sensor_data(char *data)
+{
+ struct mqtt_pub_input arg;
+ char mqtt_str[128];
+
+ snprintf(mqtt_str, 128, "mqtt_pub -h %s -t %s -p %s -m %s", MQTT_BROKER_IP_ADDRESS, MQTT_TOPIC, MQTT_BROKER_PORT, data);
+
+ create_arg(&arg, g_argv_cur, g_argv_buf, mqtt_str);
+ mqtt_client_pub_task(&arg);
+
+ return 0;
+}
+#endif /* CONFIG_EXAMPLES_SENSOR_TEST_PPD42NS_MQTT_TRANSMISSION */
+
+/****************************************************************************
+ * main
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_KERNEL
+int main(int argc, FAR char *argv[])
+#else
+int ppd42ns_test_main(int argc, char *argv[])
+#endif
+{
+ int result = -1;
+ int fd = -1;
+ float sensor_data;
+ char msg[64];
+ int sampling_interval_ms;
+ int test_cnt;
+ int loop_cnt;
+
+ if (argc != 3) {
+ printf("USAGE: sensor_ppd42ns [sampling_interval_in_ms] [loop_count] \n");
+ goto done;
+ }
+
+ sampling_interval_ms = atoi(argv[1]);
+ test_cnt = atoi(argv[2]);
+ loop_cnt = test_cnt;
+
+ /* open ppd42ns sensor driver */
+ fd = open(DUST_SENSOR_DEVNAME, O_RDONLY);
+ if (fd < 0) {
+ printf("ERROR: open() failed. devname=%s\n", DUST_SENSOR_DEVNAME);
+ goto done;
+ }
+
+ printf(">>> Start ppd42ns dust sensor test\n");
+ printf(" - interval: %d ms\n", sampling_interval_ms);
+ printf(" - loop_count: %d\n", loop_cnt);
+ printf(" - mqtt transmission: ");
+#if defined(CONFIG_EXAMPLES_SENSOR_TEST_PPD42NS_MQTT_TRANSMISSION)
+ printf("ON\n");
+#else
+ printf("OFF\n");
+#endif
+
+ while (loop_cnt) {
+ usleep(sampling_interval_ms * 1000);
+ if (read(fd, (void *)&sensor_data, sizeof(float)) == sizeof(float)) {
+ /* make sensor data message with json style */
+ snprintf(msg, sizeof(msg), "{\"dust\":%.2f}", sensor_data);
+ printf("[%d] %s \n", (test_cnt - loop_cnt + 1), msg);
+
+#if defined(CONFIG_EXAMPLES_SENSOR_TEST_PPD42NS_MQTT_TRANSMISSION)
+ send_sensor_data(msg);
+#endif
+ } else {
+ printf("ERROR: read() failed. devname=%s, remaining loop_cnt=%d\n", DUST_SENSOR_DEVNAME, loop_cnt - 1);
+ }
+
+ loop_cnt--;
+ }
+ printf("<<< End ppd42ns dust sensor test\n");
+
+ /* close ppd42ns sensor driver */
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+
+ result = 0;
+
+done:
+ return result;
+}
#include <arch/board/artik053_alc5658_i2c.h>
#include "up_arch.h"
#include "s5j_gpio.h"
+#include "s5j_ppd42ns.h"
/*****************************************************************************
* Private Functions
* Name: board_i2c_initialize
*
* Description:
- * Expose board dependent I2Cs
+ * Expose board dependent I2Cs
****************************************************************************/
static void board_i2c_initialize(void)
{
#endif
}
+/****************************************************************************
+ * Name: board_sensor_initialize
+ *
+ * Description:
+ * Expose board dependent Sensors
+ ****************************************************************************/
+static void board_sensor_initialize(void)
+{
+#if defined(CONFIG_SENSOR_PPD42NS) && defined(CONFIG_S5J_SENSOR_PPD42NS)
+ s5j_ppd42ns_initialize();
+#endif
+}
+
/*****************************************************************************
* Public Functions
****************************************************************************/
board_gpio_initialize();
board_i2c_initialize();
-
#if defined(CONFIG_AUDIO_ALC5658)
s5j_alc5658_initialize(0);
#elif defined(CONFIG_AUDIO_ALC5658CHAR)
alc5658_i2c_initialize();
i2schar_devinit();
#endif
+ board_sensor_initialize();
}
#endif /* CONFIG_BOARD_INITIALIZE */
endmenu
+config S5J_SENSOR_PPD42NS
+ bool "PPD42NS Dust Sensor"
+ default n
+
endmenu
# built-in static library
EXTRA_LIBS += chip/sss/libispdriver.a
endif
+
+ifeq ($(CONFIG_S5J_SENSOR_PPD42NS),y)
+CHIP_CSRCS += s5j_ppd42ns.c
+endif
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * arch/arm/src/s5j/s5j_ppd42ns.c
+ *
+ * Copyright (C) 2009-2010, 2014-2015 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <tinyara/config.h>
+#include <tinyara/irq.h>
+#include <tinyara/sensors/ppd42ns.h>
+#include <debug.h>
+#include <errno.h>
+#include "s5j_gpio.h"
+
+#ifdef CONFIG_SENSOR_PPD42NS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+#define DEVNAME_FORMAT "/dev/dust%d"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct s5j_gpio_info_s {
+ uint8_t pinnum;
+ uint16_t pincfg;
+};
+
+struct s5j_ppd42ns_priv_s {
+ uint32_t irqvector;
+ uint32_t pincfg;
+ int event_on_rising;
+ int event_on_falling;
+};
+
+struct s5j_ppd42ns_dev_s {
+ /* Configuration structure as seen by the ppd42ns driver */
+ struct ppd42ns_config_s config;
+
+ /* Additional private definitions only known to this driver */
+ ppd42ns_handler_t handler;
+ FAR void *arg;
+};
+
+/****************************************************************************
+ * Private Functions Prototype
+ ****************************************************************************/
+static int s5j_ppd42ns_gpio_read(struct ppd42ns_config_s *config);
+static int s5j_ppd42ns_irq_attach(struct ppd42ns_config_s *config, ppd42ns_handler_t handler, FAR char *arg);
+static int s5j_ppd42ns_irq_enable(struct ppd42ns_config_s *config, int enable);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+static struct s5j_ppd42ns_dev_s g_s5j_dev = {
+ .config = {
+ .gpionum = CONFIG_SENSOR_PPD42NS_GPIO_NUM,
+ .read_gpio = s5j_ppd42ns_gpio_read,
+ .attach = s5j_ppd42ns_irq_attach,
+ .enable = s5j_ppd42ns_irq_enable,
+ .priv = NULL,
+ },
+
+ .handler = NULL
+};
+
+static struct s5j_gpio_info_s g_gpio_info[] = {
+ {57, GPIO_INPUT | GPIO_PULLDOWN | GPIO_PORTA0 | GPIO_PIN0}, /* XEINT0 */
+ {58, GPIO_INPUT | GPIO_PULLDOWN | GPIO_PORTA0 | GPIO_PIN1}, /* XEINT1 */
+ {59, GPIO_INPUT | GPIO_PULLDOWN | GPIO_PORTA0 | GPIO_PIN2}, /* XEINT2 */
+};
+
+static struct s5j_ppd42ns_priv_s g_s5j_priv;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+static int s5j_ppd42ns_gpio_read(struct ppd42ns_config_s *config)
+{
+ struct s5j_ppd42ns_dev_s *dev = (struct s5j_ppd42ns_dev_s *)config;
+ struct s5j_ppd42ns_priv_s *priv = dev ? (struct s5j_ppd42ns_priv_s *)dev->config.priv : NULL;
+
+ if (priv == NULL) {
+ lldbg("ERROR: s5j_ppd42ns_gpio_read() is failed.\n");
+ return -1;
+ }
+
+ return s5j_gpioread(priv->pincfg) ? 1 : 0;
+}
+
+static int s5j_ppd42ns_irq_handler(int irq, FAR void *context, FAR void *arg)
+{
+ struct s5j_ppd42ns_dev_s *dev = (struct s5j_ppd42ns_dev_s *)arg;
+ struct s5j_ppd42ns_priv_s *priv = dev ? (struct s5j_ppd42ns_priv_s *)dev->config.priv : NULL;
+
+ if (priv == NULL) {
+ return -1;
+ }
+
+ s5j_gpio_clear_pending(priv->pincfg);
+
+ if (dev->handler) {
+ dev->handler(dev->arg);
+ }
+
+ return 0;
+}
+
+static int s5j_ppd42ns_irq_attach(struct ppd42ns_config_s *config, ppd42ns_handler_t handler, FAR char *arg)
+{
+ struct s5j_ppd42ns_dev_s *dev = (struct s5j_ppd42ns_dev_s *)config;
+ struct s5j_ppd42ns_priv_s *priv = dev ? (struct s5j_ppd42ns_priv_s *)dev->config.priv : NULL;
+
+ if (priv == NULL) {
+ lldbg("ERROR: s5j_ppd42ns_irq_attach() is failed.\n");
+ return -1;
+ }
+
+ dev->handler = handler;
+ dev->arg = arg;
+
+ return 0;
+}
+
+static int s5j_ppd42ns_irq_enable(struct ppd42ns_config_s *config, int enable)
+{
+ int result = -1;
+ struct s5j_ppd42ns_dev_s *dev = (struct s5j_ppd42ns_dev_s *)config;
+ struct s5j_ppd42ns_priv_s *priv = dev ? (struct s5j_ppd42ns_priv_s *)dev->config.priv : NULL;
+ uint32_t pincfg;
+ irqstate_t flags;
+
+ if (priv == NULL) {
+ lldbg("ERROR: s5j_ppd42ns_irq_enable() is failed.\n");
+ return -1;
+ }
+
+ /* disable interrupt */
+ flags = irqsave();
+
+ pincfg = priv->pincfg;
+ pincfg &= ~GPIO_FUNC_MASK;
+ if (priv->event_on_rising && priv->event_on_falling) {
+ pincfg |= GPIO_EINT | GPIO_EINT_BOTH_EDGE;
+ } else if (priv->event_on_rising) {
+ pincfg |= GPIO_EINT | GPIO_EINT_RISING_EDGE;
+ } else if (priv->event_on_falling) {
+ pincfg |= GPIO_EINT | GPIO_EINT_FALLING_EDGE;
+ }
+
+ if (enable) {
+ irq_attach(priv->irqvector, s5j_ppd42ns_irq_handler, dev);
+ up_enable_irq(priv->irqvector);
+
+ } else {
+ up_disable_irq(priv->irqvector);
+ irq_detach(priv->irqvector);
+ }
+
+ if (s5j_configgpio(pincfg) != 0) {
+ goto done;
+ }
+
+ result = 0;
+
+done:
+ /* enable interrupt */
+ irqrestore(flags);
+
+ return result;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s5j_ppd42ns_initialize
+ *
+ * Description:
+ * Initialize the ppd42ns dust sensor driver.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+int s5j_ppd42ns_initialize(void)
+{
+ int result = -1;
+ int i;
+ int total_pins = sizeof(g_gpio_info) / sizeof(g_gpio_info[0]);
+ char devpath[32];
+
+ for (i = 0; i < total_pins; i++) {
+ if (g_gpio_info[i].pinnum == CONFIG_SENSOR_PPD42NS_GPIO_NUM) {
+ g_s5j_priv.pincfg = g_gpio_info[i].pincfg;
+ g_s5j_priv.irqvector = s5j_gpio_irqvector(g_s5j_priv.pincfg);
+ break;
+ }
+ }
+ if (i == total_pins) {
+ result = -EINVAL;
+ goto done;
+ }
+ /* set both edge */
+ g_s5j_priv.event_on_rising = true;
+ g_s5j_priv.event_on_falling = true;
+
+ /* set ppd42ns config */
+ g_s5j_dev.config.priv = (void *)&g_s5j_priv;
+
+ /* register ppd42ns driver */
+ snprintf(devpath, sizeof(devpath), DEVNAME_FORMAT, 0);
+ if (ppd42ns_register(devpath, &g_s5j_dev.config) != 0) {
+ goto done;
+ }
+
+ /* result is success */
+ result = 0;
+
+done:
+ return result;
+}
+
+#endif /* CONFIG_SENSOR_PPD42NS */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * arch/arm/src/s5j/s5j_ppd42ns.h
+ *
+ * Copyright (C) 2009-2010, 2014-2015 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_S5J_S5J_PPD42NS_H
+#define __ARCH_ARM_SRC_S5J_S5J_PPD42NS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#include <tinyara/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s5j_ppd42ns_initialize
+ *
+ * Description:
+ * Initialize the ppd42ns dust sensor driver.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+int s5j_ppd42ns_initialize(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_S5J_S5J_PPD42NS_H */
#include "sidk_s5jt200.h"
#include "s5j_gpio.h"
+#include "s5j_ppd42ns.h"
/****************************************************************************
* Pre-processor Definitions
}
/****************************************************************************
+ * Name: board_sensor_initialize
+ *
+ * Description:
+ * initialize board dependent sensor driver code
+ ****************************************************************************/
+static void board_sensor_initialize(void)
+{
+#if defined(CONFIG_SENSOR_PPD42NS) && defined(CONFIG_S5J_SENSOR_PPD42NS)
+ s5j_ppd42ns_initialize();
+#endif
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_SIDK_S5JT200_EEPROM
sidk_s5jt200_eeprom_init();
#endif
+
+ board_sensor_initialize();
}
#endif /* CONFIG_BOARD_INITIALIZE */
# see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt
#
-comment "Sensor Drivers"
-
-if SENSOR
-
config SENSOR_PPD42NS
bool "Shinyei PPD42NS Dust Sensor"
default n
---help---
the pin number of GPIO that is connected to PPD42NS's Dust Signal Pin
-endif # SENSOR_PPD42NS
-
-endif # SENSOR
+config SENSOR_PPD42NS_DEBUG
+ bool "PPD42NS driver debug message"
+ default n
+ ---help---
+ enable PPD42ns dust sensor driver's debug message
+endif # SENSOR_PPD42NS
****************************************************************************/
#include <tinyara/config.h>
#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
#include <errno.h>
+#include <debug.h>
#include <math.h>
-#include <semaphore.h>
-#include <poll.h>
-#include <tinyara/gpio.h>
-#include <tinyara/sensors/sensor.h>
+
#include <tinyara/sensors/ppd42ns.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+#define PPD42NS_TIME_GET(time) gettimeofday(&time, NULL)
+#define PPD42NS_TIME_DIFF_USEC(old_time, cur_time) \
+ ((cur_time.tv_sec * 1000000 + cur_time.tv_usec) - (old_time.tv_sec * 1000000 + old_time.tv_usec))
+
#define GPIO_SIGNAL_LOW 0
#define GPIO_SIGNAL_HIGH 1
/****************************************************************************
- * Structures
+ * Private Types
****************************************************************************/
-typedef struct {
- int initialized;
- int activated;
- sem_t exclsem;
- int fd;
- char devpath[16];
- int old_signal;
- int lowpulseoccupancy;
- struct timeval start_time;
- struct timeval lowpulse_start_time;
- int pipe_evt_task[2];
- int evt_task_loop;
-} ppd42ns_priv;
+struct ppd42ns_dev_s {
+ FAR struct ppd42ns_config_s *config; /* ppd42ns driver config */
+ int crefs; /* reference count on the driver instance */
+ sem_t exclsem; /* exclusive access to the device */
+ sem_t datasem; /* exclusive access while reading sensor data */
+ int old_signal; /* previous gpio signal */
+ int lowpulseoccupancy; /* low pulse signal time */
+ struct timeval start_time; /* start time of total period */
+ struct timeval lowpulse_start_time; /* start time of low pulse signal period */
+};
/****************************************************************************
- * Static Function Prototype
+ * Private Functions Prototype
****************************************************************************/
-static int ppd42ns_init(sensor_device_t *sensor);
-static int ppd42ns_deinit(sensor_device_t *sensor);
-static int ppd42ns_activate(sensor_device_t *sensor);
-static int ppd42ns_deactivate(sensor_device_t *sensor);
-static int ppd42ns_ioctl(sensor_device_t *sensor, int id, sensor_ioctl_value_t *val);
-static int ppd42ns_get_data(sensor_device_t *sensor, sensor_data_t *data);
+static int ppd42ns_open(FAR struct file *filep);
+static int ppd42ns_close(FAR struct file *filep);
+static ssize_t ppd42ns_read(FAR struct file *filep, FAR char *buffer, size_t len);
/****************************************************************************
- * Variables
+ * Private Data
****************************************************************************/
-static sensor_operations_t g_ops = {
- .init = ppd42ns_init,
- .deinit = ppd42ns_deinit,
- .activate = ppd42ns_activate,
- .deactivate = ppd42ns_deactivate,
- .ioctl = ppd42ns_ioctl,
- .set_trigger = NULL,
- .get_data = ppd42ns_get_data,
-};
-static ppd42ns_priv g_priv;
+/* ppd42ns driver instance */
+static FAR struct ppd42ns_dev_s g_ppd42ns_priv;
+
+/* This the vtable that supports the character driver interface */
+static const struct file_operations g_ppd42ns_fops = {
+ ppd42ns_open, /* open */
+ ppd42ns_close, /* close */
+ ppd42ns_read, /* read */
+ 0, /* write */
+ 0, /* seek */
+ 0, /* ioctl */
+};
/****************************************************************************
- * Static Function
+ * Private Function
****************************************************************************/
-static void ppd42ns_event_handler(sensor_device_t *sensor)
+/****************************************************************************
+ * Name: ppd42ns_takesem
+ *
+ * Description:
+ * Take the lock, waiting as necessary
+ *
+ ****************************************************************************/
+static inline int ppd42ns_takesem(FAR sem_t *sem)
{
- /* this is both edge interrupt handler on ppd42ns's digital signal pin */
-
- struct timeval time;
- ppd42ns_priv *priv;
-
- if (sensor && sensor->priv) {
- priv = (ppd42ns_priv *) sensor->priv;
- } else {
- return;
+ /* Take a count from the semaphore, possibly waiting */
+ if (sem_wait(sem) < 0) {
+ /* EINTR is the only error that we expect */
+ int errcode = get_errno();
+ DEBUGASSERT(errcode == EINTR);
+ return errcode;
}
- if (priv->old_signal == GPIO_SIGNAL_LOW) {
- /* signal LOW -> HIGH */
- SENSOR_TIME_GET(time);
- priv->lowpulseoccupancy += SENSOR_TIME_DIFF_USEC(priv->lowpulse_start_time, time);
- priv->old_signal = GPIO_SIGNAL_HIGH;
-#if PPD42NS_DEBUG_ON
- SENSOR_DEBUG("LOW -> HIGH : tv_sec=%d, tv_usec=%d, lowpulse_time=%d\n", time.tv_sec, time.tv_usec, SENSOR_TIME_DIFF_USEC(priv->lowpulse_start_time, time));
-#endif
- } else {
- /* signal HIGH -> LOW */
- SENSOR_TIME_GET(priv->lowpulse_start_time);
- priv->old_signal = GPIO_SIGNAL_LOW;
-#if PPD42NS_DEBUG_ON
- SENSOR_DEBUG("HIGH -> LOW : tv_sec=%d, tv_usec=%d\n", priv->lowpulse_start_time.tv_sec, priv->lowpulse_start_time.tv_usec);
-#endif
- }
+ return 0;
}
-static void ppd42ns_event_task(sensor_device_t *sensor)
+/****************************************************************************
+ * Name: ppd42ns_givesem
+ *
+ * Description:
+ * release the lock
+ *
+ ****************************************************************************/
+static inline void ppd42ns_givesem(sem_t *sem)
{
- int ret;
- ppd42ns_priv *priv;
- struct pollfd fds[2];
- int size;
- int timeout;
-
-#if PPD42NS_DEBUG_ON
- SENSOR_DEBUG("start event task \n");
-#endif
-
- if (sensor && sensor->priv) {
- priv = (ppd42ns_priv *) sensor->priv;
- } else {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- return;
- }
-
- /* initializes pollfd */
- memset(fds, 0, sizeof(fds));
- fds[0].fd = priv->pipe_evt_task[1];
- fds[0].events = POLLIN;
- fds[1].fd = priv->fd;
- fds[1].events = POLLIN;
-
- timeout = 1000;
- size = sizeof(fds) / sizeof(struct pollfd);
- priv->evt_task_loop = 1;
- while (priv->evt_task_loop) {
- ret = poll(fds, size, timeout);
- if (ret < 0) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n");
- return;
- } else if (ret == 0) {
- /* poll timeout */
- continue;
- }
-
- /* stop message via pipe */
- if (fds[0].revents & POLLIN) {
-#if PPD42NS_DEBUG_ON
- SENSOR_DEBUG("received stop message via pipe.\n");
-#endif
- priv->evt_task_loop = 0;
- break;
- }
-
- /* gpio interrupt */
- if (fds[1].revents & POLLIN) {
-#if PPD42NS_DEBUG_ON
- SENSOR_DEBUG("gpio interrupt occurred.\n");
-#endif
- ppd42ns_event_handler(sensor);
- }
- }
-
-#if PPD42NS_DEBUG_ON
- SENSOR_DEBUG("stop event task \n");
-#endif
+ sem_post(sem);
}
-static int ppd42ns_event_task_start(sensor_device_t *sensor)
+/****************************************************************************
+ * Name: ppd42ns_interrupt_handler
+ *
+ * Description:
+ * handle ppd42ns's digital pin interrupt
+ *
+ ****************************************************************************/
+static void ppd42ns_interrupt_handler(FAR void *arg)
{
- int result = -1;
- int ret;
- pthread_t tid;
- ppd42ns_priv *priv;
-
- if (sensor && sensor->priv) {
- priv = (ppd42ns_priv *) sensor->priv;
- } else {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- return -1;
- }
-
- /* create pipe which is connected to event task */
- priv->pipe_evt_task[0] = -1;
- priv->pipe_evt_task[1] = -1;
- ret = pipe(priv->pipe_evt_task);
- if (ret == -1) {
- SENSOR_DEBUG("ERROR: pipe() failed.\n");
- goto done;
- }
+ /* this is both edge interrupt handler on ppd42ns's digital signal pin */
+ FAR struct ppd42ns_dev_s *priv = (FAR struct ppd42ns_dev_s *)arg;
+ struct timeval time;
+ irqstate_t flags;
- /* create event task */
- ret = pthread_create(&tid, NULL, (pthread_startroutine_t) ppd42ns_event_task, (void *)sensor);
- if (ret != 0) {
- SENSOR_DEBUG("ERROR: pthread_create() failed. (ret=%d)\n", ret);
- goto done;
- }
- ret = pthread_detach(tid);
- if (ret != 0) {
- SENSOR_DEBUG("ERROR: pthread_detach() failed. (ret=%d)\n", ret);
+ if (priv == NULL) {
+ return;
}
- /* result is success */
- result = 0;
-
-done:
- if (result != 0) {
- if (priv->pipe_evt_task[0] != -1) {
- close(priv->pipe_evt_task[0]);
- priv->pipe_evt_task[0] = -1;
- }
-
- if (priv->pipe_evt_task[1] != -1) {
- close(priv->pipe_evt_task[1]);
- priv->pipe_evt_task[1] = -1;
- }
-
- SENSOR_DEBUG("ERROR: fail to start event task\n");
+ /* This ISR handles only when gpio signal is changed. */
+ if (priv->config->read_gpio(priv->config) == priv->old_signal) {
+ return;
}
- return result;
-
-}
+ /* disable interrupt */
+ flags = irqsave();
-static int ppd42ns_event_task_stop(sensor_device_t *sensor)
-{
- ppd42ns_priv *priv;
-
- if (sensor && sensor->priv) {
- priv = (ppd42ns_priv *) sensor->priv;
+ if (priv->old_signal == GPIO_SIGNAL_LOW) {
+ /* signal LOW -> HIGH */
+ PPD42NS_TIME_GET(time);
+ priv->lowpulseoccupancy += PPD42NS_TIME_DIFF_USEC(priv->lowpulse_start_time, time);
+ priv->old_signal = GPIO_SIGNAL_HIGH;
} else {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- return -1;
- }
-
- if (priv->evt_task_loop) {
- if (write(priv->pipe_evt_task[1], "#", 1) < 0) {
- SENSOR_DEBUG("ERROR: pipe write() failed. (errno=%d)\n", errno);
- }
-
- while (priv->evt_task_loop) {
- usleep(100 * 1000);
- }
- }
-
- if (priv->pipe_evt_task[0] != -1) {
- close(priv->pipe_evt_task[0]);
- priv->pipe_evt_task[0] = -1;
- }
-
- if (priv->pipe_evt_task[1] != -1) {
- close(priv->pipe_evt_task[1]);
- priv->pipe_evt_task[1] = -1;
- }
-
- return 0;
-}
-
-static int ppd42ns_init(sensor_device_t *sensor)
-{
- int result = -1;
- ppd42ns_priv *priv;
-
- if (sensor == NULL || sensor->priv == NULL) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- goto done;
- }
- priv = sensor->priv;
-
- if (priv->initialized) {
- SENSOR_DEBUG("ERROR: ppd42ns driver has already been initialized.\n");
- goto done;
- }
-
- /* set gpio device */
- snprintf(priv->devpath, 16, "/dev/gpio%d", CONFIG_SENSOR_PPD42NS_GPIO_NUM);
-
- /* init semaphore */
- sem_init(&priv->exclsem, 0, 1);
-
- /* init private variables */
- priv->activated = 0;
- priv->evt_task_loop = 0;
- priv->pipe_evt_task[0] = -1;
- priv->pipe_evt_task[1] = -1;
-
- /* initialized flag is set */
- priv->initialized = 1;
-
- /* result is success */
- result = 0;
-
-done:
- return result;
-}
-
-static int ppd42ns_deinit(sensor_device_t *sensor)
-{
- int result = -1;
- ppd42ns_priv *priv;
-
- if (sensor == NULL || sensor->priv == NULL) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- goto done;
- }
- priv = sensor->priv;
-
- /* deactivate if activated currently */
- if (priv->activated) {
- ppd42ns_deactivate(sensor);
+ /* signal HIGH -> LOW */
+ PPD42NS_TIME_GET(priv->lowpulse_start_time);
+ priv->old_signal = GPIO_SIGNAL_LOW;
}
- /* deinit semaphore */
- sem_destroy(&priv->exclsem);
-
- /* clear priv data */
- memset(priv, 0, sizeof(*priv));
-
- /* result is success */
- result = 0;
-
-done:
- return result;
+ /* enable interrupt */
+ irqrestore(flags);
}
-static int ppd42ns_activate(sensor_device_t *sensor)
+/****************************************************************************
+ * Name: ppd42ns_open
+ *
+ * Description:
+ * Standard character driver open method.
+ *
+ ****************************************************************************/
+static int ppd42ns_open(FAR struct file *filep)
{
- int result = -1;
int ret;
- int signal;
- ppd42ns_priv *priv;
- struct gpio_pollevents_s pollevents;
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct ppd42ns_dev_s *priv = inode->i_private;
- if (sensor == NULL || sensor->priv == NULL) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- goto done_without_sem;
- }
-
- if (sensor == NULL || sensor->priv == NULL) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- goto done_without_sem;
- }
- priv = sensor->priv;
-
- if (priv->activated) {
- SENSOR_DEBUG("ERROR: ppd42ns driver has already been activated.\n");
- goto done_without_sem;
+ ret = ppd42ns_takesem(&priv->exclsem);
+ if (ret < 0) {
+ /*
+ * A signal received while waiting for the last close
+ * operation.
+ */
+ lldbg("ERROR: ppd42ns_takesem() failed: %d\n", ret);
+ return ret;
}
- do {
- ret = sem_wait(&priv->exclsem);
- } while (ret != 0 && errno == EINTR);
-
- if (ret != 0) {
- SENSOR_DEBUG("ERROR: sem_wait() failed.\n");
- goto done_without_sem;
+ /* ppd42ns driver allows only 1 instance */
+ if (priv->crefs > 0) {
+ lldbg("ERROR: ppd42ns driver is already opened.\n");
+ goto errout_with_sem;
}
- /* open gpio pin */
- priv->fd = open(priv->devpath, O_RDWR);
- if (priv->fd < 0) {
- SENSOR_DEBUG("ERROR: open() failed. (dev: %s)\n", priv->devpath);
- goto done;
- }
+ /* set reference count */
+ priv->crefs = 1;
- /* set gpio direction */
- ret = ioctl(priv->fd, GPIOIOC_SET_DIRECTION, GPIO_DIRECTION_IN);
+ /* enable the gpio pin interrupt */
+ ret = priv->config->enable(priv->config, 1);
if (ret < 0) {
- SENSOR_DEBUG("ERROR: ioctl() failed. (dev: %s, ioctl_id: %d, errno: %d)\n", priv->devpath, GPIOIOC_SET_DIRECTION, errno);
- goto done;
+ lldbg("ERROR: failed to enable the interrupt handler. (ret=%d)\n", ret);
+ goto errout_with_sem;
}
/* set start time */
- SENSOR_TIME_GET(priv->start_time);
+ PPD42NS_TIME_GET(priv->start_time);
+ priv->lowpulse_start_time = priv->start_time;
/* get initial signal */
- ret = read(priv->fd, (void *)&signal, sizeof(int));
- if (ret < 0) {
- SENSOR_DEBUG("ERROR: read() failed. (fd: %d, errno: %d)\n", priv->fd, errno);
- goto done;
- }
+ priv->old_signal = priv->config->read_gpio(priv->config);
- if (signal == GPIO_SIGNAL_LOW) {
- SENSOR_TIME_GET(priv->lowpulse_start_time);
- }
+ /* initialize lowpulseoccupancy */
priv->lowpulseoccupancy = 0;
- priv->old_signal = signal;
- /* set interrupt on both edge and poll event */
- pollevents.gp_rising = true;
- pollevents.gp_falling = true;
- ret = ioctl(priv->fd, GPIOIOC_POLLEVENTS, (unsigned long)&pollevents);
- if (ret < 0) {
- SENSOR_DEBUG("ERROR: ioctl() failed. (dev: %s, ioctl_id: %d, errno: %d)\n", priv->devpath, GPIOIOC_POLLEVENTS, errno);
- goto done;
- }
+ ret = 0;
- if (ppd42ns_event_task_start(sensor) != 0) {
- SENSOR_DEBUG("ERROR: ppd42ns_event_task_start() failed. (dev: %s)\n", priv->devpath);
- goto done;
- }
-
- /* activated flag is set */
- priv->activated = 1;
-
- /* result is success */
- result = 0;
-
-done:
- sem_post(&priv->exclsem);
-
-done_without_sem:
- return result;
-}
-
-static int ppd42ns_deactivate(sensor_device_t *sensor)
-{
- int result = -1;
- int ret;
- ppd42ns_priv *priv;
-
- if (sensor == NULL || sensor->priv == NULL) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- goto done_without_sem;
- }
- priv = sensor->priv;
-
- do {
- ret = sem_wait(&priv->exclsem);
- } while (ret != 0 && errno == EINTR);
-
- if (ret != 0) {
- SENSOR_DEBUG("ERROR: sem_wait() failed.\n");
- goto done_without_sem;
- }
-
- ppd42ns_event_task_stop(sensor);
-
- /* close gpio */
- close(priv->fd);
-
- /* activated flag is unset */
- priv->activated = 0;
-
- /* result is success */
- result = 0;
-
- sem_post(&priv->exclsem);
-
-done_without_sem:
- return result;
+errout_with_sem:
+ ppd42ns_givesem(&priv->exclsem);
+ return ret;
}
-static int ppd42ns_ioctl(sensor_device_t *sensor, int id, sensor_ioctl_value_t *val)
+/****************************************************************************
+ * Name: ppd42ns_close
+ *
+ * Description:
+ * Standard character driver close method.
+ *
+ ****************************************************************************/
+static int ppd42ns_close(FAR struct file *filep)
{
- int result = -1;
int ret;
- ppd42ns_priv *priv;
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct ppd42ns_dev_s *priv = inode->i_private;
- if (sensor == NULL || sensor->priv == NULL) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- goto done_without_sem;
- }
- priv = sensor->priv;
-
- if (!priv->initialized) {
- SENSOR_DEBUG("ERROR: ppd42ns driver is not initialized.\n");
- goto done_without_sem;
+ /* Get exclusive access to the driver structure */
+ ret = ppd42ns_takesem(&priv->exclsem);
+ if (ret < 0) {
+ lldbg("ERROR: ppd42ns_takesem() failed: %d\n", ret);
+ return ret;
}
- if (val == NULL) {
- SENSOR_DEBUG("ERROR: ioctl val is null.\n");
- goto done_without_sem;
+ if (priv->crefs == 0) {
+ lldbg("ERROR: ppd42ns driver is already closed.\n");
+ goto errout_with_sem;
}
- do {
- ret = sem_wait(&priv->exclsem);
- } while (ret != 0 && errno == EINTR);
-
- if (ret != 0) {
- SENSOR_DEBUG("ERROR: sem_wait() failed.\n");
- goto done_without_sem;
- }
+ priv->crefs = 0;
- switch (id) {
- case PPD42NS_IOCTL_ID_GET_GPIO_DEVPATH:
- val->p_str = priv->devpath;
- break;
- default:
- SENSOR_DEBUG("ERROR: unknown ioctl id. (id: %d)\n", id);
- goto done;
+ /* disable the gpio pin interrupt */
+ ret = priv->config->enable(priv->config, 0);
+ if (ret < 0) {
+ lldbg("ERROR: failed to disable the interrupt handler. (ret=%d)\n", ret);
+ goto errout_with_sem;
}
- /* result is success */
- result = 0;
-
-done:
- sem_post(&priv->exclsem);
+ ret = 0;
-done_without_sem:
- return result;
+errout_with_sem:
+ ppd42ns_givesem(&priv->exclsem);
+ return ret;
}
-static int ppd42ns_get_data(sensor_device_t *sensor, sensor_data_t *data)
+/****************************************************************************
+ * Name: ppd42ns_read
+ *
+ * Description:
+ * Standard character driver read method.
+ *
+ ****************************************************************************/
+static ssize_t ppd42ns_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
- int result = -1;
+ int ret;
+ FAR struct inode *inode = filep->f_inode;
+ FAR struct ppd42ns_dev_s *priv = inode->i_private;
+ int signal;
float ratio = 0.0;
float concentration;
struct timeval time;
- int ret;
- int signal;
- ppd42ns_priv *priv;
-
- if (sensor == NULL || sensor->priv == NULL) {
- SENSOR_DEBUG("ERROR: %s is NULL.\n", sensor == NULL ? "sensor" : "sensor->priv");
- goto done_without_sem;
- }
- priv = sensor->priv;
- if (!priv->activated) {
- SENSOR_DEBUG("ERROR: ppd42ns driver is not activated.\n");
- goto done_without_sem;
+ ret = ppd42ns_takesem(&priv->datasem);
+ if (ret < 0) {
+ lldbg("ERROR: ppd42ns_takesem() failed: %d\n", ret);
+ return ret;
}
- do {
- ret = sem_wait(&priv->exclsem);
- } while (ret != 0 && errno == EINTR);
-
- if (ret != 0) {
- SENSOR_DEBUG("ERROR: sem_wait() failed.\n");
- goto done_without_sem;
- }
+ /* disable gpio pin interrupt */
+ priv->config->enable(priv->config, 0);
- lseek(priv->fd, 0, SEEK_SET);
- ret = read(priv->fd, (void *)&signal, sizeof(int));
- if (ret < 0) {
- SENSOR_DEBUG("ERROR: read() failed. (fd: %d, errno: %d)\n", priv->fd, errno);
- goto done;
- }
+ /* get gpio signal */
+ signal = priv->config->read_gpio(priv->config);
- SENSOR_TIME_GET(time);
+ PPD42NS_TIME_GET(time);
if (signal == GPIO_SIGNAL_LOW) {
- priv->lowpulseoccupancy += SENSOR_TIME_DIFF_USEC(priv->lowpulse_start_time, time);
+ priv->lowpulseoccupancy += PPD42NS_TIME_DIFF_USEC(priv->lowpulse_start_time, time);
priv->lowpulse_start_time = time;
}
if (priv->lowpulseoccupancy != 0) {
- ratio = (float)priv->lowpulseoccupancy / (float)SENSOR_TIME_DIFF_USEC(priv->start_time, time) * 100.0; /* Integer percentage 0=>100 */
+ ratio = (float)priv->lowpulseoccupancy / (float)PPD42NS_TIME_DIFF_USEC(priv->start_time, time) * 100.0; /* percentage 0~100 */
concentration = 1.1 * pow(ratio, 3) - 3.8 * pow(ratio, 2) + 520 * ratio + 0.62; /* using spec sheet curve */
} else {
concentration = 0.0;
}
- data->fval = concentration;
-#if PPD42NS_DEBUG_ON
- SENSOR_DEBUG("lowpulse_time=%d, total_time=%d, ratio=%.2f \n", priv->lowpulseoccupancy, SENSOR_TIME_DIFF_USEC(priv->start_time, time), ratio);
+#ifdef CONFIG_SENSOR_PPD42NS_DEBUG
+ lldbg("lowpulse_time=%d, total_time=%d, ratio=%.2f, concentration=%.2f \n", priv->lowpulseoccupancy, PPD42NS_TIME_DIFF_USEC(priv->start_time, time), ratio, concentration);
#endif
priv->start_time = time;
priv->lowpulseoccupancy = 0;
priv->old_signal = signal;
- /* result is success */
- result = 0;
+ /* enable gpio pin interrupt */
+ priv->config->enable(priv->config, 1);
-done:
- sem_post(&priv->exclsem);
+ memcpy(buffer, &concentration, sizeof(float));
-done_without_sem:
- return result;
+ ppd42ns_givesem(&priv->datasem);
+
+ return sizeof(float);
}
/****************************************************************************
- * Create Sensor Instance
+ * Public Function
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ppd42ns_register
+ *
+ * Description:
+ * This function will register ppd42ns dust sensor driver as /dev/dustN where N
+ * is the minor device number
+ *
+ * Input Parameters:
+ * devname - The full path to the driver to register. E.g., "/dev/dust0"
+ * config - configuration for the ppd42ns driver.
+ *
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
+ *
****************************************************************************/
-SENSOR_CREATE_INSTANCE(SENSOR_NAME_PPD42NS, SENSOR_DEVICE_TYPE_DUST, &g_ops, &g_priv);
+int ppd42ns_register(FAR const char *devname, FAR struct ppd42ns_config_s *config)
+{
+ int ret;
+ struct ppd42ns_dev_s *priv = &g_ppd42ns_priv;
+
+ /* validate ppd42ns config */
+ if (config == NULL || config->read_gpio == NULL || config->attach == NULL || config->enable == NULL) {
+ ret = EINVAL;
+ lldbg("ERROR: invalid ppd42ns config\n");
+ return ret;
+ }
+
+ /* set ppd42ns config */
+ priv->config = config;
+
+ /* reference count is set to 0 */
+ priv->crefs = 0;
+
+ /* init semaphore */
+ sem_init(&priv->exclsem, 0, 1);
+ sem_init(&priv->datasem, 0, 1);
+
+ /* attach the interrupt handler */
+ ret = priv->config->attach(priv->config, ppd42ns_interrupt_handler, (FAR void *)priv);
+ if (ret < 0) {
+ lldbg("ERROR: failed to attach the interrupt handler. (ret=%d)\n", ret);
+ sem_destroy(&priv->exclsem);
+ sem_destroy(&priv->datasem);
+ return ret;
+ }
+
+ /* register the character device driver */
+ ret = register_driver(devname, &g_ppd42ns_fops, 0666, priv);
+ if (ret < 0) {
+ lldbg("ERROR: failed to register driver %s. (ret=%d)\n", devname, ret);
+ sem_destroy(&priv->exclsem);
+ sem_destroy(&priv->datasem);
+ return ret;
+ }
+
+ lldbg("Registered %s\n", devname);
+
+ return 0;
+}
/****************************************************************************
* Included Files
****************************************************************************/
-#include <tinyara/sensors/sensor.h>
-#define SENSOR_NAME_PPD42NS ppd42ns
-SENSOR_EXTERNAL_FUNCTION_PROTOTYPE(SENSOR_NAME_PPD42NS);
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+typedef void (*ppd42ns_handler_t)(FAR void *arg);
+
+struct ppd42ns_config_s {
+ /* gpio pin number */
+ int gpionum;
+
+ /* callback function: read gpio pin signal */
+ int (*read_gpio)(struct ppd42ns_config_s *config);
-/********************
- definitions
- ********************/
-#define PPD42NS_DEBUG_ON 0
+ /* callback function: attach the ppd42ns interrupt handler to the GPIO interrupt */
+ int (*attach)(struct ppd42ns_config_s *config, ppd42ns_handler_t handler, FAR char *arg);
-/********************
- custom ioctl id
- ********************/
-#define PPD42NS_IOCTL_ID_GET_GPIO_DEVPATH (SENSOR_IOCTL_ID_CUSTOM + 0)
+ /* callback function: enable or disable gpio pin interrupt */
+ int (*enable)(struct ppd42ns_config_s *config, int enable);
+
+ /* board specific data */
+ void *priv;
+};
+
+/****************************************************************************
+ * Public Function
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ppd42ns_register
+ *
+ * Description:
+ * This function will register ppd42ns dust sensor driver as /dev/dustN where N
+ * is the minor device number
+ *
+ * Input Parameters:
+ * devname - The full path to the driver to register. E.g., "/dev/dust0"
+ * config - configuration for the ppd42ns driver.
+ *
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+int ppd42ns_register(FAR const char *devname, FAR struct ppd42ns_config_s *config);
#endif /* __PPD42NS_H__ */
+++ /dev/null
-/****************************************************************************
- *
- * Copyright 2017 Samsung Electronics All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- ****************************************************************************/
-/**
- * @file sensor.h
- * @brief Sensor API definition
- * @version 0.3
- */
-
-#ifndef __SENSOR_H__
-#define __SENSOR_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <debug.h>
-
-/****************************************************************************
- * Public Types
- ****************************************************************************/
-/**
- * @brief Enumeration of sensor device type
- */
-typedef enum {
- SENSOR_DEVICE_TYPE_ACCELEROMETER,
- SENSOR_DEVICE_TYPE_GYROSCOPE,
- SENSOR_DEVICE_TYPE_MAGNETIC_FIELD,
- SENSOR_DEVICE_TYPE_TEMPERATURE,
- SENSOR_DEVICE_TYPE_HUMIDITY,
- SENSOR_DEVICE_TYPE_PRESSURE,
- SENSOR_DEVICE_TYPE_LIGHT,
- SENSOR_DEVICE_TYPE_DUST,
- SENSOR_DEVICE_TYPE_END
-}
-sensor_device_type_e;
-
-/**
- * @brief Enumeration of sensor device attribute
- */
-typedef enum {
- SENSOR_IOCTL_ID_GET_TRIGGER_TYPE,
- SENSOR_IOCTL_ID_FREQUENCY,
- SENSOR_IOCTL_ID_CUSTOM = 0x8000,
-} sensor_ioctl_id_e;
-
-/**
- * @brief Enumeration of sensor trigger type
- */
-typedef enum {
- SENSOR_TRIGGER_TYPE_DATA_READY,
- SENSOR_TRIGGER_TYPE_TIMER,
- SENSOR_TRIGGER_TYPE_END
-} sensor_trigger_type_e;
-
-/**
- * @brief Structure of sensor value
- */
-typedef struct {
- union {
- int ival;
- float fval;
- double dval;
- char *p_str;
- void *p;
- };
-} sensor_ioctl_value_t;
-
-/**
- * @brief Structure of sensor data
- */
-typedef struct {
- union {
- float v[3];
- struct {
- float x;
- float y;
- float z;
- };
- struct {
- float azimuth;
- float pitch;
- float roll;
- };
- int ival;
- float fval;
- double dval;
- };
-} sensor_data_t;
-
-/**
- * @brief Structure of sensor trigger information
- */
-typedef struct {
- sensor_trigger_type_e type;
-} sensor_trigger_info_t;
-
-/**
- * @brief Definition of sensor_device_t type
- */
-typedef struct sensor_device_t sensor_device_t;
-
-/**
- * @brief Pointer definition to trigger callback function
- */
-typedef int (*sensor_trigger_callback_t)(sensor_device_t *sensor, sensor_data_t *data);
-
-/**
- * @brief Pointer definition to sensor operations
- */
-typedef int (*sensor_init_t)(sensor_device_t *sensor);
-typedef int (*sensor_deinit_t)(sensor_device_t *sensor);
-typedef int (*sensor_activate_t)(sensor_device_t *sensor);
-typedef int (*sensor_deactivate_t)(sensor_device_t *sensor);
-typedef int (*sensor_ioctl_t)(sensor_device_t *sensor, int id, sensor_ioctl_value_t *val);
-typedef int (*sensor_set_trigger_t)(sensor_device_t *sensor, sensor_trigger_info_t info, sensor_trigger_callback_t callback);
-typedef int (*sensor_get_data_t)(sensor_device_t *sensor, sensor_data_t *data);
-
-/**
- * @brief Structure of sensor operations
- */
-typedef struct {
- sensor_init_t init; /* initialize sensor device */
- sensor_deinit_t deinit; /* deinitialize sensor device */
- sensor_activate_t activate; /* activate sensor device */
- sensor_deactivate_t deactivate; /* deactivate sensor device */
- sensor_ioctl_t ioctl; /* ioctl on sensor device */
- sensor_set_trigger_t set_trigger; /* set trigger information and calback function */
- sensor_get_data_t get_data; /* get sensor data from device */
-} sensor_operations_t;
-
-/**
- * @brief Structure of sensor device
- */
-struct sensor_device_t {
- sensor_device_type_e type; /* sensor device type */
- sensor_operations_t *ops; /* sensor opertaions */
- void *priv; /* private data of a specified device */
-};
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-#define __NAME_STRING(name) #name
-#define __SENSOR_CREATE_INSTANCE(name, _type, _ops, _priv) \
- static sensor_device_t g_sensor_##name = { \
- .type = _type, \
- .ops = _ops, \
- .priv = _priv, \
- }; \
- \
- sensor_device_t * name##_get_handle(void) { \
- return &g_sensor_##name; \
- }; \
- \
- sensor_operations_t * name##_get_ops_handle(void) { \
- return (&g_sensor_##name)->ops ? (&g_sensor_##name)->ops : NULL; \
- }
-
-#define __SENSOR_EXTERNAL_FUNCTION_PROTOTYPE(name) \
- sensor_device_t * name##_get_handle(void); \
- sensor_operations_t * name##_get_ops_handle(void)
-
-#define __SENSOR_GET_HANDLE(name) name##_get_handle()
-#define __SENSOR_GET_OPS_HANDLE(name) name##_get_ops_handle()
-#define __SENSOR_GET_NAME_STRING(name) __NAME_STRING(name)
-
-/***************************
- For Debug
- ***************************/
-#define SENSOR_DEBUG_ON 1
-#if SENSOR_DEBUG_ON
-#define SENSOR_DEBUG(format, ...) dbg(format, ##__VA_ARGS__)
-#else
-#define SENSOR_DEBUG(x...) (void)0
-#endif
-
-/***************************
- For Sensor Driver Developers
- ***************************/
-
-/****************************************************************************
- * Name: SENSOR_CREATE_INSTANCE
- *
- * Description:
- * create a sensor device instance as sensor_device_t.
- *
- * Parameters:
- * name - sensor device name.
- * generally, SENSOR_NAME_XXXXX will be a name. it is in the specified sensor driver's header file.
- * _type - sensor device type as sensor_device_type_e type.
- * _ops - sensor operations handle as sensor_operations_t type.
- * _priv - sensor device's private data handle as void type.
- *
- * Returned Value:
- * none.
- *
- ****************************************************************************/
-#define SENSOR_CREATE_INSTANCE(name, _type, _ops, _priv) __SENSOR_CREATE_INSTANCE(name, _type, _ops, _priv)
-
-/****************************************************************************
- * Name: SENSOR_GET_NAME_STRING
- *
- * Description:
- * declare external function prototype.
- *
- * Parameters:
- * name - sensor device name.
- * generally, SENSOR_NAME_XXXXX will be a name. it is in the specified sensor driver's header file.
- *
- * Returned Value:
- * none.
- *
- ****************************************************************************/
-#define SENSOR_EXTERNAL_FUNCTION_PROTOTYPE(name) __SENSOR_EXTERNAL_FUNCTION_PROTOTYPE(name)
-
-/***************************
- For Upper Layer Developers
- ***************************/
-
-/****************************************************************************
- * Name: SENSOR_GET_NAME_STRING
- *
- * Description:
- * get a name as string type.
- *
- * Parameters:
- * name - sensor device name.
- * generally, SENSOR_NAME_XXXXX will be a name. it is in the specified sensor driver's header file.
- *
- * Returned Value:
- * a name as string type is returned.
- *
- ****************************************************************************/
-#define SENSOR_GET_NAME_STRING(name) __SENSOR_GET_NAME_STRING(name)
-
-/****************************************************************************
- * Name: SENSOR_GET_HANDLE
- *
- * Description:
- * get a sensor device handle.
- *
- * Parameters:
- * name - sensor device name.
- * generally, SENSOR_NAME_XXXXX will be a name. it is in the specified sensor driver's header file.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_GET_HANDLE(name) __SENSOR_GET_HANDLE(name)
-
-/****************************************************************************
- * Name: SENSOR_GET_DEVICE_TYPE
- *
- * Description:
- * get sensor device type as sensor_device_type_e type.
- *
- * Parameters:
- * handle - sensor device handle.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_GET_DEVICE_TYPE(handle) (handle ? handle->type : -1)
-
-/****************************************************************************
- * Name: SENSOR_INIT
- *
- * Description:
- * initialize the specified sensor device.
- *
- * Parameters:
- * handle - sensor device handle.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_INIT(handle) (handle && handle->ops ? handle->ops->init(handle) : -1)
-
-/****************************************************************************
- * Name: SENSOR_DEINIT
- *
- * Description:
- * deinitialize the specified sensor device.
- *
- * Parameters:
- * handle - sensor device handle.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_DEINIT(handle) (handle && handle->ops ? handle->ops->deinit(handle) : -1)
-
-/****************************************************************************
- * Name: SENSOR_ACTIVATE
- *
- * Description:
- * activate the specified sensor device.
- *
- * Parameters:
- * handle - sensor device handle.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_ACTIVATE(handle) (handle && handle->ops ? handle->ops->activate(handle) : -1)
-
-/****************************************************************************
- * Name: SENSOR_DEACTIVATE
- *
- * Description:
- * deactivate the specified sensor device.
- *
- * Parameters:
- * handle - sensor device handle.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_DEACTIVATE(handle) (handle && handle->ops ? handle->ops->deactivate(handle) : -1)
-
-/****************************************************************************
- * Name: SENSOR_IOCTL
- *
- * Description:
- * do ioctl on the specified sensor device.
- *
- * Parameters:
- * handle - sensor device handle.
- * id - ioctl id as sensor_ioctl_id_e type.
- * pval -ioctl value as sensor_ioctl_value_t type.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_IOCTL(handle, id, pval) (handle && handle->ops ? handle->ops->ioctl(handle, id, pval) : -1)
-
-/****************************************************************************
- * Name: SENSOR_SET_TRIGGER
- *
- * Description:
- * set trigger on the specified sensor device.
- *
- * Parameters:
- * handle - sensor device handle.
- * info - trigger information as sensor_trigger_info_t type.
- * callback - callback function as sensor_trigger_callback_t type.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_SET_TRIGGER(handle, info, callback) (handle && handle->ops ? handle->ops->set_trigger(handle, info, callback) : -1)
-
-/****************************************************************************
- * Name: SENSOR_GET_DATA
- *
- * Description:
- * get data from the specified sensor device.
- *
- * Parameters:
- * handle - sensor device handle.
- * pdata - data as sensor_data_t type.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_GET_DATA(handle, pdata) (handle && handle->ops ? handle->ops->get_data(handle, pdata) : -1)
-
-/***************************
- Utilities
- ***************************/
-
-/****************************************************************************
- * Name: SENSOR_TIME_GET
- *
- * Description:
- * get time information as 'struct timeval' type.
- *
- * Parameters:
- * time - the pointer of 'struct timeval' type variable.
- *
- * Returned Value:
- * on success, 0 is returned. on failure, a negative value is returned.
- *
- ****************************************************************************/
-#define SENSOR_TIME_GET(time) gettimeofday(&time, NULL)
-
-/****************************************************************************
- * Name: SENSOR_TIME_GET
- *
- * Description:
- * get time differential in usec beween old time and current time.
- *
- * Parameters:
- * old_time - old time's pointer variable that points 'struct timeval' type.
- * cur_time - current time's pointer variable that points 'struct timeval' type.
- *
- * Returned Value:
- * time differentil in usec
- *
- ****************************************************************************/
-#define SENSOR_TIME_DIFF_USEC(old_time, cur_time) \
- ((cur_time.tv_sec * 1000000 + cur_time.tv_usec) - (old_time.tv_sec * 1000000 + old_time.tv_usec))
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* __SENSOR_H__ */