1/* 2 * Author: Brendan Le Foll <brendan.le.foll@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 37namespace mraa 38{ 39 40// These enums must match the enums in gpio.h 41 42/** 43 * Gpio Output modes 44 */ 45typedef 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 */ 55typedef 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 */ 65typedef 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 */ 79class 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