26 #include "freertos/FreeRTOS.h" 27 #include "freertos/task.h" 28 #include "freertos/timers.h" 29 #include "freertos/queue.h" 43 const KeyboardLayout USLayout {
252 const KeyboardLayout UKLayout {
296 const KeyboardLayout GermanLayout {
369 const KeyboardLayout ItalianLayout {
445 const KeyboardLayout SpanishLayout {
605 : m_keyboardAvailable(false),
613 PS2Device::begin(PS2Port);
620 m_SCROLLLOCK =
false;
622 m_numLockLED =
false;
623 m_capsLockLED =
false;
624 m_scrollLockLED =
false;
626 m_SCodeToVKConverterTask =
nullptr;
627 m_virtualKeyQueue =
nullptr;
633 if (generateVirtualKeys || createVKQueue) {
635 m_virtualKeyQueue = xQueueCreate(FABGLIB_KEYBOARD_VIRTUALKEY_QUEUE_SIZE,
sizeof(uint16_t));
641 void Keyboard::begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO,
bool generateVirtualKeys,
bool createVKQueue)
644 PS2->
begin(clkGPIO, dataGPIO);
645 PS2->setKeyboard(
this);
646 begin(generateVirtualKeys, createVKQueue, 0);
653 memset(m_VKMap, 0,
sizeof(m_VKMap));
659 for (
int i = 0; i < 3; ++i) {
660 m_keyboardAvailable = send_cmdReset() && send_cmdSetScancodeSet(2);
661 if (m_keyboardAvailable)
663 vTaskDelay(500 / portTICK_PERIOD_MS);
666 return m_keyboardAvailable;
672 *numLock = m_numLockLED;
673 *capsLock = m_capsLockLED;
674 *scrollLock = m_scrollLockLED;
680 return dataAvailable();
687 int r = getData(timeOutMS);
688 if (r == -1 && requestResendOnTimeOut) {
689 requestToResendLastByte();
697 void Keyboard::updateLEDs()
699 send_cmdLEDs(m_NUMLOCK, m_CAPSLOCK, m_SCROLLLOCK);
700 m_numLockLED = m_NUMLOCK;
701 m_capsLockLED = m_CAPSLOCK;
702 m_scrollLockLED = m_SCROLLLOCK;
712 #if FABGLIB_HAS_VirtualKeyO_STRING 713 char const * Keyboard::virtualKeyToString(
VirtualKey virtualKey)
715 char const * VKTOSTR[] = {
"VK_NONE",
"VK_SPACE",
"VK_0",
"VK_1",
"VK_2",
"VK_3",
"VK_4",
"VK_5",
"VK_6",
"VK_7",
"VK_8",
"VK_9",
"VK_KP_0",
"VK_KP_1",
"VK_KP_2",
716 "VK_KP_3",
"VK_KP_4",
"VK_KP_5",
"VK_KP_6",
"VK_KP_7",
"VK_KP_8",
"VK_KP_9",
"VK_a",
"VK_b",
"VK_c",
"VK_d",
"VK_e",
"VK_f",
"VK_g",
"VK_h",
717 "VK_i",
"VK_j",
"VK_k",
"VK_l",
"VK_m",
"VK_n",
"VK_o",
"VK_p",
"VK_q",
"VK_r",
"VK_s",
"VK_t",
"VK_u",
"VK_v",
"VK_w",
"VK_x",
"VK_y",
"VK_z",
718 "VK_A",
"VK_B",
"VK_C",
"VK_D",
"VK_E",
"VK_F",
"VK_G",
"VK_H",
"VK_I",
"VK_J",
"VK_K",
"VK_L",
"VK_M",
"VK_N",
"VK_O",
"VK_P",
"VK_Q",
"VK_R",
719 "VK_S",
"VK_T",
"VK_U",
"VK_V",
"VK_W",
"VK_X",
"VK_Y",
"VK_Z",
"VK_GRAVEACCENT",
"VK_ACUTEACCENT",
"VK_QUOTE",
"VK_QUOTEDBL",
"VK_EQUALS",
"VK_MINUS",
"VK_KP_MINUS",
720 "VK_PLUS",
"VK_KP_PLUS",
"VK_KP_MULTIPLY",
"VK_ASTERISK",
"VK_BACKSLASH",
"VK_KP_DIVIDE",
"VK_SLASH",
"VK_KP_PERIOD",
"VK_PERIOD",
"VK_COLON",
721 "VK_COMMA",
"VK_SEMICOLON",
"VK_AMPERSAND",
"VK_VERTICALBAR",
"VK_HASH",
"VK_AT",
"VK_CARET",
"VK_DOLLAR",
"VK_POUND",
"VK_EURO",
"VK_PERCENT",
722 "VK_EXCLAIM",
"VK_QUESTION",
"VK_LEFTBRACE",
"VK_RIGHTBRACE",
"VK_LEFTBRACKET",
"VK_RIGHTBRACKET",
"VK_LEFTPAREN",
"VK_RIGHTPAREN",
"VK_LESS",
723 "VK_GREATER",
"VK_UNDERSCORE",
"VK_DEGREE",
"VK_SECTION",
"VK_TILDE",
"VK_NEGATION",
"VK_LSHIFT",
"VK_RSHIFT",
"VK_LALT",
"VK_RALT",
"VK_LCTRL",
"VK_RCTRL",
724 "VK_LGUI",
"VK_RGUI",
"VK_ESCAPE",
"VK_PRINTSCREEN1",
"VK_PRINTSCREEN2",
"VK_SYSREQ",
"VK_INSERT",
"VK_KP_INSERT",
"VK_DELETE",
"VK_KP_DELETE",
"VK_BACKSPACE",
"VK_HOME",
"VK_KP_HOME",
"VK_END",
"VK_KP_END",
"VK_PAUSE",
"VK_BREAK",
725 "VK_SCROLLLOCK",
"VK_NUMLOCK",
"VK_CAPSLOCK",
"VK_TAB",
"VK_RETURN",
"VK_KP_ENTER",
"VK_APPLICATION",
"VK_PAGEUP",
"VK_KP_PAGEUP",
"VK_PAGEDOWN",
"VK_KP_PAGEDOWN",
"VK_UP",
"VK_KP_UP",
726 "VK_DOWN",
"VK_KP_DOWN",
"VK_LEFT",
"VK_KP_LEFT",
"VK_RIGHT",
"VK_KP_RIGHT",
"VK_KP_CENTER",
"VK_F1",
"VK_F2",
"VK_F3",
"VK_F4",
"VK_F5",
"VK_F6",
"VK_F7",
"VK_F8",
"VK_F9",
"VK_F10",
"VK_F11",
"VK_F12",
727 "VK_GRAVE_a",
"VK_GRAVE_e",
"VK_ACUTE_e",
"VK_GRAVE_i",
"VK_GRAVE_o",
"VK_GRAVE_u",
"VK_CEDILLA_c",
"VK_ESZETT",
"VK_UMLAUT_u",
728 "VK_UMLAUT_o",
"VK_UMLAUT_a",
"VK_CEDILLA_C",
"VK_TILDE_n",
"VK_TILDE_N",
"VK_UPPER_a",
"VK_ACUTE_a",
"VK_ACUTE_i",
"VK_ACUTE_o",
"VK_ACUTE_u",
"VK_UMLAUT_i",
"VK_EXCLAIM_INV",
"VK_QUESTION_INV",
729 "VK_ACUTE_A",
"VK_ACUTE_E",
"VK_ACUTE_I",
"VK_ACUTE_O",
"VK_ACUTE_U",
"VK_GRAVE_A",
"VK_GRAVE_E",
"VK_GRAVE_I",
"VK_GRAVE_O",
"VK_GRAVE_U",
"VK_INTERPUNCT",
"VK_DIAERESIS",
730 "VK_UMLAUT_e",
"VK_UMLAUT_A",
"VK_UMLAUT_E",
"VK_UMLAUT_I",
"VK_UMLAUT_O",
"VK_UMLAUT_U",
"VK_CARET_a",
"VK_CARET_e",
"VK_CARET_i",
"VK_CARET_o",
"VK_CARET_u",
"VK_CARET_A",
"VK_CARET_E",
"VK_CARET_I",
"VK_CARET_O",
"VK_CARET_U",
732 return VKTOSTR[virtualKey];
740 switch (virtualKey) {
742 return m_CTRL ? ASCII_NUL : ASCII_SPC;
745 return virtualKey -
VK_0 +
'0';
748 return virtualKey -
VK_KP_0 +
'0';
751 return virtualKey -
VK_a + (m_CTRL ? ASCII_SOH :
'a');
754 return virtualKey -
VK_A + (m_CTRL ? ASCII_SOH :
'A');
817 return m_CTRL ? ASCII_FS :
'\\';
867 return m_CTRL ? ASCII_US :
'?';
876 return m_CTRL ? ASCII_ESC :
'[';
879 return m_CTRL ? ASCII_GS :
']';
903 return m_CTRL ? ASCII_RS :
'~';
926 return m_SCROLLLOCK ? ASCII_XOFF : ASCII_XON;
1054 if (layout ==
nullptr)
1065 vk = scancodeToVK(scancode, isExtended, layout->
inherited);
1075 if (layout ==
nullptr)
1078 for (AltVirtualKeyDef
const * def = layout->alternateVK; def->reqVirtualKey !=
VK_NONE; ++def) {
1079 if (def->reqVirtualKey == in_vk && def->ctrl == m_CTRL &&
1080 def->alt == m_ALT &&
1081 (def->shift == m_SHIFT || (def->capslock && def->capslock == m_CAPSLOCK)) &&
1082 def->numlock == m_NUMLOCK) {
1088 if (vk ==
VK_NONE && layout->inherited)
1089 vk = VKtoAlternateVK(in_vk, layout->inherited);
1091 return vk ==
VK_NONE ? in_vk : vk;
1095 VirtualKey Keyboard::blockingGetVirtualKey(
bool * keyDown)
1101 if (scode == 0xE0) {
1104 if (scode == 0xF0) {
1107 vk = scancodeToVK(scode,
true);
1111 vk = scancodeToVK(scode,
true);
1113 }
else if (scode == 0xE1) {
1115 const uint8_t PAUSECODES[] = {0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77};
1117 for (i = 0; i < 7; ++i) {
1119 if (scode != PAUSECODES[i])
1124 }
else if (scode == 0xF0) {
1127 vk = scancodeToVK(scode,
false);
1131 vk = scancodeToVK(scode,
false);
1138 vk = VKtoAlternateVK(vk);
1156 m_CAPSLOCK = !m_CAPSLOCK;
1162 m_NUMLOCK = !m_NUMLOCK;
1168 m_SCROLLLOCK = !m_SCROLLLOCK;
1188 if (vk != m_lastDeadKey && vk !=
VK_NONE) {
1189 for (DeadKeyVirtualKeyDef
const * dk = m_layout->
deadkeysToVK; dk->deadKey !=
VK_NONE; ++dk) {
1190 if (vk == dk->reqVirtualKey && m_lastDeadKey == dk->deadKey) {
1191 vk = dk->virtualKey;
1207 m_VKMap[(int)virtualKey >> 3] |= 1 << ((
int)virtualKey & 7);
1209 m_VKMap[(int)virtualKey >> 3] &= ~(1 << ((
int)virtualKey & 7));
1212 if (m_virtualKeyQueue) {
1213 uint16_t code = (uint16_t)virtualKey | (keyDown ? 0x8000 : 0);
1214 auto ticksToWait = (m_uiApp ? 0 : portMAX_DELAY);
1216 xQueueSendToFront(m_virtualKeyQueue, &code, ticksToWait);
1218 xQueueSendToBack(m_virtualKeyQueue, &code, ticksToWait);
1223 void Keyboard::SCodeToVKConverterTask(
void * pvParameters)
1228 VirtualKey vk = keyboard->blockingGetVirtualKey(&keyDown);
1238 if (keyboard->m_uiApp) {
1239 uiEvent evt = uiEvent(
nullptr, keyDown ? UIEVT_KEYDOWN : UIEVT_KEYUP);
1240 evt.params.key.VK = vk;
1257 vTaskSuspend(m_SCodeToVKConverterTask);
1259 vTaskResume(m_SCodeToVKConverterTask);
1265 bool r = m_VKMap[(int)virtualKey >> 3] & (1 << ((
int)virtualKey & 7));
1269 m_VKMap[(int)virtualKey >> 3] &= ~(1 << ((
int)virtualKey & 7));
1278 if (m_SCodeToVKConverterTask) {
1280 if (xQueueReceive(m_virtualKeyQueue, &code, msToTicks(timeOutMS)) == pdTRUE) {
1283 *keyDown = code & 0x8000;
1292 return m_virtualKeyQueue ? uxQueueMessagesWaiting(m_virtualKeyQueue) : 0;
1298 xQueueReset(m_virtualKeyQueue);
void injectVirtualKey(VirtualKey virtualKey, bool keyDown, bool insert=false)
Adds or inserts a virtual key into the virtual keys queue.
All in one structure to fully represent a keyboard layout.
DeadKeyVirtualKeyDef deadkeysToVK[64]
VirtualKeyDef exScancodeToVK[32]
int virtualKeyToASCII(VirtualKey virtualKey)
Converts virtual key to ASCII.
This file contains fabgl::Keyboard definition.
void emptyVirtualKeyQueue()
Empties the virtual keys queue.
Delegate< VirtualKey *, bool > onVirtualKey
Delegate called whenever a new virtual key is decoded from scancodes.
void getLEDs(bool *numLock, bool *capsLock, bool *scrollLock)
Gets keyboard LEDs status.
bool isVKDown(VirtualKey virtualKey)
Gets the virtual keys status.
The PS2 Keyboard controller class.
VirtualKeyDef scancodeToVK[92]
VirtualKey
Represents each possible real or derived (SHIFT + real) key.
void begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO, bool generateVirtualKeys=true, bool createVKQueue=true)
Initializes Keyboard specifying CLOCK and DATA GPIOs.
static PS2Controller * instance()
Returns the singleton instance of PS2Controller class.
VirtualKey getNextVirtualKey(bool *keyDown=nullptr, int timeOutMS=-1)
Gets a virtual key from the queue.
int virtualKeyAvailable()
Gets the number of virtual keys available in the queue.
Associates scancode to virtualkey.
bool reset()
Sends a Reset command to the keyboard.
int getNextScancode(int timeOutMS=-1, bool requestResendOnTimeOut=false)
Gets a scancode from the queue.
int scancodeAvailable()
Gets the number of scancodes available in the queue.
static int scancodeToVirtualKeyTaskStackSize
Stack size of the task that converts scancodes to Virtual Keys Keyboard.
The PS2 device controller class.
bool postEvent(uiEvent const *event)
Places an event in the event queue and returns without waiting for the receiver to process the event...
void setLayout(KeyboardLayout const *layout)
Sets keyboard layout.
KeyboardLayout const * inherited
void suspendVirtualKeyGeneration(bool value)
Suspends or resume the virtual key generation task.
void begin(gpio_num_t port0_clkGPIO, gpio_num_t port0_datGPIO, gpio_num_t port1_clkGPIO=GPIO_UNUSED, gpio_num_t port1_datGPIO=GPIO_UNUSED)
Initializes PS2 device controller.