diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index 3b1c805c7..05f090d48 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -19,7 +19,7 @@ objs += $(addprefix ion/src/device/, \ console.o \ device.o\ display.o\ - events_keyboard.o\ + events.o\ keyboard.o\ led.o\ power.o\ diff --git a/ion/src/device/events.cpp b/ion/src/device/events.cpp index e313a16ba..7f1443566 100644 --- a/ion/src/device/events.cpp +++ b/ion/src/device/events.cpp @@ -1,111 +1,93 @@ #include +#include namespace Ion { namespace Events { -static constexpr char s_textAtIndex[] = { 'A', 0, 'B', 0, 'C', 0,'D', 0}; - -class EventInfo { -public: - static constexpr EventInfo Undefined() { return EventInfo(0); } - static constexpr EventInfo Textless() { return EventInfo(1); } - static constexpr EventInfo Text(int index) { return EventInfo(index << 2 & 3); } - bool isUndefined() const { return (m_data == 0); } - const char * text() const; -private: - constexpr EventInfo(uint8_t data) : m_data(data) {} - uint8_t m_data; -}; - -const char * EventInfo::text() const { - if (m_data <= 1) { - return nullptr; +static bool sleepWithTimeout(int duration, int * timeout) { + if (*timeout >= duration) { + msleep(duration); + *timeout -= duration; + return false; + } else { + msleep(*timeout); + *timeout = 0; + return true; } - return s_textAtIndex + (m_data >> 2); } -static constexpr EventInfo s_infoForEvent[] = { - EventInfo::Textless(), EventInfo::Textless(), EventInfo::Textless(), EventInfo::Undefined() -}; +Event sLastEvent = Events::None; +Keyboard::State sLastKeyboardState; +bool sLastUSBPlugged = false; +bool sLastUSBEnumerated = false; +bool sEventIsRepeating = 0; +constexpr int delayBeforeRepeat = 200; +constexpr int delayBetweenRepeat = 50; - -Event::Event(Keyboard::Key key, bool shift, bool alpha) { - // We're mapping a key, shift and alpha to an event - // This can be a bit more complicated than it seems since we want to fall back: - // for example, alpha-up is just plain up. - // Fallback order : - // alpha-X -> X - // shift-X -> X - // shift-alpha-X -> alpha-X -> X - - m_data = 255;// Undefined. FIXME - - int noFallbackOffsets[] = {0}; - int alphaFallbackOffsets[] = {2*k_eventPageSize, 0}; - int shiftFallbackOffsets[] = {k_eventPageSize, 0}; - int shiftAlphaFallbackOffsets[] = {3*k_eventPageSize, 2*k_eventPageSize, 0}; - - int * fallbackOffsets[] = {noFallbackOffsets, shiftFallbackOffsets, alphaFallbackOffsets, shiftAlphaFallbackOffsets}; - - int * fallbackOffset = fallbackOffsets[shift+2*alpha]; - int i=0; - int offset = 0; - do { - offset = fallbackOffset[i++]; - m_data = offset + (int)key; - } while (offset > 0 && s_infoForEvent[m_data].isUndefined()); - - //TODO assert(m_data != 255); //FIXME: Undefined +bool canRepeatEvent(Event e) { + return (e == Events::Left || e == Events::Up || e == Events::Down || e == Events::Right || e == Events::Backspace); } -const char * Event::text() const { - EventInfo info = s_infoForEvent[m_data]; - return info.text(); +Event getEvent(int * timeout) { + assert(*timeout > delayBeforeRepeat); + assert(*timeout > delayBetweenRepeat); + int time = 0; + uint64_t keysSeenUp = 0; + uint64_t keysSeenTransitionningFromUpToDown = 0; + while (true) { + // First, check if the USB plugged status has changed + bool usbPlugged = USB::isPlugged(); + if (usbPlugged != sLastUSBPlugged) { + sLastUSBPlugged = usbPlugged; + return Events::USBPlug; + } + + // Second, check if the USB device has been connected to an USB host + bool usbEnumerated = USB::isEnumerated(); + if (usbEnumerated != sLastUSBEnumerated) { + sLastUSBEnumerated = usbEnumerated; + if (usbEnumerated) { + return Events::USBEnumeration; + } + } + + Keyboard::State state = Keyboard::scan(); + keysSeenUp |= ~state; + keysSeenTransitionningFromUpToDown = keysSeenUp & state; + + if (keysSeenTransitionningFromUpToDown != 0) { + sEventIsRepeating = false; + /* The key that triggered the event corresponds to the first non-zero bit + * in "match". This is a rather simple logic operation for the which many + * processors have an instruction (ARM thumb uses CLZ). + * Unfortunately there's no way to express this in standard C, so we have + * to resort to using a builtin function. */ + Keyboard::Key key = (Keyboard::Key)(63-__builtin_clzll(keysSeenTransitionningFromUpToDown)); + Event event(key, isShiftActive(), isAlphaActive()); + updateModifiersFromEvent(event); + sLastEvent = event; + sLastKeyboardState = state; + return event; + } + + if (sleepWithTimeout(10, timeout)) { + // Timeout occured + return Events::None; + } + time += 10; + + // At this point, we know that keysSeenTransitionningFromUpToDown has *always* been zero + // In other words, no new key has been pressed + if (canRepeatEvent(sLastEvent) && (state == sLastKeyboardState)) { + int delay = (sEventIsRepeating ? delayBetweenRepeat : delayBeforeRepeat); + if (time >= delay) { + sEventIsRepeating = true; + sLastKeyboardState = state; + return sLastEvent; + } + } + } } } } - -#if 0 -class Event { - Event(); // Constructor, by the hardware - -private: - uint8_t m_data; -}; - - -ActionInfo Event::Action::info() { - return s_actionInfo[(int)this]; -} - -Event::Event(Key key, bool shift, bool alpha) { - // We're mapping a key, shift and alpha to an action - // This can be a bit more complicated than it seems since we want to fall back: - // for example, alpha-up is just plain up. - // Fallback order : - // alpha-X -> X - // shift-X -> X - // shift-alpha-X -> alpha-X -> X - - int noFallbackOffsets[] = {0}; - int alphaFallbackOffsets[] = {2*k_actionPageSize, 0}; - int shiftFallbackOffsets[] = {k_actionPageSize, 0}; - int shiftAlphaFallbackOffsets[] = {3*k_actionPageSize, 2*k_actionPageSize, 0}; - - int * fallbackOffsets[] = {noFallbackOffsets, shiftFallbackOffsets, alphaFallbackOffsets, shiftAlphaFallbackOffsets}; - - int * fallbackOffset = fallbackOffsets[shift+2*alpha]; - Action action = Action::Undefined; - int action = A - int i=0; - int offset = 0; - do { - offset = fallbackOffset[i++]; - action = offset + (int)key; - } while (offset > 0 && action.info().isUndefined()); - - assert(!action.info().isUndefined()); - return action; -} -#endif diff --git a/ion/src/device/events_keyboard.cpp b/ion/src/device/events_keyboard.cpp deleted file mode 100644 index 7f1443566..000000000 --- a/ion/src/device/events_keyboard.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -namespace Ion { -namespace Events { - -static bool sleepWithTimeout(int duration, int * timeout) { - if (*timeout >= duration) { - msleep(duration); - *timeout -= duration; - return false; - } else { - msleep(*timeout); - *timeout = 0; - return true; - } -} - -Event sLastEvent = Events::None; -Keyboard::State sLastKeyboardState; -bool sLastUSBPlugged = false; -bool sLastUSBEnumerated = false; -bool sEventIsRepeating = 0; -constexpr int delayBeforeRepeat = 200; -constexpr int delayBetweenRepeat = 50; - -bool canRepeatEvent(Event e) { - return (e == Events::Left || e == Events::Up || e == Events::Down || e == Events::Right || e == Events::Backspace); -} - -Event getEvent(int * timeout) { - assert(*timeout > delayBeforeRepeat); - assert(*timeout > delayBetweenRepeat); - int time = 0; - uint64_t keysSeenUp = 0; - uint64_t keysSeenTransitionningFromUpToDown = 0; - while (true) { - // First, check if the USB plugged status has changed - bool usbPlugged = USB::isPlugged(); - if (usbPlugged != sLastUSBPlugged) { - sLastUSBPlugged = usbPlugged; - return Events::USBPlug; - } - - // Second, check if the USB device has been connected to an USB host - bool usbEnumerated = USB::isEnumerated(); - if (usbEnumerated != sLastUSBEnumerated) { - sLastUSBEnumerated = usbEnumerated; - if (usbEnumerated) { - return Events::USBEnumeration; - } - } - - Keyboard::State state = Keyboard::scan(); - keysSeenUp |= ~state; - keysSeenTransitionningFromUpToDown = keysSeenUp & state; - - if (keysSeenTransitionningFromUpToDown != 0) { - sEventIsRepeating = false; - /* The key that triggered the event corresponds to the first non-zero bit - * in "match". This is a rather simple logic operation for the which many - * processors have an instruction (ARM thumb uses CLZ). - * Unfortunately there's no way to express this in standard C, so we have - * to resort to using a builtin function. */ - Keyboard::Key key = (Keyboard::Key)(63-__builtin_clzll(keysSeenTransitionningFromUpToDown)); - Event event(key, isShiftActive(), isAlphaActive()); - updateModifiersFromEvent(event); - sLastEvent = event; - sLastKeyboardState = state; - return event; - } - - if (sleepWithTimeout(10, timeout)) { - // Timeout occured - return Events::None; - } - time += 10; - - // At this point, we know that keysSeenTransitionningFromUpToDown has *always* been zero - // In other words, no new key has been pressed - if (canRepeatEvent(sLastEvent) && (state == sLastKeyboardState)) { - int delay = (sEventIsRepeating ? delayBetweenRepeat : delayBeforeRepeat); - if (time >= delay) { - sEventIsRepeating = true; - sLastKeyboardState = state; - return sLastEvent; - } - } - } -} - -} -}