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),
61 PS2DeviceLock
lock(
this);
62 if (m_SCodeToVKConverterTask)
63 vTaskDelete(m_SCodeToVKConverterTask);
64 if (m_virtualKeyQueue)
65 vQueueDelete(m_virtualKeyQueue);
71 PS2Device::begin(PS2Port);
83 m_capsLockLED =
false;
84 m_scrollLockLED =
false;
86 m_SCodeToVKConverterTask =
nullptr;
87 m_virtualKeyQueue =
nullptr;
93 if (generateVirtualKeys || createVKQueue) {
101 void Keyboard::begin(gpio_num_t clkGPIO, gpio_num_t dataGPIO,
bool generateVirtualKeys,
bool createVKQueue)
104 PS2Controller::setKeyboard(
this);
105 begin(generateVirtualKeys, createVKQueue, 0);
112 memset(m_VKMap, 0,
sizeof(m_VKMap));
118 vTaskDelay(350 / portTICK_PERIOD_MS);
121 for (
int i = 0; i < 3; ++i) {
122 m_keyboardAvailable = send_cmdReset();
123 if (m_keyboardAvailable)
125 vTaskDelay(350 / portTICK_PERIOD_MS);
128 vTaskDelay(200 / portTICK_PERIOD_MS);
130 send_cmdSetScancodeSet(2);
132 return m_keyboardAvailable;
138 if (m_SCodeToVKConverterTask) {
140 if (value == 1 || value == 2) {
141 m_scancodeSet = value;
146 if (send_cmdSetScancodeSet(value)) {
147 m_scancodeSet = value;
157 m_numLockLED = numLock;
158 m_capsLockLED = capsLock;
159 m_scrollLockLED = scrollLock;
160 return send_cmdLEDs(numLock, capsLock, scrollLock);
166 *numLock = m_numLockLED;
167 *capsLock = m_capsLockLED;
168 *scrollLock = m_scrollLockLED;
172 void Keyboard::updateLEDs()
174 send_cmdLEDs(m_NUMLOCK, m_CAPSLOCK, m_SCROLLLOCK);
175 m_numLockLED = m_NUMLOCK;
176 m_capsLockLED = m_CAPSLOCK;
177 m_scrollLockLED = m_SCROLLLOCK;
183 return dataAvailable();
190 int r = getData(timeOutMS);
191 if (r == -1 && CLKTimeOutError()) {
193 send_cmdEnableScanning();
195 if (r == -1 && requestResendOnTimeOut) {
196 requestToResendLastByte();
210 #if FABGLIB_HAS_VirtualKeyO_STRING 211 char const * Keyboard::virtualKeyToString(
VirtualKey virtualKey)
213 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",
214 "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",
215 "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",
216 "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",
217 "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",
218 "VK_PLUS",
"VK_KP_PLUS",
"VK_KP_MULTIPLY",
"VK_ASTERISK",
"VK_BACKSLASH",
"VK_KP_DIVIDE",
"VK_SLASH",
"VK_KP_PERIOD",
"VK_PERIOD",
"VK_COLON",
219 "VK_COMMA",
"VK_SEMICOLON",
"VK_AMPERSAND",
"VK_VERTICALBAR",
"VK_HASH",
"VK_AT",
"VK_CARET",
"VK_DOLLAR",
"VK_POUND",
"VK_EURO",
"VK_PERCENT",
220 "VK_EXCLAIM",
"VK_QUESTION",
"VK_LEFTBRACE",
"VK_RIGHTBRACE",
"VK_LEFTBRACKET",
"VK_RIGHTBRACKET",
"VK_LEFTPAREN",
"VK_RIGHTPAREN",
"VK_LESS",
221 "VK_GREATER",
"VK_UNDERSCORE",
"VK_DEGREE",
"VK_SECTION",
"VK_TILDE",
"VK_NEGATION",
"VK_LSHIFT",
"VK_RSHIFT",
"VK_LALT",
"VK_RALT",
"VK_LCTRL",
"VK_RCTRL",
222 "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",
223 "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",
224 "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",
225 "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",
226 "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",
227 "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",
228 "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",
229 "VK_CARET_I",
"VK_CARET_O",
"VK_CARET_U",
"VK_ASCII",
231 return VKTOSTR[virtualKey];
240 item.
vk = virtualKey;
245 item.
SHIFT = m_SHIFT;
250 return fabgl::virtualKeyToASCII(item, m_codepage);
258 if (layout ==
nullptr)
269 vk = scancodeToVK(scancode, isExtended, layout->
inherited);
275 if (m_NUMLOCK & !m_SHIFT) {
332 VirtualKey Keyboard::VKtoAlternateVK(
VirtualKey in_vk,
bool down, KeyboardLayout
const * layout)
336 if (layout ==
nullptr)
347 for (AltVirtualKeyDef
const * def = layout->alternateVK; def->reqVirtualKey !=
VK_NONE; ++def) {
359 for (AltVirtualKeyDef
const * def = layout->alternateVK; def->reqVirtualKey !=
VK_NONE; ++def) {
360 if (def->reqVirtualKey == in_vk && def->ctrl == m_CTRL &&
361 def->lalt == m_LALT &&
362 def->ralt == m_RALT &&
363 def->shift == m_SHIFT) {
370 if (vk ==
VK_NONE && layout->inherited)
371 vk = VKtoAlternateVK(in_vk, down, layout->inherited);
373 return vk ==
VK_NONE ? in_vk : vk;
377 bool Keyboard::blockingGetVirtualKey(VirtualKeyItem * item)
384 item->SHIFT = m_SHIFT;
386 item->CAPSLOCK = m_CAPSLOCK;
387 item->NUMLOCK = m_NUMLOCK;
388 item->SCROLLLOCK = m_SCROLLLOCK;
390 uint8_t * scode = item->scancode;
393 if (*scode == 0xE0) {
396 if (*scode == 0xF0) {
399 item->vk = scancodeToVK(*scode,
true);
403 item->vk = scancodeToVK(*scode,
true);
405 }
else if (*scode == 0xE1) {
407 static const uint8_t PAUSECODES[] = {0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77};
408 for (
int i = 0; i <
sizeof(PAUSECODES); ++i) {
410 if (*scode != PAUSECODES[i])
412 else if (i ==
sizeof(PAUSECODES) - 1)
415 }
else if (*scode == 0xF0) {
418 item->vk = scancodeToVK(*scode,
false);
422 item->vk = scancodeToVK(*scode,
false);
428 item->vk = manageCAPSLOCK(item->vk);
431 item->vk = VKtoAlternateVK(item->vk, item->down);
447 m_SHIFT = item->down;
455 m_CAPSLOCK = !m_CAPSLOCK;
461 m_NUMLOCK = !m_NUMLOCK;
467 m_SCROLLLOCK = !m_SCROLLLOCK;
479 if (item->vk == *dk) {
480 m_lastDeadKey = item->vk;
484 if (item->vk != m_lastDeadKey && item->vk !=
VK_NONE) {
485 for (DeadKeyVirtualKeyDef
const * dk = m_layout->
deadkeysToVK; dk->deadKey !=
VK_NONE; ++dk) {
486 if (item->vk == dk->reqVirtualKey && m_lastDeadKey == dk->deadKey) {
487 item->vk = dk->virtualKey;
491 if (!item->down && (item->vk != m_lastDeadKey) && (item->vk !=
VK_RSHIFT) && (item->vk !=
VK_LSHIFT))
500 int ascii = fabgl::virtualKeyToASCII(*item, m_codepage);
501 item->ASCII = ascii > -1 ? ascii : 0;
511 m_VKMap[(int)item.
vk >> 3] |= 1 << ((
int)item.
vk & 7);
513 m_VKMap[(int)item.
vk >> 3] &= ~(1 << ((
int)item.
vk & 7));
516 if (m_virtualKeyQueue) {
517 auto ticksToWait = (m_uiApp ? 0 : portMAX_DELAY);
519 xQueueSendToFront(m_virtualKeyQueue, &item, ticksToWait);
521 xQueueSendToBack(m_virtualKeyQueue, &item, ticksToWait);
529 item.
vk = virtualKey;
536 item.
SHIFT = m_SHIFT;
553 uiEvent evt = uiEvent(
nullptr, item.
down ? UIEVT_KEYDOWN : UIEVT_KEYUP);
554 evt.params.key.VK = item.
vk;
555 evt.params.key.ASCII = item.
ASCII;
556 evt.params.key.LALT = item.
LALT;
557 evt.params.key.RALT = item.
RALT;
558 evt.params.key.CTRL = item.
CTRL;
559 evt.params.key.SHIFT = item.
SHIFT;
560 evt.params.key.GUI = item.
GUI;
568 int Keyboard::convKeypadVKToNum(
VirtualKey vk)
607 void Keyboard::SCodeToVKConverterTask(
void * pvParameters)
609 Keyboard * keyboard = (Keyboard*) pvParameters;
612 uint8_t ALTNUMValue = 0;
618 if (keyboard->blockingGetVirtualKey(&item)) {
621 keyboard->onVirtualKey(&item.vk, item.down);
626 if (!isALT(item.vk) && keyboard->m_LALT) {
628 int num = convKeypadVKToNum(item.vk);
632 ALTNUMValue = (ALTNUMValue * 10 + num) & 0xff;
636 keyboard->postVirtualKeyItem(item);
638 }
else if (ALTNUMValue > 0 && isALT(item.vk) && !item.down) {
640 keyboard->postVirtualKeyItem(item);
643 item.scancode[0] = 0;
644 item.ASCII = ALTNUMValue;
645 keyboard->postVirtualKeyItem(item);
647 keyboard->postVirtualKeyItem(item);
651 keyboard->postVirtualKeyItem(item);
665 bool r = m_VKMap[(int)virtualKey >> 3] & (1 << ((
int)virtualKey & 7));
669 m_VKMap[(int)virtualKey >> 3] &= ~(1 << ((
int)virtualKey & 7));
677 bool r = (m_SCodeToVKConverterTask && item && xQueueReceive(m_virtualKeyQueue, item, msToTicks(timeOutMS)) == pdTRUE);
678 if (r && m_scancodeSet == 1)
679 convertScancode2to1(item);
689 *keyDown = item.
down;
698 return m_virtualKeyQueue ? uxQueueMessagesWaiting(m_virtualKeyQueue) : 0;
704 xQueueReset(m_virtualKeyQueue);
711 uint8_t * wpos = rpos;
713 while (*rpos && rpos < epos) {
716 *wpos++ = 0x80 | convScancodeSet2To1(*rpos++);
718 *wpos++ = convScancodeSet2To1(*rpos++);
725 uint8_t Keyboard::convScancodeSet2To1(uint8_t code)
728 static const uint8_t S2TOS1[256] = {
729 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
730 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
731 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
732 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
733 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
734 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
735 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
736 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
737 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
738 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
739 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
740 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
741 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
742 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
743 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
744 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.
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.