diff options
| author | Hannes Schulze <hannes.hs.schulze@fau.de> | 2025-05-02 12:50:57 +0200 |
|---|---|---|
| committer | Hannes Schulze <hannes.hs.schulze@fau.de> | 2025-05-02 12:50:57 +0200 |
| commit | 24c521f5a4b9f2e1a98668e9d9f7b19b4c9a9bd7 (patch) | |
| tree | a48ca9a718c719b30dae19a78b709874ca9b2bc5 /app | |
| parent | def315971fccfe6a1a1743b3de62addd5f0527dc (diff) | |
add controller test program
Diffstat (limited to 'app')
| -rw-r--r-- | app/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | app/controller/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | app/controller/main.cc | 33 | ||||
| -rw-r--r-- | app/controller/serial-controller.cc | 96 | ||||
| -rw-r--r-- | app/controller/serial-controller.hh | 29 | ||||
| -rw-r--r-- | app/encrypt/CMakeLists.txt | 10 |
6 files changed, 178 insertions, 5 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 8cc4763..25c8c84 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -14,3 +14,4 @@ else() endif() add_subdirectory(encrypt) +add_subdirectory(controller) diff --git a/app/controller/CMakeLists.txt b/app/controller/CMakeLists.txt new file mode 100644 index 0000000..27137e5 --- /dev/null +++ b/app/controller/CMakeLists.txt @@ -0,0 +1,14 @@ +add_executable(nes_app_controller) + +target_include_directories(nes_app_controller PRIVATE .) +target_link_libraries( + nes_app_controller + PRIVATE + nes::options + nes::nes) + +target_sources( + nes_app_controller + PRIVATE + main.cc + serial-controller.cc) diff --git a/app/controller/main.cc b/app/controller/main.cc new file mode 100644 index 0000000..a9ea5bd --- /dev/null +++ b/app/controller/main.cc @@ -0,0 +1,33 @@ +#include <iostream> +#include <cstdlib> +#include <thread> +#include "serial-controller.hh" + +int main(int argc, char** argv) +{ + if (argc != 2) + { + std::cerr << "Usage:\n"; + std::cerr << " " << argv[0] << " <controller-path>" << std::endl; + return EXIT_FAILURE; + } + + auto const path = argv[1]; + auto controller = nes::app::test::serial_controller{ path }; + if (!controller.is_reliable()) + { + return EXIT_FAILURE; + } + + while (true) + { + auto const buttons = controller.read_buttons(); + if (!buttons.is_empty()) + { + std::cout << "Buttons: " << buttons.get_raw_value() << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + + return EXIT_SUCCESS; +} diff --git a/app/controller/serial-controller.cc b/app/controller/serial-controller.cc new file mode 100644 index 0000000..8485ec4 --- /dev/null +++ b/app/controller/serial-controller.cc @@ -0,0 +1,96 @@ +#include "serial-controller.hh" +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <termios.h> +#include <sys/ioctl.h> + +namespace nes::app::test +{ + serial_controller::serial_controller(char const* path) + : path_{ path } + { + fd_ = open(path, O_RDONLY | O_NOCTTY | O_NDELAY | O_NONBLOCK); + if (fd_ == -1) + { + perror("serial_controller: open"); + return; + } + + if (!set_up()) { close(); } + } + + serial_controller::~serial_controller() + { + close(); + } + + auto serial_controller::is_reliable() const -> bool + { + return fd_ != -1; + } + + auto serial_controller::read_buttons() -> sys::button_mask + { + if (fd_ == -1) { return sys::button_mask{}; } + + // Poll for any updates until we can't read anymore. + while (true) + { + auto buf = u8{}; + auto const res = read(fd_, &buf, 1); + if (res == -1) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) { break; } + + perror("read from controller"); + close(); + break; + } + + current_ = sys::button_mask::from_raw_value(buf); + } + + return current_; + } + + + auto serial_controller::set_up() -> bool + { + if (ioctl(fd_, TIOCEXCL) == -1) + { + perror("serial_controller: ioctl"); + return false; + } + + auto attr = termios{}; + if (tcgetattr(fd_, &attr) == -1) + { + perror("serial_controller: tcgetattr"); + return false; + } + + cfsetispeed(&attr, B57600); + cfsetospeed(&attr, B57600); + attr.c_cflag = attr.c_cflag | CLOCAL | CREAD; + attr.c_cflag = (attr.c_cflag & static_cast<tcflag_t>(~CSIZE)) | CS8; + + if (tcsetattr(fd_, TCSANOW, &attr) == -1) + { + perror("serial_controller: tcsetattr"); + return false; + } + + return true; + } + + auto serial_controller::close() -> void + { + if (fd_ != -1) + { + ::close(fd_); + fd_ = -1; + } + } +} // namespace nes::app::mac diff --git a/app/controller/serial-controller.hh b/app/controller/serial-controller.hh new file mode 100644 index 0000000..bc217b0 --- /dev/null +++ b/app/controller/serial-controller.hh @@ -0,0 +1,29 @@ +#pragma once + +#include "nes/app/input/input-device-controller.hh" + +namespace nes::app::test +{ + /// Input device for an NES controller plugged in via serial port. + class serial_controller final : public input_device_controller + { + char const* path_; + int fd_{ -1 }; + sys::button_mask current_{}; + index index_{ index::unused }; + + public: + explicit serial_controller(char const* path); + ~serial_controller() override; + + auto is_reliable() const -> bool override; + auto get_name() const -> string_view override { return path_; } + auto get_index() const -> index override { return index_; } + auto set_index(index const v) -> void override { index_ = v; } + auto read_buttons() -> sys::button_mask override; + + private: + auto set_up() -> bool; + auto close() -> void; + }; +} // namespace nes::app:mac diff --git a/app/encrypt/CMakeLists.txt b/app/encrypt/CMakeLists.txt index 5da53af..d147284 100644 --- a/app/encrypt/CMakeLists.txt +++ b/app/encrypt/CMakeLists.txt @@ -1,13 +1,13 @@ -add_executable(nes_app_test) +add_executable(nes_app_encrypt) -target_include_directories(nes_app_test PRIVATE .) +target_include_directories(nes_app_encrypt PRIVATE .) target_link_libraries( - nes_app_test + nes_app_encrypt PRIVATE nes::options nes::nes) target_sources( - nes_app_test + nes_app_encrypt PRIVATE - main.cc)
\ No newline at end of file + main.cc) |
