integrate V-USB support into ps2_usb
27 files changed, 176 insertions(+), 1183 deletions(-) M Makefile.rules M command.c D key_process.c D key_process.h M keyboard.c R {keymap_skel => keymap}.h M layer.c A main_pjrc.c R {matrix_skel => matrix}.h M ps2.c M ps2_usb/Makefile R ps2_vusb/Makefile => ps2_usb/Makefile.vusb M ps2_usb/README R ps2_usb/{config => config_pjrc}.h R {ps2_vusb/config => ps2_usb/config_vusb}.h M ps2_usb/keymap.c R {ps2_vusb => ps2_usb}/led.c R {ps2_vusb/main => ps2_usb/main_vusb}.c M ps2_usb/matrix.c R {ps2_vusb => ps2_usb}/ps2_usart.c R {ps2_vusb => ps2_usb}/sendchar_dummy.c R {ps2_vusb => ps2_usb}/sendchar_usart.c R {ps2_vusb => ps2_usb}/usbconfig.h D ps2_vusb/README D ps2_vusb/keymap.c D ps2_vusb/matrix.c M tmk.c
M Makefile.rules => Makefile.rules +5 -6
@@ 47,7 47,7 @@ FORMAT = ihex # Object files directory # To put object files in current directory, use a dot (.), do NOT make # this an empty or blank macro! OBJDIR = obj OBJDIR = obj_$(TARGET) @@ # Optimization level, can be [0, 1, 2, 3, s]. 121,7 121,7 @@ CFLAGS += -Wstrict-prototypes CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) CFLAGS += $(CSTANDARD) CFLAGS += -include config.h CFLAGS += -include $(CONFIG_H) @@ #---------------- Compiler Options C++ ---------------- 149,7 149,7 @@ CPPFLAGS += -Wundef CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) #CPPFLAGS += $(CSTANDARD) CPPFLAGS += -include config.h CPPFLAGS += -include $(CONFIG_H) @@ #---------------- Assembler Options ---------------- 162,7 162,7 @@ CPPFLAGS += -include config.h # -listing-cont-lines: Sets the maximum number of continuation lines of hex # dump that will be displayed for a given single line of source input. ASFLAGS = $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100 ASFLAGS += -include config.h ASFLAGS += -include $(CONFIG_H) @@ #---------------- Library Options ---------------- 273,7 273,6 @@ OBJDUMP = avr-objdump SIZE = avr-size AR = avr-ar rcs NM = avr-nm AVRDUDE = avrdude REMOVE = rm -f REMOVEDIR = rmdir @@ COPY = cp 377,7 376,7 @@ gccversion : # Program the device. program: $(TARGET).hex $(TARGET).eep $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) $(PROGRAM_CMD) # Generate avr-gdb config/init file which does the following:
M command.c => command.c +3 -1
@@ 8,7 8,7 @@ #include "util.h" #include "timer.h" #include "layer.h" #include "matrix_skel.h" #include "matrix.h" #include "command.h" @@ #ifdef HOST_PJRC 107,6 107,8 @@ uint8_t command_proc(void) break; #ifdef USB_NKRO_ENABLE case KB_N: host_clear_keyboard_report(); host_send_keyboard_report(); keyboard_nkro = !keyboard_nkro; if (keyboard_nkro) print("USB_NKRO: enabled\n");
D key_process.c => key_process.c +0 -392
@@ 1,392 0,0 @@ #include <stdbool.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "print.h" #include "debug.h" #include "timer.h" #include "util.h" #include "jump_bootloader.h" #include "usb_keyboard.h" #include "usb_keycodes.h" #include "usb.h" #include "layer.h" #include "matrix_skel.h" #include "keymap_skel.h" #include "key_process.h" #ifdef MOUSEKEY_ENABLE # include "mousekey.h" #endif #ifdef PS2_MOUSE_ENABLE # include "ps2_mouse.h" #endif #ifdef USB_EXTRA_ENABLE # include "usb_extra.h" #endif #ifdef USB_MOUSE_ENABLE # include "usb_mouse.h" #endif // TODO: refactoring void proc_matrix(void) { bool modified = false; uint8_t fn_bits = 0; matrix_scan(); modified = matrix_is_modified(); if (modified) { if (debug_matrix) matrix_print(); #ifdef DEBUG_LED // LED flash for debug DEBUG_LED_CONFIG; DEBUG_LED_ON; #endif } if (matrix_has_ghost()) { // should send error? debug("matrix has ghost!!\n"); return; } usb_keyboard_swap_report(); usb_keyboard_clear_report(); for (int row = 0; row < matrix_rows(); row++) { for (int col = 0; col < matrix_cols(); col++) { if (!matrix_is_on(row, col)) continue; uint8_t code = layer_get_keycode(row, col); if (code == KB_NO) { // do nothing } else if (IS_MOD(code)) { usb_keyboard_add_mod(code); } else if (IS_FN(code)) { fn_bits |= FN_BIT(code); } #ifdef MOUSEKEY_ENABLE else if (IS_MOUSEKEY(code)) { mousekey_decode(code); } #endif #ifdef USB_EXTRA_ENABLE // audio control & system control else if (code == KB_MUTE) { usb_extra_audio_send(AUDIO_MUTE); usb_extra_audio_send(0); _delay_ms(500); } else if (code == KB_VOLU) { usb_extra_audio_send(AUDIO_VOL_UP); usb_extra_audio_send(0); _delay_ms(200); } else if (code == KB_VOLD) { usb_extra_audio_send(AUDIO_VOL_DOWN); usb_extra_audio_send(0); _delay_ms(200); } else if (code == KB_PWR) { if (suspend && remote_wakeup) { usb_remote_wakeup(); } else { usb_extra_system_send(SYSTEM_POWER_DOWN); } _delay_ms(1000); } #endif // normal key else if (IS_KEY(code)) { usb_keyboard_add_key(code); } else { debug("ignore keycode: "); debug_hex(code); debug("\n"); } } } if (modified) { #ifdef DEBUG_LED // LED flash for debug DEBUG_LED_CONFIG; DEBUG_LED_OFF; #endif } layer_switching(fn_bits); // TODO: clean code // special mode for control, develop and debug if (keymap_is_special_mode(fn_bits)) { switch (usb_keyboard_get_key()) { case KB_H: // help usb_keyboard_clear_report(); usb_keyboard_send(); print_enable = true; print("b: jump to bootloader\n"); print("d: toggle debug enable\n"); print("x: toggle matrix debug\n"); print("k: toggle keyboard debug\n"); print("m: toggle mouse debug\n"); print("p: toggle print enable\n"); print("v: print version\n"); print("t: print timer count\n"); print("s: print status\n"); print("`: toggle protcol(boot/report)\n"); #ifdef USB_NKRO_ENABLE print("n: toggle USB_NKRO\n"); #endif print("Backspace: clear matrix\n"); print("ESC: power down/wake up\n"); print("0: switch to Layer0 \n"); print("1: switch to Layer1 \n"); print("2: switch to Layer2 \n"); print("3: switch to Layer3 \n"); print("4: switch to Layer4 \n"); #ifdef PS2_MOUSE_ENABLE print("[: ps2_mouse_init \n"); print("]: ps2_mouse_read \n"); print("\: ps2_mouse: on/off toggle \n"); #endif _delay_ms(500); print_enable = false; break; case KB_BSPC: usb_keyboard_clear_report(); usb_keyboard_send(); matrix_init(); print("clear matrix\n"); _delay_ms(500); break; case KB_0: usb_keyboard_clear_report(); usb_keyboard_send(); print("current_layer: "); phex(current_layer); print("\n"); print("default_layer: "); phex(default_layer); print("\n"); current_layer = 0; default_layer = 0; print("switch to Layer0 \n"); _delay_ms(500); break; case KB_1: usb_keyboard_clear_report(); usb_keyboard_send(); print("current_layer: "); phex(current_layer); print("\n"); print("default_layer: "); phex(default_layer); print("\n"); current_layer = 1; default_layer = 1; print("switch to Layer1 \n"); _delay_ms(500); break; case KB_2: usb_keyboard_clear_report(); usb_keyboard_send(); print("current_layer: "); phex(current_layer); print("\n"); print("default_layer: "); phex(default_layer); print("\n"); current_layer = 2; default_layer = 2; print("switch to Layer2 \n"); _delay_ms(500); break; case KB_3: usb_keyboard_clear_report(); usb_keyboard_send(); print("current_layer: "); phex(current_layer); print("\n"); print("default_layer: "); phex(default_layer); print("\n"); current_layer = 3; default_layer = 3; print("switch to Layer3 \n"); _delay_ms(500); break; case KB_4: usb_keyboard_clear_report(); usb_keyboard_send(); print("current_layer: "); phex(current_layer); print("\n"); print("default_layer: "); phex(default_layer); print("\n"); current_layer = 4; default_layer = 4; print("switch to Layer4 \n"); _delay_ms(500); break; #ifdef PS2_MOUSE_ENABLE case KB_LBRC: usb_keyboard_clear_report(); usb_keyboard_send(); print_enable = true; print("ps2_mouse_init...\n"); _delay_ms(500); ps2_mouse_init(); break; case KB_RBRC: usb_keyboard_clear_report(); usb_keyboard_send(); print_enable = true; print("ps2_mouse_read[btn x y]: "); _delay_ms(100); ps2_mouse_read(); phex(ps2_mouse_btn); print(" "); phex(ps2_mouse_x); print(" "); phex(ps2_mouse_y); print("\n"); print("ps2_mouse_error_count: "); phex(ps2_mouse_error_count); print("\n"); break; case KB_BSLS: ps2_mouse_enable = !ps2_mouse_enable; print("ps2_mouse: "); if (ps2_mouse_enable) print("on"); else print("off"); print("\n"); _delay_ms(500); break; #endif case KB_B: // bootloader usb_keyboard_clear_report(); usb_keyboard_send(); print_enable = true; print("jump to bootloader...\n"); _delay_ms(1000); jump_bootloader(); // not return break; case KB_D: // debug all toggle usb_keyboard_clear_report(); usb_keyboard_send(); debug_enable = !debug_enable; if (debug_enable) { print_enable = true; print("debug enabled.\n"); //debug_matrix = true; //debug_keyboard = true; //debug_mouse = true; } else { print("debug disabled.\n"); print_enable = false; //debug_matrix = false; //debug_keyboard = false; //debug_mouse = false; } _delay_ms(1000); break; case KB_X: // debug matrix toggle usb_keyboard_clear_report(); usb_keyboard_send(); debug_matrix = !debug_matrix; if (debug_matrix) print("debug matrix enabled.\n"); else print("debug matrix disabled.\n"); _delay_ms(1000); break; case KB_K: // debug keyboard toggle usb_keyboard_clear_report(); usb_keyboard_send(); debug_keyboard = !debug_keyboard; if (debug_keyboard) print("debug keyboard enabled.\n"); else print("debug keyboard disabled.\n"); _delay_ms(1000); break; case KB_M: // debug mouse toggle usb_keyboard_clear_report(); usb_keyboard_send(); debug_mouse = !debug_mouse; if (debug_mouse) print("debug mouse enabled.\n"); else print("debug mouse disabled.\n"); _delay_ms(1000); break; case KB_V: // print version & information usb_keyboard_clear_report(); usb_keyboard_send(); print_enable = true; print(STR(DESCRIPTION) "\n"); _delay_ms(1000); break; case KB_T: // print timer usb_keyboard_clear_report(); usb_keyboard_send(); print_enable = true; print("timer: "); phex16(timer_count); print("\n"); _delay_ms(500); break; case KB_P: // print toggle usb_keyboard_clear_report(); usb_keyboard_send(); if (print_enable) { print("print disabled.\n"); print_enable = false; } else { print_enable = true; print("print enabled.\n"); } _delay_ms(1000); break; case KB_S: usb_keyboard_clear_report(); usb_keyboard_send(); print("UDCON: "); phex(UDCON); print("\n"); print("UDIEN: "); phex(UDIEN); print("\n"); print("UDINT: "); phex(UDINT); print("\n"); print("usb_keyboard_leds:"); phex(usb_keyboard_leds); print("\n"); print("usb_keyboard_protocol:"); phex(usb_keyboard_protocol); print("\n"); print("usb_keyboard_idle_config:"); phex(usb_keyboard_idle_config); print("\n"); print("usb_keyboard_idle_count:"); phex(usb_keyboard_idle_count); print("\n"); #ifdef USB_MOUSE_ENABLE print("usb_mouse_protocol:"); phex(usb_mouse_protocol); print("\n"); #endif if (usb_keyboard_nkro) print("USB_NKRO: enabled\n"); else print("USB_NKRO: disabled\n"); _delay_ms(500); break; case KB_GRV: usb_keyboard_clear_report(); usb_keyboard_send(); usb_keyboard_protocol = !usb_keyboard_protocol; print("keyboard protcol: "); if (usb_keyboard_protocol) print("report"); else print("boot"); print("\n"); #ifdef USB_MOUSE_ENABLE usb_mouse_protocol = !usb_mouse_protocol; print("mouse protcol: "); if (usb_mouse_protocol) print("report"); else print("boot"); print("\n"); #endif _delay_ms(1000); break; #ifdef USB_NKRO_ENABLE case KB_N: usb_keyboard_clear_report(); usb_keyboard_send(); usb_keyboard_nkro = !usb_keyboard_nkro; if (usb_keyboard_nkro) print("USB_NKRO: enabled\n"); else print("USB_NKRO: disabled\n"); _delay_ms(1000); break; #endif #ifdef USB_EXTRA_ENABLE case KB_ESC: usb_keyboard_clear_report(); usb_keyboard_send(); if (suspend && remote_wakeup) { usb_remote_wakeup(); } else { usb_extra_system_send(SYSTEM_POWER_DOWN); } _delay_ms(1000); break; #endif } } if (modified) { usb_keyboard_send(); } #ifdef MOUSEKEY_ENABLE mousekey_usb_send(); #endif #ifdef PS2_MOUSE_ENABLE if (ps2_mouse_read() == 0) ps2_mouse_usb_send(); #endif }
D key_process.h => key_process.h +0 -7
M keyboard.c => keyboard.c +6 -4
@@ 1,7 1,7 @@ #include "keyboard.h" #include "host.h" #include "layer.h" #include "matrix_skel.h" #include "matrix.h" #include "led.h" #include "usb_keycodes.h" @@ #include "timer.h" 11,6 11,11 @@ #ifdef MOUSEKEY_ENABLE #include "mousekey.h" #endif /* TODO: shoud make new API */ #ifdef USB_EXTRA_ENABLE #include "usb_extra.h" #include <util/delay.h> #endif @@ static uint8_t last_leds = 0; 61,7 66,6 @@ void keyboard_proc(void) fn_bits |= FN_BIT(code); } #ifdef USB_EXTRA_ENABLE /* TODO: use new API // audio control & system control else if (code == KB_MUTE) { @@ usb_extra_audio_send(AUDIO_MUTE); 83,7 87,6 @@ void keyboard_proc(void) } _delay_ms(1000); } */ #endif else if (IS_KEY(code)) { @@ host_add_key(code); 102,7 105,6 @@ void keyboard_proc(void) layer_switching(fn_bits); if (command_proc()) { // not send report return; }
R keymap_skel.h => keymap.h +2 -5
@@ 1,5 1,5 @@ #ifndef KEYMAP_SKEL_H #define KEYMAP_SKEL_H 1 #ifndef KEYMAP_H #define KEYMAP_H #include <stdint.h> @@ #include <stdbool.h> 15,7 15,4 @@ uint8_t keymap_fn_layer(uint8_t fn_bits); /* keycode to send when release Fn key without using */ uint8_t keymap_fn_keycode(uint8_t fn_bits); /* whether special key combination */ bool keymap_is_special_mode(uint8_t fn_bits); #endif
M layer.c => layer.c +1 -1
@@ 1,4 1,4 @@ #include "keymap_skel.h" #include "keymap.h" #include "host.h" #include "debug.h" #include "timer.h"
A main_pjrc.c => main_pjrc.c +97 -0
@@ 0,0 1,97 @@ /* 2010/08/23 noname * keyboard firmware based on PJRC USB keyboard example */ /* Keyboard example with debug channel, for Teensy USB Development Board * http://www.pjrc.com/teensy/usb_keyboard.html * Copyright (c) 2008 PJRC.COM, LLC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include <stdbool.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "keyboard.h" #include "usb.h" #include "matrix.h" #include "print.h" #include "debug.h" #include "util.h" #include "jump_bootloader.h" #ifdef PS2_MOUSE_ENABLE # include "ps2_mouse.h" #endif #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) bool debug_enable = false; bool debug_matrix = false; bool debug_keyboard = false; bool debug_mouse = false; int main(void) { DEBUG_LED_CONFIG; DEBUG_LED_OFF; // set for 16 MHz clock CPU_PRESCALE(0); // Initialize the USB, and then wait for the host to set configuration. // If the Teensy is powered without a PC connected to the USB port, // this will wait forever. usb_init(); while (!usb_configured()) /* wait */ ; keyboard_init(); matrix_scan(); if (matrix_key_count() >= 3) { #ifdef DEBUG_LED for (int i = 0; i < 6; i++) { DEBUG_LED_CONFIG; DEBUG_LED_ON; _delay_ms(500); DEBUG_LED_OFF; _delay_ms(500); } #else _delay_ms(5000); #endif print_enable = true; debug_enable = true; debug_matrix = true; debug_keyboard = true; debug_mouse = true; print("debug enabled.\n"); } if (matrix_key_count() >= 4) { print("jump to bootloader...\n"); _delay_ms(1000); jump_bootloader(); // not return } while (1) { keyboard_proc(); } }
R matrix_skel.h => matrix.h +2 -2
@@ 1,5 1,5 @@ #ifndef MATRIX_SKEL_H #define MATRIX_SKEL_H 1 #ifndef MATRIX_H #define MATRIX_H #include <stdbool.h>
M ps2.c => ps2.c +10 -2
@@ 187,6 187,9 @@ static inline void pbuf_enqueue(uint8_t data) { if (!data) return; uint8_t sreg = SREG; cli(); uint8_t next = (pbuf_head + 1) % PBUF_SIZE; if (next != pbuf_tail) { @@ pbuf[pbuf_head] = data; 194,10 197,12 @@ static inline void pbuf_enqueue(uint8_t data) } else { debug("pbuf: full\n"); } SREG = sreg; } static inline uint8_t pbuf_dequeue(void) { uint8_t val = 0; uint8_t sreg = SREG; cli(); @@ if (pbuf_head != pbuf_tail) { 205,17 210,20 @@ static inline uint8_t pbuf_dequeue(void) pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; } SREG = sreg; return val; } /* get data received by interrupt */ uint8_t ps2_host_recv(void) { // TODO: release clock line after 100us when inhibited by error if (ps2_error) { print("x"); phex(ps2_error); ps2_host_send(0xFE); // request to resend ps2_error = PS2_ERR_NONE; } idle(); return pbuf_dequeue(); } @@ 281,7 289,7 @@ ISR(PS2_INT_VECT) } goto RETURN; ERROR: DEBUGP(0xFF); DEBUGP(0x0F); inhibit(); ps2_error = state; DONE:
M ps2_usb/Makefile => ps2_usb/Makefile +13 -43
@@ 1,46 1,5 @@ # Hey Emacs, this is a -*- makefile -*- #---------------------------------------------------------------------------- # WinAVR Makefile Template written by Eric B. Weddington, J�rg Wunsch, et al. # # Released to the Public Domain # # Additional material for this makefile was written by: # Peter Fleury # Tim Henigan # Colin O'Flynn # Reiner Patommel # Markus Pfaff # Sander Pool # Frederik Rouleau # Carlos Lamas # #---------------------------------------------------------------------------- # On command line: # # make all = Make software. # # make clean = Clean out built project files. # # make coff = Convert ELF to AVR COFF. # # make extcoff = Convert ELF to AVR Extended COFF. # # make program = Download the hex file to the device, using avrdude. # Please customize the avrdude settings below first! # # make debug = Start either simulavr or avarice as specified for debugging, # with avr-gdb or avr-insight as the front end for debugging. # # make filename.s = Just compile filename.c into the assembler code only. # # make filename.i = Create a preprocessed source file for use in submitting # bug reports to the GCC project. # # To rebuild project do "make clean" then "make all". #---------------------------------------------------------------------------- # Target file name (without extension). TARGET = tmk_ps2_usb TARGET = ps2_usb # Directory common source filess exist @@ COMMON_DIR = .. 49,10 8,14 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files TARGET_SRC = keymap.c \ TARGET_SRC = main_pjrc.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 78,4 41,11 @@ USB_EXTRA_ENABLE = yes # Enhanced feature for Windows(Audio control and System c USB_NKRO_ENABLE = yes # USB Nkey Rollover #---------------- Programming Options -------------------------- PROGRAM_CMD = teensy_loader_cli.exe -mmcu=$(MCU) -w -v $(TARGET).hex include $(COMMON_DIR)/Makefile.pjrc include $(COMMON_DIR)/Makefile.common
R ps2_vusb/Makefile => ps2_usb/Makefile.vusb +8 -2
@@ 8,7 8,7 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files TARGET_SRC = main.c \ TARGET_SRC = main_vusb.c \ keymap.c \ matrix.c \ @@ led.c \ 16,6 16,9 @@ TARGET_SRC = main.c \ sendchar_dummy.c # sendchar_usart.c CONFIG_H = config_vusb.h OPT_DEFS = -DDEBUG_LEVEL=0 @@ 45,7 48,8 @@ MOUSEKEY_ENABLE = yes # Mouse keys #---------------- Programming Options (avrdude) ---------------- #---------------- Programming Options -------------------------- AVRDUDE = avrdude # Type: avrdude -c ? to get a full listing. AVRDUDE_PROGRAMMER = usbasp @@ AVRDUDE_PORT = 72,6 76,8 @@ 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 $(COMMON_DIR)/Makefile.vusb
M ps2_usb/README => ps2_usb/README +12 -3
@@ 47,10 47,10 @@ Keymap customization You can customize keymaps easily by editing source code. Build ----- Build for Teensy ---------------- 0. Connect PS/2 keyboard to Teensy by 4 lines(Vcc, GND, Data, Clock). 1. Define following macros for PS/2 connection in config.h: 1. Define following macros for PS/2 connection in config_pjrc.h: PS2_DATA_PORT PS2_DATA_PIN @@ PS2_DATA_DDR 65,6 65,15 @@ Build http://www.pjrc.com/teensy/loader.html Build for V-USB --------------- 0. Build V-USB controller board and connect PS/2 keyboard. 1. Define macros in config_vusb.h if needed. 2. Edit Makefile.vusb for build options and MCU setting. 3. make -f Makefile.vusb 4. program your V-USB controller. Keymap ------ You can change a keymap by editing code of keymap.c like following.
R ps2_usb/config.h => ps2_usb/config_pjrc.h +10 -6
@@ 10,22 10,26 @@ #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 /* define if matrix has ghost */ //#define MATRIX_HAS_GHOST /* USB NKey Rollover */ #ifdef USB_NKRO_ENABLE #endif /* key combination for command */ #define IS_COMMAND() ( \ keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ ) /* mouse keys */ #ifdef MOUSEKEY_ENABLE # define MOUSEKEY_DELAY_TIME 255 #endif /* PS/2 mouse */ /* PS/2 lines */ #define PS2_CLOCK_PORT PORTF #define PS2_CLOCK_PIN PINF #define PS2_CLOCK_DDR DDRF
R ps2_vusb/config.h => ps2_usb/config_vusb.h +2 -4
@@ 10,10 10,12 @@ #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 == (BIT_LSHIFT | BIT_RSHIFT) || \ 21,10 23,6 @@ ) /* USB NKey Rollover */ #ifdef USB_NKRO_ENABLE #endif /* mouse keys */ #ifdef MOUSEKEY_ENABLE # define MOUSEKEY_DELAY_TIME 255
M ps2_usb/keymap.c => ps2_usb/keymap.c +1 -8
@@ 4,12 4,11 @@ #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_skel.h" #include "keymap.h" @@ #define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) 181,9 180,3 @@ uint8_t keymap_fn_keycode(uint8_t fn_bits) { return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); } // define a condition to enter special function mode bool keymap_is_special_mode(uint8_t fn_bits) { return usb_keyboard_mods == (BIT_LSHIFT | BIT_RSHIFT) || usb_keyboard_mods == (BIT_LCTRL | BIT_RSHIFT); }
R ps2_vusb/led.c => ps2_usb/led.c +0 -0
R ps2_vusb/main.c => ps2_usb/main_vusb.c +1 -1
@@ 46,10 46,10 @@ int main(void) _delay_ms(1); } usbDeviceConnect(); sei(); keyboard_init(); sei(); while (1) { DEBUGP(0x1); wdt_reset();
M ps2_usb/matrix.c => ps2_usb/matrix.c +1 -49
@@ 9,8 9,7 @@ #include "util.h" #include "debug.h" #include "ps2.h" #include "usb_keyboard.h" #include "matrix_skel.h" #include "matrix.h" @@ #if (MATRIX_COLS > 16) 60,8 59,6 @@ static bool matrix_has_ghost_in_row(uint8_t row); #endif static void matrix_make(uint8_t code); static void matrix_break(uint8_t code); static void ps2_reset(void); static void ps2_set_leds(uint8_t leds); @@ inline 78,20 75,8 @@ uint8_t matrix_cols(void) void matrix_init(void) { print_enable = true; ps2_host_init(); ps2_reset(); // flush LEDs ps2_set_leds(1<<PS2_LED_NUM_LOCK); _delay_ms(100); ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK); _delay_ms(100); ps2_set_leds(1<<PS2_LED_NUM_LOCK|1<<PS2_LED_CAPS_LOCK|1<<PS2_LED_SCROLL_LOCK); _delay_ms(300); ps2_set_leds(0x00); // initialize matrix state: all keys off for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; @@ 191,7 176,6 @@ uint8_t matrix_scan(void) uint8_t code; while ((code = ps2_host_recv())) { debug_hex(code); debug(" "); switch (state) { case INIT: @@ switch (code) { 349,22 333,6 @@ debug_hex(code); debug(" "); state = INIT; } } // handle LED indicators static uint8_t prev_leds = 0; if (prev_leds != usb_keyboard_leds) { uint8_t leds = 0; if (usb_keyboard_leds&(1<<USB_LED_SCROLL_LOCK)) leds |= (1<<PS2_LED_SCROLL_LOCK); if (usb_keyboard_leds&(1<<USB_LED_NUM_LOCK)) leds |= (1<<PS2_LED_NUM_LOCK); if (usb_keyboard_leds&(1<<USB_LED_CAPS_LOCK)) leds |= (1<<PS2_LED_CAPS_LOCK); ps2_set_leds(leds); prev_leds = usb_keyboard_leds; } return 1; } @@ 472,19 440,3 @@ static void matrix_break(uint8_t code) is_modified = true; } } static void ps2_reset(void) { ps2_host_send(0xFF); ps2_host_recv(); // 0xFA ps2_host_recv(); // 0xAA _delay_ms(1000); } static void ps2_set_leds(uint8_t leds) { ps2_host_send(0xED); ps2_host_recv(); // 0xFA ps2_host_send(leds); ps2_host_recv(); // 0xFA }
R ps2_vusb/ps2_usart.c => ps2_usb/ps2_usart.c +0 -0
R ps2_vusb/sendchar_dummy.c => ps2_usb/sendchar_dummy.c +0 -0
R ps2_vusb/sendchar_usart.c => ps2_usb/sendchar_usart.c +0 -0
R ps2_vusb/usbconfig.h => ps2_usb/usbconfig.h +1 -1
@@ 11,7 11,7 @@ #ifndef __usbconfig_h_included__ #define __usbconfig_h_included__ #include "config.h" #include "config_vusb.h" /* General Description:
D ps2_vusb/README => ps2_vusb/README +0 -12
@@ 1,12 0,0 @@ PS/2 to USB keyboard converter with V-USB ========================================= 2011/02/07 NOT COMPLETED development was suspended. TODO: PS/2 library: losts data from keyboard occasionally, should use interrupt thoroughly for communication. Code cleaning: merge code changed here to other subprojects and common modules.
D ps2_vusb/keymap.c => ps2_vusb/keymap.c +0 -189
@@ 1,189 0,0 @@ /* * Keymap for PS/2 keyboard */ #include <stdint.h> #include <stdbool.h> #include <avr/pgmspace.h> #include "usb_keycodes.h" #include "host.h" #include "print.h" #include "debug.h" #include "util.h" #include "keymap_skel.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. #define KEYMAP( \ K76, K05,K06,K04,K0C, K03,K0B,K83,K0A, K01,K09,K78,K07, KFC,K7E,KFE, KB7,KBF,KDE, \ 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 \ ) { \ { KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ { KB_NO, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_NO }, \ { KB_NO, KB_##K11, KB_##K12, KB_NO, KB_##K14, KB_##K15, KB_##K16, KB_NO }, \ { KB_NO, KB_NO, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_NO }, \ { KB_NO, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ { KB_NO, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_NO }, \ { KB_NO, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_NO }, \ { KB_NO, KB_NO, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \ { KB_NO, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ { KB_NO, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_NO }, \ { KB_NO, KB_NO, KB_##K52, KB_NO, KB_##K54, KB_##K55, KB_NO, KB_NO }, \ { KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_NO, KB_##K5D, KB_NO, KB_NO }, \ { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K66, KB_NO }, \ { KB_NO, KB_##K69, KB_NO, 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_NO, KB_##K91, KB_NO, KB_NO, KB_##K94, KB_NO, KB_NO, KB_NO }, \ { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K9F }, \ { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KA7 }, \ { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KAF }, \ { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KB7 }, \ { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KBF }, \ { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ { KB_NO, KB_NO, KB_##KCA, 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_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 }, \ } // 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 5, // 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_A, // 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] = { /* 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| .| | * `-----------------------------------------------------------' `-----------' `---------------' */ /* 0: default */ 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,FN2, 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 */ 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 ), /* 2: Colemak http://colemak.com */ 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, 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 */ 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, 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/ */ 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, 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 */ KEYMAP( ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14, 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,FN2, 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 */ KEYMAP( ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14, 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 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))]); } // define a condition to enter special function mode bool keymap_is_special_mode(uint8_t fn_bits) { return host_get_mods() == (BIT_LSHIFT | BIT_RSHIFT) || host_get_mods() == (BIT_LCTRL | BIT_RSHIFT); }
D ps2_vusb/matrix.c => ps2_vusb/matrix.c +0 -444
@@ 1,444 0,0 @@ /* * 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 "ps2.h" #include "matrix_skel.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 /* * Matrix usage: * "PS/2 Scan Codes Set 2" is assigned to 256(32x8)cells matrix. * Hmm, It is very sparse and not efficient :( * * 8bit * --------- * 0| | * :| XX | 00-7F for normal codes(without E0-prefix) * f|_________| * 10| | * :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code) * 1f| | * --------- * exceptions: * 83: F8[0x83](normal codes but > 0x7F) * FC: PrintScreen[E0 7C or 84] * FE: Puause */ #define F8 (0x83) #define PRINT_SCREEN (0xFC) #define PAUSE (0xFE) #define ROW(code) (code>>3) #define COL(code) (code&0x07) static bool is_modified = false; // matrix state buffer(1:on, 0:off) #if (MATRIX_COLS <= 8) static uint8_t matrix[MATRIX_ROWS]; #else static uint16_t matrix[MATRIX_ROWS]; #endif #ifdef MATRIX_HAS_GHOST static bool matrix_has_ghost_in_row(uint8_t row); #endif static void matrix_make(uint8_t code); static void matrix_break(uint8_t code); 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. * * References: * http://www.microsoft.com/whdc/archive/scancode.mspx * http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc * * * Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left: * Num Lock: 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 * * Num Lock: on * modifiers | make | break * ----------+---------------------------+---------------------- * Other | E0 12 <make> | <break> E0 F0 12 * Shift'd | <make> | <break> * * Handling: ignore these prefix/postfix codes * * * 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: ignore these prefix/postfix codes * * * PrintScreen: * With hoding down modifiers, the scan code is sent as following: * * 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: ignore prefix/postfix codes and treat both scan code * E0 7C and 84 as PrintScreen. * * Pause: * With hoding down modifiers, the scan code is sent as following: * * modifiers | make(no break code) * ----------+-------------------------------------------------- * no mods | E1 14 77 E1 F0 14 F0 77 * Control'd | E0 7E E0 F0 7E * * Handling: treat these two code sequence as Pause * */ uint8_t matrix_scan(void) { static enum { INIT, F0, E0, E0_F0, // states for Pause/Break 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, } state = INIT; is_modified = false; // Pause/Break off(PS/2 has no break for this key) 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: // 2byte make state = E0; break; case 0xF0: // break code state = F0; break; case 0xE1: // Pause/Break state = E1; break; case 0x83: // F8 matrix_make(F8); state = INIT; break; case 0x84: // 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: switch (code) { case 0x12: // postfix/postfix code for exceptional keys case 0x59: // postfix/postfix code for exceptional keys // ignore state = INIT; break; case 0x7E: // former part of Control-Pause[E0 7E E0 F0 7E] matrix_make(PAUSE); state = INIT; break; case 0xF0: // E0 break state = E0_F0; break; default: // E0 make if (code < 0x80) { matrix_make(code|0x80); } else { debug("unexpected scan code at E0: "); debug_hex(code); debug("\n"); } state = INIT; } break; case F0: switch (code) { case 0x83: matrix_break(F8); state = INIT; break; case 0x84: 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: // E0 break switch (code) { case 0x12: // postfix/postfix code for exceptional keys case 0x59: // postfix/postfix code for exceptional keys case 0x7E: // latter part of Control-Pause[E0 7E E0 F0 7E] // ignore 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; /* 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; default: state = INIT; } } 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 #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 matrix_make(uint8_t code) { if (!matrix_is_on(ROW(code), COL(code))) { matrix[ROW(code)] |= 1<<COL(code); is_modified = true; //print("matrix_make: "); phex(code); print("\n"); } } 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; //print("matrix_break: "); phex(code); print("\n"); } }
M tmk.c => tmk.c +1 -1