30 #include "freertos/FreeRTOS.h" 31 #include "freertos/task.h" 32 #include "freertos/timers.h" 33 #include "freertos/queue.h" 38 #pragma GCC optimize ("O2") 51 : m_keyboardAvailable(false),
52 m_SCodeToVKConverterTask(nullptr),
53 m_virtualKeyQueue(nullptr),
69 PS2Device::begin(PS2Port);
81 m_capsLockLED =
false;
82 m_scrollLockLED =
false;
92 void Keyboard::begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO,
bool generateVirtualKeys,
bool createVKQueue)
95 PS2Controller::setKeyboard(
this);
96 begin(generateVirtualKeys, createVKQueue, 0);
102 PS2DeviceLock
lock(
this);
105 generateVirtualKeys =
true;
109 if (!m_virtualKeyQueue && createVKQueue)
112 if (!m_SCodeToVKConverterTask && generateVirtualKeys)
117 if (m_SCodeToVKConverterTask && !generateVirtualKeys) {
118 vTaskDelete(m_SCodeToVKConverterTask);
119 m_SCodeToVKConverterTask =
nullptr;
122 if (m_virtualKeyQueue && !createVKQueue) {
123 vQueueDelete(m_virtualKeyQueue);
124 m_virtualKeyQueue =
nullptr;
132 memset(m_VKMap, 0,
sizeof(m_VKMap));
138 vTaskDelay(350 / portTICK_PERIOD_MS);
141 for (
int i = 0; i < 3; ++i) {
142 m_keyboardAvailable = send_cmdReset();
143 if (m_keyboardAvailable)
145 vTaskDelay(350 / portTICK_PERIOD_MS);
148 vTaskDelay(200 / portTICK_PERIOD_MS);
150 send_cmdSetScancodeSet(2);
152 return m_keyboardAvailable;
158 if (m_SCodeToVKConverterTask) {
160 if (value == 1 || value == 2) {
161 m_scancodeSet = value;
166 if (send_cmdSetScancodeSet(value)) {
167 m_scancodeSet = value;
177 m_numLockLED = numLock;
178 m_capsLockLED = capsLock;
179 m_scrollLockLED = scrollLock;
180 return send_cmdLEDs(numLock, capsLock, scrollLock);
186 *numLock = m_numLockLED;
187 *capsLock = m_capsLockLED;
188 *scrollLock = m_scrollLockLED;
192 void Keyboard::updateLEDs()
194 send_cmdLEDs(m_NUMLOCK, m_CAPSLOCK, m_SCROLLLOCK);
195 m_numLockLED = m_NUMLOCK;
196 m_capsLockLED = m_CAPSLOCK;
197 m_scrollLockLED = m_SCROLLLOCK;
203 return dataAvailable();
210 int r = getData(timeOutMS);
211 if (r == -1 && CLKTimeOutError()) {
213 send_cmdEnableScanning();
215 if (r == -1 && requestResendOnTimeOut) {
216 requestToResendLastByte();
230 #if FABGLIB_HAS_VirtualKeyO_STRING 231 char const * Keyboard::virtualKeyToString(
VirtualKey virtualKey)
233 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",
234 "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",
235 "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",
236 "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",
237 "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",
238 "VK_PLUS",
"VK_KP_PLUS",
"VK_KP_MULTIPLY",
"VK_ASTERISK",
"VK_BACKSLASH",
"VK_KP_DIVIDE",
"VK_SLASH",
"VK_KP_PERIOD",
"VK_PERIOD",
"VK_COLON",
239 "VK_COMMA",
"VK_SEMICOLON",
"VK_AMPERSAND",
"VK_VERTICALBAR",
"VK_HASH",
"VK_AT",
"VK_CARET",
"VK_DOLLAR",
"VK_POUND",
"VK_EURO",
"VK_PERCENT",
240 "VK_EXCLAIM",
"VK_QUESTION",
"VK_LEFTBRACE",
"VK_RIGHTBRACE",
"VK_LEFTBRACKET",
"VK_RIGHTBRACKET",
"VK_LEFTPAREN",
"VK_RIGHTPAREN",
"VK_LESS",
241 "VK_GREATER",
"VK_UNDERSCORE",
"VK_DEGREE",
"VK_SECTION",
"VK_TILDE",
"VK_NEGATION",
"VK_LSHIFT",
"VK_RSHIFT",
"VK_LALT",
"VK_RALT",
"VK_LCTRL",
"VK_RCTRL",
242 "VK_LGUI",
"VK_RGUI",
"VK_ESCAPE",
"VK_PRINTSCREEN",
"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",
243 "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",
244 "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",
245 "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",
246 "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",
247 "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",
248 "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",
249 "VK_CARET_I",
"VK_CARET_O",
"VK_CARET_U",
"VK_ASCII",
251 return VKTOSTR[virtualKey];
260 item.
vk = virtualKey;
265 item.
SHIFT = m_SHIFT;
270 return fabgl::virtualKeyToASCII(item, m_codepage);
278 if (layout ==
nullptr)
289 vk = scancodeToVK(scancode, isExtended, layout->
inherited);
295 if (m_NUMLOCK & !m_SHIFT) {
352 VirtualKey Keyboard::VKtoAlternateVK(
VirtualKey in_vk,
bool down, KeyboardLayout
const * layout)
356 if (layout ==
nullptr)
367 for (AltVirtualKeyDef
const * def = layout->alternateVK; def->reqVirtualKey !=
VK_NONE; ++def) {
379 for (AltVirtualKeyDef
const * def = layout->alternateVK; def->reqVirtualKey !=
VK_NONE; ++def) {
380 if (def->reqVirtualKey == in_vk && def->ctrl == m_CTRL &&
381 def->lalt == m_LALT &&
382 def->ralt == m_RALT &&
383 def->shift == m_SHIFT) {
390 if (vk ==
VK_NONE && layout->inherited)
391 vk = VKtoAlternateVK(in_vk, down, layout->inherited);
393 return vk ==
VK_NONE ? in_vk : vk;
397 bool Keyboard::blockingGetVirtualKey(VirtualKeyItem * item)
404 item->SHIFT = m_SHIFT;
406 item->CAPSLOCK = m_CAPSLOCK;
407 item->NUMLOCK = m_NUMLOCK;
408 item->SCROLLLOCK = m_SCROLLLOCK;
410 uint8_t * scode = item->scancode;
413 if (*scode == 0xE0) {
416 if (*scode == 0xF0) {
419 item->vk = scancodeToVK(*scode,
true);
423 item->vk = scancodeToVK(*scode,
true);
425 }
else if (*scode == 0xE1) {
427 static const uint8_t PAUSECODES[] = {0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77};
428 for (
int i = 0; i <
sizeof(PAUSECODES); ++i) {
430 if (*scode != PAUSECODES[i])
432 else if (i ==
sizeof(PAUSECODES) - 1)
435 }
else if (*scode == 0xF0) {
438 item->vk = scancodeToVK(*scode,
false);
442 item->vk = scancodeToVK(*scode,
false);
448 item->vk = manageCAPSLOCK(item->vk);
451 item->vk = VKtoAlternateVK(item->vk, item->down);
467 m_SHIFT = item->down;
475 m_CAPSLOCK = !m_CAPSLOCK;
481 m_NUMLOCK = !m_NUMLOCK;
487 m_SCROLLLOCK = !m_SCROLLLOCK;
499 if (item->vk == *dk) {
500 m_lastDeadKey = item->vk;
504 if (item->vk != m_lastDeadKey && item->vk !=
VK_NONE) {
505 for (DeadKeyVirtualKeyDef
const * dk = m_layout->
deadkeysToVK; dk->deadKey !=
VK_NONE; ++dk) {
506 if (item->vk == dk->reqVirtualKey && m_lastDeadKey == dk->deadKey) {
507 item->vk = dk->virtualKey;
511 if (!item->down && (item->vk != m_lastDeadKey) && (item->vk !=
VK_RSHIFT) && (item->vk !=
VK_LSHIFT))
520 int ascii = fabgl::virtualKeyToASCII(*item, m_codepage);
521 item->ASCII = ascii > -1 ? ascii : 0;
531 m_VKMap[(int)item.
vk >> 3] |= 1 << ((
int)item.
vk & 7);
533 m_VKMap[(int)item.
vk >> 3] &= ~(1 << ((
int)item.
vk & 7));
536 if (m_virtualKeyQueue) {
537 auto ticksToWait = (m_uiApp ? 0 : portMAX_DELAY);
539 xQueueSendToFront(m_virtualKeyQueue, &item, ticksToWait);
541 xQueueSendToBack(m_virtualKeyQueue, &item, ticksToWait);
549 item.
vk = virtualKey;
556 item.
SHIFT = m_SHIFT;
573 uiEvent evt = uiEvent(
nullptr, item.
down ? UIEVT_KEYDOWN : UIEVT_KEYUP);
574 evt.params.key.VK = item.
vk;
575 evt.params.key.ASCII = item.
ASCII;
576 evt.params.key.LALT = item.
LALT;
577 evt.params.key.RALT = item.
RALT;
578 evt.params.key.CTRL = item.
CTRL;
579 evt.params.key.SHIFT = item.
SHIFT;
580 evt.params.key.GUI = item.
GUI;
588 int Keyboard::convKeypadVKToNum(
VirtualKey vk)
627 void Keyboard::SCodeToVKConverterTask(
void * pvParameters)
629 Keyboard * keyboard = (Keyboard*) pvParameters;
632 uint8_t ALTNUMValue = 0;
638 if (keyboard->blockingGetVirtualKey(&item)) {
641 keyboard->onVirtualKey(&item.vk, item.down);
646 if (!isALT(item.vk) && keyboard->m_LALT) {
648 int num = convKeypadVKToNum(item.vk);
652 ALTNUMValue = (ALTNUMValue * 10 + num) & 0xff;
656 keyboard->postVirtualKeyItem(item);
658 }
else if (ALTNUMValue > 0 && isALT(item.vk) && !item.down) {
660 keyboard->postVirtualKeyItem(item);
663 item.scancode[0] = 0;
664 item.ASCII = ALTNUMValue;
665 keyboard->postVirtualKeyItem(item);
667 keyboard->postVirtualKeyItem(item);
671 keyboard->postVirtualKeyItem(item);
685 bool r = m_VKMap[(int)virtualKey >> 3] & (1 << ((
int)virtualKey & 7));
689 m_VKMap[(int)virtualKey >> 3] &= ~(1 << ((
int)virtualKey & 7));
697 bool r = (m_SCodeToVKConverterTask && item && xQueueReceive(m_virtualKeyQueue, item, msToTicks(timeOutMS)) == pdTRUE);
698 if (r && m_scancodeSet == 1)
699 convertScancode2to1(item);
709 *keyDown = item.
down;
718 return m_virtualKeyQueue ? uxQueueMessagesWaiting(m_virtualKeyQueue) : 0;
724 xQueueReset(m_virtualKeyQueue);
731 uint8_t * wpos = rpos;
733 while (*rpos && rpos < epos) {
736 *wpos++ = 0x80 | convScancodeSet2To1(*rpos++);
738 *wpos++ = convScancodeSet2To1(*rpos++);
745 uint8_t Keyboard::convScancodeSet2To1(uint8_t code)
748 static const uint8_t S2TOS1[256] = {
749 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
750 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
751 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
752 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
753 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
754 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
755 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
756 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
757 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
758 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
759 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
760 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
761 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
762 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
763 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
764 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
#define FABGLIB_SCODETOVK_TASK_PRIORITY
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.
void enableVirtualKeys(bool generateVirtualKeys, bool createVKQueue)
Dynamically enables or disables Virtual Keys generation.
bool lock(int timeOutMS)
Gets exclusive access to the device.
int virtualKeyToASCII(VirtualKey virtualKey)
Converts virtual key to ASCII.
This file contains fabgl::Keyboard definition.
void emptyVirtualKeyQueue()
Empties the virtual keys queue.
void getLEDs(bool *numLock, bool *capsLock, bool *scrollLock)
Gets keyboard LEDs status.
bool isVKDown(VirtualKey virtualKey)
Gets the virtual keys status.
A struct which contains a virtual key, key state and associated scan code.
#define FABGLIB_DEFAULT_SCODETOVK_TASK_STACK_SIZE
VirtualKey
Represents each possible real or derived (SHIFT + real) key.
bool setLEDs(bool numLock, bool capsLock, bool scrollLock)
Sets keyboard LEDs status.
VirtualKeyDef exScancodeToVK[22]
void begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO, bool generateVirtualKeys=true, bool createVKQueue=true)
Initializes Keyboard specifying CLOCK and DATA GPIOs.
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.
DeadKeyVirtualKeyDef deadkeysToVK[60]
#define FABGLIB_KEYBOARD_VIRTUALKEY_QUEUE_SIZE
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.
bool postEvent(uiEvent const *event)
Places an event in the event queue and returns without waiting for the receiver to process the event...
bool setScancodeSet(int value)
Sets the scancode set.
void setLayout(KeyboardLayout const *layout)
Sets keyboard layout.
KeyboardLayout const * inherited
VirtualKeyDef scancodeToVK[86]
static 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.