vulp  2.3.0
Keyboard.cpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0
2 // Copyright 2023 Inria
3 
5 
8  termios term;
9  tcgetattr(STDIN_FILENO, &term);
10  term.c_lflag &= ~ICANON;
11  tcsetattr(STDIN_FILENO, TCSANOW, &term);
12  setbuf(stdin, NULL);
13 
14  key_pressed_ = false;
15  key_code_ = Key::UNKNOWN;
16 
17  last_key_poll_time_ = system_clock::now() - milliseconds(kPollingIntervalMS);
18 }
19 
21 
22 bool Keyboard::read_event() {
23  ssize_t bytes_available = 0;
24  ioctl(STDIN_FILENO, FIONREAD, &bytes_available);
25 
26  if (bytes_available) {
27  ssize_t bytes_to_read =
28  bytes_available < kMaxKeyBytes ? bytes_available : kMaxKeyBytes;
29  ssize_t bytes_read = ::read(STDIN_FILENO, &buf_, bytes_to_read);
30 
31  if (bytes_read < bytes_available) {
32  // Skip the remaining bytes
33  do {
34  unsigned char garbage[bytes_available - bytes_read];
35  bytes_read =
36  ::read(STDIN_FILENO, &garbage, bytes_available - bytes_read);
37  ioctl(STDIN_FILENO, FIONREAD, &bytes_available);
38  } while (bytes_available);
39  }
40  return 1;
41  }
42  return 0;
43 }
44 
45 Key Keyboard::map_char_to_key(unsigned char* buf) {
46  // Check for 3-byte characters first (i.e. arrows)
47  if (!memcmp(buf_, DOWN_BYTES, kMaxKeyBytes)) {
48  return Key::DOWN;
49  }
50  if (!memcmp(buf_, UP_BYTES, kMaxKeyBytes)) {
51  return Key::UP;
52  }
53  if (!memcmp(buf_, LEFT_BYTES, kMaxKeyBytes)) {
54  return Key::LEFT;
55  }
56  if (!memcmp(buf_, RIGHT_BYTES, kMaxKeyBytes)) {
57  return Key::RIGHT;
58  }
59 
60  // If the first byte corresponds to a lowercase ASCII alphabetic
61  if (is_lowercase_alpha(buf[0])) {
62  buf[0] -= 32; // Map to uppercase equivalent
63  }
64 
65  // We treat any printable ASCII as a single key code
66  if (is_printable_ascii(buf[0])) {
67  switch (buf[0]) {
68  case 87: // 0x57
69  return Key::W;
70  case 65: // 0x41
71  return Key::A;
72  case 83: // 0x53
73  return Key::S;
74  case 68: // 0x44
75  return Key::D;
76  case 88: // 0x58
77  return Key::X;
78  }
79  }
80  return Key::UNKNOWN;
81 }
82 
83 void Keyboard::write(Dictionary& observation) {
84  // Check elapsed time since last key polling
85  auto elapsed = system_clock::now() - last_key_poll_time_;
86  auto elapsed_ms = duration_cast<milliseconds>(elapsed).count();
87 
88  // Poll for key press if enough time has elapsed or if no key is pressed
89  if (elapsed_ms >= kPollingIntervalMS || !key_pressed_) {
90  key_pressed_ = read_event();
91 
92  if (key_pressed_) {
93  key_code_ = map_char_to_key(buf_);
94  } else {
95  key_code_ = Key::NONE;
96  }
97 
98  last_key_poll_time_ = system_clock::now();
99  }
100 
101  auto& output = observation(prefix());
102  output("key_pressed") = key_pressed_;
103  output("up") = key_code_ == Key::UP;
104  output("down") = key_code_ == Key::DOWN;
105  output("left") = key_code_ == Key::LEFT;
106  output("right") = key_code_ == Key::RIGHT;
107  output("w") = key_code_ == Key::W;
108  output("a") = key_code_ == Key::A;
109  output("s") = key_code_ == Key::S;
110  output("d") = key_code_ == Key::D;
111  output("x") = key_code_ == Key::X;
112  output("unknown") = key_code_ == Key::UNKNOWN;
113 }
114 
115 } // namespace vulp::observation::sources
bool is_printable_ascii(unsigned char c)
Definition: Keyboard.h:42
constexpr unsigned char LEFT_BYTES[]
Definition: Keyboard.h:34
constexpr unsigned char UP_BYTES[]
Definition: Keyboard.h:31
constexpr unsigned char DOWN_BYTES[]
Definition: Keyboard.h:32
bool is_lowercase_alpha(unsigned char c)
Definition: Keyboard.h:36
constexpr ssize_t kMaxKeyBytes
Maximum number of bytes to encode a key.
Definition: Keyboard.h:25
constexpr int64_t kPollingIntervalMS
Polling interval in milliseconds.
Definition: Keyboard.h:28
constexpr unsigned char RIGHT_BYTES[]
Definition: Keyboard.h:33
Keyboard()
Constructor sets up the terminal in non-canonical mode where input is available immediately without w...
Definition: Keyboard.cpp:7
~Keyboard() override
Destructor.
Definition: Keyboard.cpp:20
std::string prefix() const noexcept final
Prefix of output in the observation dictionary.
Definition: Keyboard.h:82
void write(Dictionary &output) final
Write output to a dictionary.
Definition: Keyboard.cpp:83