/* * Author: Pawel Jablonski * E-mail: pj@xirx.net * WWW: xirx.net * GIT: git.xirx.net * * License: You can use this code however you like * but leave information about the original author. * Code is free for non-commercial and commercial use. */ #include #include #include #include #include #include "type.h" #include "led.h" #include "keyboard.h" #define KEYBOARD_COLUMN_QUANTITY 15 //!< Quantity of key columns of keyboard #define KEYBOARD_ROW_QUANTITY 5 //!< Quantity of key rows of keyboard #define KEYBOARD_STATUS_RETRY 5 //!< How many times read status of all keys #define KEYBOARD_STATUS_MIN 4 //!< How many statuses must be high to count a key as clicked #define KEYBOARD_BUFFER_SIZE 16 //!< Global input buffer size #define KEYBOARD_LOCAL_BUFFER_SIZE 8 //!< Local input buffer size for the read function #define KEYBOARD_KEY_ESC 0x1b //!< Escape key code #define KEYBOARD_KEY_BACKSPACE 0x08 //!< Backspace key code #define KEYBOARD_KEY_TAB 0x09 //!< Tab key code #define KEYBOARD_KEY_ENTER 0x0d //!< Enter key code #define KEYBOARD_KEY_DELETE 0x7f //!< Delete key code #define KEYBOARD_KEY_UP 0x11 //!< Up arrow key code #define KEYBOARD_KEY_DOWN 0x12 //!< Down arrow key code #define KEYBOARD_KEY_LEFT 0x13 //!< Left arrow key code #define KEYBOARD_KEY_RIGHT 0x14 //!< Right arrow key code #define KEYBOARD_CTRL_MASK 0x80 //!< Mask used to check if the control key is pressed too #define KEYBOARD_CTRL_MIN_CODE 0x20 //!< Minimum key code where the control mask can be set #define KEYBOARD_POS_SHIFT_LEFT_COLUMN 14 //!< Left shift key column position in the key statuses matrix #define KEYBOARD_POS_SHIFT_LEFT_ROW 1 //!< Left shift key row position in the key statuses matrix #define KEYBOARD_POS_SHIFT_RIGHT_COLUMN 3 //!< Right shift key column position in the key statuses matrix #define KEYBOARD_POS_SHIFT_RIGHT_ROW 1 //!< Right shift key row position in the key statuses matrix #define KEYBOARD_POS_CAPSLOCK_COLUMN 14 //!< Capslock key column position in the key statuses matrix #define KEYBOARD_POS_CAPSLOCK_ROW 2 //!< Capslock key row position in the key statuses matrix #define KEYBOARD_POS_CTRL_COLUMN 14 //!< Control key column position in the key statuses matrix #define KEYBOARD_POS_CTRL_ROW 0 //!< Control key row position in the key statuses matrix //! Keyboard matrix with data for every key for down and upper case static const unsigned char keyCode[2][KEYBOARD_ROW_QUANTITY][KEYBOARD_COLUMN_QUANTITY] = { { { 0x00, KEYBOARD_KEY_RIGHT, KEYBOARD_KEY_DOWN, KEYBOARD_KEY_LEFT, 0x00, 0x00, 0x00, 0x00, 0x00, ' ', 0x00, 0x00, 0x00, 0x00, 0xff }, { 0x00, KEYBOARD_KEY_DELETE, KEYBOARD_KEY_UP, 0xff, '/', '.', ',', 'm', 'n', 'b', 'v', 'c', 'x', 'z', 0xff }, { 0x00, KEYBOARD_KEY_ENTER, 0x00, '\'', ';', 'l', 'k', 'j', 'h', 'g', 'f', 'd', 's', 'a', 0xff }, { 0x00, '\\', ']', '[', 'p', 'o', 'i', 'u', 'y', 't', 'r', 'e', 'w', 'q', KEYBOARD_KEY_TAB }, { KEYBOARD_KEY_BACKSPACE, '`', '+', '-', '0', '9', '8', '7', '6', '5', '4', '3', '2', '1', KEYBOARD_KEY_ESC } }, { { 0x00, KEYBOARD_KEY_RIGHT, KEYBOARD_KEY_DOWN, KEYBOARD_KEY_LEFT, 0x00, 0x00, 0x00, 0x00, 0x00, ' ', 0x00, 0x00, 0x00, 0x00, 0xff }, { 0x00, KEYBOARD_KEY_DELETE, KEYBOARD_KEY_UP, 0xff, '?', '>', '<', 'M', 'N', 'B', 'V', 'C', 'X', 'Z', 0xff }, { 0x00, KEYBOARD_KEY_ENTER, 0x00, '"', ':', 'L', 'K', 'J', 'H', 'G', 'F', 'D', 'S', 'A', 0xff }, { 0x00, '|', '}', '{', 'P', 'O', 'I', 'U', 'Y', 'T', 'R', 'E', 'W', 'Q', KEYBOARD_KEY_TAB }, { KEYBOARD_KEY_BACKSPACE, '~', '+', '_', ')', '(', '*', '&', '^', '%', '$', '#', '@', '!', KEYBOARD_KEY_ESC }, } }; static bool keyLastStatus[KEYBOARD_ROW_QUANTITY][KEYBOARD_COLUMN_QUANTITY]; //!< Last key statuses matrix static bool capslock = 0; //!< Capslock key status static unsigned char buffer[KEYBOARD_BUFFER_SIZE]; //!< Circular keyboard input buffer static volatile unsigned int bufferStart = 0; //!< Data start position static volatile unsigned int bufferEnd = 0; //!< Data end position //! Init keyboard and set up the pin outs and inputs void keyboardInit(void) { GPIO_InitTypeDef gpioInit = {0}; __HAL_RCC_GPIOC_CLK_ENABLE(); gpioInit.Pin = (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); gpioInit.Mode = GPIO_MODE_OUTPUT_PP; gpioInit.Pull = GPIO_NOPULL; gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOC, &gpioInit); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); __HAL_RCC_GPIOA_CLK_ENABLE(); gpioInit.Pin = (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); gpioInit.Mode = GPIO_MODE_OUTPUT_PP; gpioInit.Pull = GPIO_NOPULL; gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &gpioInit); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); __HAL_RCC_GPIOD_CLK_ENABLE(); gpioInit.Pin = GPIO_PIN_2; gpioInit.Mode = GPIO_MODE_INPUT; gpioInit.Pull = GPIO_PULLDOWN; gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOD, &gpioInit); for(int i = 0; i < KEYBOARD_ROW_QUANTITY; i++) { for(int j = 0; j < KEYBOARD_COLUMN_QUANTITY; j++) { keyLastStatus[i][j] = FALSE; } } } //! Process the keyboard fire event. It reads current keyboard status and adds new data to the input buffer. void keyboardFire(void) { static unsigned char keyStatus[KEYBOARD_ROW_QUANTITY][KEYBOARD_COLUMN_QUANTITY]; bool shift = FALSE; bool ctrl = FALSE; unsigned char localBuffer[KEYBOARD_LOCAL_BUFFER_SIZE]; unsigned char localBufferEnd = 0; for(int i = 0; i < KEYBOARD_ROW_QUANTITY; i++) { for(int j = 0; j < KEYBOARD_COLUMN_QUANTITY; j++) { keyStatus[i][j] = 0; } } for(int retry = 0; retry < KEYBOARD_STATUS_RETRY; retry++) { for(int i = 0; i < KEYBOARD_ROW_QUANTITY; i++) { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, ((i & 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET)); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, ((i & 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET)); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, ((i & 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET)); for(int j = 0; j < KEYBOARD_COLUMN_QUANTITY; j++) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, ((j & 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET)); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, ((j & 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET)); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, ((j & 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET)); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, ((j & 0x08) ? GPIO_PIN_SET : GPIO_PIN_RESET)); // wait { volatile int w = 15; while(w--); } if(HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_2) == GPIO_PIN_SET) { keyStatus[i][j]++; } } } } if(keyStatus[KEYBOARD_POS_SHIFT_LEFT_ROW][KEYBOARD_POS_SHIFT_LEFT_COLUMN] >= KEYBOARD_STATUS_MIN) { shift = TRUE; } else if(keyStatus[KEYBOARD_POS_SHIFT_RIGHT_ROW][KEYBOARD_POS_SHIFT_RIGHT_COLUMN] >= KEYBOARD_STATUS_MIN) { shift = TRUE; } if(keyStatus[KEYBOARD_POS_CAPSLOCK_ROW][KEYBOARD_POS_CAPSLOCK_COLUMN] >= KEYBOARD_STATUS_MIN) { if(!(keyLastStatus[KEYBOARD_POS_CAPSLOCK_ROW][KEYBOARD_POS_CAPSLOCK_COLUMN])) { if(capslock) { ledSetCapslock(FALSE); capslock = FALSE; } else { ledSetCapslock(TRUE); capslock = TRUE; } keyLastStatus[KEYBOARD_POS_CAPSLOCK_ROW][KEYBOARD_POS_CAPSLOCK_COLUMN] = TRUE; } } else { keyLastStatus[KEYBOARD_POS_CAPSLOCK_ROW][KEYBOARD_POS_CAPSLOCK_COLUMN] = FALSE; } if(keyStatus[KEYBOARD_POS_CTRL_ROW][KEYBOARD_POS_CTRL_COLUMN] >= KEYBOARD_STATUS_MIN) { ctrl = TRUE; } for(int i = 0; i < KEYBOARD_ROW_QUANTITY; i++) { for(int j = 0; j < KEYBOARD_COLUMN_QUANTITY; j++) { if((keyCode[0][i][j] > 0x00) && (keyCode[0][i][j] < 0xff)) { if(keyStatus[i][j] >= KEYBOARD_STATUS_MIN) { if(!(keyLastStatus[i][j])) { unsigned char key; if(((!capslock) && shift) || (capslock && (!shift))) { key = keyCode[1][i][j]; } else { key = keyCode[0][i][j]; } if(ctrl && (key >= KEYBOARD_CTRL_MIN_CODE)) { key |= KEYBOARD_CTRL_MASK; } if(localBufferEnd < KEYBOARD_LOCAL_BUFFER_SIZE) { localBuffer[localBufferEnd] = key; localBufferEnd++; } keyLastStatus[i][j] = TRUE; } } else { keyLastStatus[i][j] = FALSE; } } } } for(int i = 0; i < localBufferEnd; i++) { __disable_irq(); { if(bufferStart == ((bufferEnd + 1) % KEYBOARD_BUFFER_SIZE)) { __enable_irq(); break; } buffer[bufferEnd] = localBuffer[i]; bufferEnd = ((bufferEnd + 1) % KEYBOARD_BUFFER_SIZE); } __enable_irq(); } } /** * Read a next char from input buffer * * @return Next char from the input buffer */ unsigned char keyboardGetKey(void) { __disable_irq(); if(bufferStart == bufferEnd) { __enable_irq(); return(0x00); } else { unsigned int first = bufferStart; bufferStart = ((first + 1) % KEYBOARD_BUFFER_SIZE); unsigned char val = buffer[first]; __enable_irq(); return(val); } } /** * Check if is a new data in the input buffer * * @return Status of waiting data in the input buffer */ bool keyboardIsData(void) { __disable_irq(); if(bufferStart == bufferEnd) { __enable_irq(); return(FALSE); } else { __enable_irq(); return(TRUE); } }