FluxSand 1.0
FluxSand - Interactive Digital Hourglass
Loading...
Searching...
No Matches
bsp_gpio.hpp
1#pragma once
2
3#include <gpiod.h>
4
5#include <atomic>
6#include <cassert>
7#include <functional>
8#include <stdexcept>
9#include <string>
10#include <thread>
11#include <utility>
12
19class Gpio {
20 public:
21 using Callback = std::function<void()>;
22
31 Gpio(const std::string& chip_name, unsigned int line_num, bool is_output,
32 int default_value = 1)
33 : chip_(gpiod_chip_open_by_name(chip_name.c_str())),
34 is_output_(is_output),
35 line_num_(line_num) {
36 assert(!chip_name.empty()); /* Ensure chip name is valid */
37
38 if (!chip_) {
39 std::perror("Failed to open GPIO chip");
40 }
41
42 line_ = gpiod_chip_get_line(chip_, line_num_);
43 if (!line_) {
44 gpiod_chip_close(chip_);
45 std::perror("Failed to get GPIO line");
46 }
47
48 int ret = is_output_
49 ? gpiod_line_request_output(line_, nullptr, default_value)
50 : gpiod_line_request_input(line_, nullptr);
51 if (ret < 0) {
52 std::perror("Failed to configure GPIO line");
53 }
54 }
55
62 running_ = false;
63
64 if (interrupt_thread_.joinable()) {
65 interrupt_thread_.join();
66 }
67
68 if (line_) {
69 gpiod_line_release(line_);
70 }
71
72 if (chip_) {
73 gpiod_chip_close(chip_);
74 }
75 }
76
82 void Write(int value) {
83 assert(is_output_);
84 if (gpiod_line_set_value(line_, value) < 0) {
85 std::perror("GPIO write failed");
86 }
87 }
88
94 int Read() const {
95 int value = gpiod_line_get_value(line_);
96 if (value < 0) {
97 std::perror("GPIO read failed");
98 }
99 return value;
100 }
101
110 if (is_output_) {
111 std::perror("Cannot register interrupt on output GPIO");
112 }
113
114 /* If line is already in use, release it */
115 if (line_) {
116 gpiod_line_release(line_);
117 }
118
119 /* Request GPIO line for interrupt events */
120 if (gpiod_line_request_rising_edge_events(line_, nullptr) < 0) {
121 std::perror("Failed to enable rising edge interrupt");
122 }
123
124 callback_ = std::move(cb);
125 running_ = true;
126
127 interrupt_thread_ = std::thread(&Gpio::InterruptWaitLoop, this);
128 }
129
130 private:
135 while (running_) {
136 int ret = gpiod_line_event_wait(line_, nullptr); // block until event
137 if (ret == 1 && callback_) {
138 struct gpiod_line_event event;
139 if (gpiod_line_event_read(line_, &event) == 0 &&
140 event.event_type == GPIOD_LINE_EVENT_RISING_EDGE) {
141 callback_();
142 }
143 }
144 }
145 }
146
147 gpiod_chip* chip_; // GPIO chip handle
148 gpiod_line* line_{}; // GPIO line handle
149 unsigned int line_num_; // Line number
150 bool is_output_; // Output mode flag
151
152 std::atomic<bool> running_{false}; // Interrupt thread flag
153 std::thread interrupt_thread_; // Interrupt handler thread
154 Callback callback_; // Registered callback
155};
~Gpio()
Definition bsp_gpio.hpp:61
int Read() const
Definition bsp_gpio.hpp:94
void EnableInterruptRisingEdgeWithCallback(Callback cb)
Definition bsp_gpio.hpp:109
void InterruptWaitLoop()
Definition bsp_gpio.hpp:134
Gpio(const std::string &chip_name, unsigned int line_num, bool is_output, int default_value=1)
Definition bsp_gpio.hpp:31
void Write(int value)
Definition bsp_gpio.hpp:82