Numworks Epsilon  1.4.1
Graphing Calculator Operating System
events_keyboard.cpp
Go to the documentation of this file.
1 #include <ion.h>
2 #include <assert.h>
3 
4 namespace Ion {
5 namespace Events {
6 
7 static bool sleepWithTimeout(int duration, int * timeout) {
8  if (*timeout >= duration) {
9  msleep(duration);
10  *timeout -= duration;
11  return false;
12  } else {
13  msleep(*timeout);
14  *timeout = 0;
15  return true;
16  }
17 }
18 
21 bool sLastUSBPlugged = false;
22 bool sLastUSBEnumerated = false;
24 constexpr int delayBeforeRepeat = 200;
25 constexpr int delayBetweenRepeat = 50;
26 
28  return (e == Events::Left || e == Events::Up || e == Events::Down || e == Events::Right || e == Events::Backspace);
29 }
30 
31 Event getEvent(int * timeout) {
32  assert(*timeout > delayBeforeRepeat);
33  assert(*timeout > delayBetweenRepeat);
34  int time = 0;
35  uint64_t keysSeenUp = 0;
36  uint64_t keysSeenTransitionningFromUpToDown = 0;
37  while (true) {
38  // First, check if the USB plugged status has changed
39  bool usbPlugged = USB::isPlugged();
40  if (usbPlugged != sLastUSBPlugged) {
41  sLastUSBPlugged = usbPlugged;
42  return Events::USBPlug;
43  }
44 
45  // Second, check if the USB device has been connected to an USB host
46  bool usbEnumerated = USB::isEnumerated();
47  if (usbEnumerated != sLastUSBEnumerated) {
48  sLastUSBEnumerated = usbEnumerated;
49  if (usbEnumerated) {
51  }
52  }
53 
54  Keyboard::State state = Keyboard::scan();
55  keysSeenUp |= ~state;
56  keysSeenTransitionningFromUpToDown = keysSeenUp & state;
57 
58  if (keysSeenTransitionningFromUpToDown != 0) {
59  sEventIsRepeating = false;
60  /* The key that triggered the event corresponds to the first non-zero bit
61  * in "match". This is a rather simple logic operation for the which many
62  * processors have an instruction (ARM thumb uses CLZ).
63  * Unfortunately there's no way to express this in standard C, so we have
64  * to resort to using a builtin function. */
65  Keyboard::Key key = (Keyboard::Key)(63-__builtin_clzll(keysSeenTransitionningFromUpToDown));
66  Event event(key, isShiftActive(), isAlphaActive());
68  sLastEvent = event;
69  sLastKeyboardState = state;
70  return event;
71  }
72 
73  if (sleepWithTimeout(10, timeout)) {
74  // Timeout occured
75  return Events::None;
76  }
77  time += 10;
78 
79  // At this point, we know that keysSeenTransitionningFromUpToDown has *always* been zero
80  // In other words, no new key has been pressed
81  if (canRepeatEvent(sLastEvent) && (state == sLastKeyboardState)) {
83  if (time >= delay) {
84  sEventIsRepeating = true;
85  sLastKeyboardState = state;
86  return sLastEvent;
87  }
88  }
89  }
90 }
91 
92 }
93 }
bool isPlugged()
Definition: usb.cpp:12
Event getEvent(int *timeout)
Definition: events.cpp:12
#define assert(e)
Definition: assert.h:9
constexpr Event Up
Definition: events.h:62
constexpr Event Down
Definition: events.h:63
void msleep(long ms)
Definition: ion.cpp:4
void updateModifiersFromEvent(Event e)
constexpr Event None
Definition: events.h:215
constexpr int delayBeforeRepeat
unsigned long long uint64_t
Definition: stdint.h:7
Keyboard::State sLastKeyboardState
constexpr int delayBetweenRepeat
constexpr Event USBPlug
Definition: events.h:219
bool isAlphaActive()
constexpr Event Left
Definition: events.h:61
bool isShiftActive()
bool canRepeatEvent(Event e)
bool isEnumerated()
Definition: usb.cpp:16
State scan()
Definition: keyboard.cpp:50
constexpr Event Right
Definition: events.h:64
constexpr Event USBEnumeration
Definition: events.h:218
Definition: backlight.h:6
constexpr Event Backspace
Definition: events.h:76