/* * Keyboard.c * * Created on: 20 Apr 2019 * Author: Peter */ /*************************************************************************************************************************** MMBasic keyboard.c Does all the hard work in getting data from the PS2 keyboard Copyright 2011 - 2018 Geoff Graham. All Rights Reserved. This file and modified versions of this file are supplied to specific individuals or organisations under the following provisions: - This file, or any files that comprise the MMBasic source (modified or not), may not be distributed or copied to any other person or organisation without written permission. - Object files (.o and .hex files) generated using this file (modified or not) may not be distributed or copied to any other person or organisation without written permission. - This file is provided in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **************************************************************************************************************************** This routine is based on a technique and code presented by Lucio Di Jasio in his excellent book "Programming 32-bit Microcontrollers in C - Exploring the PIC32". Thanks to Muller Fabrice (France), Alberto Leibovich (Argentina) and the other contributors who provided the code for the non US keyboard layouts ****************************************************************************************************************************/ #include "MMBasic_Includes.h" #include "Hardware_Includes.h" void setLEDs(int num, int caps, int scroll); bool sendCommand(int cmd, int clock, int data); volatile char CapsLock; volatile char NumLock; volatile int setleds = 0; // PS2 KBD state machine and buffer static volatile int PS2State; unsigned char KBDBuf; static int KCount, KParity; extern volatile int ConsoleRxBufHead; extern volatile int ConsoleRxBufTail; int justset = 0; // extern char ConsoleRxBuf[]; volatile int KeyDownRegister; volatile int KeyDownCode; volatile int PS2code=0; volatile bool PS2int=false; // key codes that must be tracked for up/down state #define CTRL 0x14 // left and right generate the same code #define L_SHFT 0x12 #define R_SHFT 0x59 #define CAPS 0x58 #define NUML 0x77 static char LShift = 0; static char RShift = 0; static char PS2Ctrl = 0; static char AltGrDown = 0; static char KeyUpCode = false; static char KeyE0 = false; // this is a map of the keycode characters and the character to be returned for the keycode const char keyCodes[8][128] = // US Layout { { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '`', 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'q', '1', 0, // 16-23 10-07 0, 0, 'z', 's', 'a', 'w', '2', 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '4', '3', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '5', 0, // 40-48 28-2F 0, 'n', 'b', 'h', 'g', 'y', '6', 0, // 48-56 30-37 0, 0, 'm', 'j', 'u', '7', '8', 0, // 56-63 38-3F 0, ',', 'k', 'i', 'o', '0', '9', 0, // 64-71 40-47 0, '.', '/', 'l', ';', 'p', '-', 0, // 72-79 48-4F 0, 0, '\'', 0, '[', '=', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, ']', 0, 0x5c, 0, 0, // 88-95 58-5F 0, 0, 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // FR Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0, 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'a', '&', 0, // 16-23 10-07 0, 0, 'w', 's', 'q', 'z', 0, 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '\'', '"', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '(', 0, // 40-48 28-2F 0, 'n', 'b', 'h', 'g', 'y', '-', 0, // 48-56 30-37 0, 0, ',', 'j', 'u', 0, '_', 0, // 56-63 38-3F 0, ';', 'k', 'i', 'o', 0, 0, 0, // 64-71 40-47 0, ':', '!', 'l', 'm', 'p', ')', 0, // 72-79 48-4F 0, 0, 0, 0, '^', '=', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '$', 0, '*', 0, 0, // 88-95 58-5F 0, '<', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // GR Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '^', 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'q', '1', 0, // 16-23 10-07 0, 0, 'y', 's', 'a', 'w', '2', 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '4', '3', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '5', 0, // 40-47 28-2F 0, 'n', 'b', 'h', 'g', 'z', '6', 0, // 48-55 30-37 0, 0, 'm', 'j', 'u', '7', '8', 0, // 56-63 38-3F 0, ',', 'k', 'i', 'o', '0', '9', 0, // 64-71 40-47 0, '.', '-', 'l', 0, 'p', 0, 0, // 72-79 48-4F 0, 0, 0, 0, 0, '\'', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '+', 0, '#', 0, 0, // 88-95 58-5F 0, '<', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // IT Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0x5c, 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'q', '1', 0, // 16-23 10-07 0, 0, 'z', 's', 'a', 'w', '2', 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '4', '3', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '5', 0, // 40-48 28-2F 0, 'n', 'b', 'h', 'g', 'y', '6', 0, // 48-56 30-37 0, 0, 'm', 'j', 'u', '7', '8', 0, // 56-63 38-3F 0, ',', 'k', 'i', 'o', '0', '9', 0, // 64-71 40-47 0, '.', '-', 'l', 0, 'p', '\'', 0, // 72-79 48-4F 0, 0, 0, 0, 0, 0, 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '+', 0, 0, 0, 0, // 88-95 58-5F 0, '<', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // BE Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0, 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'a', '&', 0, // 16-23 10-07 0, 0, 'w', 's', 'q', 'z', 0, 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '\'', '"', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '(', 0, // 40-48 28-2F 0, 'n', 'b', 'h', 'g', 'y', 0, 0, // 48-56 30-37 0, 0, ',', 'j', 'u', 0, '!', 0, // 56-63 38-3F 0, ';', 'k', 'i', 'o', 0, 0, 0, // 64-71 40-47 0, ':', '=', 'l', 'm', 'p', ')', 0, // 72-79 48-4F 0, 0, 0, 0, '^', '-', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '$', 0, 0, 0, 0, // 88-95 58-5F 0, '<', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // UK Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '`', 0, // 08-15 08-0F 0, ALT, L_SHFT, 0x5C, CTRL, 'q', '1', 0, // 16-23 10-07 0, 0, 'z', 's', 'a', 'w', '2', 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '4', '3', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '5', 0, // 40-48 28-2F 0, 'n', 'b', 'h', 'g', 'y', '6', 0, // 48-56 30-37 0, 0, 'm', 'j', 'u', '7', '8', 0, // 56-63 38-3F 0, ',', 'k', 'i', 'o', '0', '9', 0, // 64-71 40-47 0, '.', '/', 'l', ';', 'p', '-', 0, // 72-79 48-4F 0, 0, '\'', 0, '[', '=', 0x5C, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, ']', '#', '#', 0, 0, // 88-95 58-5F 0, 0x5C, 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // ES Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0x5c, 0, // 08-15 08-0F 0x5C is backslash 0, ALT, L_SHFT, 0, CTRL, 'q', '1', 0, // 16-23 10-07 0, 0, 'z', 's', 'a', 'w', '2', 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '4', '3', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '5', 0, // 40-47 28-2F 0, 'n', 'b', 'h', 'g', 'y', '6', 0, // 48-55 30-37 0, 0, 'm', 'j', 'u', '7', '8', 0, // 56-63 38-3F 0, ',', 'k', 'i', 'o', '0', '9', 0, // 64-71 40-47 0, '.', '-', 'l', 0, 'p', '\'', 0, // 72-79 48-4F 0, 0, '\'', 0, 0x60, 0, 0, 0, // 80-87 50-57 0x60 a single quote CAPS, R_SHFT, ENTER, '+', 0, 0, 0, 0, // 88-95 58-5F 0, '<', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // BR Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '\'', 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'q', '1', 0, // 16-23 10-17 0, 0, 'z', 's', 'a', 'w', '2', 0, // 24-31 18-1F 0, 'c', 'x', 'd', 'e', '4', '3', 0, // 32-39 20-27 0, ' ', 'v', 'f', 't', 'r', '5', 0, // 40-48 28-2F 0, 'n', 'b', 'h', 'g', 'y', '6', 0, // 48-56 30-37 0, 0, 'm', 'j', 'u', '7', '8', 0, // 56-63 38-3F 0, ',', 'k', 'i', 'o', '0', '9', 0, // 64-71 40-47 0, '.', ';', 'l', 'c', 'p', '-', 0, // 72-79 48-4F 0, '/', '~', 0, 0, '=', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '[', 0, ']', 0, 0, // 88-95 58-5F 0, '\\', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', '.', 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }}; // this map is with the shift key pressed const char keySCodes[8][128] = // US Layout { { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '~', 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'Q', '!', 0, // 16-23 10-17 0, 0, 'Z', 'S', 'A', 'W', '@', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '$', '#', 0, // 32-39 20-27 0, ' ', 'V', 'F', 'T', 'R', '%', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, // 48-55 30-37 0, 0, 'M', 'J', 'U', '&', '*', 0, // 56-63 38-3F 0, '<', 'K', 'I', 'O', ')', '(', 0, // 64-71 40-47 0, '>', '?', 'L', ':', 'P', '_', 0, // 72-79 48-4F 0, 0, '\"', 0, '{', '+', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '}', 0, '|', 0, 0, // 88-95 58-5F 0, 0, 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // FR Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0, 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'A', '1', 0, // 16-23 10-17 0, 0, 'W', 'S', 'Q', 'Z', '2', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '4', '3', 0, // 32-39 20-27 0, ' ', 'V', 'F', 'T', 'R', '5', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Y', '6', 0, // 48-55 30-37 0, 0, '?', 'J', 'U', '7', '8', 0, // 56-63 38-3F 0, '.', 'K', 'I', 'O', '0', '9', 0, // 64-71 40-47 0, '/', 0, 'L', 'M', 'P', 0, 0, // 72-79 48-4F 0, 0, '%', 0, 0, '+', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, 0, 0, 0, 0, 0, // 88-95 58-5F 0, '>', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // GR Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0, 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'Q', '!', 0, // 16-23 10-07 0, 0, 'Y', 'S', 'A', 'W', '\"', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '$', 0, 0, // 32-39 20-27 0, '\'', 'V', 'F', 'T', 'R', '%', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Z', '&', 0, // 48-55 30-37 0, 0, 'M', 'J', 'U', '/', '(', 0, // 56-63 38-3F 0, ';', 'K', 'I', 'O', '=', ')', 0, // 64-71 40-47 0, ':', '_', 'L', 0, 'P', '?', 0, // 72-79 48-4F 0, 0, 0, 0, 0, 0, 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '*', 0, 0, 0, 0, // 88-95 58-5F 0, '>', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // IT Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '|', 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'Q', '!', 0, // 16-23 10-17 0, 0, 'Z', 'S', 'A', 'W', '\"', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '$', 0, 0, // 32-39 20-27 0, ' ', 'V', 'F', 'T', 'R', '%', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Y', '&', 0, // 48-55 30-37 0, 0, 'M', 'J', 'U', '/', '(', 0, // 56-63 38-3F 0, ';', 'K', 'I', 'O', '=', ')', 0, // 64-71 40-47 0, ':', '_', 'L', 0, 'P', '?', 0, // 72-79 48-4F 0, 0, 0, 0, 0, '^', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '*', 0, 0, 0, 0, // 88-95 58-5F 0, '>', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // BE Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0, 0, // 08-15 08-0F 0, ALT, L_SHFT, 0, CTRL, 'A', '1', 0, // 16-23 10-17 0, 0, 'W', 'S', 'Q', 'Z', '2', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '4', '3', 0, // 32-39 20-27 0, ' ', 'V', 'F', 'T', 'R', '5', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Y', '6', 0, // 48-55 30-37 0, 0, '?', 'J', 'U', '7', '8', 0, // 56-63 38-3F 0, '.', 'K', 'I', 'O', '0', '9', 0, // 64-71 40-47 0, '/', '+', 'L', 'M', 'P', 0, 0, // 72-79 48-4F 0, 0, '%', 0, 0, '_', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '*', 0, 0, 0, 0, // 88-95 58-5F 0, '>', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // UK Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '~', 0, // 08-15 08-0F 0, ALT, L_SHFT, '|', CTRL, 'Q', '!', 0, // 16-23 10-17 0, 0, 'Z', 'S', 'A', 'W', '\"', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '$', '#', 0, // 32-39 20-27 0, ' ', 'V', 'F', 'T', 'R', '%', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, // 48-55 30-37 0, 0, 'M', 'J', 'U', '&', '*', 0, // 56-63 38-3F 0, '<', 'K', 'I', 'O', ')', '(', 0, // 64-71 40-47 0, '>', '?', 'L', ':', 'P', '_', 0, // 72-79 48-4F 0, 0, '@', 0, '{', '+', '|', 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '}', '~', '~', 0, 0, // 88-95 58-5F 0, '|', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // ES Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, 0x5C, 0, // 08-15 08-0F 0x5C is backslash 0, ALT, L_SHFT, 0, CTRL, 'Q', '!', 0, // 16-23 10-17 0, 0, 'Z', 'S', 'A', 'W', '\"', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '$', 0, 0, // 32-39 20-27 0, ' ', 'V', 'F', 'T', 'R', '%', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Y', '&', 0, // 48-55 30-37 0, 0, 'M', 'J', 'U', '/', '(', 0, // 56-63 38-3F 0, ';', 'K', 'I', 'O', '=', ')', 0, // 64-71 40-47 0, ':', '_', 'L', 0, 'P', '?', 0, // 72-79 48-4F 0, 0, 0, 0, '^', 0, 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '*', 0, 0, 0, 0, // 88-95 58-5F 0, '>', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', 0, 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }, // BR Layout { // Base 10 Hex 0, F9, 0, F5, F3, F1, F2, F12, // 00-07 00-07 0, F10, F8, F6, F4, TAB, '\"', 0, // 08-15 08-0F 0, ALT, L_SHFT, CTRL, 'Q', 0, '!', 0, // 16-23 10-17 0, 0, 'Z', 'S', 'A', 'W', '@', 0, // 24-31 18-1F 0, 'C', 'X', 'D', 'E', '$', '#', 0, // 32-39 20-27 0, ' ', 'V', 'F', 'T', 'R', '%', 0, // 40-47 28-2F 0, 'N', 'B', 'H', 'G', 'Y', 0, 0, // 48-55 30-37 0, 0, 'M', 'J', 'U', '&', '*', 0, // 56-63 38-3F 0, '<', 'K', 'I', 'O', ')', '(', 0, // 64-71 40-47 0, '>', ':', 'L', 'C', 'P', '_', 0, // 72-79 48-4F 0, '?', '^', 0, 0, '+', 0, 0, // 80-87 50-57 CAPS, R_SHFT, ENTER, '{', 0, '}', 0, 0, // 88-95 58-5F 0, '|', 0, 0, 0, 0, BKSP, 0, // 96-103 60-67 0, '1', 0, '4', '7', '.', 0, 0, // 104-111 68-6F '0', '.', '2', '5', '6', '8', ESC, NUML, // 112-119 70-77 F11, '+', '3', '-', '*', '9', 0, 0 // 120-127 78-7F }}; // this map is for when the keycode preceeded by 0xe0 const char keyE0Codes[56] = // General Layout on all Keyboard for the Keypad { // Base 10 0, END, 0, LEFT, HOME, 0, 0, 0, // 104-111 INSERT, DEL, DOWN, 0, RIGHT, UP, ESC, NUML, // 112-119 F11, '+', PDOWN, '-', '*', PUP, SLOCK, 0, // 120-127 }; const char keyE0Codes_ES[56] = // Layout for spanish Keyboard for the Keypad { // Base 10 0, END, 0, LEFT, HOME, 0, 0, 0, // 104-111 INSERT, DEL, DOWN, PUP, RIGHT, UP, ESC, NUML, // 112-119 F11, 0, PDOWN, 0, 0, 0, SLOCK, 0, // 120-127 }; void KBDIntEnable(int status) { PinSetBit(Option.KEYBOARD_CLOCK, TRISSET); // if tris = 1 then it is an input PinSetBit(Option.KEYBOARD_DATA, TRISSET); // if tris = 1 then it is an input PinSetBit(Option.KEYBOARD_CLOCK, CNPUSET); // if tris = 1 then it is an input PinSetBit(Option.KEYBOARD_DATA, CNPUSET); // if tris = 1 then it is an input if (status) { if (!CallBackEnabled) { CallBackEnabled = 32; gpio_set_irq_enabled_with_callback(PinDef[Option.KEYBOARD_CLOCK].GPno, GPIO_IRQ_EDGE_FALL, true, &gpio_callback); } else { CallBackEnabled |= 32; gpio_set_irq_enabled(PinDef[Option.KEYBOARD_CLOCK].GPno, GPIO_IRQ_EDGE_FALL, true); } } else { if (CallBackEnabled == 32) gpio_set_irq_enabled_with_callback(PinDef[Option.KEYBOARD_CLOCK].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else gpio_set_irq_enabled(PinDef[Option.KEYBOARD_CLOCK].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~32); } } /*************************************************************************************************** initKeyboard Initialise the keyboard routine. ****************************************************************************************************/ void initKeyboard(void) { // GPIO_InitTypeDef GPIO_InitDef; if (Option.KeyboardConfig == NO_KEYBOARD || Option.KeyboardConfig==CONFIG_I2C) return; KBDIntEnable(0); // disable interrupt in case called from within CNInterrupt() // enable pullups on the clock and data lines. // sendCommand(0xFF); // HAL_Delay(100); // setup Change Notification interrupt KBDIntEnable(1); // enable interrupt PS2State = PS2START; CapsLock = Option.capslock; NumLock = Option.numlock; uSec(100000); setLEDs(CapsLock, NumLock, 0); } /*************************************************************************************************** sendCommand - Send a command to to keyboard. ****************************************************************************************************/ bool sendCommand(int cmd, int clock, int data) { int i, j; // calculate the parity and add to the command as the 9th bit for (j = i = 0; i < 8; i++) j += ((cmd >> i) & 1); cmd = (cmd & 0xff) | (((j + 1) & 1) << 8); InkeyTimer = 0; /* while (!PinRead(clock)) //wait for clock high if (InkeyTimer >= 500) { // wait for the keyboard to pull the clock low return false; // wait for the keyboard to pull the clock low }*/ PinSetBit(clock, TRISCLR); PinSetBit(clock, LATCLR); uSec(250); PinSetBit(data, TRISCLR); PinSetBit(data, LATCLR); uSec(2); PinSetBit(clock, TRISSET); uSec(2); while (PinRead(clock)) if (InkeyTimer >= 500) { // wait for the keyboard to pull the clock low return false; // wait for the keyboard to pull the clock low } // send each bit including parity for (i = 0; i < 9; i++) { if (cmd & 1) { PinSetBit(data, LATSET); } else { PinSetBit(data, LATCLR); } while (!PinRead(clock)) if (InkeyTimer >= 500) { // wait for the keyboard to pull the clock low return false; // wait for the keyboard to pull the clock low } while (PinRead(clock)) if (InkeyTimer >= 500) { // wait for the keyboard to pull the clock low return false; // wait for the keyboard to pull the clock low } cmd >>= 1; } // PinSetBit(clock, TRISSET); PinSetBit(data, TRISSET); while (PinRead(data)) if (InkeyTimer >= 500) { // wait for the keyboard to pull the clock low return false; // wait for the keyboard to pull the clock low } // wait for the keyboard to pull data low (ACK) while (PinRead(clock)) if (InkeyTimer >= 500) { // wait for the keyboard to pull the clock low return false; // wait for the keyboard to pull the clock low } // wait for the clock to go low while (!(PinRead(clock)) || !(PinRead(data))) if (InkeyTimer >= 500) { // wait for the keyboard to pull the clock low return false; // wait for the keyboard to pull the clock low } return true; } // set the keyboard LEDs void setLEDs(int caps, int num, int scroll) { setleds = 0; KBDIntEnable(0); // disable interrupt while we play PS2State = PS2START; sendCommand(0xED, Option.KEYBOARD_CLOCK, Option.KEYBOARD_DATA); // Set/Reset Status Indicators Command uSec(50000); sendCommand(((caps & 1) << 2) | ((num & 1) << 1) | (scroll & 1), Option.KEYBOARD_CLOCK, Option.KEYBOARD_DATA); // set the various LEDs uSec(50000); sendCommand(0xF3, Option.KEYBOARD_CLOCK, Option.KEYBOARD_DATA); // Set/Reset Status Indicators Command uSec(50000); sendCommand(Option.repeat, Option.KEYBOARD_CLOCK, Option.KEYBOARD_DATA); KBDIntEnable(1); // re enable interrupt justset = 1; } void __not_in_flash_func(CheckKeyboard)(void) { if (setleds) { setLEDs(CapsLock, NumLock, 0); } } void processcode(unsigned char Code){ unsigned char c = 0; // unsigned int dly; if(!(Code==0xe0 || Code==0xf0 || (Code==0x12 && KeyE0) || (Code==0x12 && KeyUpCode)) && Code){ PS2int=true; PS2code=Code; } if(KeyUpCode)PS2code|=0xf000; if(KeyE0)PS2code|=0xe000; if(KeyE0 && KeyUpCode)PS2code|=0xe0f000; if (Code == 0xaa) { // self test code (a keyboard must have just been plugged in) CapsLock = 0; NumLock = 1; } // so initialise it else if (Code == 0xf0) // a key has been released KeyUpCode = true; else if (Code == 0xe0) // extended keycode prefix KeyE0 = true; else { // Process a scan code from the keyboard into an ASCII character. // It then inserts the char into the keyboard queue. // for the US keyboard and the right Alt key we need to make it the same as the left Alt key if (Option.KeyboardConfig == CONFIG_US && KeyE0 && Code == 0x11) KeyE0 = false; // if a key has been released we are only interested in resetting state keys if (KeyUpCode) { if (Code == L_SHFT) LShift = 0; // left shift button is released else if (Code == R_SHFT) RShift = 0; // right shift button is released else if (Code == CTRL) PS2Ctrl = 0; // left control button is released else if (KeyE0 && Code == 0x11) AltGrDown = 0; // release the AltGr key on non US keyboards else if (Code == KeyDownCode) KeyDownRegister = 0; // normal char so record that it is no longer depressed goto SkipOut; } // we are only here if the key has been pressed (NOT released) if (Code == L_SHFT) { LShift = 1; goto SkipOut; } // left shift button is pressed if (Code == R_SHFT) { RShift = 1; goto SkipOut; } // right shift button is pressed if (Code == CTRL) { PS2Ctrl = 1; goto SkipOut; } // left control button is pressed if (Code == CAPS) { CapsLock = !CapsLock; setleds = 1; // setLEDs(CapsLock, NumLock, 3); goto SkipOut; } if (Code == NUML) { // caps or num lock pressed NumLock = !NumLock; setleds = 1; // setLEDs(CapsLock, NumLock, 7); goto SkipOut; } if (KeyE0 && Code == 0x11) { AltGrDown = 1; goto SkipOut; } // AltGr key pressed on non US Keyboard // now get the character into c. Why, oh why, are scan codes so random? if (!KeyE0 && Code == 0x83) c = 0x97; // a special case, function key F7 else if (KeyE0 && Code == 0x4A) c = '/'; // another special case, this time the keypad forward slash else if (KeyE0 && Code == 0x5A) c = NUM_ENT; // yet another special case, this time the keypad enter key else if ((KeyE0 || !NumLock) && Code >= 104 && Code < 0x80 && !AltGrDown) { // a keycode from the numeric keypad LShift = 0; // when num lock LED is on codes are preceeded by left shift if (Option.KeyboardConfig == CONFIG_ES) c = keyE0Codes_ES[Code - 104]; else c = keyE0Codes[Code - 104]; if (PS2Ctrl) { // special for PB if (c == UP) c = PUP; // CTRL-UP to page up if (c == DOWN) c = PDOWN; // CTRL-DOWN to page down if (c == LEFT) c = HOME; // CTRL-LEFT to home if (c == RIGHT) c = END; // CTRL-RIGHT to end } } else if ((Code >= 0x15 && Code < 0x62) && AltGrDown != 0) // a keycode preceeded by Alt-Gr switch (Option.KeyboardConfig) { // an international keycode pressed with case CONFIG_US: // the AltGr key break; // no code for US keyboard case CONFIG_FR: // French Keyboard switch (Code) { case 0x45: c = 0x40; // @ AltGrDown = 0; break; case 0x25: c = 0x7b; // { AltGrDown = 0; break; case 0x2e: c = 0x5b; // [ AltGrDown = 0; break; case 0x55: c = 0x7d; // } AltGrDown = 0; break; case 0x4e: c = 0x5d; // ] AltGrDown = 0; break; case 0x3e: c = 0x5c; // '\' AltGrDown = 0; break; case 0x1e: c = 0x7e; // ~ AltGrDown = 0; break; case 0x36: c = 0x7c; // | AltGrDown = 0; break; case 0x26: c = 0x23; // # AltGrDown = 0; break; default: c = 0; // invalid code AltGrDown = 0; break; } break; case CONFIG_GR: // German Keyboard switch (Code) { case 0x15: c = 0x40; // @ AltGrDown = 0; break; case 0x3d: c = 0x7b; // { AltGrDown = 0; break; case 0x3e: c = 0x5b; // [ AltGrDown = 0; break; case 0x45: c = 0x7d; // } AltGrDown = 0; break; case 0x46: c = 0x5d; // ] AltGrDown = 0; break; case 0x4e: c = 0x5c; // '\' AltGrDown = 0; break; case 0x5b: c = 0x7e; // ~ AltGrDown = 0; break; case 0x61: c = 0x7c; // | AltGrDown = 0; break; default: c = 0; // invalid code AltGrDown = 0; break; } break; case CONFIG_IT: // Italian Keyboard switch (Code) { case 0x4C: c = 0x40; // @ AltGrDown = 0; break; case 0x54: c = 0x5b; // [ AltGrDown = 0; break; case 0x5b: c = 0x5d; // ] AltGrDown = 0; break; case 0x52: c = 0x23; // # AltGrDown = 0; break; default: c = 0; // invalid code AltGrDown = 0; break; } break; case CONFIG_BE: // Belgian Keyboard switch (Code) { case 0x1e: c = 0x40; // @ AltGrDown = 0; break; case 0x46: c = 0x7b; // { AltGrDown = 0; break; case 0x54: c = 0x5b; // [ AltGrDown = 0; break; case 0x45: c = 0x7d; // } AltGrDown = 0; break; case 0x5b: c = 0x5d; // ] AltGrDown = 0; break; case 0x1a: c = 0x5c; // '\' AltGrDown = 0; break; case 0x4a: c = 0x7e; // ~ AltGrDown = 0; break; case 0x16: c = 0x7c; // | AltGrDown = 0; break; case 0x26: c = 0x23; // # AltGrDown = 0; break; default: c = 0; // invalid code AltGrDown = 0; break; } break; case CONFIG_ES: // Spanish Keyboard switch (Code) { case 0x1E: c = 0x40; // @ AltGrDown = 0; break; case 0x54: c = 0x5b; // [ AltGrDown = 0; break; case 0x5b: c = 0x5d; // ] AltGrDown = 0; break; case 0x26: c = 0x23; // # AltGrDown = 0; break; case 0x52: c = 0x7b; // { AltGrDown = 0; break; case 0x5d: c = 0x7d; // } AltGrDown = 0; break; case 0x16: c = 0x7c; // | AltGrDown = 0; break; case 0x0e: c = 0x5c; // '\' AltGrDown = 0; break; case 0x25: c = 0x7e; // ~ AltGrDown = 0; break; default: c = 0; // invalid code AltGrDown = 0; break; } break; case CONFIG_BR: // Brazilian Keyboard (TO DO) switch (Code) { case 0x1D: c = '?'; // ? AltGrDown = 0; break; case 0x14: c = '/'; // / AltGrDown = 0; break; default: c = 0; // invalid code AltGrDown = 0; break; } break; } else { switch (Option.KeyboardConfig) { case CONFIG_US: if (LShift || RShift) c = keySCodes[0][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[0][Code % 128]; // just a keycode break; case CONFIG_FR: if (LShift || RShift) c = keySCodes[1][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[1][Code % 128]; // just a keycode break; case CONFIG_GR: if (LShift || RShift) c = keySCodes[2][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[2][Code % 128]; // just a keycode break; case CONFIG_IT: if (LShift || RShift) c = keySCodes[3][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[3][Code % 128]; // just a keycode break; case CONFIG_BE: if (LShift || RShift) c = keySCodes[4][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[4][Code % 128]; // just a keycode break; case CONFIG_UK: if (LShift || RShift) c = keySCodes[5][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[5][Code % 128]; // just a keycode break; case CONFIG_ES: if (LShift || RShift) c = keySCodes[6][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[6][Code % 128]; // just a keycode break; case CONFIG_BR: if (LShift || RShift) c = keySCodes[7][Code % 128]; // a keycode preceeded by a shift else c = keyCodes[7][Code % 128]; // just a keycode break; } } if (!c) goto SkipOut; if (c <= 0x7F) { // a normal character if (CapsLock && c >= 'a' && c <= 'z') c -= 32; // adj for caps lock if (PS2Ctrl) c &= 0x1F; // adj for control } else { // must be a function key or similar if (LShift || RShift) c |= 0b00100000; // NOTE: Special for PB, CTRL-UP to page up, CTRL-DOWN to page down, CTRL-LEFT to home, CTRL-RIGHT to end if (PS2Ctrl && !(c == PUP || c == PDOWN || c == HOME || c == END)) c |= 0b01000000; } if (BreakKey && c == BreakKey) { // if the user wants to stop the progran MMAbort = true; // set the flag for the interpreter to see ConsoleRxBufHead = ConsoleRxBufTail; // empty the buffer // break; } else { if (!(justset && c == '3')) { Timer3=0; ConsoleRxBuf[ConsoleRxBufHead] = c; // store the byte in the ring buffer if (ConsoleRxBuf[ConsoleRxBufHead] == keyselect && KeyInterrupt != NULL) { Keycomplete = true; } else { ConsoleRxBufHead = (ConsoleRxBufHead + 1) % CONSOLE_RX_BUF_SIZE; // advance the head of the queue if (ConsoleRxBufHead == ConsoleRxBufTail) { // if the buffer has overflowed ConsoleRxBufTail = (ConsoleRxBufTail + 1) % CONSOLE_RX_BUF_SIZE; // throw away the oldest char } } } else justset = 0; } SkipOut: // end lump of self contained code ////////////////////////////////////////////////////////////////////////////////////////////////////////// KeyUpCode = false; KeyE0 = false; } } /*************************************************************************************************** change notification interrupt service routine ****************************************************************************************************/ void __not_in_flash_func(CNInterrupt)(uint64_t dd) { static unsigned char Code = 0; int d = dd & (1<>= 1; // shift in data bit if (d) Code |= 0x80; // PS2DAT == 1 KParity ^= Code; // calculate parity if (--KCount <= 0) PS2State = PS2PARITY; // all bit read break; case PS2PARITY: if (d) KParity ^= 0x80; // PS2DAT == 1 if (KParity & 0x80) // parity odd, continue PS2State = PS2STOP; else { PS2State = PS2ERROR; putConsole('q',1); } break; case PS2STOP: if (d) { // PS2DAT == 1 processcode(Code); Code = 0; } PS2State = PS2START; break; } } }