diff options
Diffstat (limited to 'converter')
46 files changed, 5042 insertions, 0 deletions
diff --git a/converter/adb_usb/Makefile b/converter/adb_usb/Makefile new file mode 100644 index 0000000000..64a23d09dc --- /dev/null +++ b/converter/adb_usb/Makefile @@ -0,0 +1,54 @@ +# Target file name (without extension). +TARGET = adb_usb + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + adb.c + +CONFIG_H = config.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# comment out to disable the options. +# +#MOUSEKEY_ENABLE = yes # Mouse keys +#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support +EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/adb_usb/README b/converter/adb_usb/README new file mode 100644 index 0000000000..5d0e1bc86b --- /dev/null +++ b/converter/adb_usb/README @@ -0,0 +1,70 @@ +ADB to USB keyboard converter +============================= +http://geekhack.org/showwiki.php?title=Island:14290 + +This firmware converts ADB keyboard protocol to USB. + + +Build +----- +0. Connect ADB keyboard to Teensy by 3 lines(Vcc, GND, Data). + You need a external pull-up resistor on DATA line in most case, + in particular when you want to use a long or coiled cable. + This converter uses AVR's internal pull-up, but it seems to be too weak. + The external pull-up resistor is strongly recommended. + PSW line is optional. See ADB.txt for details. +1. Define following macros for ADB connection in config.h: + ADB_PORT + ADB_PIN + ADB_DDR + ADB_DATA_BIT + ADB_PSW_BIT +2. make +3. program Teensy. + + +Keymap +------ +You can change a keymap by editing code of keymap.c like following. +This is a keymap for AEK, however, also used for other keyboards. +How to define the keymap is probably obvious. You can find key +symbols in usb_keycodes.h. +If you want to define some keymaps than just one, see hhkb/keymap.c and +macway/keymap.c as examples. Keymap(layer) switching may needs a bit of +effort at this time. + + /* Default Layer: plain keymap + * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,---. + * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr| + * `---' `---------------' `---------------' `---------------' `-----------' `---' + * ,-----------------------------------------------------------. ,-----------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| + * |-----------------------------------------------------------| |-----------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -| + * |-----------------------------------------------------------| `-----------' |---------------| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +| + * |-----------------------------------------------------------| ,---. |---------------| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------| ,-----------. |-----------|Ent| + * |Ctrl |Gui |Alt | Space | | | | |Lef|Dow|Rig| | 0| .| | + * `-----------------------------------------------------------' `-----------' `---------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, PMNS, + CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + +Notes +----- +Many ADB keyboards has no discrimination between right modifier and left one, +you will always see left control even if you press right control key. +Apple Extended Keyboard and Apple Extended Keyboard II are the examples. +Though ADB protocol itsef has the ability of distinction between right and left. +And most ADB keyboard has no NKRO functionality, though ADB protocol itsef has that. + +EOF diff --git a/converter/adb_usb/config.h b/converter/adb_usb/config.h new file mode 100644 index 0000000000..52d5925a50 --- /dev/null +++ b/converter/adb_usb/config.h @@ -0,0 +1,72 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x0ADB +#define DEVICE_VER 0x0101 +#define MANUFACTURER t.m.k. +#define PRODUCT ADB keyboard converter +#define DESCRIPTION convert ADB keyboard to USB + +/* matrix size */ +#define MATRIX_ROWS 16 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + +/* Locking Caps Lock support */ +#define MATRIX_HAS_LOCKING_CAPS + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 192 +#endif + + +/* PS/2 mouse */ +#ifdef PS2_MOUSE_ENABLE +# define PS2_CLOCK_PORT PORTF +# define PS2_CLOCK_PIN PINF +# define PS2_CLOCK_DDR DDRF +# define PS2_CLOCK_BIT 0 +# define PS2_DATA_PORT PORTF +# define PS2_DATA_PIN PINF +# define PS2_DATA_DDR DDRF +# define PS2_DATA_BIT 1 +#endif + + +/* ADB port setting */ +#define ADB_PORT PORTF +#define ADB_PIN PINF +#define ADB_DDR DDRF +#define ADB_DATA_BIT 0 +//#define ADB_PSW_BIT 1 // optional + +#endif diff --git a/converter/adb_usb/keymap.c b/converter/adb_usb/keymap.c new file mode 100644 index 0000000000..cdaa935d32 --- /dev/null +++ b/converter/adb_usb/keymap.c @@ -0,0 +1,150 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Keymap for ADB keyboard + */ +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keyboard.h" +#include "usb_keycodes.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + +#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) + +// Convert physical keyboard layout to matrix array. +// This is a macro to define keymap easily in keyboard layout form. +/* Apple Extended Keyboard */ +#define KEYMAP( \ + K35, K7A,K78,K63,K76, K60,K61,K62,K64, K65,K6D,K67,K6F, K69,K6B,K71, K7F, \ + K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, K72,K73,K74, K47,K51,K4B,K43, \ + K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, K75,K77,K79, K59,K5B,K5C,K4E, \ + K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, K56,K57,K58,K45, \ + K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, K7B, K3E, K53,K54,K55, \ + K36,K3A,K37, K31, K3B,K3D,K3C, K52, K41,K4C \ +) { \ + { KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K08, KB_##K09, KB_NO, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_NO, KB_##K35, KB_##K36, KB_##K37 }, \ + { KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \ + { KB_NO, KB_##K41, KB_NO, KB_##K43, KB_NO, KB_##K45, KB_NO, KB_##K47 }, \ + { KB_NO, KB_NO, KB_NO, KB_##K4B, KB_##K4C, KB_NO, KB_##K4E, KB_NO }, \ + { KB_NO, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ + { KB_##K58, KB_##K59, KB_NO, KB_##K5B, KB_##K5C, KB_NO, KB_NO, KB_NO }, \ + { KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_NO, KB_##K67 }, \ + { KB_NO, KB_##K69, KB_NO, KB_##K6B, KB_NO, KB_##K6D, KB_NO, KB_##K6F }, \ + { KB_NO, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ + { KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_NO, KB_NO, KB_NO, KB_##K7F } \ +} +/* plain keymap + { + { KB_A, KB_S, KB_D, KB_F, KB_H, KB_G, KB_Z, KB_X }, // 00-07 + { KB_C, KB_V, KB_NO, KB_B, KB_Q, KB_W, KB_E, KB_R }, // 08-0F + { KB_Y, KB_T, KB_1, KB_2, KB_3, KB_4, KB_6, KB_5 }, // 10-17 + { KB_EQL, KB_9, KB_7, KB_MINS,KB_8, KB_0, KB_RBRC,KB_O }, // 18-1F + { KB_U, KB_LBRC,KB_I, KB_P, KB_ENT, KB_L, KB_J, KB_QUOT}, // 20-27 + { KB_K, KB_SCLN,KB_BSLS,KB_COMM,KB_SLSH,KB_N, KB_M, KB_DOT }, // 28-2F + { KB_TAB, KB_SPC, KB_GRV, KB_BSPC,KB_NO, KB_ESC, KB_LCTL,KB_LGUI}, // 30-37 + { KB_LSFT,KB_CAPS,KB_LALT,KB_LEFT,KB_RGHT,KB_DOWN,KB_UP, KB_NO }, // 38-3F + { KB_NO, KB_PDOT,KB_NO, KB_PAST,KB_NO, KB_PPLS,KB_NO, KB_NLCK}, // 40-47 + { KB_NO, KB_NO, KB_NO, KB_PSLS,KB_PENT,KB_NO, KB_PMNS,KB_NO }, // 48-4F + { KB_NO, KB_PEQL,KB_P0, KB_P1, KB_P2, KB_P3, KB_P4, KB_P5 }, // 50-57 + { KB_P6, KB_P7, KB_NO, KB_P8, KB_P9, KB_NO, KB_NO, KB_NO }, // 58-5F + { KB_F5, KB_F6, KB_F7, KB_F3, KB_F8, KB_F9, KB_NO, KB_F11 }, // 60-67 + { KB_NO, KB_PSCR,KB_NO, KB_SLCK,KB_NO, KB_F10, KB_NO, KB_F12 }, // 68-6F + { KB_NO, KB_BRK, KB_INS, KB_HOME,KB_PGUP,KB_DEL, KB_F4, KB_END }, // 70-77 + { KB_F2, KB_PGDN,KB_F1, KB_RSFT,KB_NO, KB_NO, KB_NO, KB_PWR }, // 78-7F + }, +*/ + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { + 0, // Fn0 + 0, // Fn1 + 0, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { + KB_NO, // Fn0 + KB_NO, // Fn1 + KB_NO, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +}; + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Default Layer: plain keymap + * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,---. + * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr| + * `---' `---------------' `---------------' `---------------' `-----------' `---' + * ,-----------------------------------------------------------. ,-----------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| + * |-----------------------------------------------------------| |-----------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -| + * |-----------------------------------------------------------| `-----------' |---------------| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +| + * |-----------------------------------------------------------| ,---. |---------------| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------| ,-----------. |-----------|Ent| + * |Ctrl |Gui |Alt | Space | | | | |Lef|Dow|Rig| | 0| .| | + * `-----------------------------------------------------------' `-----------' `---------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, PMNS, + CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return KEYCODE(layer, row, col); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/converter/adb_usb/led.c b/converter/adb_usb/led.c new file mode 100644 index 0000000000..0e162f379b --- /dev/null +++ b/converter/adb_usb/led.c @@ -0,0 +1,26 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdint.h" +#include "adb.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + adb_host_kbd_led(~usb_led); +} diff --git a/converter/adb_usb/matrix.c b/converter/adb_usb/matrix.c new file mode 100644 index 0000000000..a2367af56a --- /dev/null +++ b/converter/adb_usb/matrix.c @@ -0,0 +1,241 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * scan matrix + */ +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "debug.h" +#include "host.h" +#include "led.h" +#include "adb.h" +#include "matrix.h" + + +#if (MATRIX_COLS > 16) +# error "MATRIX_COLS must not exceed 16" +#endif +#if (MATRIX_ROWS > 255) +# error "MATRIX_ROWS must not exceed 255" +#endif + +#define CAPS 0x39 +#define CAPS_UP (CAPS | 0x80) +#define ROW(key) ((key)>>3&0x0F) +#define COL(key) ((key)&0x07) + + +static bool _matrix_is_modified = false; + +// matrix state buffer(1:on, 0:off) +#if (MATRIX_COLS <= 8) +static uint8_t *matrix; +static uint8_t _matrix0[MATRIX_ROWS]; +#else +static uint16_t *matrix; +static uint16_t _matrix0[MATRIX_ROWS]; +#endif + +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); +#endif +static void _register_key(uint8_t key); + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + adb_host_init(); + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; + matrix = _matrix0; + + print_enable = true; + debug_enable = true; + debug_matrix = true; + debug_keyboard = true; + debug_mouse = true; + print("debug enabled.\n"); + return; +} + +uint8_t matrix_scan(void) +{ + uint16_t codes; + uint8_t key0, key1; + + _matrix_is_modified = false; + codes = adb_host_kbd_recv(); + key0 = codes>>8; + key1 = codes&0xFF; + +#ifdef MATRIX_HAS_LOCKING_CAPS + // Send Caps key up event + if (matrix_is_on(ROW(CAPS), COL(CAPS))) { + _matrix_is_modified = true; + _register_key(CAPS_UP); + } +#endif + if (codes == 0) { // no keys + return 0; + } else if (key0 == 0xFF && key1 != 0xFF) { // error + return codes&0xFF; + } else { +#ifdef MATRIX_HAS_LOCKING_CAPS + if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { + // Ignore LockingCaps key down event when CAPS LOCK is on + if (key0 == CAPS && (key1 == CAPS || key1 == 0xFF)) return 0; + if (key0 == CAPS) key0 = key1; + if (key1 == CAPS) key1 = 0xFF; + // Convert LockingCaps key up event into down event + if (key0 == CAPS_UP) key0 = CAPS; + if (key1 == CAPS_UP) key1 = CAPS; + } else { + // CAPS LOCK off: + // Ignore LockingCaps key up event when CAPS LOCK is off + if (key0 == CAPS_UP && (key1 == CAPS_UP || key1 == 0xFF)) return 0; + if (key0 == CAPS_UP) key0 = key1; + if (key1 == CAPS_UP) key1 = 0xFF; + } +#endif + _matrix_is_modified = true; + _register_key(key0); + if (key1 != 0xFF) // key1 is 0xFF when no second key. + _register_key(key1); + } + + if (debug_enable) { + print("adb_host_kbd_recv: "); phex16(codes); print("\n"); + } + return 1; +} + +bool matrix_is_modified(void) +{ + return _matrix_is_modified; +} + +inline +bool matrix_has_ghost(void) +{ +#ifdef MATRIX_HAS_GHOST + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + if (matrix_has_ghost_in_row(i)) + return true; + } +#endif + return false; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & (1<<col)); +} + +inline +#if (MATRIX_COLS <= 8) +uint8_t matrix_get_row(uint8_t row) +#else +uint16_t matrix_get_row(uint8_t row) +#endif +{ + return matrix[row]; +} + +void matrix_print(void) +{ +#if (MATRIX_COLS <= 8) + print("\nr/c 01234567\n"); +#else + print("\nr/c 0123456789ABCDEF\n"); +#endif + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); +#if (MATRIX_COLS <= 8) + pbin_reverse(matrix_get_row(row)); +#else + pbin_reverse16(matrix_get_row(row)); +#endif +#ifdef MATRIX_HAS_GHOST + if (matrix_has_ghost_in_row(row)) { + print(" <ghost"); + } +#endif + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +#if (MATRIX_COLS <= 8) + count += bitpop(matrix[i]); +#else + count += bitpop16(matrix[i]); +#endif + } + return count; +} + +#ifdef MATRIX_HAS_GHOST +inline +static bool matrix_has_ghost_in_row(uint8_t row) +{ + // no ghost exists in case less than 2 keys on + if (((matrix[row] - 1) & matrix[row]) == 0) + return false; + + // ghost exists in case same state as other row + for (uint8_t i=0; i < MATRIX_ROWS; i++) { + if (i != row && (matrix[i] & matrix[row]) == matrix[row]) + return true; + } + return false; +} +#endif + +inline +static void _register_key(uint8_t key) +{ + uint8_t col, row; + col = key&0x07; + row = (key>>3)&0x0F; + if (key&0x80) { + matrix[row] &= ~(1<<col); + } else { + matrix[row] |= (1<<col); + } +} diff --git a/converter/m0110_usb/Makefile b/converter/m0110_usb/Makefile new file mode 100644 index 0000000000..4a687b9333 --- /dev/null +++ b/converter/m0110_usb/Makefile @@ -0,0 +1,57 @@ +# Target file name (without extension). +TARGET = m0110 + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + m0110.c + +CONFIG_H = config.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support +EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk + +hasu: EXTRAFLAGS += -DHASU +hasu: all diff --git a/converter/m0110_usb/README.md b/converter/m0110_usb/README.md new file mode 100644 index 0000000000..0ad3631f7c --- /dev/null +++ b/converter/m0110_usb/README.md @@ -0,0 +1,124 @@ +M0110/M0110A to USB keyboard converter +====================================== +This firmware converts the protocol of Apple Macintosh keyboard M0110/M0110A into USB. +Target board of this project is [PJRC Teensy](http://www.pjrc.com/teensy/), though, +you can use other board with USB AVR like `ATmega32U4` and `AT90USB`. + +![M0110](https://github.com/tmk/tmk_keyboard/raw/master/m0110_usb/doc/m0110.jpg) + +M0110A support was contributed by [skagon@github](https://github.com/skagon). + + + +Connection +---------- +You need 4P4C plug and cable to connect Teensy or other AVR dev board into the keyboard. +Teensy port `PF0` is assigned for `CLOCK` line and `PF1` for `DATA` by default, +you can change pin configuration with editing *config.h*. + +You can find 4P4C plugs on telephone handset cable. Note that it is *crossover* connection +while Macintosh keyboard cable is *straight*. + +[![Conection](http://i.imgur.com/vJoVOm.jpg)](http://i.imgur.com/vJoVO.jpg) + +In this pic: + +1. `GND`(Black) +2. `CLOCK`(Red) +3. `DATA`(Green) +4. `+5V`(Yellow) + +Not that wire colors may vary in your cable. + + +### Pinout +- <http://pinouts.ru/Inputs/MacKeyboard_pinout.shtml> +- <http://en.wikipedia.org/wiki/Modular_connector#4P4C> + +![Jack fig](http://www.kbdbabel.org/conn/kbd_connector_macplus.png) + + +### Pull-up Registor +You may need pull-up registors on signal lines(`CLOCK`, `DATA`) in particular +when you have long or coiled cable. 1k-10k Ohm will be OK for this purpose. +In some cases MCU can't read signal from keyboard correctly without pull-up resistors. + + + +Building Frimware +----------------- +To compile firmware you need AVR GCC. You can use [WinAVR](http://winavr.sourceforge.net/) on Windows. +You can edit *Makefile* and *config.h* to change compile options and pin configuration. + + $ git clone git://github.com/tmk/tmk_keyboard.git (or download source) + $ cd m0110_usb + $ make + +and program your Teensy with [PJRC Teensy loader](http://www.pjrc.com/teensy/loader.html). + + + +Keymap +------ +You can change keymaps by editing *keymap.c*. + +### M0110 +#### *Default* + ,---------------------------------------------------------. + | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| + |---------------------------------------------------------| + |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| + |---------------------------------------------------------| + |Fn0 | A| S| D| F| G| H| J| K| L| ;| '|Return| + |---------------------------------------------------------| + |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | + `---------------------------------------------------------' + |Ctr|Alt | Space |Gui |Ctr| + `-----------------------------------------------' +#### *HHKB/WASD Layer* + ,---------------------------------------------------------. + |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delet| + |---------------------------------------------------------| + |Caps |Hom| Up|PgU| | | | |Psc|Slk|Pau|Up | |Ins| + |---------------------------------------------------------| + |Fn0 |Lef|Dow|Rig| | | | |Hom|PgU|Lef|Rig|Return| + |---------------------------------------------------------| + |Shift |End| |PgD| |VoD|VoU|Mut|End|PgD|Dow|Shift | + `---------------------------------------------------------' + |Ctr|Alt | Space |Gui |Ctr| + `-----------------------------------------------' + +### M0110A +#### *Default* + ,---------------------------------------------------------. ,---------------. + | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Gui| =| /| *| + |---------------------------------------------------------| |---------------| + |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| + |-----------------------------------------------------' | |---------------| + |Fn0 | A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| + |---------------------------------------------------------| |---------------| + |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | + |---------------------------------------------------------| |-----------|Ent| + |Ctrl |Alt | Space | \|Lft|Rgt|Dn | | 0| .| | + `---------------------------------------------------------' `---------------' +#### *HHKB/WASD/mousekey Layer* + ,---------------------------------------------------------. ,---------------. + |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delet| |Nlk|Mb1|Mb3|Mb2| + |---------------------------------------------------------| |---------------| + |Caps |Hom| Up|PgU| | | | |Psc|Slk|Pau|Up | | | |MwD|McU|MwU|MwU| + |-----------------------------------------------------' | |---------------| + |Fn0 |Lef|Dow|Rig| | | | |Hom|PgU|Lef|Rig|Return| |McL|McD|McR|MwD| + |---------------------------------------------------------| |---------------| + |Shift |End| |PgD| |VoD|VoU|Mut|End|PgD|Dow|Shif|Up | |MwL|McD|MwR| | + |---------------------------------------------------------| |-----------|Mb2| + |Ctrl |Alt | Space |Ins|Lft|Rgt|Dn | | Mb1|Mb3| | + `---------------------------------------------------------' `---------------' + + + +Debug +----- +You can use [PJRC HID listen](http://www.pjrc.com/teensy/hid_listen.html) to see debug output. + +The converter has some functions for debug, press `Alt+Gui+H` simultaneously to get help. +These function is totally undocumented, tentative, inconsistent and buggy. diff --git a/converter/m0110_usb/config.h b/converter/m0110_usb/config.h new file mode 100644 index 0000000000..4563d6da54 --- /dev/null +++ b/converter/m0110_usb/config.h @@ -0,0 +1,61 @@ +/* +Copyright 2011,2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x0110 +#define MANUFACTURER t.m.k. +#define PRODUCT M0110 keyboard converter +#define DESCRIPTION convert M0110 keyboard to USB + + +/* matrix size */ +#define MATRIX_ROWS 14 +#define MATRIX_COLS 8 + +/* Locking Caps Lock support */ +//#define MATRIX_HAS_LOCKING_CAPS + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 192 +#endif + + +/* ports */ +#define M0110_CLOCK_PORT PORTF +#define M0110_CLOCK_PIN PINF +#define M0110_CLOCK_DDR DDRF +#define M0110_CLOCK_BIT 0 +#define M0110_DATA_PORT PORTF +#define M0110_DATA_PIN PINF +#define M0110_DATA_DDR DDRF +#define M0110_DATA_BIT 1 + +#endif diff --git a/converter/m0110_usb/doc/m0110.jpg b/converter/m0110_usb/doc/m0110.jpg Binary files differnew file mode 100644 index 0000000000..ef9a123abc --- /dev/null +++ b/converter/m0110_usb/doc/m0110.jpg diff --git a/converter/m0110_usb/doc/teensy.jpg b/converter/m0110_usb/doc/teensy.jpg Binary files differnew file mode 100644 index 0000000000..96e93e7e24 --- /dev/null +++ b/converter/m0110_usb/doc/teensy.jpg diff --git a/converter/m0110_usb/keymap.c b/converter/m0110_usb/keymap.c new file mode 100644 index 0000000000..b5cdd300bf --- /dev/null +++ b/converter/m0110_usb/keymap.c @@ -0,0 +1,214 @@ +/* +Copyright 2011,2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +/* M0110A Support was contributed by skagon@github */ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keyboard.h" +#include "usb_keycodes.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + +#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) + +#define KEYMAP( \ + K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, K47,K68,K6D,K62, \ + K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E, K59,K5B,K5C,K4E, \ + K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, K56,K57,K58,K66, \ + K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, K4D, K53,K54,K55,K4C, \ + K3A,K37, K31, K34,K2A,K46,K42,K48, K52, K41 \ +) { \ + { KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K08, KB_##K09, KB_NO, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_NO, KB_NO, KB_##K37 }, \ + { KB_##K38, KB_##K39, KB_##K3A, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ + { KB_NO, KB_##K41, KB_##K42, KB_NO, KB_NO, KB_NO, KB_##K46, KB_##K47 }, \ + { KB_##K48, KB_NO, KB_NO, KB_NO, KB_##K4C, KB_##K4D, KB_##K4E, KB_NO }, \ + { KB_NO, KB_NO, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ + { KB_##K58, KB_##K59, KB_NO, KB_##K5B, KB_##K5C, KB_NO, KB_NO, KB_NO }, \ + { KB_NO, KB_NO, KB_##K62, KB_NO, KB_NO, KB_NO, KB_##K66, KB_NO }, \ + { KB_##K68, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K6D, KB_NO, KB_NO }, \ +} + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { +#ifndef HASU + 1, // Fn0 + 0, // Fn1 + 0, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +#else + 1, // Fn0 + 2, // Fn1 + 3, // Fn2 + 1, // Fn3 + 2, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +#endif +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { +#ifndef HASU + KB_NO, // Fn0 + KB_NO, // Fn1 + KB_NO, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +#else + KB_ENTER, // Fn0 + KB_SCOLON, // Fn1 + KB_SLASH, // Fn2 + KB_UP, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +#endif +}; + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* + * The keymap works with both M0110 and M0110A keyboards. As you can see, the M0110A is a superset + * of the M0110 keyboard, with only one exception: 'Enter' in M0110 does not exist + * on the M0110A, but since it generates a unique scan code which is not used for some other key in + * the M0110A, they are totally interchangeable. In fact, the M0110A is functionally (almost) + * identical to the combination of the M0110 along with the M0120 keypad. The only difference + * (which is causing some problems as you will read below) is that the M0110+M0120 don't have + * dedicated arrow keys, while the M0110A does. However, the M0120 did have arrow keys, which + * doubled as the [comma], [/], [*] and [+] keys, when used with the [Shift] key. The M0110A has + * substituted the [comma] key with the [=] key, however its scancode is the same. + * + * Default: + * ,---------------------------------------------------------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Gui| =| /| *| + * |---------------------------------------------------------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| + * |-----------------------------------------------------' | |---------------| + * |Fn0 | A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| + * |---------------------------------------------------------| |---------------| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | + * |---------------------------------------------------------| |-----------|Ent| + * |Ctrl |Alt | Space |Gui| \|Lft|Rgt|Dn | | 0| .| | + * `---------------------------------------------------------' `---------------' + * + * HHKB/WASD/Mouse Layer(Fn0): + * ,---------------------------------------------------------. ,---------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delet| |Nlk|Mb1|Mb3|Mb2| + * |---------------------------------------------------------| |---------------| + * |Caps |Hom| Up|PgU| | | | |Psc|Slk|Pau|Up |Ins| | |MwD|McU|MwU|MwU| + * |-----------------------------------------------------' | |---------------| + * |Fn0 |Lef|Dow|Rig| | | | |Hom|PgU|Lef|Rig|Return| |McL|McD|McR|MwD| + * |---------------------------------------------------------| |---------------| + * |Shift |End| |PgD| |VoD|VoU|Mut|End|PgD|Dow|Shif|Up | |MwL|McD|MwR| | + * |---------------------------------------------------------| |-----------|Mb2| + * |Ctrl |Alt | Space |Gui | \|Lft|Rgt|Dn | | Mb1|Mb3| | + * `---------------------------------------------------------' `---------------' + * Mb: Mouse Button / Mc: Mouse Cursor / Mw: Mouse Wheel + * + * NOTE: M0110 has no arrow and keypad keys. + * NOTE: \ is located next to ] on M0110. + * NOTE: Gui between Space and \ is Enter on M0110 not exists on M0110A. + * NOTE: LShift and RShift are logically same key. (M0110, M0110A) + * NOTE: LOption and ROption are logically same key. (M0110) + */ +#ifndef HASU + KEYMAP( + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, LGUI,EQL, PSLS,PAST, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS, + FN0, A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, UP, P1, P2, P3, PENT, + LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT + ), + // HHKB & WASD + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,BTN1,BTN3,BTN2, + CAPS,HOME,UP, PGUP,NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, WH_D,MS_U,WH_U,WH_U, + FN0, LEFT,DOWN,RGHT,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT, ENT, MS_L,MS_D,MS_R,WH_D, + LSFT,END, NO, PGDN,NO, VOLD,VOLU,MUTE,END, PGDN,DOWN, UP, WH_L,MS_D,WH_R,BTN2, + LCTL,LALT, SPC, LGUI,INS, LEFT,RGHT,DOWN, BTN1, BTN3 + ), +#else + // hasu's keymap(To enable this use 'make hasu' to add option flag: EXTRAFLAGS=-DHASU) + KEYMAP( + ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, LGUI,EQL, PSLS,PAST, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS, + LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT, FN0, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, FN3, P1, P2, P3, PENT, + FN4, LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, LGUI, PDOT + ), + // HHKB & WASD + KEYMAP( + GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,EQL, PSLS,PAST, + CAPS,HOME,UP, PGUP,NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, P7, P8, P9, PMNS, + LCTL,LEFT,DOWN,RGHT,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT, FN0, P4, P5, P6, PPLS, + LSFT,END, NO, PGDN,NO, VOLD,VOLU,MUTE,END, PGDN,DOWN, FN3, P1, P2, P3, PENT, + LCTL,LALT, SPC, LGUI,INS, LEFT,RGHT,DOWN, P0, PDOT + ), + // vi mousekeys + KEYMAP( + GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,EQL, PSLS,PAST, + CAPS,NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, P7, P8, P9, PMNS, + NO, VOLD,VOLU,MUTE,NO, NO, MS_L,MS_D,MS_U,MS_R,FN1, NO, ENT, P4, P5, P6, PPLS, + LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,NO, NO, NO, UP, P1, P2, P3, PENT, + FN4, LALT, BTN1, LGUI,NO, LEFT,RGHT,DOWN, P0, PDOT + ), + // vi cusorkeys + KEYMAP( + GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,EQL, PSLS,PAST, + CAPS,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, PSCR,SLCK,PAUS, P7, P8, P9, PMNS, + NO, NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, + LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, UP, P1, P2, P3, PENT, + LCTL,LALT, SPC, LGUI,INS, LEFT,RGHT,DOWN, P0, PDOT + ), +#endif +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return KEYCODE(layer, row, col); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/converter/m0110_usb/led.c b/converter/m0110_usb/led.c new file mode 100644 index 0000000000..f76545f0ba --- /dev/null +++ b/converter/m0110_usb/led.c @@ -0,0 +1,24 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdint.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ +} diff --git a/converter/m0110_usb/matrix.c b/converter/m0110_usb/matrix.c new file mode 100644 index 0000000000..1ca6894c44 --- /dev/null +++ b/converter/m0110_usb/matrix.c @@ -0,0 +1,169 @@ +/* +Copyright 2011,2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * scan matrix + */ +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "debug.h" +#include "host.h" +#include "led.h" +#include "m0110.h" +#include "matrix.h" + + +#define CAPS 0x39 +#define CAPS_BREAK (CAPS | 0x80) +#define ROW(key) ((key)>>3&0x0F) +#define COL(key) ((key)&0x07) + + +static bool is_modified = false; + +// matrix state buffer(1:on, 0:off) +static uint8_t *matrix; +static uint8_t _matrix0[MATRIX_ROWS]; + +static void register_key(uint8_t key); + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + print_enable = true; + debug_enable = true; + debug_matrix = false; + debug_keyboard = false; + debug_mouse = false; + print("debug enabled.\n"); + + m0110_init(); + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; + matrix = _matrix0; + return; +} + +uint8_t matrix_scan(void) +{ + uint8_t key; + + is_modified = false; + key = m0110_recv_key(); + +#ifdef MATRIX_HAS_LOCKING_CAPS + // Send Caps key up event + if (matrix_is_on(ROW(CAPS), COL(CAPS))) { + is_modified = true; + register_key(CAPS_BREAK); + } +#endif + if (key == M0110_NULL) { + return 0; + } else if (key == M0110_ERROR) { + return 0; + } else { +#ifdef MATRIX_HAS_LOCKING_CAPS + if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { + // CAPS LOCK on: + // Ignore LockingCaps key down event + if (key == CAPS) return 0; + // Convert LockingCaps key up event into down event + if (key == CAPS_BREAK) key = CAPS; + } else { + // CAPS LOCK off: + // Ignore LockingCaps key up event + if (key == CAPS_BREAK) return 0; + } +#endif + is_modified = true; + register_key(key); + } + + if (debug_enable) { + print("["); phex(key); print("]\n"); + } + return 1; +} + +bool matrix_is_modified(void) +{ + return is_modified; +} + +inline +bool matrix_has_ghost(void) +{ + return false; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & (1<<col)); +} + +inline +uint8_t matrix_get_row(uint8_t row) +{ + return matrix[row]; +} + +void matrix_print(void) +{ + print("\nr/c 01234567\n"); + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); + pbin_reverse(matrix_get_row(row)); + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += bitpop(matrix[i]); + } + return count; +} + +inline +static void register_key(uint8_t key) +{ + if (key&0x80) { + matrix[ROW(key)] &= ~(1<<COL(key)); + } else { + matrix[ROW(key)] |= (1<<COL(key)); + } +} diff --git a/converter/news_usb/Makefile.pjrc b/converter/news_usb/Makefile.pjrc new file mode 100644 index 0000000000..376133ad5e --- /dev/null +++ b/converter/news_usb/Makefile.pjrc @@ -0,0 +1,58 @@ +# +# Makefile for PJRC Teensy +# + + +# Target file name (without extension). +TARGET = news_usb_pjrc + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + news.c + +CONFIG_H = config_pjrc.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/news_usb/config_pjrc.h b/converter/news_usb/config_pjrc.h new file mode 100644 index 0000000000..e9cf7dedb6 --- /dev/null +++ b/converter/news_usb/config_pjrc.h @@ -0,0 +1,66 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x5021 +#define MANUFACTURER t.m.k. +#define PRODUCT SONY NEWS keyboard converter +#define DESCRIPTION converts SONY NEWS protocol into USB + + +/* matrix size */ +#define MATRIX_ROWS 16 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ + keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +/* Asynchronous USART + * 8-data bit, non parity, 1-stop bit, no flow control + */ +#ifdef __AVR_ATmega32U4__ +# define NEWS_KBD_RX_VECT USART1_RX_vect +# define NEWS_KBD_RX_DATA UDR1 +# define NEWS_KBD_RX_BAUD 9600 +# define NEWS_KBD_RX_UBBR ((F_CPU/(16UL*NEWS_KBD_RX_BAUD))-1) +# define NEWS_KBD_RX_INIT() do { \ + UBRR1L = (uint8_t) NEWS_KBD_RX_UBBR; \ + UBRR1H = (uint8_t) (NEWS_KBD_RX_UBBR>>8); \ + UCSR1B |= (1<<RXCIE1) | (1<<RXEN1); \ + } while(0) +#else +# error "USART configuration is needed." +#endif + +#endif diff --git a/converter/news_usb/keymap.c b/converter/news_usb/keymap.c new file mode 100644 index 0000000000..4bd556ba09 --- /dev/null +++ b/converter/news_usb/keymap.c @@ -0,0 +1,125 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keycodes.h" +#include "util.h" +#include "keymap.h" + + + + +// Following macros help you to define a keymap with the form of actual keyboard layout. + +/* SONY NEWS NWP-5461 */ +#define KEYMAP( \ + K7A, K01,K02,K03,K04,K05, K06,K07,K08,K09,K0A, K68,K69, K64,K65,K52, \ + K0B,K0C,K0D,K0E,K0F,K10,K11,K12,K13,K14,K15,K16,K17,K18,K19, K6A, K4B,K4C,K4D,K4E, \ + K1A,K1B,K1C,K1D,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27, K6B, K4F,K50,K51,K56, \ + K28,K29,K2A,K2B,K2C,K2D,K2E,K2F,K30,K31,K32,K33,K34, K35, K6C, K53,K54,K55,K5A, \ + K36,K37,K38,K39,K3A,K3B,K3C,K3D,K3E,K3F,K40,K41, K42, K6D, K57,K59,K58, \ + K43,K44,K45, K46, K47, K48,K49,K4A, K6E, K66,K5B,K5C,K5D \ +) { \ + { KB_NO, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ + { KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ + { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ + { KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ + { KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ + { KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_NO, KB_NO }, \ + { KB_NO, KB_NO, KB_NO, KB_NO, KB_##K64, KB_##K65, KB_##K66, KB_NO }, \ + { KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_##K6D, KB_##K6E, KB_NO }, \ + { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, }, \ + { KB_NO, KB_NO, KB_##K7A, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO } \ +} + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { + 0, // Fn0 + 0, // Fn1 + 0, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { + KB_NO, // Fn0 + KB_NO, // Fn1 + KB_NO, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +}; + + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* 0: default + * ,---. ,------------------------, ,------------------------. ,---------. + * |Pow| | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10| | F11| F12| ,-----------. + * `---' `------------------------' `------------------------' `---------' | *| /| +| + * ,-------------------------------------------------------------. ,---. ,---------------| + * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| BS | |Hlp| | 7| 8| 9| -| + * |-------------------------------------------------------------| |---| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Del| | |Ins| | 4| 5| 6| ,| + * |---------------------------------------------------------' | |---| |---------------| + * |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| `|Return| |Clr| | 1| 2| 3| | + * |-------------------------------------------------------------| |---| |-----------|Ent| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /| |Shift | |PgU| | 0| .| Up| | + * |-------------------------------------------------------------| |---| |---------------| + * |Alt |Gui |Alt | Space | |Gui|App|Ctrl | |PgD| |Tab|Lef|Dow|Rig| + * `-------------------------------------------------------------' `---' `---------------' + */ + KEYMAP( + PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PAST,PSLS,PPLS, + ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,BSPC, HELP, P7, P8, P9, PMNS, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,DEL, INS, P4, P5, P6, PCMM, + CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,GRV, ENT, CLR, P1, P2, P3, PENT, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RO, RSFT, PGUP, P0, PDOT,UP, + LCTL,LGUI,LALT, SPC, ERAS, RALT,RGUI,RCTL, PGDN, TAB, LEFT,DOWN,RGHT + ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/converter/news_usb/led.c b/converter/news_usb/led.c new file mode 100644 index 0000000000..51e601318a --- /dev/null +++ b/converter/news_usb/led.c @@ -0,0 +1,26 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdint.h" +#include "news.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + // not supported now +} diff --git a/converter/news_usb/matrix.c b/converter/news_usb/matrix.c new file mode 100644 index 0000000000..bf363e7d9b --- /dev/null +++ b/converter/news_usb/matrix.c @@ -0,0 +1,141 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "news.h" +#include "matrix.h" + + +/* + * Matrix Array usage: + * + * ROW: 16 + * COL:8 + * + * 8bit wide + * +---------+ + * 0|00 ... 07| + * 1|08 ... 0F| + * :| ... | + * :| ... | + * E|70 ... 77| + * F|78 ... 7F| + * +---------+ + * + */ +static uint8_t matrix[MATRIX_ROWS]; +#define ROW(code) ((code>>3)&0xF) +#define COL(code) (code&0x07) + +static bool is_modified = false; + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + news_init(); + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; + + return; +} + +uint8_t matrix_scan(void) +{ + is_modified = false; + + uint8_t code; + code = news_recv(); + if (code == 0) { + return 0; + } + + phex(code); print(" "); + if (code&0x80) { + // break code + if (matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] &= ~(1<<COL(code)); + is_modified = true; + } + } else { + // make code + if (!matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] |= (1<<COL(code)); + is_modified = true; + } + } + return code; +} + +bool matrix_is_modified(void) +{ + return is_modified; +} + +inline +bool matrix_has_ghost(void) +{ + return false; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & (1<<col)); +} + +inline +uint8_t matrix_get_row(uint8_t row) +{ + return matrix[row]; +} + +void matrix_print(void) +{ + print("\nr/c 01234567\n"); + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); + pbin_reverse(matrix_get_row(row)); + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += bitpop(matrix[i]); + } + return count; +} diff --git a/converter/ps2_usb/Makefile b/converter/ps2_usb/Makefile new file mode 100644 index 0000000000..0bba191a38 --- /dev/null +++ b/converter/ps2_usb/Makefile @@ -0,0 +1,58 @@ +# +# Makefile for PJRC Teensy +# + + +# Target file name (without extension). +TARGET = ps2_usb_pjrc + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + ps2.c + +CONFIG_H = config_pjrc.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/ps2_usb/Makefile.pjrc_usart b/converter/ps2_usb/Makefile.pjrc_usart new file mode 100644 index 0000000000..3dad7e2f8c --- /dev/null +++ b/converter/ps2_usb/Makefile.pjrc_usart @@ -0,0 +1,58 @@ +# +# Makefile for PJRC Teensy +# + + +# Target file name (without extension). +TARGET = ps2_usb_pjrc_usart + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + ps2_usart.c + +CONFIG_H = config_pjrc_usart.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/ps2_usb/Makefile.vusb b/converter/ps2_usb/Makefile.vusb new file mode 100644 index 0000000000..4d5240c309 --- /dev/null +++ b/converter/ps2_usb/Makefile.vusb @@ -0,0 +1,92 @@ +# +# Makefile for V-USB +# + + +# Target file name (without extension). +TARGET = ps2_usb_vusb + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + ps2_usart.c + +CONFIG_H = config_vusb.h + + +# V-USB debug level: To use ps2_usart.c level must be 0 +# ps2_usart.c requires USART to receive PS/2 signal. +OPT_DEFS = -DDEBUG_LEVEL=0 + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +#MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 +MCU = atmega168 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 20000000 + + +# Build Options +# comment out to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover +NO_UART = yes # UART is unavailable + + + +#---------------- Programming Options -------------------------- +AVRDUDE = avrdude +# Type: avrdude -c ? to get a full listing. +AVRDUDE_PROGRAMMER = usbasp +AVRDUDE_PORT = +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + +PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + + +include $(TOP_DIR)/protocol/vusb.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/ps2_usb/README b/converter/ps2_usb/README new file mode 100644 index 0000000000..c10393e5e7 --- /dev/null +++ b/converter/ps2_usb/README @@ -0,0 +1,116 @@ +PS/2 to USB keyboard converter +============================== +This firmware converts PS/2 keyboard protocol to USB and for now supports only Scan Code Set 2. +This will works on USB AVR(ATMega32U4, AT90USB) or V-USB. + + +Features +-------- +Mouse keys + You can emulates mouse move and button click using keyboard. +System/Media control + You can sends Power event, Volume down/up and Mute. +USB NKRO(actually 120KRO+8Modifiers) + You can tolggles NKRO feature. +Keymap customization + You can customize keymaps easily by editing source code. See keymap.c. + + +PS/2 signal handling implementations +------------------------------------ +Following three methods are used to implement PS/2 signal handling. +a. Simple and stupid wait & read loop(intensive use of cycles) + This is implemented with (expected) portable C code for reference. See ps2.c. +b. Interrupt driven + See ps2_intr.c +c. Using USART hardware module(no cycle needed) + This uses AVR USART function to recevie PS/2 signal and be used in V-USB converter. + See ps2_usart.c. + + +Build Converter +--------------- +Connect PS/2 keyboard into Teensy with 4 lines(Vcc, GND, Data, Clock). +For a. Simple and stupid and b. Interrupt implementaion: + By default Clock is on PF0 and Data on PF1. + You can change this pin configuration by editing config_pjrc.h. + In this photo Vcc is yellow, GND is green, Data is red and Clock is black. + http://img17.imageshack.us/img17/7243/201101181933.jpg +For c. USART implementation: + In case of Teensny(ATMega32u4) CLock is on PD5 and Data on PD2. + + +Build Frimware +-------------- +1. Edit Makefile for build options and MCU setting. + Use 'atmega32u4' for Teensy 2.0 or 'at90usb1286' for Teensy++ 2.0. +2. make + Just type 'make' in a terminal. + Use '-f Makefile.pjrc_intr' option to use b. Interrupt. + Use '-f Makefile.pjrc_usart' option to use c. USART. + Use '-f Makefile.vusb' option to build V-USB converter. +3. program with Teensy Loader. + http://www.pjrc.com/teensy/loader.html + + +Demonstration of Features +------------------------- +In default configuration, you can try several keymaps, mousekeys and USB NKRO. +Use following magic key combinations to enable some features. + +keymaps and NKRO: + Magic+0: Qwerty with mousekeys(default) + Magic+1: Qwerty without mousekeys + Magic+2: Colemak + Magic+3: Dvorak + Magic+4: Workman + Magic+N: toggles NKRO/6KRO(6KRO by default) + Magic+Esc: sends Power Event(Power button) + + where Magic=(LShift+RShift) or (LControl+RShift) + +Fn layer function: + Fn0+(hjkl): Mousekey move(vi cursor like) + Fn0+(yuio): Mouse wheel(left,down,up,right) + Fn0+space: Mouse left button + Fn0+(mnb): Mouse buttons(m=left, n=right, b=middle) + Fn0+(zxc): Media control(Volup, Voldown, Mute) + Fn1+(hjkl): Cursor move(vi cursor like) + Fn1+(nm,.): Cursor move(Home,PageDown,PageUp,End) + + where Fn0=;, Fn1=/ + + +Keymap +------ +You can change a keymap by editing code of keymap.c like following. +How to define the keymap is probably obvious. You can find key symbols in usb_keycodes.h. +To define keymap layer switching may needs a bit of your effort at this time. + + /* Default Layer: plain keymap + * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. + * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|Slp|Wak| + * `---' `---------------' `---------------' `---------------' `-----------' `-----------' + * ,-----------------------------------------------------------. ,-----------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| /| *| -| + * |-----------------------------------------------------------| |-----------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | + * |-----------------------------------------------------------| `-----------' |-----------| +| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| | + * |-----------------------------------------------------------| ,---. |---------------| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------| ,-----------. |-----------|Ent| + * |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| | 0| .| | + * `-----------------------------------------------------------' `-----------' `---------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, + CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + +EOF diff --git a/converter/ps2_usb/README.vusb b/converter/ps2_usb/README.vusb new file mode 100644 index 0000000000..c92871bcdd --- /dev/null +++ b/converter/ps2_usb/README.vusb @@ -0,0 +1,37 @@ +V-USB Support +============= +You can also use this converter on ATmega(168/328) with V-USB instead of Teensy. +The converter on V-USB lacks some features for now: USB NKRO and System/Media control. + +To build a firmware use Makefile.vusb instead of Makefile. + + +Circuit +------- + +---+ +---------------+ +USB GND | | ATmega168 | +=== C3 | | +5V <-------+--------+---|Vcc,AVCC | PS/2 + R1 | | ==== +D- <----+--+-----R2-----|INT1 RXD|------->DATA +D+ <----|---+----R3-----|INT0 XCK|------->CLOCK + Z1 Z2 | | ->5V +GND<----+---+--+--+-----|GND | ->GND + | | | | + | C2-+--|XTAL1 | + | X1 | | + +--C3-+--|XTAL2 | + +---------------+ +R1: 1.5K Ohm +R2,R3: 68 Ohm +Z1,Z2: Zenner 3.6V +C1,C2: 22pF +C3: 0.1uF +X1: Crystal 20MHz(16MHz/12MHz) + + +This is my V-USB converter on breadboard. +[IMG]http://i.imgur.com/8jJCZl.jpg[/IMG] + + +EOF diff --git a/converter/ps2_usb/config_pjrc.h b/converter/ps2_usb/config_pjrc.h new file mode 100644 index 0000000000..883ffab275 --- /dev/null +++ b/converter/ps2_usb/config_pjrc.h @@ -0,0 +1,59 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6512 +#define MANUFACTURER t.m.k. +#define PRODUCT PS/2 keyboard converter +#define DESCRIPTION convert PS/2 keyboard to USB + + +/* matrix size */ +#define MATRIX_ROWS 32 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ + keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +/* PS/2 lines */ +#define PS2_CLOCK_PORT PORTF +#define PS2_CLOCK_PIN PINF +#define PS2_CLOCK_DDR DDRF +#define PS2_CLOCK_BIT 0 +#define PS2_DATA_PORT PORTF +#define PS2_DATA_PIN PINF +#define PS2_DATA_DDR DDRF +#define PS2_DATA_BIT 1 + +#endif diff --git a/converter/ps2_usb/config_pjrc_usart.h b/converter/ps2_usb/config_pjrc_usart.h new file mode 100644 index 0000000000..83ddbf7703 --- /dev/null +++ b/converter/ps2_usb/config_pjrc_usart.h @@ -0,0 +1,91 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6513 +#define MANUFACTURER t.m.k. +#define PRODUCT PS/2 keyboard converter(USART) +#define DESCRIPTION convert PS/2 keyboard to USB + + +/* matrix size */ +#define MATRIX_ROWS 32 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ + keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +/* PS/2 lines */ +#define PS2_CLOCK_PORT PORTD +#define PS2_CLOCK_PIN PIND +#define PS2_CLOCK_DDR DDRD +#define PS2_CLOCK_BIT 5 +#define PS2_DATA_PORT PORTD +#define PS2_DATA_PIN PIND +#define PS2_DATA_DDR DDRD +#define PS2_DATA_BIT 2 + + +// synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge +// set DDR of CLOCK as input to be slave +#define PS2_USART_INIT() do { \ + PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ + PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ + UCSR1C = ((1 << UMSEL10) | \ + (3 << UPM10) | \ + (0 << USBS1) | \ + (3 << UCSZ10) | \ + (0 << UCPOL1)); \ + UCSR1A = 0; \ + UBRR1H = 0; \ + UBRR1L = 0; \ +} while (0) +#define PS2_USART_RX_INT_ON() do { \ + UCSR1B = ((1 << RXCIE1) | \ + (1 << RXEN1)); \ +} while (0) +#define PS2_USART_RX_POLL_ON() do { \ + UCSR1B = (1 << RXEN1); \ +} while (0) +#define PS2_USART_OFF() do { \ + UCSR1C = 0; \ + UCSR1B &= ~((1 << RXEN1) | \ + (1 << TXEN1)); \ +} while (0) +#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1)) +#define PS2_USART_RX_DATA UDR1 +#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) +#define PS2_USART_RX_VECT USART1_RX_vect + +#endif diff --git a/converter/ps2_usb/config_vusb.h b/converter/ps2_usb/config_vusb.h new file mode 100644 index 0000000000..afd2f7911f --- /dev/null +++ b/converter/ps2_usb/config_vusb.h @@ -0,0 +1,133 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x2233 +// TODO: share these strings with usbconfig.h +// Edit usbconfig.h to change these. +#define MANUFACTURER t.m.k. +#define PRODUCT PS/2 keyboard converter +#define DESCRIPTION convert PS/2 keyboard to USB + + +/* matrix size */ +#define MATRIX_ROWS 32 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ + keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +/* PS/2 lines */ +#define PS2_CLOCK_PORT PORTD +#define PS2_CLOCK_PIN PIND +#define PS2_CLOCK_DDR DDRD +#define PS2_CLOCK_BIT 4 +#define PS2_DATA_PORT PORTD +#define PS2_DATA_PIN PIND +#define PS2_DATA_DDR DDRD +#define PS2_DATA_BIT 0 + + +// Synchronous USART is used to receive data from keyboard. +// Use RXD pin for PS/2 DATA line and XCK for PS/2 CLOCK. +// NOTE: This is recomended strongly if you use V-USB library. +#define PS2_USE_USART + +// External or Pin Change Interrupt is used to receive data from keyboard. +// Use INT1 or PCINTxx for PS/2 CLOCK line. see below. +//#define PS2_USE_INT + + +#ifdef PS2_USE_USART +// synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge +// set DDR of CLOCK as input to be slave +#define PS2_USART_INIT() do { \ + PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ + PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ + UCSR0C = ((1 << UMSEL00) | \ + (3 << UPM00) | \ + (0 << USBS0) | \ + (3 << UCSZ00) | \ + (0 << UCPOL0)); \ + UCSR0A = 0; \ + UBRR0H = 0; \ + UBRR0L = 0; \ +} while (0) +#define PS2_USART_RX_INT_ON() do { \ + UCSR0B = ((1 << RXCIE0) | \ + (1 << RXEN0)); \ +} while (0) +#define PS2_USART_RX_POLL_ON() do { \ + UCSR0B = (1 << RXEN0); \ +} while (0) +#define PS2_USART_OFF() do { \ + UCSR0C = 0; \ + UCSR0B &= ~((1 << RXEN0) | \ + (1 << TXEN0)); \ +} while (0) +#define PS2_USART_RX_READY (UCSR0A & (1<<RXC0)) +#define PS2_USART_RX_DATA UDR0 +#define PS2_USART_ERROR (UCSR0A & ((1<<FE0) | (1<<DOR0) | (1<<UPE0))) +#define PS2_USART_RX_VECT USART_RX_vect +#endif + + +#ifdef PS2_USE_INT +/* INT1 +#define PS2_INT_INIT() do { \ + EICRA |= ((1<<ISC11) | \ + (0<<ISC10)); \ +} while (0) +#define PS2_INT_ON() do { \ + EIMSK |= (1<<INT1); \ +} while (0) +#define PS2_INT_OFF() do { \ + EIMSK &= ~(1<<INT1); \ +} while (0) +#define PS2_INT_VECT INT1_vect +*/ + +/* PCINT20 */ +#define PS2_INT_INIT() do { \ + PCICR |= (1<<PCIE2); \ +} while (0) +#define PS2_INT_ON() do { \ + PCMSK2 |= (1<<PCINT20); \ +} while (0) +#define PS2_INT_OFF() do { \ + PCMSK2 &= ~(1<<PCINT20); \ + PCICR &= ~(1<<PCIE2); \ +} while (0) +#define PS2_INT_VECT PCINT2_vect +#endif + +#endif diff --git a/converter/ps2_usb/keymap.c b/converter/ps2_usb/keymap.c new file mode 100644 index 0000000000..f1e34a929a --- /dev/null +++ b/converter/ps2_usb/keymap.c @@ -0,0 +1,379 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Keymap for PS/2 keyboard + */ +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keycodes.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + + + +// Following macros help you to define a keymap with the form of actual keyboard layout. + +/* US layout plus all other various keys */ +#define KEYMAP_ALL( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + K61, /* for European ISO */ \ + K51, K13, K6A, K64, K67, /* for Japanese JIS */ \ + K08, K10, K18, K20, K28, K30, K38, K40, K48, K50, K57, K5F, /* F13-24 */ \ + KB7, KBF, KDE, /* System Power, Sleep, Wake */ \ + KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \ + KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \ + KC8, KAB, KC0, /* Mail, Calculator, My Computer */ \ + K90, KBA, KB8, KB0, /* WWW Search, Home, Back, Forward */ \ + KA8, KA0, K98 /* WWW Stop, Refresh, Favorites */ \ +) { \ + { KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_NO }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_NO }, \ + { KB_##K18, KB_NO, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_NO }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_NO }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_NO }, \ + { KB_##K38, KB_NO, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \ + { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ + { KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_NO }, \ + { KB_##K50, KB_##K51, KB_##K52, KB_NO, KB_##K54, KB_##K55, KB_NO, KB_##K57 }, \ + { KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_NO, KB_##K5D, KB_NO, KB_##K5F }, \ + { KB_NO, KB_##K61, KB_NO, KB_NO, KB_##K64, KB_NO, KB_##K66, KB_##K67 }, \ + { KB_NO, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_NO, KB_NO, KB_NO }, \ + { KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ + { KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \ + { KB_NO, KB_NO, KB_NO, KB_##K83, KB_NO, KB_NO, KB_NO, KB_NO }, \ + { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ + { KB_##K90, KB_##K91, KB_NO, KB_NO, KB_##K94, KB_##K95, KB_NO, KB_NO }, \ + { KB_##K98, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K9F }, \ + { KB_##KA0, KB_##KA1, KB_NO, KB_##KA3, KB_NO, KB_NO, KB_NO, KB_##KA7 }, \ + { KB_##KA8, KB_NO, KB_NO, KB_##KAB, KB_NO, KB_NO, KB_NO, KB_##KAF }, \ + { KB_##KB0, KB_NO, KB_##KB2, KB_NO, KB_##KB4, KB_NO, KB_NO, KB_##KB7 }, \ + { KB_##KB8, KB_NO, KB_##KBA, KB_##KBB, KB_NO, KB_NO, KB_NO, KB_##KBF }, \ + { KB_##KC0, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ + { KB_##KC8, KB_NO, KB_##KCA, KB_NO, KB_NO, KB_##KCD, KB_NO, KB_NO }, \ + { KB_##KD0, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ + { KB_NO, KB_NO, KB_##KDA, KB_NO, KB_NO, KB_NO, KB_##KDE, KB_NO }, \ + { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ + { KB_NO, KB_##KE9, KB_NO, KB_##KEB, KB_##KEC, KB_NO, KB_NO, KB_NO }, \ + { KB_##KF0, KB_##KF1, KB_##KF2, KB_NO, KB_##KF4, KB_##KF5, KB_NO, KB_NO }, \ + { KB_NO, KB_NO, KB_##KFA, KB_NO, KB_##KFC, KB_##KFD, KB_##KFE, KB_NO }, \ +} + +/* US layout */ +#define KEYMAP( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ +) \ +KEYMAP_ALL( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + NUBS, \ + RO, KANA, JYEN, HENK, MHEN, \ + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ + SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ + AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ + MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ + MAIL, CALCULATOR, MY_COMPUTER, \ + WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ + WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ +) + +/* ISO layout */ +#define KEYMAP_ISO( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,K5A, K6B,K73,K74,K79, \ + K12,K61,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ +) \ +KEYMAP_ALL( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + K61, \ + RO, KANA, JYEN, HENK, MHEN, \ + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ + SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ + AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ + MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ + MAIL, CALCULATOR, MY_COMPUTER, \ + WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ + WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ +) + +/* JIS layout */ +#define KEYMAP_JIS( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K67,K29,K64,K13, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ +) \ +KEYMAP_ALL( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + NUBS, \ + K51, K13, K6A, K64, K67, \ + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ + SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ + AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ + MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ + MAIL, CALCULATOR, MY_COMPUTER, \ + WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ + WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ +) + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { + 5, // Fn0 + 6, // Fn1 + 0, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { + KB_SCLN, // Fn0 + KB_SLSH, // Fn1 + KB_NO, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +}; + + +// The keymap is a 32*8 byte array which convert a PS/2 scan code into a USB keycode. +// See usb_keycodes.h for USB keycodes. You should omit a 'KB_' prefix of USB keycodes in keymap macro. +// Use KEYMAP_ISO() or KEYMAP_JIS() instead of KEYMAP() if your keyboard is ISO or JIS. +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* 0: default + * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. + * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|Slp|Wak| + * `---' `---------------' `---------------' `---------------' `-----------' `-----------' + * ,-----------------------------------------------------------. ,-----------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| /| *| -| + * |-----------------------------------------------------------| |-----------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | + * |-----------------------------------------------------------| `-----------' |-----------| +| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| | + * |-----------------------------------------------------------| ,---. |---------------| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------| ,-----------. |-----------|Ent| + * |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| | 0| .| | + * `-----------------------------------------------------------' `-----------' `---------------' + * ; = Fn0(to Layer 5) + * / = Fn1(to Layer 6) + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, + CAPS,A, S, D, F, G, H, J, K, L, FN0, QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN1, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + /* 1: plain Qwerty without layer switching + * ,-----------------------------------------------------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| + * |-----------------------------------------------------------| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | + * |-----------------------------------------------------------| + * |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| + * `-----------------------------------------------------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, + CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + /* 2: Colemak http://colemak.com + * ,-----------------------------------------------------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| + * |-----------------------------------------------------------| + * |Tab | Q| W| F| P| G| J| L| U| Y| ;| [| ]| \| + * |-----------------------------------------------------------| + * |BackSp| A| R| S| T| D| H| N| E| I| O| '|Return | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| K| M| ,| ,| /|Shift | + * |-----------------------------------------------------------| + * |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| + * `----------------------------------------------------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, Q, W, F, P, G, J, L, U, Y, SCLN,LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, + BSPC,A, R, S, T, D, H, N, E, I, O, QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, C, V, B, K, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + /* 3: Dvorak http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard + * ,-----------------------------------------------------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| [| ]|Backspa| + * |-----------------------------------------------------------| + * |Tab | '| ,| .| P| Y| F| G| C| R| L| /| =| \| + * |-----------------------------------------------------------| + * |BackSp| A| O| E| U| I| D| H| T| N| S| -|Return | + * |-----------------------------------------------------------| + * |Shift | ;| Q| J| K| X| B| M| Wl V| Z|Shift | + * |-----------------------------------------------------------| + * |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| + * `-----------------------------------------------------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, DEL, END, PGDN, P7, P8, P9, + CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4, P5, P6, PPLS, + LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + /* 4: Workman http://viralintrospection.wordpress.com/2010/09/06/a-different-philosophy-in-designing-keyboard-layouts/ + * ,-----------------------------------------------------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| + * |-----------------------------------------------------------| + * |Tab | Q| D| R| W| B| J| F| U| P| ;| [| ]| \| + * |-----------------------------------------------------------| + * |CapsLo| A| S| H| T| G| Y| N| E| O| I| '|Return | + * |-----------------------------------------------------------| + * |Shift | Z| X| M| C| V| K| L| ,| ,| /|Shift | + * |-----------------------------------------------------------| + * |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| + * `-----------------------------------------------------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, Q, D, R, W, B, J, F, U, P, SCLN,LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, + BSPC,A, S, H, T, G, Y, N, E, O, I, QUOT, ENT, P4, P5, P6, PPLS, + LSFT,Z, X, M, C, V, K, L, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + /* 5: Mouse keys + * ,-----------------------------------------------------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| + * |-----------------------------------------------------------| + * |Tab |MwL|MwU|McU|WwU|WwR|MwL|MwD|MwU|MwR| | | | \| + * |-----------------------------------------------------------| + * |CapsLo| |McL|McD|McR| |McL|McD|McU|McR|Fn0| |Return | + * |-----------------------------------------------------------| + * |Shift |VoD|VoU|Mut|Mb2|Mb3|Mb2|Mb1|VoD|VoU|Mut|Shift | + * |-----------------------------------------------------------| + * |Ctrl |Gui |Alt | Mb1 |Alt |Gui |Menu|Ctrl| + * `-----------------------------------------------------------' + * Mc = mouse cursor, Mw = mouse wheel, Mb = mouse button + * Vo = Volume, Mut = Mute + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, + CAPS,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, P4, P5, P6, PPLS, + LSFT,VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, BTN1, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), + + /* 6: Cursor keys + * ,-----------------------------------------------------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| + * |-----------------------------------------------------------| + * |Tab |Hom|PgU| Up|PgU|End|Hom|PgD|PgU|End| | | | \| + * |-----------------------------------------------------------| + * |CapsLo| |Lef|Dow|Rig| |Lef|Dow| Up|Rig| | |Return | + * |-----------------------------------------------------------| + * |Shift | | | | | |Hom|PgD|PgU|End|Fn1|Shift | + * |-----------------------------------------------------------| + * |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| + * `-----------------------------------------------------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, + CAPS,NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, + LSFT,VOLD,VOLU,MUTE,NO, NO, HOME,PGDN,PGUP,END, FN1, RSFT, UP, P1, P2, P3, + LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT + ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/converter/ps2_usb/led.c b/converter/ps2_usb/led.c new file mode 100644 index 0000000000..e448e84ec7 --- /dev/null +++ b/converter/ps2_usb/led.c @@ -0,0 +1,33 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdint.h" +#include "ps2.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + uint8_t ps2_led = 0; + if (usb_led & (1<<USB_LED_SCROLL_LOCK)) + ps2_led |= (1<<PS2_LED_SCROLL_LOCK); + if (usb_led & (1<<USB_LED_NUM_LOCK)) + ps2_led |= (1<<PS2_LED_NUM_LOCK); + if (usb_led & (1<<USB_LED_CAPS_LOCK)) + ps2_led |= (1<<PS2_LED_CAPS_LOCK); + ps2_host_set_led(ps2_led); +} diff --git a/converter/ps2_usb/matrix.c b/converter/ps2_usb/matrix.c new file mode 100644 index 0000000000..4187ea0601 --- /dev/null +++ b/converter/ps2_usb/matrix.c @@ -0,0 +1,452 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "debug.h" +#include "ps2.h" +#include "matrix.h" + + +static void matrix_make(uint8_t code); +static void matrix_break(uint8_t code); +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); +#endif + + +/* + * Matrix Array usage: + * 'Scan Code Set 2' is assigned into 256(32x8)cell matrix. + * Hmm, it is very sparse and not efficient :( + * + * Notes: + * Both 'Hanguel/English'(F1) and 'Hanja'(F2) collide with 'Delete'(E0 71) and 'Down'(E0 72). + * These two Korean keys need exceptional handling and are not supported for now. Sorry. + * + * 8bit wide + * +---------+ + * 0| | + * :| XX | 00-7F for normal codes(without E0-prefix) + * f|_________| + * 10| | + * :| E0 YY | 80-FF for E0-prefixed codes + * 1f| | (<YY>|0x80) is used as matrix position. + * +---------+ + * + * Exceptions: + * 0x83: F7(0x83) This is a normal code but beyond 0x7F. + * 0xFC: PrintScreen + * 0xFE: Pause + */ +static uint8_t matrix[MATRIX_ROWS]; +#define ROW(code) (code>>3) +#define COL(code) (code&0x07) + +// matrix positions for exceptional keys +#define F7 (0x83) +#define PRINT_SCREEN (0xFC) +#define PAUSE (0xFE) + +static bool is_modified = false; + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + ps2_host_init(); + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; + + return; +} + +/* + * PS/2 Scan Code Set 2: Exceptional Handling + * + * There are several keys to be handled exceptionally. + * The scan code for these keys are varied or prefix/postfix'd + * depending on modifier key state. + * + * Keyboard Scan Code Specification: + * http://www.microsoft.com/whdc/archive/scancode.mspx + * http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc + * + * + * 1) Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left + * a) when Num Lock is off + * modifiers | make | break + * ----------+---------------------------+---------------------- + * Ohter | <make> | <break> + * LShift | E0 F0 12 <make> | <break> E0 12 + * RShift | E0 F0 59 <make> | <break> E0 59 + * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 + * + * b) when Num Lock is on + * modifiers | make | break + * ----------+---------------------------+---------------------- + * Other | E0 12 <make> | <break> E0 F0 12 + * Shift'd | <make> | <break> + * + * Handling: These prefix/postfix codes are ignored. + * + * + * 2) Keypad / + * modifiers | make | break + * ----------+---------------------------+---------------------- + * Ohter | <make> | <break> + * LShift | E0 F0 12 <make> | <break> E0 12 + * RShift | E0 F0 59 <make> | <break> E0 59 + * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 + * + * Handling: These prefix/postfix codes are ignored. + * + * + * 3) PrintScreen + * modifiers | make | break + * ----------+--------------+----------------------------------- + * Other | E0 12 E0 7C | E0 F0 7C E0 F0 12 + * Shift'd | E0 7C | E0 F0 7C + * Control'd | E0 7C | E0 F0 7C + * Alt'd | 84 | F0 84 + * + * Handling: These prefix/postfix codes are ignored, and both scan codes + * 'E0 7C' and 84 are seen as PrintScreen. + * + * 4) Pause + * modifiers | make(no break code) + * ----------+-------------------------------------------------- + * Other | E1 14 77 E1 F0 14 F0 77 + * Control'd | E0 7E E0 F0 7E + * + * Handling: Both code sequences are treated as a whole. + * And we need a ad hoc 'pseudo break code' hack to get the key off + * because it has no break code. + * + */ +uint8_t matrix_scan(void) +{ + + // scan code reading states + static enum { + INIT, + F0, + E0, + E0_F0, + // Pause + E1, + E1_14, + E1_14_77, + E1_14_77_E1, + E1_14_77_E1_F0, + E1_14_77_E1_F0_14, + E1_14_77_E1_F0_14_F0, + // Control'd Pause + E0_7E, + E0_7E_E0, + E0_7E_E0_F0, + } state = INIT; + + + is_modified = false; + + // 'pseudo break code' hack + if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) { + matrix_break(PAUSE); + } + + uint8_t code; + while ((code = ps2_host_recv())) { + switch (state) { + case INIT: + switch (code) { + case 0xE0: + state = E0; + break; + case 0xF0: + state = F0; + break; + case 0xE1: + state = E1; + break; + case 0x83: // F7 + matrix_make(F7); + state = INIT; + break; + case 0x84: // Alt'd PrintScreen + matrix_make(PRINT_SCREEN); + state = INIT; + break; + default: // normal key make + if (code < 0x80) { + matrix_make(code); + } else { + debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n"); + } + state = INIT; + } + break; + case E0: // E0-Prefixed + switch (code) { + case 0x12: // to be ignored + case 0x59: // to be ignored + state = INIT; + break; + case 0x7E: // Control'd Pause + state = E0_7E; + break; + case 0xF0: + state = E0_F0; + break; + default: + if (code < 0x80) { + matrix_make(code|0x80); + } else { + debug("unexpected scan code at E0: "); debug_hex(code); debug("\n"); + } + state = INIT; + } + break; + case F0: // Break code + switch (code) { + case 0x83: // F7 + matrix_break(F7); + state = INIT; + break; + case 0x84: // Alt'd PrintScreen + matrix_break(PRINT_SCREEN); + state = INIT; + break; + default: + if (code < 0x80) { + matrix_break(code); + } else { + debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); + } + state = INIT; + } + break; + case E0_F0: // Break code of E0-prefixed + switch (code) { + case 0x12: // to be ignored + case 0x59: // to be ignored + state = INIT; + break; + default: + if (code < 0x80) { + matrix_break(code|0x80); + } else { + debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n"); + } + state = INIT; + } + break; + // following are states of Pause + case E1: + switch (code) { + case 0x14: + state = E1_14; + break; + default: + state = INIT; + } + break; + case E1_14: + switch (code) { + case 0x77: + state = E1_14_77; + break; + default: + state = INIT; + } + break; + case E1_14_77: + switch (code) { + case 0xE1: + state = E1_14_77_E1; + break; + default: + state = INIT; + } + break; + case E1_14_77_E1: + switch (code) { + case 0xF0: + state = E1_14_77_E1_F0; + break; + default: + state = INIT; + } + break; + case E1_14_77_E1_F0: + switch (code) { + case 0x14: + state = E1_14_77_E1_F0_14; + break; + default: + state = INIT; + } + break; + case E1_14_77_E1_F0_14: + switch (code) { + case 0xF0: + state = E1_14_77_E1_F0_14_F0; + break; + default: + state = INIT; + } + break; + case E1_14_77_E1_F0_14_F0: + switch (code) { + case 0x77: + matrix_make(PAUSE); + state = INIT; + break; + default: + state = INIT; + } + break; + // Following are states of Control'd Pause + case E0_7E: + if (code == 0xE0) + state = E0_7E_E0; + else + state = INIT; + break; + case E0_7E_E0: + if (code == 0xF0) + state = E0_7E_E0_F0; + else + state = INIT; + break; + case E0_7E_E0_F0: + if (code == 0x7E) + matrix_make(PAUSE); + state = INIT; + break; + default: + state = INIT; + } + phex(code); + } + return 1; +} + +bool matrix_is_modified(void) +{ + return is_modified; +} + +inline +bool matrix_has_ghost(void) +{ +#ifdef MATRIX_HAS_GHOST + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + if (matrix_has_ghost_in_row(i)) + return true; + } +#endif + return false; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & (1<<col)); +} + +inline +uint8_t matrix_get_row(uint8_t row) +{ + return matrix[row]; +} + +void matrix_print(void) +{ + print("\nr/c 01234567\n"); + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); + pbin_reverse(matrix_get_row(row)); +#ifdef MATRIX_HAS_GHOST + if (matrix_has_ghost_in_row(row)) { + print(" <ghost"); + } +#endif + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += bitpop(matrix[i]); + } + return count; +} + +#ifdef MATRIX_HAS_GHOST +inline +static bool matrix_has_ghost_in_row(uint8_t row) +{ + // no ghost exists in case less than 2 keys on + if (((matrix[row] - 1) & matrix[row]) == 0) + return false; + + // ghost exists in case same state as other row + for (uint8_t i=0; i < MATRIX_ROWS; i++) { + if (i != row && (matrix[i] & matrix[row]) == matrix[row]) + return true; + } + return false; +} +#endif + + +inline +static void matrix_make(uint8_t code) +{ + if (!matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] |= 1<<COL(code); + is_modified = true; + } +} + +inline +static void matrix_break(uint8_t code) +{ + if (matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] &= ~(1<<COL(code)); + is_modified = true; + } +} diff --git a/converter/ps2_usb/usbconfig.h b/converter/ps2_usb/usbconfig.h new file mode 100644 index 0000000000..9038f1eb8c --- /dev/null +++ b/converter/ps2_usb/usbconfig.h @@ -0,0 +1,378 @@ +/* Name: usbconfig.h + * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Author: Christian Starkjohann + * Creation Date: 2005-04-01 + * Tabsize: 4 + * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $ + */ + +#ifndef __usbconfig_h_included__ +#define __usbconfig_h_included__ + +#include "config_vusb.h" + +/* +General Description: +This file is an example configuration (with inline documentation) for the USB +driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is +also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may +wire the lines to any other port, as long as D+ is also wired to INT0 (or any +other hardware interrupt, as long as it is the highest level interrupt, see +section at the end of this file). +*/ + +/* ---------------------------- Hardware Config ---------------------------- */ + +#define USB_CFG_IOPORTNAME D +/* This is the port where the USB bus is connected. When you configure it to + * "B", the registers PORTB, PINB and DDRB will be used. + */ +#define USB_CFG_DMINUS_BIT 3 +/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. + * This may be any bit in the port. + */ +#define USB_CFG_DPLUS_BIT 2 +/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. + * This may be any bit in the port. Please note that D+ must also be connected + * to interrupt pin INT0! [You can also use other interrupts, see section + * "Optional MCU Description" below, or you can connect D- to the interrupt, as + * it is required if you use the USB_COUNT_SOF feature. If you use D- for the + * interrupt, the USB interrupt will also be triggered at Start-Of-Frame + * markers every millisecond.] + */ +#define USB_CFG_CLOCK_KHZ (F_CPU/1000) +/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, + * 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code + * require no crystal, they tolerate +/- 1% deviation from the nominal + * frequency. All other rates require a precision of 2000 ppm and thus a + * crystal! + * Since F_CPU should be defined to your actual clock rate anyway, you should + * not need to modify this setting. + */ +#define USB_CFG_CHECK_CRC 0 +/* Define this to 1 if you want that the driver checks integrity of incoming + * data packets (CRC checks). CRC checks cost quite a bit of code size and are + * currently only available for 18 MHz crystal clock. You must choose + * USB_CFG_CLOCK_KHZ = 18000 if you enable this option. + */ + +/* ----------------------- Optional Hardware Config ------------------------ */ + +/* #define USB_CFG_PULLUP_IOPORTNAME D */ +/* If you connect the 1.5k pullup resistor from D- to a port pin instead of + * V+, you can connect and disconnect the device from firmware by calling + * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). + * This constant defines the port on which the pullup resistor is connected. + */ +/* #define USB_CFG_PULLUP_BIT 4 */ +/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined + * above) where the 1.5k pullup resistor is connected. See description + * above for details. + */ + +/* --------------------------- Functional Range ---------------------------- */ + +#define USB_CFG_HAVE_INTRIN_ENDPOINT 1 +/* Define this to 1 if you want to compile a version with two endpoints: The + * default control endpoint 0 and an interrupt-in endpoint (any other endpoint + * number). + */ +#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1 +/* Define this to 1 if you want to compile a version with three endpoints: The + * default control endpoint 0, an interrupt-in endpoint 3 (or the number + * configured below) and a catch-all default interrupt-in endpoint as above. + * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. + */ +#define USB_CFG_EP3_NUMBER 3 +/* If the so-called endpoint 3 is used, it can now be configured to any other + * endpoint number (except 0) with this macro. Default if undefined is 3. + */ +/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */ +/* The above macro defines the startup condition for data toggling on the + * interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. + * Since the token is toggled BEFORE sending any data, the first packet is + * sent with the oposite value of this configuration! + */ +#define USB_CFG_IMPLEMENT_HALT 0 +/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature + * for endpoint 1 (interrupt endpoint). Although you may not need this feature, + * it is required by the standard. We have made it a config option because it + * bloats the code considerably. + */ +#define USB_CFG_SUPPRESS_INTR_CODE 0 +/* Define this to 1 if you want to declare interrupt-in endpoints, but don't + * want to send any data over them. If this macro is defined to 1, functions + * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if + * you need the interrupt-in endpoints in order to comply to an interface + * (e.g. HID), but never want to send any data. This option saves a couple + * of bytes in flash memory and the transmit buffers in RAM. + */ +#define USB_CFG_INTR_POLL_INTERVAL 10 +/* If you compile a version with endpoint 1 (interrupt-in), this is the poll + * interval. The value is in milliseconds and must not be less than 10 ms for + * low speed devices. + */ +#define USB_CFG_IS_SELF_POWERED 0 +/* Define this to 1 if the device has its own power supply. Set it to 0 if the + * device is powered from the USB bus. + */ +#define USB_CFG_MAX_BUS_POWER 100 +/* Set this variable to the maximum USB bus power consumption of your device. + * The value is in milliamperes. [It will be divided by two since USB + * communicates power requirements in units of 2 mA.] + */ +#define USB_CFG_IMPLEMENT_FN_WRITE 1 +/* Set this to 1 if you want usbFunctionWrite() to be called for control-out + * transfers. Set it to 0 if you don't need it and want to save a couple of + * bytes. + */ +#define USB_CFG_IMPLEMENT_FN_READ 0 +/* Set this to 1 if you need to send control replies which are generated + * "on the fly" when usbFunctionRead() is called. If you only want to send + * data from a static buffer, set it to 0 and return the data from + * usbFunctionSetup(). This saves a couple of bytes. + */ +#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0 +/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. + * You must implement the function usbFunctionWriteOut() which receives all + * interrupt/bulk data sent to any endpoint other than 0. The endpoint number + * can be found in 'usbRxToken'. + */ +#define USB_CFG_HAVE_FLOWCONTROL 0 +/* Define this to 1 if you want flowcontrol over USB data. See the definition + * of the macros usbDisableAllRequests() and usbEnableAllRequests() in + * usbdrv.h. + */ +#define USB_CFG_DRIVER_FLASH_PAGE 0 +/* If the device has more than 64 kBytes of flash, define this to the 64 k page + * where the driver's constants (descriptors) are located. Or in other words: + * Define this to 1 for boot loaders on the ATMega128. + */ +#define USB_CFG_LONG_TRANSFERS 0 +/* Define this to 1 if you want to send/receive blocks of more than 254 bytes + * in a single control-in or control-out transfer. Note that the capability + * for long transfers increases the driver size. + */ +/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */ +/* This macro is a hook if you want to do unconventional things. If it is + * defined, it's inserted at the beginning of received message processing. + * If you eat the received message and don't want default processing to + * proceed, do a return after doing your things. One possible application + * (besides debugging) is to flash a status LED on each packet. + */ +/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ +/* This macro is a hook if you need to know when an USB RESET occurs. It has + * one parameter which distinguishes between the start of RESET state and its + * end. + */ +/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */ +/* This macro (if defined) is executed when a USB SET_ADDRESS request was + * received. + */ +#define USB_COUNT_SOF 0 +/* define this macro to 1 if you need the global variable "usbSofCount" which + * counts SOF packets. This feature requires that the hardware interrupt is + * connected to D- instead of D+. + */ +/* #ifdef __ASSEMBLER__ + * macro myAssemblerMacro + * in YL, TCNT0 + * sts timer0Snapshot, YL + * endm + * #endif + * #define USB_SOF_HOOK myAssemblerMacro + * This macro (if defined) is executed in the assembler module when a + * Start Of Frame condition is detected. It is recommended to define it to + * the name of an assembler macro which is defined here as well so that more + * than one assembler instruction can be used. The macro may use the register + * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages + * immediately after an SOF pulse may be lost and must be retried by the host. + * What can you do with this hook? Since the SOF signal occurs exactly every + * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in + * designs running on the internal RC oscillator. + * Please note that Start Of Frame detection works only if D- is wired to the + * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! + */ +#define USB_CFG_CHECK_DATA_TOGGLING 0 +/* define this macro to 1 if you want to filter out duplicate data packets + * sent by the host. Duplicates occur only as a consequence of communication + * errors, when the host does not receive an ACK. Please note that you need to + * implement the filtering yourself in usbFunctionWriteOut() and + * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable + * for each control- and out-endpoint to check for duplicate packets. + */ +#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 +/* define this macro to 1 if you want the function usbMeasureFrameLength() + * compiled in. This function can be used to calibrate the AVR's RC oscillator. + */ +#define USB_USE_FAST_CRC 0 +/* The assembler module has two implementations for the CRC algorithm. One is + * faster, the other is smaller. This CRC routine is only used for transmitted + * messages where timing is not critical. The faster routine needs 31 cycles + * per byte while the smaller one needs 61 to 69 cycles. The faster routine + * may be worth the 32 bytes bigger code size if you transmit lots of data and + * run the AVR close to its limit. + */ + +/* -------------------------- Device Description --------------------------- */ + +#define USB_CFG_VENDOR_ID (VENDOR_ID & 0xFF), ((VENDOR_ID >> 8) & 0xFF) +/* USB vendor ID for the device, low byte first. If you have registered your + * own Vendor ID, define it here. Otherwise you may use one of obdev's free + * shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules! + * *** IMPORTANT NOTE *** + * This template uses obdev's shared VID/PID pair for Vendor Class devices + * with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand + * the implications! + */ +#define USB_CFG_DEVICE_ID (PRODUCT_ID & 0xFF), ((PRODUCT_ID >> 8) & 0xFF) +/* This is the ID of the product, low byte first. It is interpreted in the + * scope of the vendor ID. If you have registered your own VID with usb.org + * or if you have licensed a PID from somebody else, define it here. Otherwise + * you may use one of obdev's free shared VID/PID pairs. See the file + * USB-IDs-for-free.txt for details! + * *** IMPORTANT NOTE *** + * This template uses obdev's shared VID/PID pair for Vendor Class devices + * with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand + * the implications! + */ +#define USB_CFG_DEVICE_VERSION 0x00, 0x01 +/* Version number of the device: Minor number first, then major number. + */ +#define USB_CFG_VENDOR_NAME 't', '.', 'm', '.', 'k', '.' +#define USB_CFG_VENDOR_NAME_LEN 6 +/* These two values define the vendor name returned by the USB device. The name + * must be given as a list of characters under single quotes. The characters + * are interpreted as Unicode (UTF-16) entities. + * If you don't want a vendor name string, undefine these macros. + * ALWAYS define a vendor name containing your Internet domain name if you use + * obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for + * details. + */ +#define USB_CFG_DEVICE_NAME 'P', 'S', '/', '2', ' ', 'k', 'e', 'y', 'b', 'o', 'a', 'r', 'd', ' ', 'c', 'o', 'n', 'v', 'e', 'r', 't', 'e', 'r' +#define USB_CFG_DEVICE_NAME_LEN 23 +/* Same as above for the device name. If you don't want a device name, undefine + * the macros. See the file USB-IDs-for-free.txt before you assign a name if + * you use a shared VID/PID. + */ +/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */ +/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */ +/* Same as above for the serial number. If you don't want a serial number, + * undefine the macros. + * It may be useful to provide the serial number through other means than at + * compile time. See the section about descriptor properties below for how + * to fine tune control over USB descriptors such as the string descriptor + * for the serial number. + */ +#define USB_CFG_DEVICE_CLASS 0 +#define USB_CFG_DEVICE_SUBCLASS 0 +/* See USB specification if you want to conform to an existing device class. + * Class 0xff is "vendor specific". + */ +#define USB_CFG_INTERFACE_CLASS 3 /* HID */ +#define USB_CFG_INTERFACE_SUBCLASS 1 /* Boot */ +#define USB_CFG_INTERFACE_PROTOCOL 1 /* Keyboard */ +/* See USB specification if you want to conform to an existing device class or + * protocol. The following classes must be set at interface level: + * HID class is 3, no subclass and protocol required (but may be useful!) + * CDC class is 2, use subclass 2 and protocol 1 for ACM + */ +#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0 +/* Define this to the length of the HID report descriptor, if you implement + * an HID device. Otherwise don't define it or define it to 0. + * If you use this define, you must add a PROGMEM character array named + * "usbHidReportDescriptor" to your code which contains the report descriptor. + * Don't forget to keep the array and this define in sync! + */ + +/* #define USB_PUBLIC static */ +/* Use the define above if you #include usbdrv.c instead of linking against it. + * This technique saves a couple of bytes in flash memory. + */ + +/* ------------------- Fine Control over USB Descriptors ------------------- */ +/* If you don't want to use the driver's default USB descriptors, you can + * provide our own. These can be provided as (1) fixed length static data in + * flash memory, (2) fixed length static data in RAM or (3) dynamically at + * runtime in the function usbFunctionDescriptor(). See usbdrv.h for more + * information about this function. + * Descriptor handling is configured through the descriptor's properties. If + * no properties are defined or if they are 0, the default descriptor is used. + * Possible properties are: + * + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched + * at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is + * used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if + * you want RAM pointers. + * + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found + * in static memory is in RAM, not in flash memory. + * + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), + * the driver must know the descriptor's length. The descriptor itself is + * found at the address of a well known identifier (see below). + * List of static descriptor names (must be declared PROGMEM if in flash): + * char usbDescriptorDevice[]; + * char usbDescriptorConfiguration[]; + * char usbDescriptorHidReport[]; + * char usbDescriptorString0[]; + * int usbDescriptorStringVendor[]; + * int usbDescriptorStringDevice[]; + * int usbDescriptorStringSerialNumber[]; + * Other descriptors can't be provided statically, they must be provided + * dynamically at runtime. + * + * Descriptor properties are or-ed or added together, e.g.: + * #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) + * + * The following descriptors are defined: + * USB_CFG_DESCR_PROPS_DEVICE + * USB_CFG_DESCR_PROPS_CONFIGURATION + * USB_CFG_DESCR_PROPS_STRINGS + * USB_CFG_DESCR_PROPS_STRING_0 + * USB_CFG_DESCR_PROPS_STRING_VENDOR + * USB_CFG_DESCR_PROPS_STRING_PRODUCT + * USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER + * USB_CFG_DESCR_PROPS_HID + * USB_CFG_DESCR_PROPS_HID_REPORT + * USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) + * + * Note about string descriptors: String descriptors are not just strings, they + * are Unicode strings prefixed with a 2 byte header. Example: + * int serialNumberDescriptor[] = { + * USB_STRING_DESCRIPTOR_HEADER(6), + * 'S', 'e', 'r', 'i', 'a', 'l' + * }; + */ + +#define USB_CFG_DESCR_PROPS_DEVICE 0 +#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC +//#define USB_CFG_DESCR_PROPS_CONFIGURATION 0 +#define USB_CFG_DESCR_PROPS_STRINGS 0 +#define USB_CFG_DESCR_PROPS_STRING_0 0 +#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 +#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 +#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 +//#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_HID 0 +#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC +//#define USB_CFG_DESCR_PROPS_HID_REPORT 0 +#define USB_CFG_DESCR_PROPS_UNKNOWN 0 + +/* ----------------------- Optional MCU Description ------------------------ */ + +/* The following configurations have working defaults in usbdrv.h. You + * usually don't need to set them explicitly. Only if you want to run + * the driver on a device which is not yet supported or with a compiler + * which is not fully supported (such as IAR C) or if you use a differnt + * interrupt than INT0, you may have to define some of these. + */ +/* #define USB_INTR_CFG MCUCR */ +/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */ +/* #define USB_INTR_CFG_CLR 0 */ +/* #define USB_INTR_ENABLE GIMSK */ +/* #define USB_INTR_ENABLE_BIT INT0 */ +/* #define USB_INTR_PENDING GIFR */ +/* #define USB_INTR_PENDING_BIT INTF0 */ +/* #define USB_INTR_VECTOR INT0_vect */ + +#endif /* __usbconfig_h_included__ */ diff --git a/converter/terminal_usb/Makefile.102_pjrc b/converter/terminal_usb/Makefile.102_pjrc new file mode 100644 index 0000000000..e9d14e7a05 --- /dev/null +++ b/converter/terminal_usb/Makefile.102_pjrc @@ -0,0 +1,58 @@ +# +# Makefile for PJRC Teensy +# + + +# Target file name (without extension). +TARGET = terminal_usb_102_pjrc + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap_102.c \ + matrix.c \ + led.c \ + ps2.c + +CONFIG_H = config_102_pjrc.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/terminal_usb/Makefile.122_pjrc b/converter/terminal_usb/Makefile.122_pjrc new file mode 100644 index 0000000000..bec00510e5 --- /dev/null +++ b/converter/terminal_usb/Makefile.122_pjrc @@ -0,0 +1,58 @@ +# +# Makefile for PJRC Teensy +# + + +# Target file name (without extension). +TARGET = terminal_usb_122_pjrc + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap_122.c \ + matrix.c \ + led.c \ + ps2.c + +CONFIG_H = config_122_pjrc.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +#MOUSEKEY_ENABLE = yes # Mouse keys +#EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/terminal_usb/README b/converter/terminal_usb/README new file mode 100644 index 0000000000..1ce49f33dc --- /dev/null +++ b/converter/terminal_usb/README @@ -0,0 +1,47 @@ +PS/2 to USB keyboard converter for IBM terminal keyboard +========================================================= +It supports PS/2 Scan Code Set 3 and runs on Teensy, Teensy++ and boards withATMega32u4/AT90USB. +I tested the converter only on Teensy with 1392595(102keys terminal keyboard), +though, I think it will also work with 122keys boards. + +http://geekhack.org/showwiki.php?title=Island:27272 + + +CONNECTION +---------- +Data: PD0 +Clock: PD1 +VCC and GND, of course. + +It is the same as Soarer's converter pin configuration. +See RESOURCE for keyboard connector pin assign. + + + +BUILD +----- +Get source: +$ git clone https://github.com/tmk/tmk_keyboard.git +$ cd terminal_usb + +For 102keys: +$ make -f Makefile.102_pjrc + +For 122keys(not tested): +$ make -f Makefile.122_pjrc + +I used WinAVR 20100110 to develop and build. + + + +RESOURCE +-------- +Soarer's Converter: http://geekhack.org/showwiki.php?title=Island:17458 +102keys(1392595): http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M +122keys(1390876): http://www.seasip.info/VintagePC/ibm_1390876.html +KbdBabel: http://www.kbdbabel.org/ +RJ45 Connector: http://www.kbdbabel.org/conn/kbd_connector_ibmterm.png +DIN Connector: http://www.kbdbabel.org/conn/kbd_connector_ibm3179_318x_319x.png +WinAVR: http://winavr.sourceforge.net/ + +EOF diff --git a/converter/terminal_usb/config_102_pjrc.h b/converter/terminal_usb/config_102_pjrc.h new file mode 100644 index 0000000000..2dce04af7d --- /dev/null +++ b/converter/terminal_usb/config_102_pjrc.h @@ -0,0 +1,58 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6531 +#define MANUFACTURER t.m.k. +#define PRODUCT PS/2(Set3)-USB Keyboard converter(IBM 102keys) +#define DESCRIPTION USB converter for IBM Terminal Keyboard 102keys + + +/* matrix size */ +#define MATRIX_ROWS 17 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_RALT) | MOD_BIT(KB_RCTL)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +/* PS/2 lines */ +#define PS2_CLOCK_PORT PORTD +#define PS2_CLOCK_PIN PIND +#define PS2_CLOCK_DDR DDRD +#define PS2_CLOCK_BIT 1 +#define PS2_DATA_PORT PORTD +#define PS2_DATA_PIN PIND +#define PS2_DATA_DDR DDRD +#define PS2_DATA_BIT 0 + +#endif diff --git a/converter/terminal_usb/config_122_pjrc.h b/converter/terminal_usb/config_122_pjrc.h new file mode 100644 index 0000000000..43691bd71c --- /dev/null +++ b/converter/terminal_usb/config_122_pjrc.h @@ -0,0 +1,58 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6532 +#define MANUFACTURER t.m.k. +#define PRODUCT PS/2(Set3)-USB Keyboard converter(IBM 122keys) +#define DESCRIPTION USB converter for IBM Terminal Keyboard 122keys + + +/* matrix size */ +#define MATRIX_ROWS 17 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_RALT) | MOD_BIT(KB_RCTL)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +/* PS/2 lines */ +#define PS2_CLOCK_PORT PORTD +#define PS2_CLOCK_PIN PIND +#define PS2_CLOCK_DDR DDRD +#define PS2_CLOCK_BIT 1 +#define PS2_DATA_PORT PORTD +#define PS2_DATA_PIN PIND +#define PS2_DATA_DDR DDRD +#define PS2_DATA_BIT 0 + +#endif diff --git a/converter/terminal_usb/keymap_102.c b/converter/terminal_usb/keymap_102.c new file mode 100644 index 0000000000..430570c47b --- /dev/null +++ b/converter/terminal_usb/keymap_102.c @@ -0,0 +1,208 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keycodes.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + + + +/* + * IBM Terminal keyboard 1392595(102keys) + * http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M + * http://www.seasip.info/VintagePC/ibm_1391406.html + * + * Keymap array: + * 8 bytes + * +---------+ + * 0| | + * :| | 0x00-0x87 + * ;| | + * 17| | + * +---------+ + */ +#define KEYMAP( \ + K08, K07,K0F,K17,K1F,K27,K2F,K37,K3F,K47,K4F,K56,K5E, K57,K5F,K62, \ + \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K5D,K66, K67,K6E,K6F, K76,K77,K7E,K84, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, K5C, K64,K65,K6D, K6C,K75,K7D,K7C, \ + K14,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K53,K5A, K6B,K73,K74,K7B, \ + K12,K13,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K51,K59, K63, K69,K72,K7A,K79, \ + K11, K19, K29, K39, K58, K61,K60,K6A, K68,K70,K71,K78 \ +) { \ + { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K07 }, \ + { KB_##K08, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K0D, KB_##K0E, KB_##K0F }, \ + { KB_NO, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_NO, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ + { KB_NO, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ + { KB_NO, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ + { KB_NO, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ + { KB_NO, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ + { KB_NO, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ + { KB_NO, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ + { KB_NO, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ + { KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_##K5E, KB_##K5F }, \ + { KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_##K67 }, \ + { KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_##K6D, KB_##K6E, KB_##K6F }, \ + { KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ + { KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \ + { KB_NO, KB_NO, KB_NO, KB_NO, KB_##K84, KB_NO, KB_NO, KB_NO, }, \ +} + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { + 1, // Fn0 + 2, // Fn1 + 3, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { + KB_SCLN, // Fn0 + KB_SLSH, // Fn1 + KB_ESC, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +}; + + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* 0: default + * ,---. ,---------------. ,---------------. ,---------------. ,-----------. + * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| + * `---' `---------------' `---------------' `---------------' `-----------' + * ,-----------------------------------------------------------. ,-----------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \|BS | |Ins|Hom|PgU| |NmL| /| *| -| + * |-----------------------------------------------------------| |-----------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | + * |-----------------------------------------------------------| `-----------' |-----------| +| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #|Retu| | 4| 5| 6| | + * |-----------------------------------------------------------| ,---. |---------------| + * |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------| ,-----------. |-----------|Ent| + * |Ctrl| |Alt | Space |Alt | |Ctrl| |Lef|Dow|Rig| | 0| .| | + * `----' `---------------------------------------' `----' `-----------' `---------------' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, + LCTL,A, S, D, F, G, H, J, K, L, FN0, QUOT, NUHS,ENT, P4, P5, P6, PCMM, + LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, FN1, RO, FN2, UP, P1, P2, P3, PENT, + LGUI, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO + ), + + /* 1: Mouse keys + * ,-----------------------------------------------------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| + * |-----------------------------------------------------------| + * |Tab |MwL|MwU|McU|WwU|WwR|MwL|MwD|MwU|MwR| | | | \| + * |-----------------------------------------------------------| + * |CapsLo| |McL|McD|McR| |McL|McD|McU|McR|Fn0| |Return | + * |-----------------------------------------------------------| + * |Shift |VoD|VoU|Mut|Mb2|Mb3|Mb2|Mb1|VoD|VoU|Mut|Shift | + * |-----------------------------------------------------------| + * |Ctrl | |Alt | Mb1 |Alt | |Ctrl| + * `-----' `--------------------------------------' `----' + * Mc = mouse cursor, Mw = mouse wheel, Mb = mouse button + * Vo = Volume, Mut = Mute + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, NO, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, + LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, NO, ENT, P4, P5, P6, PCMM, + LSFT,NO, VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE, NO, RSFT, UP, P1, P2, P3, PENT, + LGUI, LALT, BTN1, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO + ), + + /* 2: Cursor keys + * ,-----------------------------------------------------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| + * |-----------------------------------------------------------| + * |Tab |Hom|PgU| Up|PgU|End|Hom|PgD|PgU|End| | | | \| + * |-----------------------------------------------------------| + * |CapsLo| |Lef|Dow|Rig| |Lef|Dow| Up|Rig| | |Return | + * |-----------------------------------------------------------| + * |Shift | | | | | |Hom|PgD|PgU|End|Fn1|Shift | + * |-----------------------------------------------------------| + * |Ctrl | |Alt | Space |Alt | |Ctrl| + * `-----' `--------------------------------------' `----' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, NO, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, PMNS, + LCTL,NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, NO, ENT, P4, P5, P6, PCMM, + LSFT,NO, VOLD,VOLU,MUTE,NO, NO, HOME,PGDN,PGUP,END, FN1, NO, RSFT, UP, P1, P2, P3, PENT, + LGUI, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO + ), + + /* 3: HHKB + * ,-----------------------------------------------------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| + * |-----------------------------------------------------------| + * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs| + * |-----------------------------------------------------------| + * |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | + * |-----------------------------------------------------------| + * |Shift | | | | | | +| -|End|PgD|Dow|Fn2 | + * |-----------------------------------------------------------| + * |Ctrl | |Alt | Space |Alt | |Ctrl| + * `-----' `--------------------------------------' `----' + */ + KEYMAP( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, NO, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, + LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT, NO, ENT, P4, P5, P6, PCMM, + LSFT,NO, NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN, NO, FN2, UP, P1, P2, P3, PENT, + LGUI, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO + ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/converter/terminal_usb/keymap_122.c b/converter/terminal_usb/keymap_122.c new file mode 100644 index 0000000000..7a2168122f --- /dev/null +++ b/converter/terminal_usb/keymap_122.c @@ -0,0 +1,143 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keycodes.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + + + +/* + * IBM Terminal keyboard 1392595(102keys) + * http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M + * http://www.seasip.info/VintagePC/ibm_1391406.html + * + * Keymap array: + * 8 bytes + * +---------+ + * 0| | + * :| | 0x00-0x87 + * ;| | + * 17| | + * +---------+ + */ +#define KEYMAP( \ + K08,K10,K18,K20,K28,K30,K38,K40,K48,K50,K57,K5F, \ + K07,K0F,K17,K1F,K27,K2F,K37,K3F,K47,K4F,K56,K5E, \ + \ + K05,K06, K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K5D,K66, K67,K6E,K6F, K76,K77,K7E,K84, \ + K04,K0C, K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, K5C, K64,K65,K6D, K6C,K75,K7D,K7C, \ + K03,K0B, K14,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K53,K5A, K63, K6B,K73,K74,K7B, \ + K83,K0A, K12,K13,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K51,K59, K61,K62,K6A, K69,K72,K7A,K79, \ + K01,K09, K11, K19, K29, K39, K58, K60, K68,K70,K71,K78 \ +) { \ + { KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ + { KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ + { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ + { KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ + { KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ + { KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_##K5E, KB_##K5F }, \ + { KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_##K67 }, \ + { KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_##K6D, KB_##K6E, KB_##K6F }, \ + { KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ + { KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \ + { KB_NO, KB_NO, KB_NO, KB_##K83, KB_##K84, KB_NO, KB_NO, KB_NO, }, \ +} + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { + 0, // Fn0 + 0, // Fn1 + 0, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { + KB_NO, // Fn0 + KB_NO, // Fn1 + KB_NO, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +}; + + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* 0: default + * ,---. ,---------------. ,---------------. ,---------------. ,-----------. + * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| + * `---' `---------------' `---------------' `---------------' `-----------' + * ,-----------------------------------------------------------. ,-----------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \|BS | |Ins|Hom|PgU| |NmL| /| *| -| + * |-----------------------------------------------------------| |-----------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | + * |-----------------------------------------------------------| `-----------' |-----------| +| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #|Retu| | 4| 5| 6| | + * |-----------------------------------------------------------| ,---. |---------------| + * |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------| ,-----------. |-----------|Ent| + * |Ctrl| |Alt | Space |Alt | |Ctrl| |Lef|Dow|Rig| | 0| .| | + * `----' `---------------------------------------' `----' `-----------' `---------------' + */ + KEYMAP( + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, + F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, + + PSCR,ESC, GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + SLCK,INT4, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, + PAUS,INT5, CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, UP, P4, P5, P6, PCMM, + APP, INT6, LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RO, RSFT, LEFT,INT2,RGHT, P1, P2, P3, PENT, + RGUI,LGUI, LCTL, LALT, SPC, RALT, RCTL, DOWN, NO, P0, PDOT,NO + ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/converter/terminal_usb/led.c b/converter/terminal_usb/led.c new file mode 100644 index 0000000000..e448e84ec7 --- /dev/null +++ b/converter/terminal_usb/led.c @@ -0,0 +1,33 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdint.h" +#include "ps2.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + uint8_t ps2_led = 0; + if (usb_led & (1<<USB_LED_SCROLL_LOCK)) + ps2_led |= (1<<PS2_LED_SCROLL_LOCK); + if (usb_led & (1<<USB_LED_NUM_LOCK)) + ps2_led |= (1<<PS2_LED_NUM_LOCK); + if (usb_led & (1<<USB_LED_CAPS_LOCK)) + ps2_led |= (1<<PS2_LED_CAPS_LOCK); + ps2_host_set_led(ps2_led); +} diff --git a/converter/terminal_usb/matrix.c b/converter/terminal_usb/matrix.c new file mode 100644 index 0000000000..a6eff8c1ec --- /dev/null +++ b/converter/terminal_usb/matrix.c @@ -0,0 +1,226 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "debug.h" +#include "ps2.h" +#include "matrix.h" + + +static void matrix_make(uint8_t code); +static void matrix_break(uint8_t code); +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); +#endif + + +/* + * Matrix Array usage: + * 'Scan Code Set 3' is assigned into 17x8 cell matrix. + * + * 8bit wide + * +---------+ + * 0| | + * :| | 0x00-0x87 + * ;| | + * 17| | + * +---------+ + */ +static uint8_t matrix[MATRIX_ROWS]; +#define ROW(code) (code>>3) +#define COL(code) (code&0x07) + +static bool is_modified = false; + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + print_enable = true; + debug_enable = true; + //debug_matrix = true; + //debug_keyboard = true; + //debug_mouse = false; + + ps2_host_init(); + // Make and Break code without Typematic + while (ps2_host_send(0xF8) != 0xFA) { + debug("send F8: failed\n"); + _delay_ms(500); + } + debug("send F8: OK\n"); + + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; + + return; +} + +uint8_t matrix_scan(void) +{ + + // scan code reading states + static enum { + INIT, + F0, + } state = INIT; + + + is_modified = false; + + uint8_t code; + while ((code = ps2_host_recv())) { + debug_hex(code); + switch (state) { + case INIT: + switch (code) { + case 0xF0: + state = F0; + debug(" "); + break; + default: // normal key make + if (code < 0x88) { + matrix_make(code); + } else { + debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n"); + } + state = INIT; + debug("\n"); + } + break; + case F0: // Break code + switch (code) { + default: + if (code < 0x88) { + matrix_break(code); + } else { + debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); + } + state = INIT; + debug("\n"); + } + break; + } + } + return 1; +} + +bool matrix_is_modified(void) +{ + return is_modified; +} + +inline +bool matrix_has_ghost(void) +{ +#ifdef MATRIX_HAS_GHOST + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + if (matrix_has_ghost_in_row(i)) + return true; + } +#endif + return false; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & (1<<col)); +} + +inline +uint8_t matrix_get_row(uint8_t row) +{ + return matrix[row]; +} + +void matrix_print(void) +{ + print("\nr/c 01234567\n"); + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); + pbin_reverse(matrix_get_row(row)); +#ifdef MATRIX_HAS_GHOST + if (matrix_has_ghost_in_row(row)) { + print(" <ghost"); + } +#endif + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += bitpop(matrix[i]); + } + return count; +} + +#ifdef MATRIX_HAS_GHOST +inline +static bool matrix_has_ghost_in_row(uint8_t row) +{ + // no ghost exists in case less than 2 keys on + if (((matrix[row] - 1) & matrix[row]) == 0) + return false; + + // ghost exists in case same state as other row + for (uint8_t i=0; i < MATRIX_ROWS; i++) { + if (i != row && (matrix[i] & matrix[row]) == matrix[row]) + return true; + } + return false; +} +#endif + + +inline +static void matrix_make(uint8_t code) +{ + if (!matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] |= 1<<COL(code); + is_modified = true; + } +} + +inline +static void matrix_break(uint8_t code) +{ + if (matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] &= ~(1<<COL(code)); + is_modified = true; + } +} diff --git a/converter/x68k_usb/Makefile b/converter/x68k_usb/Makefile new file mode 100644 index 0000000000..c3b5fa29f3 --- /dev/null +++ b/converter/x68k_usb/Makefile @@ -0,0 +1,87 @@ +# +# Makefile for PJRC Teensy +# + + +# Target file name (without extension). +TARGET = x68k_usb_pjrc + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + x68k.c + +CONFIG_H = config_pjrc.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +AVRDUDE = avrdude +# Type: avrdude -c ? to get a full listing. +AVRDUDE_PROGRAMMER = avr109 +AVRDUDE_PORT = /dev/ttyACM0 +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +#AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + +#PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) +#PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex +PROGRAM_CMD = dfu-programmer atmega32u4 flash $(TARGET).hex + + + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/x68k_usb/README b/converter/x68k_usb/README new file mode 100644 index 0000000000..0b61b2c4b3 --- /dev/null +++ b/converter/x68k_usb/README @@ -0,0 +1,129 @@ +X68000 to USB keyboard protocol converter +========================================= +SHARP X68000 is a hobby computer released in Japan.(1987-93) +http://en.wikipedia.org/wiki/Sharp_X68000 + +X68000 keyboard has ALPS linear switches. +- DSETK0016CE01 green linear +- DSETK0023CE03 yellow linear + + +Hardware +-------- +Target MCU is ATMega32u4 but other USB capable AVR will also work. +You can use PJRC Teensy as dev board. + http://www.pjrc.com/teensy/ + +Wiring: + Mini-DIN Teensy + ----------------------------------------------------- + pin1 +5V VCC + pin2 MOUSE - + pin3 RXD PD2(RXD) + pin4 TXD PD3(TXD) NOTE: Not supported yet. + pin5 READY - + pin6 REMOTE - + pin7 GND GND + + +Firmware +-------- +Build: + $ cd x68k_usb + $ make + +And load the binary to MCU with your favorite programmer. +If you use Teensy you can load with PJRC Teensy Loader tool. + http://www.pjrc.com/teensy/loader.html + + +* * * * * * * * * * * * * * * * * * + + +X68000 Keyboard Protocol +======================== +http://kyoutan.jpn.org/uts/pc/pic/x68key/ + + +Connector +--------- +Mini DIN 7pin(female connector on computer side) + 7 6 5 + o o o + 4 o = o 3 + o o + 2 1 + + Mini-DIN + ------------- + pin1 +5V + pin2 MOUSE + pin3 RXD + pin4 TXD + pin5 READY + pin6 REMOTE + pin7 GND + + +Signaling +--------- +- TXD,RXD + Asynchronous, 2400baud, 1-startbit(L), 8-databit, 1-stopbit(H) + +- READY + ready/not ready(1/0) + + +Data from keyboard +------------------ +bit 7 make/break flag(0/1) +bit 6-0 following scan code + + +Data from computer +------------------ +- LED contorol ON/OFF(0/1) + bit 7 1(fixed) + bit 6 全角 + bit 5 ひらがな + bit 4 INS + bit 3 CAPS + bit 2 コード入力 + bit 1 ローマ字 + bit 0 かな + +- Repeat delay + bit 7 0(fixed) + bit 6 1(fixed) + bit 5 1(fixed) + bit 4 0(fixed) + bit 3-0 delay + REPEAT_DELAY = 200+delay*100 ms + default: 500ms + +- Repeat time + bit 7 0(fixed) + bit 6 1(fixed) + bit 5 1(fixed) + bit 4 1(fixed) + bit 3-0 time + REPEAT_TIME = 30+time^2*5 ms + default: 110ms + + +Scan Codes +---------- +,---. ,---. ,-------------------, ,-------------------. ,-----------. ,---------------. +| 61| | 62| | 63| 64| 65| 66| 67| | 68| 69| 6A| 6B| 6C| | 5A| 5B| 5C| | 5D| 52| 53| 54| +`---' `---' `-------------------' `-------------------' `-----------' `---------------' +,-----------------------------------------------------------. ,-----------. ,---------------. +| 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E| 0F| | 36| 5E| 37| | 3F| 40| 41| 42| +|-----------------------------------------------------------| |------------ |---------------| +| 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 1C| | | 38| 39| 3A| | 43| 44| 45| 46| +|------------------------------------------------------. 1D | `---=====---' |---------------| +| 71 | 1E| 1F| 20| 21| 2l| 23| 24| 25| 26| 27| 28| 29| | ___| 3C|___ | 47| 48| 49| 4A| +|-----------------------------------------------------------| | 3B|---| 3D| |-----------|---| +| 70 | 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 70 | `---| 3E|---' | 4B| 4C| 4D| | +`-----------------------------------------------------------| .---=====---. |-----------| 4E| + | 5F| 55 | 56 | 35 | 57 | 58 | 59 | 60| | 72 | 73 | | 4F| 50| 51| | + `---------------------------------------------' `-----------' `---------------' diff --git a/converter/x68k_usb/config_pjrc.h b/converter/x68k_usb/config_pjrc.h new file mode 100644 index 0000000000..20758bf249 --- /dev/null +++ b/converter/x68k_usb/config_pjrc.h @@ -0,0 +1,66 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6800 +#define MANUFACTURER t.m.k. +#define PRODUCT SHARP X68000 keyboard converter +#define DESCRIPTION converts SHARP X68000 keyboard protocol into USB + + +/* matrix size */ +#define MATRIX_ROWS 16 +#define MATRIX_COLS 8 + + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LALT) | MOD_BIT(KB_RALT)) || \ + keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +/* USART configuration + * asynchronous, 2400baud, 8-data bit, non parity, 1-stop bit, no flow control + */ +#ifdef __AVR_ATmega32U4__ +# define KBD_RX_VECT USART1_RX_vect +# define KBD_RX_DATA UDR1 +# define KBD_RX_BAUD 2400 +# define KBD_RX_UBBR ((F_CPU/(16UL*KBD_RX_BAUD))-1) +# define KBD_RX_INIT() do { \ + UBRR1L = (uint8_t) KBD_RX_UBBR; \ + UBRR1H = (uint8_t) (KBD_RX_UBBR>>8); \ + UCSR1B |= (1<<RXCIE1) | (1<<RXEN1); \ + } while(0) +#else +# error "USART configuration is needed." +#endif + +#endif diff --git a/converter/x68k_usb/keymap.c b/converter/x68k_usb/keymap.c new file mode 100644 index 0000000000..94c2aeee11 --- /dev/null +++ b/converter/x68k_usb/keymap.c @@ -0,0 +1,140 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keycodes.h" +#include "util.h" +#include "keymap.h" + + + + +// Following macros help you to define a keymap with the form of actual keyboard layout. + +/* X68000 Keyboard Scan codes + ,---. ,---. ,-------------------, ,-------------------. ,-----------. ,---------------. + | 61| | 62| | 63| 64| 65| 66| 67| | 68| 69| 6A| 6B| 6C| | 5A| 5B| 5C| | 5D| 52| 53| 54| + `---' `---' `-------------------' `-------------------' `-----------' `---------------' + ,-----------------------------------------------------------. ,-----------. ,---------------. + | 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E| 0F| | 36| 5E| 37| | 3F| 40| 41| 42| + |-----------------------------------------------------------| |------------ |---------------| + | 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 1C| | | 38| 39| 3A| | 43| 44| 45| 46| + |------------------------------------------------------. 1D | `---=====---' |---------------| + | 71 | 1E| 1F| 20| 21| 2l| 23| 24| 25| 26| 27| 28| 29| | ___| 3C|___ | 47| 48| 49| 4A| + |-----------------------------------------------------------| | 3B|---| 3D| |-----------|---| + | 70 | 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 70 | `---| 3E|---' | 4B| 4C| 4D| | + `-----------------------------------------------------------| .---=====---. |-----------| 4E| + | 5F| 55 | 56 | 35 | 57 | 58 | 59 | 60| | 72 | 73 | | 4F| 50| 51| | + `---------------------------------------------' `-----------' `---------------' +*/ +#define KEYMAP( \ + K61,K62, K63,K64,K65,K66,K67, K68,K69,K6A,K6B,K6C, K5A,K5B,K5C, K5D,K52,K53,K54, \ + K01,K02,K03,K04,K05,K06,K07,K08,K09,K0A,K0B,K0C,K0D,K0E,K0F, K36,K5E,K37, K3F,K40,K41,K42, \ + K10,K11,K12,K13,K14,K15,K16,K17,K18,K19,K1A,K1B,K1C, K1D, K38,K39,K3A, K43,K44,K45,K46, \ + K71,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27,K28,K29, K3C, K47,K48,K49,K4A, \ + K70,K2A,K2B,K2C,K2D,K2E,K2F,K30,K31,K32,K33,K34, K3B,K3E,K3D, K4B,K4C,K4D,K4E, \ + K5F,K55,K56, K35, K57,K58,K59,K60, K72, K73, K4F,K50,K51 \ +) { \ + { KB_NO, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ + { KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ + { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ + { KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ + { KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ + { KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_##K5E, KB_##K5F }, \ + { KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_##K67 }, \ + { KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_NO, KB_NO, KB_NO }, \ + { KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_NO, KB_NO, KB_NO, KB_NO, }, \ + { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO } \ +} + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { + 0, // Fn0 + 0, // Fn1 + 0, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { + KB_NO, // Fn0 + KB_NO, // Fn1 + KB_NO, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +}; + + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { +/* X68000 Keyboard Scan codes + ,---. ,---. ,-------------------, ,-------------------. ,-----------. ,---------------. + | 61| | 62| | 63| 64| 65| 66| 67| | 68| 69| 6A| 6B| 6C| | 5A| 5B| 5C| | 5D| 52| 53| 54| + `---' `---' `-------------------' `-------------------' `-----------' `---------------' + ,-----------------------------------------------------------. ,-----------. ,---------------. + | 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E| 0F| | 36| 5E| 37| | 3F| 40| 41| 42| + |-----------------------------------------------------------| |------------ |---------------| + | 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 1C| | | 38| 39| 3A| | 43| 44| 45| 46| + |------------------------------------------------------. 1D | `---=====---' |---------------| + | 71 | 1E| 1F| 20| 21| 2l| 23| 24| 25| 26| 27| 28| 29| | ___| 3C|___ | 47| 48| 49| 4A| + |-----------------------------------------------------------| | 3B|---| 3D| |-----------|---| + | 70 | 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 70 | `---| 3E|---' | 4B| 4C| 4D| | + `-----------------------------------------------------------| .---=====---. |-----------| 4E| + | 5F| 55 | 56 | 35 | 57 | 58 | 59 | 60| | 72 | 73 | | 4F| 50| 51| | + `---------------------------------------------' `-----------' `---------------' +*/ + KEYMAP( + NO, NO, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, PSCR,SLCK,PAUS, CAPS,NO, NO, NO, + ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, ENT, DEL, END, PGDN, P7, P8, P9, PPLS, + LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, UP, P4, P5, P6, PEQL, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,GRV, LEFT,DOWN,RGHT, P1, P2, P3, PENT, + LGUI,LALT,NO, SPC, RALT,RGUI,RCTL,APP, NO, NO, P0, PCMM,PDOT + ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/converter/x68k_usb/led.c b/converter/x68k_usb/led.c new file mode 100644 index 0000000000..40156cf4ac --- /dev/null +++ b/converter/x68k_usb/led.c @@ -0,0 +1,26 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdint.h" +#include "x68k.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + // not supported now +} diff --git a/converter/x68k_usb/matrix.c b/converter/x68k_usb/matrix.c new file mode 100644 index 0000000000..954e7ef129 --- /dev/null +++ b/converter/x68k_usb/matrix.c @@ -0,0 +1,141 @@ +/* +Copyright 2012 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "x68k.h" +#include "matrix.h" + + +/* + * Matrix Array usage: + * + * ROW: 16(4bits) + * COL: 8(3bits) + * + * 8bit wide + * +---------+ + * 0|00 ... 07| + * 1|08 ... 0F| + * :| ... | + * :| ... | + * E|70 ... 77| + * F|78 ... 7F| + * +---------+ + * + */ +static uint8_t matrix[MATRIX_ROWS]; +#define ROW(code) ((code>>3)&0xF) +#define COL(code) (code&0x07) + +static bool is_modified = false; + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + x68k_init(); + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; + + return; +} + +uint8_t matrix_scan(void) +{ + is_modified = false; + + uint8_t code; + code = x68k_recv(); + if (code == 0) { + return 0; + } + + phex(code); print(" "); + if (code&0x80) { + // break code + if (matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] &= ~(1<<COL(code)); + is_modified = true; + } + } else { + // make code + if (!matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] |= (1<<COL(code)); + is_modified = true; + } + } + return code; +} + +bool matrix_is_modified(void) +{ + return is_modified; +} + +inline +bool matrix_has_ghost(void) +{ + return false; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & (1<<col)); +} + +inline +uint8_t matrix_get_row(uint8_t row) +{ + return matrix[row]; +} + +void matrix_print(void) +{ + print("\nr/c 01234567\n"); + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); + pbin_reverse(matrix_get_row(row)); + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += bitpop(matrix[i]); + } + return count; +} |