From 770e43c62753a1db5b25a97c0e0142acfd294730 Mon Sep 17 00:00:00 2001 From: Jon Trulson Date: Fri, 14 Oct 2016 13:53:00 -0600 Subject: [PATCH] rpr220: add C driver and examples; FTI; C++ wraps C Signed-off-by: Jon Trulson --- examples/c/CMakeLists.txt | 2 + examples/c/rpr220-intr.c | 84 ++++++++++++++++++++++ examples/c/rpr220.c | 72 +++++++++++++++++++ src/rpr220/CMakeLists.txt | 14 ++-- src/rpr220/rpr220.c | 107 ++++++++++++++++++++++++++++ src/rpr220/rpr220.cxx | 38 +++------- src/rpr220/rpr220.h | 98 ++++++++++++++++++++++++++ src/rpr220/rpr220.hpp | 144 +++++++++++++++++++------------------- src/rpr220/rpr220_fti.c | 94 +++++++++++++++++++++++++ 9 files changed, 549 insertions(+), 104 deletions(-) create mode 100644 examples/c/rpr220-intr.c create mode 100644 examples/c/rpr220.c create mode 100644 src/rpr220/rpr220.c create mode 100644 src/rpr220/rpr220.h create mode 100644 src/rpr220/rpr220_fti.c diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 729c880b..c33cfb94 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -126,8 +126,10 @@ add_example (bmi160) add_example (jhd1313m1) add_example (lm35) add_example (rotaryencoder) +add_example (rpr220) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) add_custom_example (lcm1602-i2c-example-c lcm1602-i2c.c lcm1602) add_custom_example (lcm1602-parallel-example-c lcm1602-parallel.c lcm1602) +add_custom_example (rpr220-intr-example-c rpr220-intr.c rpr220) diff --git a/examples/c/rpr220-intr.c b/examples/c/rpr220-intr.c new file mode 100644 index 00000000..6337ab4a --- /dev/null +++ b/examples/c/rpr220-intr.c @@ -0,0 +1,84 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include +#include + +int shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +volatile unsigned int counter = 0; + +// Our interrupt handler +void rpr220_isr(void *arg) +{ + counter++; +} + + +int main() +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + // This example uses an interrupt handler to increment a counter + + // Instantiate an RPR220 digital pin D2 + // This was tested on the Grove IR Reflective Sensor + rpr220_context sensor = rpr220_init(2); + + if (!sensor) + { + printf("rpr220_init() failed\n"); + return 1; + } + + // Here, we setup our Interupt Service Routine (ISR) to count + // 'black' pulses detected. We do not pass an argument to the + // interrupt handler (NULL). + + rpr220_install_isr(sensor, rpr220_isr, NULL); + + while (shouldRun) + { + printf("Counter: %d\n", counter); + + upm_delay(1); + } + + printf("Exiting...\n"); + + rpr220_close(sensor); +//! [Interesting] + + return 0; +} diff --git a/examples/c/rpr220.c b/examples/c/rpr220.c new file mode 100644 index 00000000..923aa8d8 --- /dev/null +++ b/examples/c/rpr220.c @@ -0,0 +1,72 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include +#include + +int shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + + +int main() +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + // This example uses a simple method to determine current status + + // Instantiate an RPR220 digital pin D2 + // This was tested on the Grove IR Reflective Sensor + rpr220_context sensor = rpr220_init(2); + + if (!sensor) + { + printf("rpr220_init() failed\n"); + return 1; + } + + while (shouldRun) + { + if (rpr220_black_detected(sensor)) + printf("Black detected\n"); + else + printf("Black NOT detected\n"); + + upm_delay_ms(100); // 100ms + } + + printf("Exiting...\n"); + + rpr220_close(sensor); +//! [Interesting] + return 0; +} diff --git a/src/rpr220/CMakeLists.txt b/src/rpr220/CMakeLists.txt index 2f63724a..940d6b40 100644 --- a/src/rpr220/CMakeLists.txt +++ b/src/rpr220/CMakeLists.txt @@ -1,5 +1,9 @@ -set (libname "rpr220") -set (libdescription "upm rpr220 grove IR reflective sensor") -set (module_src ${libname}.cxx) -set (module_hpp ${libname}.hpp) -upm_module_init() +upm_mixed_module_init (NAME rpr220 + DESCRIPTION "RPR220 IR Reflective Sensor" + C_HDR rpr220.h + C_SRC rpr220.c + CPP_HDR rpr220.hpp + CPP_SRC rpr220.cxx + FTI_SRC rpr220_fti.c + CPP_WRAPS_C + REQUIRES mraa) diff --git a/src/rpr220/rpr220.c b/src/rpr220/rpr220.c new file mode 100644 index 00000000..0e8981c1 --- /dev/null +++ b/src/rpr220/rpr220.c @@ -0,0 +1,107 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include "rpr220.h" + +rpr220_context rpr220_init(int pin) +{ + rpr220_context dev = + (rpr220_context)malloc(sizeof(struct _rpr220_context)); + + if (!dev) + return NULL; + + dev->gpio = NULL; + dev->isrInstalled = false; + + // make sure MRAA is initialized + int mraa_rv; + if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) + { + printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); + rpr220_close(dev); + return NULL; + } + + // MRAA contexts... + if ( !(dev->gpio = mraa_gpio_init(pin)) ) + { + printf("%s: mraa_gpio_init() failed\n", + __FUNCTION__); + rpr220_close(dev); + return NULL; + } + + mraa_gpio_dir(dev->gpio, MRAA_GPIO_IN); + + return dev; +} + +void rpr220_close(rpr220_context dev) +{ + assert(dev != NULL); + + if (dev->isrInstalled) + rpr220_uninstall_isr(dev); + + if (dev->gpio) + mraa_gpio_close(dev->gpio); + + free(dev); +} + +bool rpr220_black_detected(const rpr220_context dev) +{ + assert(dev != NULL); + + return (mraa_gpio_read(dev->gpio) ? true : false); +} + +void rpr220_install_isr(const rpr220_context dev, + void (*isr)(void *), void *arg) +{ + assert(dev != NULL); + + if (dev->isrInstalled) + rpr220_uninstall_isr(dev); + + // install our interrupt handler + if (mraa_gpio_isr(dev->gpio, MRAA_GPIO_EDGE_RISING, isr, arg)) + { + printf("%s: mraa_gpio_isr() failed.\n", __FUNCTION__); + return; + } + + dev->isrInstalled = true; +} + +void rpr220_uninstall_isr(const rpr220_context dev) +{ + assert(dev != NULL); + + mraa_gpio_isr_exit(dev->gpio); + dev->isrInstalled = false; +} diff --git a/src/rpr220/rpr220.cxx b/src/rpr220/rpr220.cxx index acf3fc45..9f14257d 100644 --- a/src/rpr220/rpr220.cxx +++ b/src/rpr220/rpr220.cxx @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2015 Intel Corporation. + * Copyright (c) 2015-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -31,54 +31,38 @@ using namespace upm; using namespace std; -RPR220::RPR220(int pin) +RPR220::RPR220(int pin) : + m_rpr220(rpr220_init(pin)) { - m_isrInstalled = false; - - if ( !(m_gpio = mraa_gpio_init(pin)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init() failed, invalid pin?"); - return; - } - - mraa_gpio_dir(m_gpio, MRAA_GPIO_IN); + if (!m_rpr220) + throw std::runtime_error(std::string(__FUNCTION__) + + ": rpr220_init() failed"); } RPR220::~RPR220() { - if (m_isrInstalled) - uninstallISR(); - - mraa_gpio_close(m_gpio); + rpr220_close(m_rpr220); } bool RPR220::blackDetected() { - return (mraa_gpio_read(m_gpio) ? true : false); + return rpr220_black_detected(m_rpr220); } #ifdef JAVACALLBACK void RPR220::installISR(jobject runnable) { - installISR(mraa_java_isr_callback, runnable); + installISR(mraa_java_isr_callback, runnable); } #endif void RPR220::installISR(void (*isr)(void *), void *arg) { - if (m_isrInstalled) - uninstallISR(); - - // install our interrupt handler - mraa_gpio_isr(m_gpio, MRAA_GPIO_EDGE_RISING, - isr, arg); - m_isrInstalled = true; + rpr220_install_isr(m_rpr220, isr, arg); } void RPR220::uninstallISR() { - mraa_gpio_isr_exit(m_gpio); - m_isrInstalled = false; + rpr220_uninstall_isr(m_rpr220); } diff --git a/src/rpr220/rpr220.h b/src/rpr220/rpr220.h new file mode 100644 index 00000000..6b733b6c --- /dev/null +++ b/src/rpr220/rpr220.h @@ -0,0 +1,98 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * @file rpr220.h + * @library rpr220 + * @brief C API for the rpr220 driver + * + * @include rpr220.c + */ + + /** + * Device context + */ + typedef struct _rpr220_context { + mraa_gpio_context gpio; + + bool isrInstalled; + } *rpr220_context; + + /** + * RPR220 initialization. + * + * @param pin Digital pin to use. + * @return rpr220 device context + */ + rpr220_context rpr220_init(int pin); + + /** + * RPR220 destructor + * + * @param dev Device context. + */ + void rpr220_close(rpr220_context dev); + + /** + * Gets the status of the pin; true means black has been detected + * + * @param dev Device context. + * @return True if the sensor has detected black + */ + bool rpr220_black_detected(const rpr220_context dev); + + /** + * Installs an ISR to be called when + * black is detected + * + * @param dev Device context. + * @param isr Pointer to a function to be called on interrupt + * @param arg Pointer to an object to be supplied as an + * argument to the ISR. + */ + void rpr220_install_isr(const rpr220_context dev, + void (*isr)(void *), void *arg); + + /** + * Uninstalls the previously installed ISR + * + * @param dev Device context. + */ + void rpr220_uninstall_isr(const rpr220_context dev); + + +#ifdef __cplusplus +} +#endif diff --git a/src/rpr220/rpr220.hpp b/src/rpr220/rpr220.hpp index c9db2e97..552048ca 100644 --- a/src/rpr220/rpr220.hpp +++ b/src/rpr220/rpr220.hpp @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2015 Intel Corporation. + * Copyright (c) 2015-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -24,92 +24,92 @@ #pragma once #include -#include +#include namespace upm { -/** - * @brief RPR220 IR Reflective Sensor library - * @defgroup rpr220 libupm-rpr220 - * @ingroup seeed gpio light tsk hak - */ -/** - * @library rpr220 - * @sensor rpr220 - * @comname RPR220 IR Reflective Sensor - * @altname Grove IR Reflective Sensor - * @type light - * @man seeed - * @web http://www.seeedstudio.com/wiki/Grove_-_Infrared_Reflective_Sensor - * @con gpio - * @kit tsk hak - * - * @brief API for the RPR220-based Grove IR Reflective Sensor - * - * UPM module for the Grove IR reflective sensor. The sensitivity - * can be adjusted with the potentiometer on the sensor module. It - * has a range of approximately 15 mm, and a quick response time. - * - * It detects high-contrast dark areas on a light background. - * - * This module allows the user to determine the current status - * (black detected or not). Additionally, if desired, an interrupt - * service routine (ISR) can be installed that is called when - * black is detected. Either method can be used, depending on your - * use case. - * - * @image html rpr220.jpg - * @snippet rpr220.cxx Interesting - * @snippet rpr220-intr.cxx Interesting - */ - class RPR220 { - public: /** - * RPR220 constructor + * @brief RPR220 IR Reflective Sensor library + * @defgroup rpr220 libupm-rpr220 + * @ingroup seeed gpio light tsk hak + */ + /** + * @library rpr220 + * @sensor rpr220 + * @comname RPR220 IR Reflective Sensor + * @altname Grove IR Reflective Sensor + * @type light + * @man seeed + * @web http://www.seeedstudio.com/wiki/Grove_-_Infrared_Reflective_Sensor + * @con gpio + * @kit tsk hak * - * @param pin Digital pin to use - */ - RPR220(int pin); - - /** - * RPR220 destructor - */ - ~RPR220(); - - /** - * Gets the status of the pin; true means black has been detected + * @brief API for the RPR220-based Grove IR Reflective Sensor * - * @return True if the sensor has detected black + * UPM module for the Grove IR reflective sensor. The sensitivity + * can be adjusted with the potentiometer on the sensor module. It + * has a range of approximately 15 mm, and a quick response time. + * + * It detects high-contrast dark areas on a light background. + * + * This module allows the user to determine the current status + * (black detected or not). Additionally, if desired, an interrupt + * service routine (ISR) can be installed that is called when + * black is detected. Either method can be used, depending on your + * use case. + * + * @image html rpr220.jpg + * @snippet rpr220.cxx Interesting + * @snippet rpr220-intr.cxx Interesting */ - bool blackDetected(); + class RPR220 { + public: + /** + * RPR220 constructor + * + * @param pin Digital pin to use + */ + RPR220(int pin); + + /** + * RPR220 destructor + */ + ~RPR220(); + + /** + * Gets the status of the pin; true means black has been detected + * + * @return True if the sensor has detected black + */ + bool blackDetected(); #if defined(SWIGJAVA) || defined(JAVACALLBACK) - void installISR(jobject runnable); + void installISR(jobject runnable); #else - /** - * Installs an ISR to be called when - * black is detected - * - * @param fptr Pointer to a function to be called on interrupt - * @param arg Pointer to an object to be supplied as an - * argument to the ISR. - */ - void installISR(void (*isr)(void *), void *arg); + /** + * Installs an ISR to be called when + * black is detected + * + * @param fptr Pointer to a function to be called on interrupt + * @param arg Pointer to an object to be supplied as an + * argument to the ISR. + */ + void installISR(void (*isr)(void *), void *arg); #endif - /** - * Uninstalls the previously installed ISR - * - */ - void uninstallISR(); + /** + * Uninstalls the previously installed ISR + * + */ + void uninstallISR(); + + private: + rpr220_context m_rpr220; - private: #if defined(SWIGJAVA) || defined(JAVACALLBACK) - void installISR(void (*isr)(void *), void *arg); + void installISR(void (*isr)(void *), void *arg); #endif - bool m_isrInstalled; - mraa_gpio_context m_gpio; - }; + }; } diff --git a/src/rpr220/rpr220_fti.c b/src/rpr220/rpr220_fti.c new file mode 100644 index 00000000..1a6cc31f --- /dev/null +++ b/src/rpr220/rpr220_fti.c @@ -0,0 +1,94 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "rpr220.h" +#include + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_rpr220_name[] = "RPR220"; +const char upm_rpr220_description[] = "IR Reflective Sensor"; +const upm_protocol_t upm_rpr220_protocol[] = {UPM_GPIO}; +const upm_sensor_t upm_rpr220_category[] = {UPM_BINARY}; + +// forward declarations +const void* upm_rpr220_get_ft(upm_sensor_t sensor_type); +void* upm_rpr220_init_name(); +void upm_rpr220_close(void *dev); +upm_result_t upm_rpr220_black_detected(void *dev, bool *value); + +const upm_sensor_descriptor_t upm_rpr220_get_descriptor() +{ + upm_sensor_descriptor_t usd; + usd.name = upm_rpr220_name; + usd.description = upm_rpr220_description; + usd.protocol_size = 1; + usd.protocol = upm_rpr220_protocol; + usd.category_size = 1; + usd.category = upm_rpr220_category; + return usd; +} + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = upm_rpr220_init_name, + .upm_sensor_close = upm_rpr220_close, +}; + +static const upm_binary_ft bft = +{ + .upm_binary_get_value = upm_rpr220_black_detected, +}; + +const void* upm_rpr220_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft; + case UPM_BINARY: + return &bft; + default: + return NULL; + } +} + +void *upm_rpr220_init_name() +{ + return NULL; +} + +void upm_rpr220_close(void *dev) +{ + rpr220_close((rpr220_context)dev); +} + +upm_result_t upm_rpr220_black_detected(void *dev, bool *value) +{ + *value = rpr220_black_detected((rpr220_context)dev); + + return UPM_SUCCESS; +}