diff --git a/FlippR-Driver/src/input/Detector.cpp b/FlippR-Driver/src/input/Detector.cpp index 0f1d126..b321c29 100644 --- a/FlippR-Driver/src/input/Detector.cpp +++ b/FlippR-Driver/src/input/Detector.cpp @@ -10,62 +10,22 @@ #include #include -#include "../lib/wiringPi/wiringPi.h" - namespace Input { -Detector::Detector(std::map input_config, std::map events) : - gpio(input_config), input_events(events), is_running(true) +Detector::Detector(GPIOInterface& gpio_interface, std::map events, InputEventNotifier& input_event_notifier) : + gpio_interface(gpio_interface), input_events(events), is_running(true), input_event_notifier(input_event_notifier) { detect_thread = std::thread(&Detector::detect, this); - notify_thread = std::thread(&Detector::notify_handlers, this); } Detector::~Detector() { is_running = false; - notify_thread.join(); detect_thread.join(); } -void Detector::register_input_event_handler(InputEventHandler* handler) -{ - LOCK_EVENT_HANDLER(); - event_handler.insert(handler); -} - -void Detector::unregister_input_event_handler(InputEventHandler* handler) -{ - LOCK_EVENT_HANDLER(); - event_handler.erase(handler); -} - -void Detector::notify_handlers() -{ - while(is_running) - { - // return if no event in queue - if(event_queue.empty()) - { - std::this_thread::yield(); - return; - } - - InputEvent event = event_queue.front(); - event_queue.pop(); - - // getting a guard and calling all registered handlers - LOCK_EVENT_HANDLER(); - for(auto handler : event_handler) - { - // todo timeout! - handler->handle(event); - } - } -} - // Cycles over all inputs and enqueues an input event if detected. void Detector::detect() { @@ -77,7 +37,7 @@ void Detector::detect() try { InputEvent& event = input_events.at(address); - event_queue.emplace(event); + input_event_notifier.distribute_event(event); } catch(std::out_of_range& e) { @@ -87,24 +47,19 @@ void Detector::detect() } } -// todo work with gpiointerface bool Detector::check_inputs(char& address) { for(int row = 0; row < 8; row++) { - digitalWrite(gpio["ROW_A"], row & 0b001); - digitalWrite(gpio["ROW_B"], row & 0b010); - digitalWrite(gpio["ROW_C"], row & 0b100); + gpio_interface.write_input_row(row); for(int col = 0; col < 8; col++) { - digitalWrite(gpio["COL_A"], col & 0b001); - digitalWrite(gpio["COL_B"], col & 0b010); - digitalWrite(gpio["COL_C"], col & 0b100); + gpio_interface.write_input_col(col); // wait for mux to set address std::this_thread::sleep_for(std::chrono::nanoseconds(SLEEP_DURATION_NANO)); - if(digitalRead(gpio["INPUT"])) + if(gpio_interface.read_input_data()) { address = pow(2, row) + col; return true; diff --git a/FlippR-Driver/src/input/Detector.h b/FlippR-Driver/src/input/Detector.h index 6cc611d..00bcf11 100644 --- a/FlippR-Driver/src/input/Detector.h +++ b/FlippR-Driver/src/input/Detector.h @@ -14,19 +14,16 @@ #ifndef DETECTOR_H_ #define DETECTOR_H_ -#include -#include #include #include -#include + +#include "../utilities/GPIOInterface.h" #include "InputEvent.h" - -#define LOCK_EVENT_HANDLER() std::lock_guard event_handler_guard(event_handler_mutex) +#include "InputEventNotifier.h" #define SLEEP_DURATION_NANO 900 - namespace Input { @@ -40,30 +37,22 @@ class Detector { public: - Detector(std::map input_config, std::map events); + Detector(GPIOInterface& gpio_interface, std::map events, InputEventNotifier& input_event_notifier); ~Detector(); - void register_input_event_handler(InputEventHandler* handler); - void unregister_input_event_handler(InputEventHandler* handler); - private: - void notify_handlers(); - void detect(); bool check_inputs(char& address); private: - std::map gpio; + GPIOInterface& gpio_interface; std::map input_events; - std::queue event_queue; - std::set event_handler; + InputEventNotifier& input_event_notifier; bool is_running; std::thread detect_thread; - std::thread notify_thread; - std::mutex event_handler_mutex; }; } diff --git a/FlippR-Driver/src/input/InputEvent.h b/FlippR-Driver/src/input/InputEvent.h index a48478a..e017791 100644 --- a/FlippR-Driver/src/input/InputEvent.h +++ b/FlippR-Driver/src/input/InputEvent.h @@ -17,24 +17,21 @@ namespace Input class InputEvent { public: - InputEvent(char address, std::string name) : address(address), name(name){} + InputEvent(char address, char priority, std::string name) : address(address), priority(priority), name(name){} - bool operator==(const char other) + bool operator==(const InputEvent& other) { - return this->address == other; - } - - bool operator==(const std::string other) - { - return this->name == other; + return this->name == other.name; } bool operator<(const InputEvent& other) { - return this->address < other.address; + return this->priority < other.priority; } + private: const char address; + const char priority; const std::string name; }; diff --git a/FlippR-Driver/src/input/InputEventNotifier.cpp b/FlippR-Driver/src/input/InputEventNotifier.cpp new file mode 100644 index 0000000..4bed545 --- /dev/null +++ b/FlippR-Driver/src/input/InputEventNotifier.cpp @@ -0,0 +1,59 @@ +/* + * InputEventNotifier.cpp + * + * Created on: May 17, 2018 + * Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert, Rafael Vinci, Dr. Franca Rupprecht + */ + +#include "InputEventNotifier.h" + +namespace Input +{ + +InputEventNotifier::InputEventNotifier() +: is_running(true) +{ + notify_thread = std::thread(&InputEventNotifier::notify, this); +} + +InputEventNotifier::~InputEventNotifier() +{ + is_running = false; + + notify_thread.join(); +} + +void InputEventNotifier::register_input_event_handler(InputEventHandler* handler) +{ + std::lock_guard event_handler_guard(event_handler_mutex); + event_handler.insert(handler); +} + +void InputEventNotifier::unregister_input_event_handler(InputEventHandler* handler) +{ + std::lock_guard event_handler_guard(event_handler_mutex); + event_handler.erase(handler); +} + +void InputEventNotifier::distribute_event(InputEvent& event) +{ + event_queue.push(event); +} + +void InputEventNotifier::notify() +{ + while(is_running) + { + InputEvent event = event_queue.pop(); + + // getting a guard and calling all registered handlers + std::lock_guard event_handler_guard(event_handler_mutex); + for(auto handler : event_handler) + { + // todo timeout! + handler->handle(event); + } + } +} + +} diff --git a/FlippR-Driver/src/input/InputEventNotifier.h b/FlippR-Driver/src/input/InputEventNotifier.h new file mode 100644 index 0000000..850e536 --- /dev/null +++ b/FlippR-Driver/src/input/InputEventNotifier.h @@ -0,0 +1,47 @@ +/* + * InputEventNotifier.h + * + * Created on: May 17, 2018 + * Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert, Rafael Vinci, Dr. Franca Rupprecht + */ + +#ifndef SRC_INPUT_INPUTEVENTNOTIFIER_H_ +#define SRC_INPUT_INPUTEVENTNOTIFIER_H_ + +#include +#include +#include + +#include "../utilities/BlockingQueue.hpp" +#include "InputEventHandler.h" +#include "InputEvent.h" + +namespace Input +{ +class InputEventNotifier +{ +public: + InputEventNotifier(); + ~InputEventNotifier(); + + void register_input_event_handler(InputEventHandler* handler); + void unregister_input_event_handler(InputEventHandler* handler); + + void distribute_event(InputEvent& event); + +private: + void notify(); + +private: + BlockingQueue event_queue; + std::set event_handler; + + bool is_running; + std::thread notify_thread; + std::mutex event_handler_mutex; +}; +} + + + +#endif /* SRC_INPUT_INPUTEVENTNOTIFIER_H_ */ diff --git a/FlippR-Driver/src/input/InputFactory.h b/FlippR-Driver/src/input/InputFactory.h index d4472e1..d70d81e 100644 --- a/FlippR-Driver/src/input/InputFactory.h +++ b/FlippR-Driver/src/input/InputFactory.h @@ -35,7 +35,7 @@ public: std::map input_events = create_input_events(matrix_config); - return std::shared_ptr(Detector(input_config, input_events)); + return std::shared_ptr(new Detector(input_config, input_events)); } private: diff --git a/FlippR-Driver/src/utilities/BlockingQueue.hpp b/FlippR-Driver/src/utilities/BlockingQueue.hpp new file mode 100644 index 0000000..2e545f3 --- /dev/null +++ b/FlippR-Driver/src/utilities/BlockingQueue.hpp @@ -0,0 +1,43 @@ +/* + * BlockingQueue.hpp + * + * Created on: May 17, 2018 + * Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert, Rafael Vinci, Dr. Franca Rupprecht + */ + +#ifndef SRC_UTILITIES_BLOCKINGQUEUE_HPP_ +#define SRC_UTILITIES_BLOCKINGQUEUE_HPP_ + +#include +#include +#include +#include + +template +class BlockingQueue +{ +private: + std::mutex d_mutex; + std::condition_variable d_condition; + std::priority_queue d_queue; +public: + void push(T const& value) { + { + std::unique_lock lock(this->d_mutex); + d_queue.push_front(value); + } + this->d_condition.notify_one(); + } + + T pop() { + std::unique_lock lock(this->d_mutex); + this->d_condition.wait(lock, [=]{ return !this->d_queue.empty(); }); + T rc(std::move(this->d_queue.back())); + this->d_queue.pop_back(); + return rc; + } +}; + + + +#endif /* SRC_UTILITIES_BLOCKINGQUEUE_HPP_ */ diff --git a/FlippR-Driver/src/utilities/GPIOInterface.cpp b/FlippR-Driver/src/utilities/GPIOInterface.cpp new file mode 100644 index 0000000..cd20e47 --- /dev/null +++ b/FlippR-Driver/src/utilities/GPIOInterface.cpp @@ -0,0 +1,48 @@ + +/* + * GPIOInterface.cpp + * + * Created on: May 17, 2018 + * Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert, Rafael Vinci, Dr. Franca Rupprecht + */ + +#include "GPIOInterface.h" + +#include "../lib/wiringPi/wiringPi.h" + +GPIOInterface::GPIOInterface(std::string config_path) +{ +} + +GPIOInterface::~GPIOInterface() +{ +} + +bool GPIOInterface::read_input_data() +{ + return read_input_pin(input_data_address); +} + +void GPIOInterface::write_input_row(char data) +{ + write_pin(input_row_address, data & 0b001); + write_pin(input_row_address, data & 0b010); + write_pin(input_row_address, data & 0b100); +} + +void GPIOInterface::write_input_col(char data) +{ + write_pin(input_col_address, data & 0b001); + write_pin(input_col_address, data & 0b010); + write_pin(input_col_address, data & 0b100); +} + +void GPIOInterface::write_pin(char address, bool data) +{ + digitalWrite(address, data); +} + +bool GPIOInterface::read_input_pin(char address) +{ + return digitalRead(address); +} diff --git a/FlippR-Driver/src/utilities/GPIOInterface.hpp b/FlippR-Driver/src/utilities/GPIOInterface.h similarity index 54% rename from FlippR-Driver/src/utilities/GPIOInterface.hpp rename to FlippR-Driver/src/utilities/GPIOInterface.h index bc21bc4..0eba47b 100644 --- a/FlippR-Driver/src/utilities/GPIOInterface.hpp +++ b/FlippR-Driver/src/utilities/GPIOInterface.h @@ -10,12 +10,11 @@ * Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert, Rafael Vinci, Dr. Franca Rupprecht */ -#ifndef SRC_UTILITIES_GPIOINTERFACE_HPP_ -#define SRC_UTILITIES_GPIOINTERFACE_HPP_ +#ifndef SRC_UTILITIES_GPIOINTERFACE_H_ +#define SRC_UTILITIES_GPIOINTERFACE_H_ #include -#include <../lib/wiringPi/wiringPi.h> #include "../lib/json/json.hpp" using namespace nlohmann; @@ -26,18 +25,24 @@ public: GPIOInterface(std::string config_path); ~GPIOInterface(); - void write_address(); - void read_pin(); + void write_input_row(char data); + void write_input_col(char data); + bool read_input_data(); + +private: + static void write_pin(char address, bool data); + static bool read_input_pin(char address); -public: - // todo some mapping class interface shit that a user can ask for what is actually usable \ - something like: A has gpio interface at gpio -> gpio.input.column. just dont work with strings private: json config; + char input_row_address; + char input_col_address; + char input_data_address; + }; -#endif /* SRC_UTILITIES_GPIOINTERFACE_HPP_ */ +#endif /* SRC_UTILITIES_GPIOINTERFACE_H_ */