Skip to content

Commit b59c4f2

Browse files
committed
Add support for inverted (active low) logic in GPIO plugin
1 parent 84cd83a commit b59c4f2

File tree

5 files changed

+70
-6
lines changed

5 files changed

+70
-6
lines changed

plugins/gpio/GPIODriver.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <sys/types.h>
2929
#include <unistd.h>
3030

31+
#include <algorithm>
3132
#include <sstream>
3233
#include <string>
3334
#include <vector>
@@ -43,6 +44,7 @@ namespace gpio {
4344
const char GPIODriver::GPIO_BASE_DIR[] = "/sys/class/gpio/gpio";
4445

4546
using ola::thread::MutexLocker;
47+
using std::find;
4648
using std::string;
4749
using std::vector;
4850

@@ -122,7 +124,9 @@ bool GPIODriver::SetupGPIO() {
122124
* echo N > /sys/class/gpio/export
123125
* That requires root access.
124126
*/
125-
const string direction("out");
127+
const string normal_direction("low");
128+
const string inverted_direction("high");
129+
const string* direction = nullptr;
126130
bool failed = false;
127131
vector<uint16_t>::const_iterator iter = m_options.gpio_pins.begin();
128132
for (; iter != m_options.gpio_pins.end(); ++iter) {
@@ -134,7 +138,12 @@ bool GPIODriver::SetupGPIO() {
134138
break;
135139
}
136140

137-
GPIOPin pin = {pin_fd, UNDEFINED, false};
141+
// Check if pin is in the inverted pin list
142+
bool inverted = (find(m_options.gpio_inverted_pins.begin(),
143+
m_options.gpio_inverted_pins.end(),
144+
(*iter)) != m_options.gpio_inverted_pins.end());
145+
146+
GPIOPin pin = {pin_fd, UNDEFINED, false, inverted};
138147

139148
// Set dir
140149
str.str("");
@@ -144,9 +153,19 @@ bool GPIODriver::SetupGPIO() {
144153
failed = true;
145154
break;
146155
}
147-
if (write(fd, direction.c_str(), direction.size()) < 0) {
148-
OLA_WARN << "Failed to enable output on " << str.str() << " : "
149-
<< strerror(errno);
156+
// Assign correct initial state
157+
if (inverted) {
158+
direction = &inverted_direction;
159+
} else {
160+
direction = &normal_direction;
161+
}
162+
163+
OLA_DEBUG << "Configuring GPIO pin " << static_cast<int>(*iter)
164+
<< " with " << ( inverted ? "inverted" : "normal" ) << " logic";
165+
if (write(fd, direction->c_str(), direction->size()) < 0) {
166+
OLA_WARN << "Failed to enable output on " << str.str()
167+
<< " with " << ( inverted ? "inverted" : "normal" ) << " logic"
168+
<< " : " << strerror(errno);
150169
failed = true;
151170
}
152171
close(fd);
@@ -191,7 +210,14 @@ bool GPIODriver::UpdateGPIOPins(const DmxBuffer &dmx) {
191210

192211
// Change the pin state if required.
193212
if (action != NO_CHANGE) {
194-
char data = (action == TURN_ON ? '1' : '0');
213+
char data;
214+
bool state = (action == TURN_ON);
215+
// Handle inverted logic appropriately
216+
if (m_gpio_pins[i].inverted) {
217+
state = !state;
218+
}
219+
// Convert to char and write to sysfs
220+
data = (state ? '0' : '1');
195221
if (write(m_gpio_pins[i].fd, &data, sizeof(data)) < 0) {
196222
OLA_WARN << "Failed to toggle GPIO pin " << i << ", fd "
197223
<< static_cast<int>(m_gpio_pins[i].fd) << ": "

plugins/gpio/GPIODriver.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ class GPIODriver : private ola::thread::Thread {
4949
*/
5050
std::vector<uint16_t> gpio_pins;
5151

52+
/**
53+
* @brief A list of gpio_pins which use inverted logic.
54+
*/
55+
std::vector<uint16_t> gpio_inverted_pins;
56+
5257
/**
5358
* @brief The DMX512 start address of the first pin
5459
*/
@@ -108,6 +113,7 @@ class GPIODriver : private ola::thread::Thread {
108113
int fd;
109114
GPIOState state;
110115
bool last_value;
116+
bool inverted;
111117
};
112118

113119
typedef std::vector<GPIOPin> GPIOPins;

plugins/gpio/GPIOPlugin.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "plugins/gpio/GPIOPlugin.h"
2222

23+
#include <algorithm>
2324
#include <memory>
2425
#include <string>
2526
#include <vector>
@@ -35,10 +36,12 @@ namespace plugin {
3536
namespace gpio {
3637

3738
using std::auto_ptr;
39+
using std::find;
3840
using std::string;
3941
using std::vector;
4042

4143
const char GPIOPlugin::GPIO_PINS_KEY[] = "gpio_pins";
44+
const char GPIOPlugin::GPIO_PINS_INVERTED_KEY[] = "gpio_pins_inverted";
4245
const char GPIOPlugin::GPIO_SLOT_OFFSET_KEY[] = "gpio_slot_offset";
4346
const char GPIOPlugin::GPIO_TURN_OFF_KEY[] = "gpio_turn_off";
4447
const char GPIOPlugin::GPIO_TURN_ON_KEY[] = "gpio_turn_on";
@@ -87,6 +90,28 @@ bool GPIOPlugin::StartHook() {
8790
options.gpio_pins.push_back(pin);
8891
}
8992

93+
pin_list.clear();
94+
StringSplit(m_preferences->GetValue(GPIO_PINS_INVERTED_KEY), &pin_list, ",");
95+
iter = pin_list.begin();
96+
for (; iter != pin_list.end(); ++iter) {
97+
if (iter->empty()) {
98+
continue;
99+
}
100+
101+
uint16_t pin;
102+
if (!StringToInt(*iter, &pin)) {
103+
OLA_WARN << "Invalid value for GPIO pin to invert: " << *iter;
104+
return false;
105+
}
106+
107+
if (find(pin_list.begin(), pin_list.end(), (*iter)) == pin_list.end()) {
108+
OLA_WARN << "Inverted pin " << (*iter) << " not found in GPIO pin list";
109+
return false;
110+
}
111+
112+
options.gpio_inverted_pins.push_back(pin);
113+
}
114+
90115
if (options.gpio_pins.empty()) {
91116
return true;
92117
}
@@ -124,6 +149,9 @@ bool GPIOPlugin::SetDefaultPreferences() {
124149
save |= m_preferences->SetDefaultValue(GPIO_PINS_KEY,
125150
StringValidator(),
126151
"");
152+
save |= m_preferences->SetDefaultValue(GPIO_PINS_INVERTED_KEY,
153+
StringValidator(),
154+
"");
127155
save |= m_preferences->SetDefaultValue(GPIO_SLOT_OFFSET_KEY,
128156
UIntValidator(1, DMX_UNIVERSE_SIZE),
129157
"1");

plugins/gpio/GPIOPlugin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class GPIOPlugin: public ola::Plugin {
5555
bool SetDefaultPreferences();
5656

5757
static const char GPIO_PINS_KEY[];
58+
static const char GPIO_PINS_INVERTED_KEY[];
5859
static const char GPIO_SLOT_OFFSET_KEY[];
5960
static const char GPIO_TURN_OFF_KEY[];
6061
static const char GPIO_TURN_ON_KEY[];

plugins/gpio/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ The offset (start address) of the GPIO pins is configurable.
1111
`gpio_pins = [int]`
1212
The list of GPIO pins to control, each pin is mapped to a DMX512 slot.
1313

14+
`gpio_pins_inverted = [int]`
15+
The list of GPIO pins listed under `gpio_pins` which use inverted logic.
16+
1417
`gpio_slot_offset = <int>`
1518
The DMX512 slot for the first pin. Slots are indexed from 1.
1619

0 commit comments

Comments
 (0)