YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
gpio_BBB.cpp
1#include "gpio_BBB.h"
2#include <fcntl.h>
3#include <sys/ioctl.h>
4#include <unistd.h>
5#include <cstring>
6#include <cerrno>
7#include <string>
8#include <iostream>
9using namespace std;
10
11gpio_BBB gpio_BBB::inst;
12
13bool running;
14
15// Simple exception class for error handling
16class gpio_exception : public std::exception {
17 public:
18 gpio_exception (std::string msg, int err) {
19 _msg = msg + strerror(abs(err));
20 }
21 ~gpio_exception () throw() { }
22 const char* what() const throw() {
23 return _msg.c_str();
24 }
25 private:
26 std::string _msg;
27};
28
29// The user-space irq-handler thread. It blocks on a
30// read on the gpio_bbb character device. When the
31// read succeeds an irq has occured, and the gpio
32// producing the irq is returned. After that the
33// related user irq handler is called.
34
35void gpio_BBB::irq_handler() {
36 while (running) {
37 int gpio = read(_fd_gpio, NULL, 0);
38 // Exit thread if we get a wrong gpio number
39 if (gpio < 0 || gpio >= GPIO_COUNT) break;
40 // Call user handler
41 if (usrHandler[gpio]) usrHandler[gpio](gpio, NULL);
42 }
43}
44
45gpio_BBB::gpio_BBB() {
46 // Clear the irq handlers
47 for (int i=0; i < GPIO_COUNT; ++i)
48 usrHandler[i] = 0;
49 // open the GPIO device
50 _fd_gpio = open("/dev/" GPIO_DEV_NAME, O_RDWR );
51 if( _fd_gpio < 0 ) {
52 throw gpio_exception("Cannot open /dev/" GPIO_DEV_NAME ", ", errno);
53 }
54 // start the irq thread
55 running=true;
56 irq_thread = std::thread([&](){ irq_handler();} );
57}
58
59gpio_BBB::~gpio_BBB() {
60 // Stop the irq thread
61 running=false;
62 write(_fd_gpio, NULL, 0);
63 irq_thread.join();
64 close(_fd_gpio);
65}
66
68// GPIO methods //
70void gpio_BBB::gpioMode (gpio_pin_t gpio, gpio_mode_t mode) {
71 if (gpio >= GPIO_COUNT) {
72 throw gpio_exception("GPIO out of range, ", EINVAL);
73 }
74 int ret = ioctl(_fd_gpio, IOCTL_GPIO_MODE, GPIO_DATA(gpio, mode));
75 if (ret < 0) {
76 throw gpio_exception("gpioMode: ", ret);
77 }
78}
79
80bool gpio_BBB::gpioRead (gpio_pin_t gpio) {
81 return ioctl(_fd_gpio, IOCTL_GPIO_READ, gpio);
82}
83
84void gpio_BBB::gpioWrite (gpio_pin_t gpio, bool value) {
85 int ret = ioctl(_fd_gpio, IOCTL_GPIO_WRITE, GPIO_DATA(gpio, value));
86 if (ret < 0) {
87 throw gpio_exception("gpioWrite: ", ret);
88 }
89}
90
91void gpio_BBB::gpioToggle (gpio_pin_t gpio) {
92 int ret = ioctl(_fd_gpio, IOCTL_GPIO_TOGGLE, gpio);
93 if (ret < 0) {
94 throw gpio_exception("gpioToggle: ", ret);
95 }
96}
97
99// Interrupt methods //
101void gpio_BBB::gpioAttachIrq (gpio_pin_t gpio, gpio_irq_t mode,
102 void (*handler)(gpio_pin_t, void *), void * arg) {
103 if (gpio >= GPIO_COUNT) {
104 throw gpio_exception("GPIO number out of range, ", EINVAL);
105 }
106 usrHandler[gpio] = handler;
107 int ret = ioctl(_fd_gpio, IOCTL_GPIO_ATTACH_IRQ, GPIO_DATA(gpio, mode));
108 if (ret < 0) {
109 throw gpio_exception("gpioAttachIrq: ", ret);
110 }
111 gpioEnableIrq(gpio);
112}
113
114void gpio_BBB::gpioDetachIrq (gpio_pin_t gpio) {
115 gpioDisableIrq(gpio);
116 usrHandler[gpio] = 0;
117 int ret = ioctl(_fd_gpio, IOCTL_GPIO_DETACH_IRQ, gpio);
118 if (ret < 0) {
119 throw gpio_exception("gpioDetachIrq: ", ret);
120 }
121}
122
123void gpio_BBB::gpioEnableIrq (gpio_pin_t gpio) {
124 int ret = ioctl(_fd_gpio, IOCTL_GPIO_ENABLE_IRQ, gpio);
125 if (ret < 0) {
126 throw gpio_exception("gpioEnableIrq: ", ret);
127 }
128}
129
130void gpio_BBB::gpioDisableIrq(gpio_pin_t gpio) {
131 int ret = ioctl(_fd_gpio, IOCTL_GPIO_DISABLE_IRQ, gpio);
132 if (ret < 0) {
133 throw gpio_exception("gpioDisableIrq: ", ret);
134 }
135}
136
137void gpio_BBB::setDebounce (uint8_t gpio, uint16_t msdelay) {
138 int ret = ioctl(_fd_gpio, IOCTL_SET_DEBOUNCE, GPIO_DATA(gpio, msdelay));
139 if (ret < 0) {
140 throw gpio_exception("setDebounce: ", ret);
141 }
142}
143