Home | History | Annotate | Download | only in mraa
      1 /*
      2  * Author: Brendan Le Foll <brendan.le.foll (at) intel.com>
      3  * Copyright (c) 2014 Intel Corporation.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be
     14  * included in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 #pragma once
     26 
     27 #include "gpio.h"
     28 #include "types.hpp"
     29 #include <stdexcept>
     30 
     31 #if defined(SWIGJAVASCRIPT)
     32 #if NODE_MODULE_VERSION >= 0x000D
     33 #include <uv.h>
     34 #endif
     35 #endif
     36 
     37 namespace mraa
     38 {
     39 
     40 // These enums must match the enums in gpio.h
     41 
     42 /**
     43  * Gpio Output modes
     44  */
     45 typedef enum {
     46     MODE_STRONG = 0,   /**< Default. Strong High and Low */
     47     MODE_PULLUP = 1,   /**< Interupt on rising & falling */
     48     MODE_PULLDOWN = 2, /**< Interupt on rising only */
     49     MODE_HIZ = 3       /**< Interupt on falling only */
     50 } Mode;
     51 
     52 /**
     53  * Gpio Direction options
     54  */
     55 typedef enum {
     56     DIR_OUT = 0,      /**< Output. A Mode can also be set */
     57     DIR_IN = 1,       /**< Input */
     58     DIR_OUT_HIGH = 2, /**< Output. Init High */
     59     DIR_OUT_LOW = 3   /**< Output. Init Low */
     60 } Dir;
     61 
     62 /**
     63  * Gpio Edge types for interupts
     64  */
     65 typedef enum {
     66     EDGE_NONE = 0,   /**< No interrupt on Gpio */
     67     EDGE_BOTH = 1,   /**< Interupt on rising & falling */
     68     EDGE_RISING = 2, /**< Interupt on rising only */
     69     EDGE_FALLING = 3 /**< Interupt on falling only */
     70 } Edge;
     71 
     72 /**
     73  * @brief API to General Purpose IO
     74  *
     75  * This file defines the gpio interface for libmraa
     76  *
     77  * @snippet Blink-IO.cpp Interesting
     78  */
     79 class Gpio
     80 {
     81   public:
     82     /**
     83      * Instanciates a Gpio object
     84      *
     85      * @param pin pin number to use
     86      * @param owner (optional) Set pin owner, default behaviour is to 'own'
     87      * the pin if we exported it. This means we will close it on destruct.
     88      * Otherwise it will get left open. This is only valid in sysfs use
     89      * cases
     90      * @param raw (optional) Raw pins will use gpiolibs pin numbering from
     91      * the kernel module. Note that you will not get any muxers set up for
     92      * you so this may not always work as expected.
     93      */
     94     Gpio(int pin, bool owner = true, bool raw = false)
     95     {
     96         if (raw) {
     97             m_gpio = mraa_gpio_init_raw(pin);
     98         } else {
     99             m_gpio = mraa_gpio_init(pin);
    100         }
    101 
    102         if (m_gpio == NULL) {
    103             throw std::invalid_argument("Invalid GPIO pin specified");
    104         }
    105 
    106         if (!owner) {
    107             mraa_gpio_owner(m_gpio, 0);
    108         }
    109     }
    110     /**
    111      * Gpio object destructor, this will only unexport the gpio if we where
    112      * the owner
    113      */
    114     ~Gpio()
    115     {
    116         mraa_gpio_close(m_gpio);
    117     }
    118     /**
    119      * Set the edge mode for ISR
    120      *
    121      * @param mode The edge mode to set
    122      * @return Result of operation
    123      */
    124     Result
    125     edge(Edge mode)
    126     {
    127         return (Result) mraa_gpio_edge_mode(m_gpio, (mraa_gpio_edge_t) mode);
    128     }
    129 #if defined(SWIGPYTHON)
    130     Result
    131     isr(Edge mode, PyObject* pyfunc, PyObject* args)
    132     {
    133         return (Result) mraa_gpio_isr(m_gpio, (mraa_gpio_edge_t) mode, (void (*) (void*)) pyfunc, (void*) args);
    134     }
    135 #elif defined(SWIGJAVASCRIPT)
    136     static void
    137     v8isr(uv_work_t* req, int status)
    138     {
    139         mraa::Gpio* This = (mraa::Gpio*) req->data;
    140         int argc = 1;
    141         v8::Local<v8::Value> argv[] = { SWIGV8_INTEGER_NEW(-1) };
    142 #if NODE_MODULE_VERSION >= 0x000D
    143         v8::Local<v8::Function> f = v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), This->m_v8isr);
    144         f->Call(SWIGV8_CURRENT_CONTEXT()->Global(), argc, argv);
    145 #else
    146         This->m_v8isr->Call(SWIGV8_CURRENT_CONTEXT()->Global(), argc, argv);
    147 #endif
    148         delete req;
    149     }
    150 
    151     static void
    152     nop(uv_work_t* req)
    153     {
    154         // Do nothing.
    155     }
    156 
    157     static void
    158     uvwork(void* ctx)
    159     {
    160         uv_work_t* req = new uv_work_t;
    161         req->data = ctx;
    162         uv_queue_work(uv_default_loop(), req, nop, v8isr);
    163     }
    164 
    165     Result
    166     isr(Edge mode, v8::Handle<v8::Function> func)
    167     {
    168 #if NODE_MODULE_VERSION >= 0x000D
    169         m_v8isr.Reset(v8::Isolate::GetCurrent(), func);
    170 #else
    171         m_v8isr = v8::Persistent<v8::Function>::New(func);
    172 #endif
    173         return (Result) mraa_gpio_isr(m_gpio, (mraa_gpio_edge_t) mode, &uvwork, this);
    174     }
    175 #elif defined(SWIGJAVA) || defined(JAVACALLBACK)
    176     Result
    177     isr(Edge mode, jobject runnable)
    178     {
    179         return (Result) mraa_gpio_isr(m_gpio, (mraa_gpio_edge_t) mode, mraa_java_isr_callback, runnable);
    180     }
    181 #endif
    182     /**
    183      * Sets a callback to be called when pin value changes
    184      *
    185      * @param mode The edge mode to set
    186      * @param fptr Function pointer to function to be called when interupt is
    187      * triggered
    188      * @param args Arguments passed to the interrupt handler (fptr)
    189      * @return Result of operation
    190      */
    191     Result
    192     isr(Edge mode, void (*fptr)(void*), void* args)
    193     {
    194         return (Result) mraa_gpio_isr(m_gpio, (mraa_gpio_edge_t) mode, fptr, args);
    195     }
    196 
    197     /**
    198      * Exits callback - this call will not kill the isr thread immediatly
    199      * but only when it is out of it's critical section
    200      *
    201      * @return Result of operation
    202      */
    203     Result
    204     isrExit()
    205     {
    206 #if defined(SWIGJAVASCRIPT)
    207 #if NODE_MODULE_VERSION >= 0x000D
    208         m_v8isr.Reset();
    209 #else
    210         m_v8isr.Dispose();
    211         m_v8isr.Clear();
    212 #endif
    213 #endif
    214         return (Result) mraa_gpio_isr_exit(m_gpio);
    215     }
    216     /**
    217      * Change Gpio mode
    218      *
    219      * @param mode The mode to change the gpio into
    220      * @return Result of operation
    221      */
    222     Result
    223     mode(Mode mode)
    224     {
    225         return (Result )mraa_gpio_mode(m_gpio, (mraa_gpio_mode_t) mode);
    226     }
    227     /**
    228      * Change Gpio direction
    229      *
    230      * @param dir The direction to change the gpio into
    231      * @return Result of operation
    232      */
    233     Result
    234     dir(Dir dir)
    235     {
    236         return (Result )mraa_gpio_dir(m_gpio, (mraa_gpio_dir_t) dir);
    237     }
    238     /**
    239      * Read value from Gpio
    240      *
    241      * @return Gpio value
    242      */
    243     int
    244     read()
    245     {
    246         return mraa_gpio_read(m_gpio);
    247     }
    248     /**
    249      * Write value to Gpio
    250      *
    251      * @param value Value to write to Gpio
    252      * @return Result of operation
    253      */
    254     Result
    255     write(int value)
    256     {
    257         return (Result) mraa_gpio_write(m_gpio, value);
    258     }
    259     /**
    260      * Enable use of mmap i/o if available.
    261      *
    262      * @param enable true to use mmap
    263      * @return Result of operation
    264      */
    265     Result
    266     useMmap(bool enable)
    267     {
    268         return (Result) mraa_gpio_use_mmaped(m_gpio, (mraa_boolean_t) enable);
    269     }
    270     /**
    271      * Get pin number of Gpio. If raw param is True will return the
    272      * number as used within sysfs. Invalid will return -1.
    273      *
    274      * @param raw (optional) get the raw gpio number.
    275      * @return Pin number
    276      */
    277     int
    278     getPin(bool raw = false)
    279     {
    280         if (raw) {
    281             return mraa_gpio_get_pin_raw(m_gpio);
    282         }
    283         return mraa_gpio_get_pin(m_gpio);
    284     }
    285 
    286   private:
    287     mraa_gpio_context m_gpio;
    288 #if defined(SWIGJAVASCRIPT)
    289     v8::Persistent<v8::Function> m_v8isr;
    290 #endif
    291 };
    292 }
    293