diff --git a/src/dev/Makefile b/src/dev/Makefile index c729b3b..d6d15d3 100644 --- a/src/dev/Makefile +++ b/src/dev/Makefile @@ -37,7 +37,14 @@ else ifeq ($(UNIT),F256) AS=as65816 AR=nlib - SRCS_FOR_UNIT=txt_f256.c kbd_f256k.c indicators_c256.c interrupts_f256.c sdc_f256.c # timers_c256.c + SRCS_FOR_UNIT=txt_f256.c kbd_f256.c kbd_f256jr.c indicators_c256.c interrupts_f256.c sdc_f256.c # timers_c256.c + CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large # --target Foenix +else ifeq ($(UNIT),F256K) + CC=cc65816 + AS=as65816 + AR=nlib + + SRCS_FOR_UNIT=txt_f256.c kbd_f256.c kbd_f256k.c indicators_c256.c interrupts_f256.c sdc_f256.c # timers_c256.c CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large # --target Foenix endif diff --git a/src/dev/console.c b/src/dev/console.c index 91411a3..3ef98fb 100644 --- a/src/dev/console.c +++ b/src/dev/console.c @@ -22,6 +22,8 @@ #if MODEL == MODEL_FOENIX_A2560K #include "dev/kbd_mo.h" +#elif MODEL == MODEL_FOENIX_F256 +#include "dev/kbd_f256jr.h" #elif MODEL == MODEL_FOENIX_F256K #include "dev/kbd_f256k.h" #endif diff --git a/src/dev/kbd_f256.c b/src/dev/kbd_f256.c new file mode 100644 index 0000000..dec56a7 --- /dev/null +++ b/src/dev/kbd_f256.c @@ -0,0 +1,419 @@ +/** + * @file kbd_f256.h + * @author your name (you@domain.com) + * @brief Common code for F256 keyboards to convert scancodes to characters + * @version 0.1 + * @date 2024-07-12 + * + * @copyright Copyright (c) 2024 + * + */ + +#include "log_level.h" +#define DEFAULT_LOG_LEVEL LOG_ERROR + +#include + +#include "log.h" +#include "kbd_f256.h" +#include "kbd_f256jr.h" +#include "ring_buffer.h" +#include "simpleio.h" +#include "sys_macros.h" +#include "txt_screen.h" + +/* + * Modifier bit flags + */ + +#define KBD_LOCK_SCROLL 0x01 +#define KBD_LOCK_NUM 0x02 +#define KBD_LOCK_CAPS 0x04 +#define KBD_MOD_SHIFT 0x08 +#define KBD_MOD_CTRL 0x10 +#define KBD_MOD_ALT 0x20 +#define KBD_MOD_OS 0x40 +#define KBD_MOD_MENU 0x80 + +/* + * Mapping of "codepoints" 0x80 - 0x98 (function keys, etc) + * to ANSI escape codes + */ +const char * ansi_keys[] = { + "1", /* HOME */ + "2", /* INS */ + "3", /* DELETE */ + "4", /* END */ + "5", /* PgUp */ + "6", /* PgDn */ + "A", /* Up */ + "B", /* Left */ + "C", /* Right */ + "D", /* Down */ + "11", /* F1 */ + "12", /* F2 */ + "13", /* F3 */ + "14", /* F4 */ + "15", /* F5 */ + "17", /* F6 */ + "18", /* F7 */ + "19", /* F8 */ + "20", /* F9 */ + "21", /* F10 */ + "23", /* F11 */ + "24", /* F12 */ + "30", /* MONITOR */ + "31", /* CTX SWITCH */ + "32" /* MENU HELP */ +}; + +/* + * US keyboard layout scancode translation tables + */ + +#define POUND 0x9c + +const char kbd_256k_layout[] = { + // Unmodified + 0x00, 0x1B, '1', '2', '3', '4', '5', '6', /* 0x00 - 0x07 */ + '7', '8', '9', '0', '-', '=', 0x08, 0x09, /* 0x08 - 0x0F */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 0x10 - 0x17 */ + 'o', 'p', '[', ']', 0x0D, 0x00, 'a', 's', /* 0x18 - 0x1F */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 0x20 - 0x27 */ + 0x27, '`', 0x00, '\\', 'z', 'x', 'c', 'v', /* 0x28 - 0x2F */ + 'b', 'n', 'm', ',', '.', '/', 0x00, '*', /* 0x30 - 0x37 */ + 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ + 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ + 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ + 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ + 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ + + // Shifted + 0x00, 0x1B, '!', '@', '#', '$', '%', '^', /* 0x00 - 0x07 */ + '&', '*', '(', ')', '_', '+', 0x08, 0x09, /* 0x08 - 0x0F */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 0x10 - 0x17 */ + 'O', 'P', '{', '}', 0x0A, 0x00, 'A', 'S', /* 0x18 - 0x1F */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 0x20 - 0x27 */ + 0x22, '~', 0x00, '|', 'Z', 'X', 'C', 'V', /* 0x28 - 0x2F */ + 'B', 'N', 'M', '<', '>', '?', 0x00, 0x00, /* 0x30 - 0x37 */ + 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ + 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ + 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ + 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ + 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ + + // Control + 0x00, 0x1B, '1', '2', '3', '4', '5', 0x1E, /* 0x00 - 0x07 */ + '7', '8', '9', '0', 0x1F, '=', 0x08, 0x09, /* 0x08 - 0x0F */ + 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* 0x10 - 0x17 */ + 0x0F, 0x10, 0x1B, 0x1D, 0x0A, 0x00, 0x01, 0x13, /* 0x18 - 0x1F */ + 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, ';', /* 0x20 - 0x27 */ + 0x22, '`', 0x00, '\\', 0x1A, 0x18, 0x03, 0x16, /* 0x28 - 0x2F */ + 0x02, 0x0E, 0x0D, ',', '.', 0x1C, 0x00, 0x00, /* 0x30 - 0x37 */ + 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ + 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ + 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ + 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ + 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ + + + // Control-Shift + 0x00, 0x1B, '!', '@', '#', '$', '%', '^', /* 0x00 - 0x07 */ + '&', '*', '(', ')', '_', '+', 0x08, 0x09, /* 0x08 - 0x0F */ + 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* 0x10 - 0x17 */ + 0x0F, 0x10, 0x1B, 0x1D, 0x0A, 0x00, 0x01, 0x13, /* 0x18 - 0x1F */ + 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, ';', /* 0x20 - 0x27 */ + 0x22, '`', 0x00, '\\', 0x1A, 0x18, 0x03, 0x16, /* 0x28 - 0x2F */ + 0x02, 0x0E, 0x0D, ',', '.', 0x1C, 0x00, 0x00, /* 0x30 - 0x37 */ + 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ + 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ + 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ + 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ + 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ + + // Capslock + 0x00, 0x1B, '1', '2', '3', '4', '5', '6', /* 0x00 - 0x07 */ + '7', '8', '9', '0', '-', '=', 0x08, 0x09, /* 0x08 - 0x0F */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 0x10 - 0x17 */ + 'O', 'P', '[', ']', 0x0D, 0x00, 'A', 'S', /* 0x18 - 0x1F */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', /* 0x20 - 0x27 */ + 0x27, '`', 0x00, '\\', 'Z', 'X', 'C', 'V', /* 0x28 - 0x2F */ + 'B', 'N', 'M', ',', '.', '/', 0x00, 0x00, /* 0x30 - 0x37 */ + 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, '7', /* 0x40 - 0x47 */ + '8', '9', '-', '4', '5', '6', '+', '1', /* 0x48 - 0x4F */ + '2', '3', '0', '.', 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ + 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ + 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ + + // Caps-Shift + 0x00, 0x1B, '!', '@', '#', '$', '%', '^', /* 0x00 - 0x07 */ + '&', '*', '(', ')', '_', '+', 0x08, 0x09, /* 0x08 - 0x0F */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 0x10 - 0x17 */ + 'o', 'p', '{', '}', 0x0A, 0x00, 'a', 's', /* 0x18 - 0x1F */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ':', /* 0x20 - 0x27 */ + 0x22, 0x00, 0x00, 0x00, 'z', 'x', 'c', 'v', /* 0x28 - 0x2F */ + 'b', 'n', 'm', '<', '>', '?', 0x00, 0x00, /* 0x30 - 0x37 */ + 0x00, ' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38 - 0x3F */ + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, '7', /* 0x40 - 0x47 */ + '8', '9', '-', '4', '5', '6', '+', '1', /* 0x48 - 0x4F */ + '2', '3', '0', '.', 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ + 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ + 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ + + // ALT + 0x00, 0x1B, '1', '2', '3', POUND, '5', '6', /* 0x00 - 0x07 */ + '~', '`', '|', '\\', '-', '=', 0x08, 0x09, /* 0x08 - 0x0F */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 0x10 - 0x17 */ + 'o', 'p', '[', ']', 0x0D, 0x00, 'a', 's', /* 0x18 - 0x1F */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 0x20 - 0x27 */ + 0x27, 0x00, 0x00, 0x00, 'z', 'x', 'c', 'v', /* 0x28 - 0x2F */ + 'b', 'n', 'm', ',', '.', '/', 0x00, '*', /* 0x30 - 0x37 */ + 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ + 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ + 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ + 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ + 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ +}; + +// +// Driver variables +// + +static t_word_ring char_buffer; + +/* Scan code to character lookup tables */ + +static char keys_unmodified[128]; +static char keys_shift[128]; +static char keys_control[128]; +static char keys_control_shift[128]; +static char keys_caps[128]; +static char keys_caps_shift[128]; +static char keys_alt[128]; + + +/* + * Catch special keys and convert them to their ANSI terminal codes + * + * Characters 0x80 - 0x98 are reserved for function keys, arrow keys, etc. + * This function maps them to the ANSI escape codes + * + * Inputs: + * modifiers = the current modifier bit flags (ALT, CTRL, META, etc) + * c = the character found from the scan code. + */ +static unsigned char kbd_to_ansi(unsigned char modifiers, unsigned char c) { + if ((c >= 0x80) && (c <= 0x98)) { + /* The key is a function key or a special control key */ + const char * ansi_key = ansi_keys[c - 0x80]; + const char * sequence; + short modifiers_after = 0; + + // Figure out if the modifiers come before or after the sequence code + if (isdigit(ansi_key[0])) { + // Sequence is numeric, modifiers come after + modifiers_after = 1; + } + + // After ESC, all sequences have [ + rb_word_put(&char_buffer, '['); + + if (modifiers_after) { + // Sequence is numberic, get the expanded sequence and put it in the queue + for (sequence = ansi_keys[c - 0x80]; *sequence != 0; sequence++) { + rb_word_put(&char_buffer, *sequence); + } + } + + // Check to see if we need to send a modifier sequence + if (modifiers & (KBD_MOD_SHIFT | KBD_MOD_CTRL | KBD_MOD_ALT | KBD_MOD_OS)) { + unsigned char code_bcd; + short modifier_code = 0; + short i; + + if (modifiers_after) { + // Sequence is numeric, so put modifiers after the sequence and a semicolon + rb_word_put(&char_buffer, ';'); + } + + modifier_code = ((modifiers >> 3) & 0x1F) + 1; + code_bcd = i_to_bcd(modifier_code); + + if (code_bcd & 0xF0) { + rb_word_put(&char_buffer, ((code_bcd & 0xF0) >> 4) + '0'); + } + rb_word_put(&char_buffer, (code_bcd & 0x0F) + '0'); + } + + if (!modifiers_after) { + // Sequence is a letter code + rb_word_put(&char_buffer, ansi_key[0]); + } else { + // Sequence is numeric, close it with a tilda + rb_word_put(&char_buffer, '~'); + } + + return 0x1B; /* Start the sequence with an escape */ + + } else if (c == 0x1B) { + /* ESC should be doubled, to distinguish from the start of an escape sequence */ + rb_word_put(&char_buffer, 0x1B); + return c; + + } else { + /* Not a special key: return the character unmodified */ + + return c; + } +} + +/* + * Try to get a character from the keyboard... + * + * Returns: + * the next character to be read from the keyboard (0 if none available) + */ +char kbd_getc() { + if (!rb_word_empty(&char_buffer)) { + // If there is a character waiting in the character buffer, return it... + return (char)rb_word_get(&char_buffer); + + } else { + // Otherwise, we need to check the scan code queue... + unsigned short raw_code = kbd_get_scancode(); + while (raw_code != 0) { + if ((raw_code & 0x80) == 0) { + // If it's a make code, let's try to look it up... + unsigned char modifiers = (raw_code >> 8) & 0xff; // Get the modifiers + unsigned char scan_code = raw_code & 0x7f; // Get the base code for the key + + // Check the modifiers to see what we should lookup... + + if ((modifiers & (KBD_MOD_ALT | KBD_MOD_SHIFT | KBD_MOD_CTRL | KBD_LOCK_CAPS)) == 0) { + // No modifiers... just return the base character + return kbd_to_ansi(modifiers, keys_unmodified[scan_code]); + + } else if (modifiers & KBD_MOD_ALT) { + return kbd_to_ansi(modifiers, keys_alt[scan_code]); + + } else if (modifiers & KBD_MOD_CTRL) { + // If CTRL is pressed... + if (modifiers & KBD_MOD_SHIFT) { + // If SHIFT is also pressed, return CTRL-SHIFT form + return kbd_to_ansi(modifiers, keys_control_shift[scan_code]); + + } else { + // Otherwise, return just CTRL form + return kbd_to_ansi(modifiers, keys_control[scan_code]); + } + + } else if (modifiers & KBD_LOCK_CAPS) { + // If CAPS is locked... + if (modifiers & KBD_MOD_SHIFT) { + // If SHIFT is also pressed, return CAPS-SHIFT form + return kbd_to_ansi(modifiers, keys_caps_shift[scan_code]); + + } else { + // Otherwise, return just CAPS form + return kbd_to_ansi(modifiers, keys_caps[scan_code]); + } + } else { + // SHIFT is pressed, return SHIFT form + return kbd_to_ansi(modifiers, keys_shift[scan_code]); + } + } + + // If we reach this point, it wasn't a useful scan-code... + // So try to fetch another + raw_code = kbd_get_scancode(); + } + + // If we reach this point, there are no useful scan codes + return 0; + } +} + +/* + * Set the keyboard translation tables + * + * The translation tables provided to the keyboard consist of eight + * consecutive tables of 128 characters each. Each table maps from + * the MAKE scan code of a key to its appropriate 8-bit character code. + * + * The tables included must include, in order: + * - UNMODIFIED: Used when no modifier keys are pressed or active + * - SHIFT: Used when the SHIFT modifier is pressed + * - CTRL: Used when the CTRL modifier is pressed + * - CTRL-SHIFT: Used when both CTRL and SHIFT are pressed + * - CAPSLOCK: Used when CAPSLOCK is down but SHIFT is not pressed + * - CAPSLOCK-SHIFT: Used when CAPSLOCK is down and SHIFT is pressed + * - ALT: Used when only ALT is presse + * - ALT-SHIFT: Used when ALT is pressed and either CAPSLOCK is down + * or SHIFT is pressed (but not both) + * + * Inputs: + * tables = pointer to the keyboard translation tables + */ +short SYSTEMCALL kbd_layout(const char * tables) { + short i; + + for (i = 0; i < 128; i++) { + keys_unmodified[i] = tables[i]; + keys_shift[i] = tables[i + 128]; + keys_control[i] = tables[i + 256]; + // if (keys_control[i] == 0x03) { + // // We have set the scan code for CTRL-C? + // g_kbdmo_break_sc = i; + // } + // Check for CTRL-C + keys_control_shift[i] = tables[i + 384]; + keys_caps[i] = tables[i + 512]; + keys_caps_shift[i] = tables[i + 640]; + keys_alt[i] = tables[i + 768]; + } + + return 0; +} + +/** + * @brief Initialize the keyboard scancode to character converter. + * + */ +void kbd_init() { + // Initialize the low level scancode driver + kbd_sc_init(); + + // Initialize character ring buffer + rb_word_init(&char_buffer); + + // Set up the layout of the F256k keyboard + kbd_layout(kbd_256k_layout); +} + diff --git a/src/dev/kbd_f256.h b/src/dev/kbd_f256.h new file mode 100644 index 0000000..1f46ec4 --- /dev/null +++ b/src/dev/kbd_f256.h @@ -0,0 +1,60 @@ +/** + * @file kbd_f256.h + * @author your name (you@domain.com) + * @brief Common code for F256 keyboards to convert scancodes to characters + * @version 0.1 + * @date 2024-07-12 + * + * @copyright Copyright (c) 2024 + * + */ + +#ifndef __kbd_f256_h__ +#define __kbd_f256_h__ + +#if MODEL == MODEL_FOENIX_F256 +#include "kbd_f256jr.h" +#elif MODEL == MODEL_FOENIX_F256K || MODEL == MODEL_FOENIX_F256K2 +#include "kbd_f256k.h" +#endif + +#include "sys_macros.h" + +/* + * Try to get a character from the keyboard... + * + * Returns: + * the next character to be read from the keyboard (0 if none available) + */ +extern char kbd_getc(); + +/* + * Set the keyboard translation tables + * + * The translation tables provided to the keyboard consist of eight + * consecutive tables of 128 characters each. Each table maps from + * the MAKE scan code of a key to its appropriate 8-bit character code. + * + * The tables included must include, in order: + * - UNMODIFIED: Used when no modifier keys are pressed or active + * - SHIFT: Used when the SHIFT modifier is pressed + * - CTRL: Used when the CTRL modifier is pressed + * - CTRL-SHIFT: Used when both CTRL and SHIFT are pressed + * - CAPSLOCK: Used when CAPSLOCK is down but SHIFT is not pressed + * - CAPSLOCK-SHIFT: Used when CAPSLOCK is down and SHIFT is pressed + * - ALT: Used when only ALT is presse + * - ALT-SHIFT: Used when ALT is pressed and either CAPSLOCK is down + * or SHIFT is pressed (but not both) + * + * Inputs: + * tables = pointer to the keyboard translation tables + */ +extern SYSTEMCALL short kbd_layout(const char * tables); + +/** + * @brief Initialize the keyboard scancode to character converter. + * + */ +extern void kbd_init(); + +#endif diff --git a/src/dev/kbd_f256jr.c b/src/dev/kbd_f256jr.c new file mode 100644 index 0000000..28ff942 --- /dev/null +++ b/src/dev/kbd_f256jr.c @@ -0,0 +1,464 @@ +/** + * @file kbd_f256jr.h + * @author your name (you@domain.com) + * @brief Driver for the F256jr PS/2 keyboard + * @version 0.1 + * @date 2024-06-17 + * + * @copyright Copyright (c) 2024 + * + */ + +#ifndef __kbd_f256jr_h__ +#define __kbd_f256jr_h__ + +#include "log_level.h" +#ifndef DEFAULT_LOG_LEVEL + #define DEFAULT_LOG_LEVEL LOG_ERROR +#endif + +#include + +#include "interrupt.h" +#include "log.h" +#include "ps2_reg.h" +#include "ring_buffer.h" +#include "sys_macros.h" + +// +// Constants +// + +/* + * Modifier bit flags + */ + +#define KBD_LOCK_SCROLL 0x01 +#define KBD_LOCK_NUM 0x02 +#define KBD_LOCK_CAPS 0x04 +#define KBD_MOD_SHIFT 0x08 +#define KBD_MOD_CTRL 0x10 +#define KBD_MOD_ALT 0x20 +#define KBD_MOD_OS 0x40 +#define KBD_MOD_MENU 0x80 + +/* + * Special PS/2 byte codes + */ + +#define KBD_PS2_SC_LSHIFT 0x12 +#define KBD_PS2_SC_RSHIFT 0x59 +#define KBD_PS2_SC_CAPS 0x58 +#define KBD_PS2_SC_LCTRL 0x14 +#define KBD_PS2_SC_RCTRL 0x14 +#define KBD_PS2_SC_LALT 0x11 +#define KBD_PS2_SC_RALT 0x11 +#define KBD_PS2_SC_NUM 0x77 +#define KBD_PS2_SC_LGUI 0x1f +#define KBD_PS2_SC_RGUI 0x27 + +/* + * Special Foenix key scan codes + */ + +#define KEY_C 0x2e +#define KEY_BREAK 0x61 + +/** + * @brief Translation from base set 2 scancodes to Foenix scancodes + * + */ +const short kbd_ps2_default_sc[] = { + 0x00, 0x43, 0x00, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x00, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x00, // 0x00 - 0x0f + 0x00, 0x38, 0x2a, 0x00, 0x1d, 0x10, 0x02, 0x00, 0x00, 0x00, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x00, // 0x10 - 0x1f + 0x00, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x00, 0x00, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x00, // 0x20 - 0x2f + 0x00, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x00, 0x00, 0x00, 0x32, 0x24, 0x16, 0x08, 0x09, 0x00, // 0x30 - 0x3f + 0x00, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x00, 0x00, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x00, // 0x40 - 0x4f + 0x00, 0x00, 0x28, 0x00, 0x1a, 0x0d, 0x00, 0x00, 0x3a, 0x36, 0x1c, 0x1b, 0x00, 0x2b, 0x00, 0x00, // 0x50 - 0x5f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 - 0x6f + 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 0x57, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 - 0x7f + 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x8f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x9f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 - 0xaf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 - 0xbf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 - 0xcf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 - 0xdf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 - 0xef + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf0 - 0xff +}; + +/** + * @brief Translation from set 2 E0 prefixed scancodes to Foenix scancodes + * + */ +const short kbd_ps2_e0_sc[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 - 0x0f + 0x00, 0x5c, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, // 0x10 - 0x1f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, // 0x20 - 0x2f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 - 0x3f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 - 0x4f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 - 0x5f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x69, 0x63, 0x00, 0x00, 0x00, // 0x60 - 0x6f + 0x62, 0x65, 0x6a, 0x00, 0x6b, 0x68, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x64, 0x00, 0x00, // 0x70 - 0x7f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x8f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x9f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 - 0xaf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 - 0xbf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 - 0xcf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 - 0xdf + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 - 0xef + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf0 - 0xff +}; + +/** + * @brief States of the keyboard engine + * + */ +enum kbd_state_e { + kbd_state_default = 0, + kbd_state_e0, + kbd_state_e0f0, + kbd_state_f0, + kbd_state_e1, + kbd_state_e114, + kbd_state_e11477, + kbd_state_e11477e1, + kbd_state_e11477e1f0, + kbd_state_e11477e1f014, + kbd_state_e11477e1f014f0, + kbd_state_e11477e1f014f077 +}; + +// +// Module variables +// + +static enum kbd_state_e kbd_state = kbd_state_default; +static t_word_ring scan_code_buffer; +static t_word_ring char_buffer; +static uint8_t modifiers = 0; +static bool break_pressed = false; + +// +// Code +// + +static void kbd_send_cmd(uint8_t byte) { + uint8_t status = 0; + + *PS2_OUT = byte; + *PS2_CTRL |= PS2_CTRL_KBD_WR; + + do { + status = *PS2_STAT; + } while ((status & (PS2_STAT_KBD_ACK | PS2_STAT_KBD_NAK)) == 0); + + *PS2_CTRL &= ~PS2_CTRL_KBD_WR; +} + +/** + * @brief Enqueue the scancode into the keyboard scancode buffer with modifiers added + * + * @param scancode the base scancode to enqueue + * @param is_make true if the byte is a make code, false if it's a break + */ +static void kbd_enqueue_scancode(short scancode, bool is_make) { + if (is_make) { + // CTRL-C or CTRL-PAUSE trigger a break + if (modifiers & KBD_MOD_CTRL) { + if (scancode == KEY_C) { + break_pressed = true; + } + } else if (modifiers & KBD_MOD_ALT) { + if (scancode == KEY_BREAK) { + break_pressed = true; + } + } + rb_word_put(&scan_code_buffer, modifiers << 8 | (scancode & 0x00ff)); + + } else { + rb_word_put(&scan_code_buffer, modifiers << 8 | (scancode & 0x00ff) | 0x0080); + } +} + +/** + * @brief Handle the special tracking for modifier and lock keys + * + * @param modifier the modifier flag to either toggle or set/clear + * @param is_make true if the byte is a make code, false if it's a break + */ +static void kbd_process_modifier(short modifier, bool is_make) { + switch(modifier) { + case KBD_MOD_SHIFT: + case KBD_MOD_CTRL: + case KBD_MOD_ALT: + if (is_make) { + modifiers |= modifier; + } else { + modifiers &= ~modifier; + } + break; + + case KBD_LOCK_CAPS: + case KBD_LOCK_NUM: + if (!is_make) { + modifiers ^= modifier; + } + break; + + default: + break; + } +} + +/** + * @brief Handle a set 2 default scancode byte + * + * @param byte_code the set 2 scancode to handle + * @param is_make true if the byte is a make code, false if it's a break + */ +static void kbd_process_bytecode(uint8_t byte_code, bool is_make) { + // Process modifier keys + switch(byte_code) { + case KBD_PS2_SC_LSHIFT: + case KBD_PS2_SC_RSHIFT: + // Shift keys + kbd_process_modifier(KBD_MOD_SHIFT, is_make); + break; + + case KBD_PS2_SC_CAPS: + // Caps lock key + kbd_process_modifier(KBD_LOCK_CAPS, is_make); + break; + + case KBD_PS2_SC_LCTRL: + // CTRL Key + kbd_process_modifier(KBD_MOD_CTRL, is_make); + break; + + case KBD_PS2_SC_LALT: + // Alt Key + kbd_process_modifier(KBD_MOD_ALT, is_make); + break; + + case KBD_PS2_SC_NUM: + // Number lock key + kbd_process_modifier(KBD_LOCK_NUM, is_make); + break; + + default: + break; + } + + // Translate PS/2 scancode to Foenix scancode + short scancode = kbd_ps2_default_sc[byte_code]; + if (scancode) { + kbd_enqueue_scancode(scancode, is_make); + } +} + +/** + * @brief Handle a set 2 E0-prefixed scancode byte + * + * @param byte_code the set 2 E0-prefixed scancode to handle + * @param is_make true if the byte is a make code, false if it's a break + */ +static void kbd_process_e0_bytecode(uint8_t byte_code, bool is_make) { + // Process modifier keys + switch(byte_code) { + case KBD_PS2_SC_LGUI: + case KBD_PS2_SC_RGUI: + // GUI key + kbd_process_modifier(KBD_MOD_OS, is_make); + break; + + case KBD_PS2_SC_RCTRL: + // CTRL Key + kbd_process_modifier(KBD_MOD_CTRL, is_make); + break; + + case KBD_PS2_SC_RALT: + // Alt Key + kbd_process_modifier(KBD_MOD_ALT, is_make); + break; + + default: + break; + } + + // Translate PS/2 scancode with the E0 prefix to Foenix scancode + short scancode = kbd_ps2_e0_sc[byte_code]; + if (scancode) { + kbd_enqueue_scancode(scancode, is_make); + } +} + +/** + * @brief Process the bytecodes that come in from the PS/2 keyboard. Walk through the state machine for E0, F0, and E1 prefixes + * + * @param byte_code the raw bytes from the PS/2 interface + */ +static void kbd_process_set2_bytecode(uint8_t byte_code) { + switch(kbd_state) { + case kbd_state_default: + switch(byte_code) { + case 0xe0: + kbd_state = kbd_state_e0; + break; + + case 0xf0: + kbd_state = kbd_state_f0; + break; + + case 0xe1: + kbd_state = kbd_state_e1; + break; + + default: + kbd_process_bytecode(byte_code, true); + break; + } + break; + + case kbd_state_e0: + if (byte_code == 0xf0) { + kbd_state = kbd_state_e0f0; + } else { + kbd_process_e0_bytecode(byte_code, true); + kbd_state = kbd_state_default; + } + break; + + case kbd_state_f0: + kbd_process_bytecode(byte_code, false); + kbd_state = kbd_state_default; + break; + + case kbd_state_e0f0: + kbd_process_e0_bytecode(byte_code, false); + kbd_state = kbd_state_default; + break; + + case kbd_state_e1: + if (byte_code == 0x14) { + kbd_state = kbd_state_e114; + } else { + kbd_state = kbd_state_default; + } + break; + + case kbd_state_e114: + if (byte_code == 0x77) { + kbd_state = kbd_state_e11477; + } else { + kbd_state = kbd_state_default; + } + break; + + case kbd_state_e11477: + if (byte_code == 0xe1) { + kbd_state = kbd_state_e11477e1; + } else { + kbd_state = kbd_state_default; + } + break; + + case kbd_state_e11477e1: + if (byte_code == 0xf0) { + kbd_state = kbd_state_e11477e1f0; + } else { + kbd_state = kbd_state_default; + } + break; + + case kbd_state_e11477e1f0: + if (byte_code == 0x14) { + kbd_state = kbd_state_e11477e1f014; + } else { + kbd_state = kbd_state_default; + } + break; + + case kbd_state_e11477e1f014: + if (byte_code == 0xf0) { + kbd_state = kbd_state_e11477e1f014f0; + } else { + kbd_state = kbd_state_default; + } + break; + + case kbd_state_e11477e1f014f0: + if (byte_code == 0x77) { + kbd_enqueue_scancode(0x61, true); + } + kbd_state = kbd_state_default; + break; + + default: + kbd_state = kbd_state_default; + break; + } +} + +/** + * @brief Handle an IRQ to query the keyboard + * + */ +void kbd_handle_irq() { + // Check to see if there is a keyboard bytecode waiting... process it if so + if ((*PS2_STAT & PS2_STAT_KBD_EMP) == 0) { + kbd_process_set2_bytecode(*PS2_KBD_IN); + } +} + +/* + * Try to retrieve the next scancode from the keyboard. + * + * Returns: + * The next scancode to be processed, 0 if nothing. + */ +unsigned short kbd_get_scancode() { + if (!rb_word_empty(&scan_code_buffer)) { + return rb_word_get(&scan_code_buffer); + } else { + return 0; + } +} + +/* + * Check to see if a BREAK code has been pressed recently + * If so, return true and reset the internal flag. + * + * BREAK will be CTRL-PAUSE or CTRL-C on the F256jr + * + * Returns: + * true if a BREAK has been pressed since the last check + */ +bool kbd_break() { + bool result = break_pressed; + break_pressed = 0; + return result; +} + +/* + * Initialize the matrix keyboard + * + */ +short kbd_sc_init() { + // Initialize the keyboard buffers + rb_word_init(&scan_code_buffer); + rb_word_init(&char_buffer); + + // Initialize the state of the keyboard + kbd_state = kbd_state_default; + modifiers = 0; + break_pressed = false; + + // Register and enable the PS/2 interrupt handler + // int_register(INT_KBD_PS2, kbd_handle_irq); + // int_enable(INT_KBD_PS2); + + return 0; +} + +#endif \ No newline at end of file diff --git a/src/dev/kbd_f256jr.h b/src/dev/kbd_f256jr.h new file mode 100644 index 0000000..4d8cb0b --- /dev/null +++ b/src/dev/kbd_f256jr.h @@ -0,0 +1,49 @@ +/** + * @file kbd_f256jr.h + * @author your name (you@domain.com) + * @brief Driver for the F256jr PS/2 keyboard + * @version 0.1 + * @date 2024-06-17 + * + * @copyright Copyright (c) 2024 + * + */ + +#ifndef __kbd_f256jr_h__ +#define __kbd_f256jr_h__ + +#include +#include "sys_macros.h" + +/** + * @brief Handle an IRQ to query the keyboard + * + */ +extern void kbd_handle_irq(); + +/* + * Try to retrieve the next scancode from the keyboard. + * + * Returns: + * The next scancode to be processed, 0 if nothing. + */ +extern unsigned short kbd_get_scancode(); + +/* + * Check to see if a BREAK code has been pressed recently + * If so, return true and reset the internal flag. + * + * BREAK will be RUN/STOP or CTRL-C on the F256K + * + * Returns: + * true if a BREAK has been pressed since the last check + */ +extern bool kbd_break(); + +/* + * Initialize the matrix keyboard + * + */ +extern short kbd_sc_init(); + +#endif \ No newline at end of file diff --git a/src/dev/kbd_f256k.c b/src/dev/kbd_f256k.c index 3774b8f..353de82 100644 --- a/src/dev/kbd_f256k.c +++ b/src/dev/kbd_f256k.c @@ -19,7 +19,6 @@ #include "ring_buffer.h" #include "dev/kbd_f256k.h" #include "F256/via_f256.h" -#include "uart.h" #include "gabe_reg.h" #include "simpleio.h" #include "vicky_general.h" @@ -77,172 +76,6 @@ static const uint8_t kbd_scan_codes[KBD_ROWS][KBD_COLUMNS] = { {0x02, 0x01, 0x1d, 0x03, 0x39, 0x5b, 0x10, 0x61, 0x00} }; -/* - * Mapping of "codepoints" 0x80 - 0x98 (function keys, etc) - * to ANSI escape codes - */ -const char * ansi_keys[] = { - "1", /* HOME */ - "2", /* INS */ - "3", /* DELETE */ - "4", /* END */ - "5", /* PgUp */ - "6", /* PgDn */ - "A", /* Up */ - "B", /* Left */ - "C", /* Right */ - "D", /* Down */ - "11", /* F1 */ - "12", /* F2 */ - "13", /* F3 */ - "14", /* F4 */ - "15", /* F5 */ - "17", /* F6 */ - "18", /* F7 */ - "19", /* F8 */ - "20", /* F9 */ - "21", /* F10 */ - "23", /* F11 */ - "24", /* F12 */ - "30", /* MONITOR */ - "31", /* CTX SWITCH */ - "32" /* MENU HELP */ -}; - -/* - * US keyboard layout scancode translation tables - */ - -#define POUND 0x9c - -const char kbd_256k_layout[] = { - // Unmodified - 0x00, 0x1B, '1', '2', '3', '4', '5', '6', /* 0x00 - 0x07 */ - '7', '8', '9', '0', '-', '=', 0x08, 0x09, /* 0x08 - 0x0F */ - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 0x10 - 0x17 */ - 'o', 'p', '[', ']', 0x0D, 0x00, 'a', 's', /* 0x18 - 0x1F */ - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 0x20 - 0x27 */ - 0x27, '`', 0x00, '\\', 'z', 'x', 'c', 'v', /* 0x28 - 0x2F */ - 'b', 'n', 'm', ',', '.', '/', 0x00, '*', /* 0x30 - 0x37 */ - 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ - 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ - 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ - 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ - 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ - 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ - - // Shifted - 0x00, 0x1B, '!', '@', '#', '$', '%', '^', /* 0x00 - 0x07 */ - '&', '*', '(', ')', '_', '+', 0x08, 0x09, /* 0x08 - 0x0F */ - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 0x10 - 0x17 */ - 'O', 'P', '{', '}', 0x0A, 0x00, 'A', 'S', /* 0x18 - 0x1F */ - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 0x20 - 0x27 */ - 0x22, '~', 0x00, '|', 'Z', 'X', 'C', 'V', /* 0x28 - 0x2F */ - 'B', 'N', 'M', '<', '>', '?', 0x00, 0x00, /* 0x30 - 0x37 */ - 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ - 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ - 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ - 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ - 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ - 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ - - // Control - 0x00, 0x1B, '1', '2', '3', '4', '5', 0x1E, /* 0x00 - 0x07 */ - '7', '8', '9', '0', 0x1F, '=', 0x08, 0x09, /* 0x08 - 0x0F */ - 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* 0x10 - 0x17 */ - 0x0F, 0x10, 0x1B, 0x1D, 0x0A, 0x00, 0x01, 0x13, /* 0x18 - 0x1F */ - 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, ';', /* 0x20 - 0x27 */ - 0x22, '`', 0x00, '\\', 0x1A, 0x18, 0x03, 0x16, /* 0x28 - 0x2F */ - 0x02, 0x0E, 0x0D, ',', '.', 0x1C, 0x00, 0x00, /* 0x30 - 0x37 */ - 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ - 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ - 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ - 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ - 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ - 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ - - - // Control-Shift - 0x00, 0x1B, '!', '@', '#', '$', '%', '^', /* 0x00 - 0x07 */ - '&', '*', '(', ')', '_', '+', 0x08, 0x09, /* 0x08 - 0x0F */ - 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* 0x10 - 0x17 */ - 0x0F, 0x10, 0x1B, 0x1D, 0x0A, 0x00, 0x01, 0x13, /* 0x18 - 0x1F */ - 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, ';', /* 0x20 - 0x27 */ - 0x22, '`', 0x00, '\\', 0x1A, 0x18, 0x03, 0x16, /* 0x28 - 0x2F */ - 0x02, 0x0E, 0x0D, ',', '.', 0x1C, 0x00, 0x00, /* 0x30 - 0x37 */ - 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ - 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ - 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ - 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ - 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ - 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ - - // Capslock - 0x00, 0x1B, '1', '2', '3', '4', '5', '6', /* 0x00 - 0x07 */ - '7', '8', '9', '0', '-', '=', 0x08, 0x09, /* 0x08 - 0x0F */ - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 0x10 - 0x17 */ - 'O', 'P', '[', ']', 0x0D, 0x00, 'A', 'S', /* 0x18 - 0x1F */ - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', /* 0x20 - 0x27 */ - 0x27, '`', 0x00, '\\', 'Z', 'X', 'C', 'V', /* 0x28 - 0x2F */ - 'B', 'N', 'M', ',', '.', '/', 0x00, 0x00, /* 0x30 - 0x37 */ - 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, '7', /* 0x40 - 0x47 */ - '8', '9', '-', '4', '5', '6', '+', '1', /* 0x48 - 0x4F */ - '2', '3', '0', '.', 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ - 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ - 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ - 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ - - // Caps-Shift - 0x00, 0x1B, '!', '@', '#', '$', '%', '^', /* 0x00 - 0x07 */ - '&', '*', '(', ')', '_', '+', 0x08, 0x09, /* 0x08 - 0x0F */ - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 0x10 - 0x17 */ - 'o', 'p', '{', '}', 0x0A, 0x00, 'a', 's', /* 0x18 - 0x1F */ - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ':', /* 0x20 - 0x27 */ - 0x22, 0x00, 0x00, 0x00, 'z', 'x', 'c', 'v', /* 0x28 - 0x2F */ - 'b', 'n', 'm', '<', '>', '?', 0x00, 0x00, /* 0x30 - 0x37 */ - 0x00, ' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38 - 0x3F */ - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, '7', /* 0x40 - 0x47 */ - '8', '9', '-', '4', '5', '6', '+', '1', /* 0x48 - 0x4F */ - '2', '3', '0', '.', 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ - 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ - 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ - 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ - - // ALT - 0x00, 0x1B, '1', '2', '3', POUND, '5', '6', /* 0x00 - 0x07 */ - '~', '`', '|', '\\', '-', '=', 0x08, 0x09, /* 0x08 - 0x0F */ - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 0x10 - 0x17 */ - 'o', 'p', '[', ']', 0x0D, 0x00, 'a', 's', /* 0x18 - 0x1F */ - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 0x20 - 0x27 */ - 0x27, 0x00, 0x00, 0x00, 'z', 'x', 'c', 'v', /* 0x28 - 0x2F */ - 'b', 'n', 'm', ',', '.', '/', 0x00, '*', /* 0x30 - 0x37 */ - 0x00, ' ', 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, /* 0x38 - 0x3F */ - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x00, 0x00, 0x80, /* 0x40 - 0x47 */ - 0x86, 0x84, '-', 0x89, '5', 0x88, '+', 0x83, /* 0x48 - 0x4F */ - 0x87, 0x85, 0x81, 0x82, 0x96, 0x97, 0x98, 0x94, /* 0x50 - 0x57 */ - 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5F */ - 0x00, 0x00, 0x81, 0x80, 0x84, 0x82, 0x83, 0x85, /* 0x60 - 0x67 */ - 0x86, 0x89, 0x87, 0x88, '/', 0x0D, 0x00, 0x00, /* 0x68 - 0x6F */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7F */ -}; // // Driver variables @@ -252,20 +85,9 @@ static uint16_t kbd_stat[KBD_MATRIX_SIZE]; static short counter = 0; static uint8_t last_press = 0; static t_word_ring scan_code_buffer; -static t_word_ring char_buffer; static uint8_t modifiers = 0; static bool break_pressed = 0; -/* Scan code to character lookup tables */ - -static char keys_unmodified[128]; -static char keys_shift[128]; -static char keys_control[128]; -static char keys_control_shift[128]; -static char keys_caps[128]; -static char keys_caps_shift[128]; -static char keys_alt[128]; - /** * @brief Get the keys selected in a given row * @@ -423,147 +245,6 @@ void kbd_handle_irq() { } } -/* - * Catch special keys and convert them to their ANSI terminal codes - * - * Characters 0x80 - 0x98 are reserved for function keys, arrow keys, etc. - * This function maps them to the ANSI escape codes - * - * Inputs: - * modifiers = the current modifier bit flags (ALT, CTRL, META, etc) - * c = the character found from the scan code. - */ -static unsigned char kbd_to_ansi(unsigned char modifiers, unsigned char c) { - if ((c >= 0x80) && (c <= 0x98)) { - /* The key is a function key or a special control key */ - const char * ansi_key = ansi_keys[c - 0x80]; - const char * sequence; - short modifiers_after = 0; - - // Figure out if the modifiers come before or after the sequence code - if (isdigit(ansi_key[0])) { - // Sequence is numeric, modifiers come after - modifiers_after = 1; - } - - // After ESC, all sequences have [ - rb_word_put(&char_buffer, '['); - - if (modifiers_after) { - // Sequence is numberic, get the expanded sequence and put it in the queue - for (sequence = ansi_keys[c - 0x80]; *sequence != 0; sequence++) { - rb_word_put(&char_buffer, *sequence); - } - } - - // Check to see if we need to send a modifier sequence - if (modifiers & (KBD_MOD_SHIFT | KBD_MOD_CTRL | KBD_MOD_ALT | KBD_MOD_OS)) { - unsigned char code_bcd; - short modifier_code = 0; - short i; - - if (modifiers_after) { - // Sequence is numeric, so put modifiers after the sequence and a semicolon - rb_word_put(&char_buffer, ';'); - } - - modifier_code = ((modifiers >> 3) & 0x1F) + 1; - code_bcd = i_to_bcd(modifier_code); - - if (code_bcd & 0xF0) { - rb_word_put(&char_buffer, ((code_bcd & 0xF0) >> 4) + '0'); - } - rb_word_put(&char_buffer, (code_bcd & 0x0F) + '0'); - } - - if (!modifiers_after) { - // Sequence is a letter code - rb_word_put(&char_buffer, ansi_key[0]); - } else { - // Sequence is numeric, close it with a tilda - rb_word_put(&char_buffer, '~'); - } - - return 0x1B; /* Start the sequence with an escape */ - - } else if (c == 0x1B) { - /* ESC should be doubled, to distinguish from the start of an escape sequence */ - rb_word_put(&char_buffer, 0x1B); - return c; - - } else { - /* Not a special key: return the character unmodified */ - - return c; - } -} - -/* - * Try to get a character from the keyboard... - * - * Returns: - * the next character to be read from the keyboard (0 if none available) - */ -char kbd_getc() { - if (!rb_word_empty(&char_buffer)) { - // If there is a character waiting in the character buffer, return it... - return (char)rb_word_get(&char_buffer); - - } else { - // Otherwise, we need to check the scan code queue... - unsigned short raw_code = kbd_get_scancode(); - while (raw_code != 0) { - if ((raw_code & 0x80) == 0) { - // If it's a make code, let's try to look it up... - unsigned char modifiers = (raw_code >> 8) & 0xff; // Get the modifiers - unsigned char scan_code = raw_code & 0x7f; // Get the base code for the key - - // Check the modifiers to see what we should lookup... - - if ((modifiers & (KBD_MOD_ALT | KBD_MOD_SHIFT | KBD_MOD_CTRL | KBD_LOCK_CAPS)) == 0) { - // No modifiers... just return the base character - return kbd_to_ansi(modifiers, keys_unmodified[scan_code]); - - } else if (modifiers & KBD_MOD_ALT) { - return kbd_to_ansi(modifiers, keys_alt[scan_code]); - - } else if (modifiers & KBD_MOD_CTRL) { - // If CTRL is pressed... - if (modifiers & KBD_MOD_SHIFT) { - // If SHIFT is also pressed, return CTRL-SHIFT form - return kbd_to_ansi(modifiers, keys_control_shift[scan_code]); - - } else { - // Otherwise, return just CTRL form - return kbd_to_ansi(modifiers, keys_control[scan_code]); - } - - } else if (modifiers & KBD_LOCK_CAPS) { - // If CAPS is locked... - if (modifiers & KBD_MOD_SHIFT) { - // If SHIFT is also pressed, return CAPS-SHIFT form - return kbd_to_ansi(modifiers, keys_caps_shift[scan_code]); - - } else { - // Otherwise, return just CAPS form - return kbd_to_ansi(modifiers, keys_caps[scan_code]); - } - } else { - // SHIFT is pressed, return SHIFT form - return kbd_to_ansi(modifiers, keys_shift[scan_code]); - } - } - - // If we reach this point, it wasn't a useful scan-code... - // So try to fetch another - raw_code = kbd_get_scancode(); - } - - // If we reach this point, there are no useful scan codes - return 0; - } -} - /* * Check to see if a BREAK code has been pressed recently * If so, return true and reset the internal flag. @@ -579,53 +260,11 @@ bool kbd_break() { return result; } -/* - * Set the keyboard translation tables - * - * The translation tables provided to the keyboard consist of eight - * consecutive tables of 128 characters each. Each table maps from - * the MAKE scan code of a key to its appropriate 8-bit character code. - * - * The tables included must include, in order: - * - UNMODIFIED: Used when no modifier keys are pressed or active - * - SHIFT: Used when the SHIFT modifier is pressed - * - CTRL: Used when the CTRL modifier is pressed - * - CTRL-SHIFT: Used when both CTRL and SHIFT are pressed - * - CAPSLOCK: Used when CAPSLOCK is down but SHIFT is not pressed - * - CAPSLOCK-SHIFT: Used when CAPSLOCK is down and SHIFT is pressed - * - ALT: Used when only ALT is presse - * - ALT-SHIFT: Used when ALT is pressed and either CAPSLOCK is down - * or SHIFT is pressed (but not both) - * - * Inputs: - * tables = pointer to the keyboard translation tables - */ -short SYSTEMCALL kbd_layout(const char * tables) { - short i; - - for (i = 0; i < 128; i++) { - keys_unmodified[i] = tables[i]; - keys_shift[i] = tables[i + 128]; - keys_control[i] = tables[i + 256]; - // if (keys_control[i] == 0x03) { - // // We have set the scan code for CTRL-C? - // g_kbdmo_break_sc = i; - // } - // Check for CTRL-C - keys_control_shift[i] = tables[i + 384]; - keys_caps[i] = tables[i + 512]; - keys_caps_shift[i] = tables[i + 640]; - keys_alt[i] = tables[i + 768]; - } - - return 0; -} - /* * Initialize the matrix keyboard * */ -short kbd_init() { +short kbd_sc_init() { // Initialize VIA0 -- we'll just read from PB7 via0->ddra = 0x00; via0->ddrb = 0x00; @@ -652,9 +291,6 @@ short kbd_init() { // Set up and clear out the buffer for the scan codes rb_word_init(&scan_code_buffer); - // Set up the layout of the F256k keyboard - kbd_layout(kbd_256k_layout); - int_register(INT_VIA0, kbd_handle_irq); via0->acr = 0x40; // Timer #0 in free running mode diff --git a/src/dev/kbd_f256k.h b/src/dev/kbd_f256k.h index a3608e8..6140bed 100644 --- a/src/dev/kbd_f256k.h +++ b/src/dev/kbd_f256k.h @@ -40,41 +40,10 @@ extern unsigned short kbd_get_scancode(); */ extern bool kbd_break(); -/* - * Try to get a character from the keyboard... - * - * Returns: - * the next character to be read from the keyboard (0 if none available) - */ -extern char kbd_getc(); - -/* - * Set the keyboard translation tables - * - * The translation tables provided to the keyboard consist of eight - * consecutive tables of 128 characters each. Each table maps from - * the MAKE scan code of a key to its appropriate 8-bit character code. - * - * The tables included must include, in order: - * - UNMODIFIED: Used when no modifier keys are pressed or active - * - SHIFT: Used when the SHIFT modifier is pressed - * - CTRL: Used when the CTRL modifier is pressed - * - CTRL-SHIFT: Used when both CTRL and SHIFT are pressed - * - CAPSLOCK: Used when CAPSLOCK is down but SHIFT is not pressed - * - CAPSLOCK-SHIFT: Used when CAPSLOCK is down and SHIFT is pressed - * - ALT: Used when only ALT is presse - * - ALT-SHIFT: Used when ALT is pressed and either CAPSLOCK is down - * or SHIFT is pressed (but not both) - * - * Inputs: - * tables = pointer to the keyboard translation tables - */ -extern SYSTEMCALL short kbd_layout(const char * tables); - /* * Initialize the matrix keyboard * */ -extern short kbd_init(); +extern short kbd_sc_init(); #endif \ No newline at end of file diff --git a/src/toolbox.c b/src/toolbox.c index 3109cec..65f8bce 100644 --- a/src/toolbox.c +++ b/src/toolbox.c @@ -35,7 +35,7 @@ #include "dev/txt_evid.h" #elif MODEL == MODEL_FOENIX_F256 || MODEL == MODEL_FOENIX_F256K || MODEL == MODEL_FOENIX_F256K2 #include "dev/txt_f256.h" -#include "dev/kbd_f256k.h" +#include "dev/kbd_f256.h" #include "dev/sdc_f256.h" #endif @@ -400,13 +400,7 @@ void read_sample_file(const char * path) { } } -int main(int argc, char * argv[]) { - short result; - short i; - char message[256]; - - initialize(); - +void test_sdc() { print_directory(); printf("\nfsys_rename(\"/sd0/hello.txt\", \"/sd0/renamed.txt\")"); @@ -423,6 +417,40 @@ int main(int argc, char * argv[]) { read_sample_file("/sd0/test.txt"); read_sample_file("/sd0/hello.txt"); +} + +void test_kbd_sc() { + printf("> "); + do { + unsigned short scancode = kbd_get_scancode(); + if (scancode != 0) { + printf("%04X ", scancode); + } + } while (!kbd_break()); + printf("\n\n"); +} + +void test_kbd() { + printf("> "); + do { + kbd_handle_irq(); + char c = kbd_getc(); + if (c != 0) { + txt_put(0, c); + } + } while (!kbd_break()); + printf("\n\n"); +} + +int main(int argc, char * argv[]) { + short result; + short i; + char message[256]; + + initialize(); + kbd_init(); + + test_kbd(); // Attempt to start up the user code // log(LOG_INFO, "Looking for user startup code:");