Merge branch 'ps2_keyboard_fix'
18 files changed, 769 insertions(+), 738 deletions(-) M converter/ps2_usb/Makefile A converter/ps2_usb/Makefile.pjrc M converter/ps2_usb/config.h A converter/ps2_usb/keymap_common.c R converter/ps2_usb/{keymap.c => keymap_common.h} A converter/ps2_usb/keymap_plain.c M converter/ps2_usb/matrix.c R keyboard/onekey/{Makefile.lufa => Makefile} M keyboard/onekey/README.md M keyboard/onekey/config.h M keyboard/onekey/matrix.c M protocol.mk M protocol/lufa/lufa.c M protocol/pjrc/usb.c M protocol/ps2.h A protocol/ps2_busywait.c R protocol/{ps2 => ps2_interrupt}.c M protocol/ps2_usart.c
M converter/ps2_usb/Makefile => converter/ps2_usb/Makefile +69 -42
@@ 1,5 1,5 @@ # Target file name (without extension). TARGET = ps2_usb TARGET = ps2_usb_lufa # Directory common source filess exist @@ TOP_DIR = ../.. 7,69 7,96 @@ TOP_DIR = ../.. # Directory keyboard dependent files exist TARGET_DIR = . # project specific files SRC = keymap_common.c \ matrix.c \ led.c ifdef KEYMAP SRC := keymap_$(KEYMAP).c $(SRC) else SRC := keymap_plain.c $(SRC) endif 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 # MCU name #MCU = at90usb1287 MCU = atmega32u4 # 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. # This will define a symbol, F_CPU, in all source code files equal to the # processor frequency in Hz. You can then use this symbol in your source code to # calculate timings. Do NOT tack on a 'UL' at the end, this will be done # automatically to create a 32-bit value in your source code. # # This will be an integer division of F_USB below, as it is sourced by # F_USB after it has run through any CPU prescalers. Note that this value # does not *change* the processor frequency - it should merely be updated to # reflect the processor speed set externally so that the code can use accurate # software delays. 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 # LUFA specific # # Target architecture (see library "Board Types" documentation). ARCH = AVR8 # Input clock frequency. # This will define a symbol, F_USB, in all source code files equal to the # input clock frequency (before any prescaling is performed) in Hz. This value may # differ from F_CPU if prescaling is used on the latter, and is required as the # raw input clock is fed directly to the PLL sections of the AVR for high speed # clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' # at the end, this will be done automatically to create a 32-bit value in your # source code. # # If no clock division is performed on the input clock inside the AVR (via the # CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. F_USB = $(F_CPU) PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened) #PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin #PS2_USE_BUSYWAIT = yes # uses primitive reference code # Interrupt driven control endpoint task(+60) OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT # keyboard dependent files SRC = keymap.c \ matrix.c \ led.c # Boot Section Size in *bytes* # Teensy halfKay 512 # Teensy++ halfKay 1024 # Atmel DFU loader 4096 # LUFA bootloader 4096 # USBaspLoader 2048 OPT_DEFS += -DBOOTLOADER_SIZE=4096 ifdef PS2_USE_USART SRC += protocol/ps2_usart.c OPT_DEFS += -DPS2_USE_USART endif ifdef PS2_USE_INT SRC += protocol/ps2.c OPT_DEFS += -DPS2_USE_INT endif ifdef PS2_USE_BUSYWAIT SRC += protocol/ps2.c OPT_DEFS += -DPS2_USE_BUSYWAIT endif # Build Options # comment out to disable the options. # #BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) MOUSEKEY_ENABLE = yes # Mouse keys(+4700) EXTRAKEY_ENABLE = yes # Audio control and System control(+450) CONSOLE_ENABLE = yes # Console for debug(+400) COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA #CONFIG_H = config_pjrc_usart.h CONFIG_H = config.h # PS/2 Options # #PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened) #PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin PS2_USE_BUSYWAIT = yes # uses primitive reference code #---------------- Programming Options -------------------------- PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex # Optimize size but this may cause error "relocation truncated to fit" #EXTRALDFLAGS = -Wl,--relax # Search Path VPATH += $(TARGET_DIR) VPATH += $(TOP_DIR) include $(TOP_DIR)/protocol/pjrc.mk include $(TOP_DIR)/protocol.mk include $(TOP_DIR)/protocol/lufa.mk include $(TOP_DIR)/common.mk include $(TOP_DIR)/rules.mk
A converter/ps2_usb/Makefile.pjrc => converter/ps2_usb/Makefile.pjrc +75 -0
@@ 0,0 1,75 @@ # 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 = keymap_common.c \ matrix.c \ led.c ifdef KEYMAP SRC := keymap_$(KEYMAP).c $(SRC) else SRC := keymap_plain.c $(SRC) endif 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 # Boot Section Size in *bytes* # Teensy halfKay 512 # Teensy++ halfKay 1024 # Atmel DFU loader 4096 # LUFA bootloader 4096 # USBaspLoader 2048 OPT_DEFS += -DBOOTLOADER_SIZE=4096 # Build Options # *Comment out* to disable the options. # #BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) MOUSEKEY_ENABLE = yes # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = yes # Console for debug(+400) COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # USB Nkey Rollover # PS/2 Options # #PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened) #PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin PS2_USE_BUSYWAIT = yes # uses primitive reference code # Search Path VPATH += $(TARGET_DIR) VPATH += $(TOP_DIR) include $(TOP_DIR)/protocol.mk include $(TOP_DIR)/protocol/pjrc.mk include $(TOP_DIR)/common.mk include $(TOP_DIR)/rules.mk
M converter/ps2_usb/config.h => converter/ps2_usb/config.h +45 -42
@@ 22,6 22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define VENDOR_ID 0xFEED #define PRODUCT_ID 0x6512 #define DEVICE_VER 0x0001 #define MANUFACTURER t.m.k. #define PRODUCT PS/2 keyboard converter @@ #define DESCRIPTION convert PS/2 keyboard to USB 39,10 40,52 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ) /* legacy keymap support */ #define USE_LEGACY_KEYMAP //#define NO_SUSPEND_POWER_DOWN /* * PS/2 Busywait */ #ifdef PS2_USE_BUSYWAIT #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 #endif /* * PS/2 Pin interrupt */ #ifdef PS2_USE_INT /* uses INT1 for clock line(ATMega32U4) */ #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 2 #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 #endif /* * PS/2 USART */ #ifdef PS2_USE_USART #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) @@ /* XCK for clock line and RXD for data line */ 54,7 97,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #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 { \ 85,7 127,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #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 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) /* XCK for clock line and RXD for data line */ @@ #define PS2_CLOCK_PORT PORTD 96,7 137,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define PS2_DATA_PIN PIND #define PS2_DATA_DDR DDRD #define PS2_DATA_BIT 0 /* 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 { \ 130,41 170,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #endif #endif #ifdef PS2_USE_INT /* uses INT1 for clock line(ATMega32U4) */ #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 2 #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 #endif #ifdef PS2_USE_BUSYWAIT #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 #endif
A converter/ps2_usb/keymap_common.c => converter/ps2_usb/keymap_common.c +30 -0
@@ 0,0 1,30 @@ /* Copyright 2011,2012,2013 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 "keymap_common.h" /* translates key to keycode */ uint8_t keymap_key_to_keycode(uint8_t layer, key_t key) { return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); } /* translates Fn keycode to action */ action_t keymap_fn_to_action(uint8_t keycode) { return (action_t){ .code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) }; }
R converter/ps2_usb/keymap.c => converter/ps2_usb/keymap_common.h +11 -216
@@ 1,5 1,5 @@ /* Copyright 2011 Jun Wako <wakojun@gmail.com> Copyright 2011,2012,2013 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 14,25 14,27 @@ 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 KEYMAP_COMMON_H #define KEYMAP_COMMON_H /* * Keymap for PS/2 keyboard */ #include <stdint.h> #include <stdbool.h> #include <avr/pgmspace.h> #include "keycode.h" #include "action.h" #include "action_macro.h" #include "report.h" #include "print.h" #include "debug.h" #include "util.h" #include "keymap.h" // 32*8(256) byte array which converts PS/2 code into USB code extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; extern const uint16_t fn_actions[]; // Following macros help you to define a keymap with the form of actual keyboard layout. /* US layout plus all other various keys */ /* All 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, \ 169,211 171,4 @@ KEYMAP_ALL( \ 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[] = { KC_SCLN, // Fn0 KC_SLSH, // Fn1 KC_NO, // Fn2 KC_NO, // Fn3 KC_NO, // Fn4 KC_NO, // Fn5 KC_NO, // Fn6 KC_NO // Fn7 }; // The keymap is a 32*8 byte array which convert a PS/2 scan code into a USB keycode. // See keycode.h for USB keycodes. You should omit a 'KC_' 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 index) { return pgm_read_byte(&fn_layer[index]); } uint8_t keymap_fn_keycode(uint8_t index) { return pgm_read_byte(&fn_keycode[index]); } #endif
A converter/ps2_usb/keymap_plain.c => converter/ps2_usb/keymap_plain.c +50 -0
@@ 0,0 1,50 @@ /* Copyright 2011,2012,2013 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 "keymap_common.h" 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, 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 ), }; const uint16_t PROGMEM fn_actions[] = { };
M converter/ps2_usb/matrix.c => converter/ps2_usb/matrix.c +42 -7
@@ 19,6 19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <stdbool.h> #include <avr/io.h> #include <util/delay.h> #include "action.h" #include "print.h" #include "util.h" @@ #include "debug.h" 28,6 29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. static void matrix_make(uint8_t code); static void matrix_break(uint8_t code); static void matrix_clear(void); #ifdef MATRIX_HAS_GHOST static bool matrix_has_ghost_in_row(uint8_t row); @@ #endif 83,6 85,7 @@ uint8_t matrix_cols(void) void matrix_init(void) { debug_enable = true; ps2_host_init(); @@ // initialize matrix state: all keys off 185,8 188,8 @@ uint8_t matrix_scan(void) matrix_break(PAUSE); } uint8_t code; while ((code = ps2_host_recv())) { uint8_t code = ps2_host_recv(); if (!ps2_error) { switch (state) { case INIT: @@ switch (code) { 207,11 210,19 @@ uint8_t matrix_scan(void) matrix_make(PRINT_SCREEN); state = INIT; break; case 0x00: // Overrun [3]p.25 matrix_clear(); clear_keyboard(); print("Overrun\n"); 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"); matrix_clear(); clear_keyboard(); xprintf("unexpected scan code at INIT: %02X\n", code); } state = INIT; @@ } 232,7 243,9 @@ uint8_t matrix_scan(void) if (code < 0x80) { matrix_make(code|0x80); } else { debug("unexpected scan code at E0: "); debug_hex(code); debug("\n"); matrix_clear(); clear_keyboard(); xprintf("unexpected scan code at E0: %02X\n", code); } state = INIT; @@ } 247,11 260,18 @@ uint8_t matrix_scan(void) matrix_break(PRINT_SCREEN); state = INIT; break; case 0xF0: matrix_clear(); clear_keyboard(); xprintf("unexpected scan code at F0: F0(clear and cont.)\n"); break; default: if (code < 0x80) { matrix_break(code); } else { debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); matrix_clear(); clear_keyboard(); xprintf("unexpected scan code at F0: %02X\n", code); } state = INIT; @@ } 266,7 286,9 @@ uint8_t matrix_scan(void) if (code < 0x80) { matrix_break(code|0x80); } else { debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n"); matrix_clear(); clear_keyboard(); xprintf("unexpected scan code at E0_F0: %02X\n", code); } state = INIT; @@ } 357,8 379,15 @@ uint8_t matrix_scan(void) default: state = INIT; } phex(code); } // TODO: request RESEND when error occurs? /* if (PS2_IS_FAILED(ps2_error)) { uint8_t ret = ps2_host_send(PS2_RESEND); xprintf("Resend: %02X\n", ret); } */ return 1; } @@ 450,3 479,9 @@ static void matrix_break(uint8_t code) is_modified = true; } } inline static void matrix_clear(void) { for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; }
R keyboard/onekey/Makefile.lufa => keyboard/onekey/Makefile +2 -2
@@ 116,8 116,8 @@ CONSOLE_ENABLE = yes # Console for debug(+400) #SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend #NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support PS2_USE_BUSYWAIT = yes # uses primitive reference code #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support #PS2_USE_BUSYWAIT = yes # uses primitive reference code #PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin #PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened)
M keyboard/onekey/README.md => keyboard/onekey/README.md +1 -1
@@ 1,5 1,5 @@ Onekey ====== Just one key keyboard for example. It sends 'a' key if pins PD0 and PD1 are short-circuited. Just one key keyboard for example. It sends 'a' key if pins PB0 and PB1 are short-circuited. https://github.com/tmk/tmk_keyboard/issues/56
M keyboard/onekey/config.h => keyboard/onekey/config.h +2 -2
@@ 73,7 73,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # define PS2_CLOCK_PORT PORTD # define PS2_CLOCK_PIN PIND # define PS2_CLOCK_DDR DDRD # define PS2_CLOCK_BIT 5 # define PS2_CLOCK_BIT 1 # define PS2_DATA_PORT PORTD # define PS2_DATA_PIN PIND @@ # define PS2_DATA_DDR DDRD 87,7 87,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define PS2_CLOCK_PORT PORTD #define PS2_CLOCK_PIN PIND #define PS2_CLOCK_DDR DDRD #define PS2_CLOCK_BIT 5 #define PS2_CLOCK_BIT 1 #define PS2_DATA_PORT PORTD #define PS2_DATA_PIN PIND #define PS2_DATA_DDR DDRD
M keyboard/onekey/matrix.c => keyboard/onekey/matrix.c +9 -9
@@ 139,29 139,29 @@ uint8_t matrix_key_count(void) /* Column pin configuration * col: 0 * pin: D0 * pin: B0 */ static void init_cols(void) { // Input with pull-up(DDR:0, PORT:1) DDRD &= ~(1<<0); PORTD |= (1<<0); DDRB &= ~(1<<0); PORTB |= (1<<0); } static matrix_row_t read_cols(void) { return (PIND&(1<<0) ? 0 : (1<<0)); return (PINB&(1<<0) ? 0 : (1<<0)); } /* Row pin configuration * row: 0 * pin: D1 * pin: B1 */ static void unselect_rows(void) { // Hi-Z(DDR:0, PORT:0) to unselect DDRD &= ~0b00000010; PORTD &= ~0b00000010; DDRB &= ~0b00000010; PORTB &= ~0b00000010; } @@ static void select_row(uint8_t row) 169,8 169,8 @@ static void select_row(uint8_t row) // Output low(DDR:1, PORT:0) to select switch (row) { case 0: DDRD |= (1<<1); PORTD &= ~(1<<1); DDRB |= (1<<1); PORTB &= ~(1<<1); break; } }
M protocol.mk => protocol.mk +2 -2
@@ 8,12 8,12 @@ ifdef PS2_MOUSE_ENABLE endif ifdef PS2_USE_BUSYWAIT SRC += protocol/ps2.c SRC += protocol/ps2_busywait.c OPT_DEFS += -DPS2_USE_BUSYWAIT endif ifdef PS2_USE_INT SRC += protocol/ps2.c SRC += protocol/ps2_interrupt.c OPT_DEFS += -DPS2_USE_INT endif
M protocol/lufa/lufa.c => protocol/lufa/lufa.c +2 -2
@@ 148,7 148,6 @@ static void Console_Task(void) */ void EVENT_USB_Device_Connect(void) { led_set(0x1f); // all on } @@ void EVENT_USB_Device_Disconnect(void) 172,8 171,9 @@ void EVENT_USB_Device_WakeUp() #ifdef SLEEP_LED_ENABLE sleep_led_disable(); #endif // NOTE: converters may not accept this led_set(host_keyboard_leds()); #endif } void EVENT_USB_Device_StartOfFrame(void)
M protocol/pjrc/usb.c => protocol/pjrc/usb.c +2 -1
@@ 662,8 662,9 @@ ISR(USB_GEN_vect) suspend_wakeup_init(); #ifdef SLEEP_LED_ENABLE sleep_led_disable(); #endif // NOTE: converters may not accept this led_set(host_keyboard_leds()); #endif UDIEN |= (1<<SUSPE); UDIEN &= ~(1<<WAKEUPE);
M protocol/ps2.h => protocol/ps2.h +124 -22
@@ 1,5 1,5 @@ /* Copyright 2010,2011 Jun WAKO <wakojun@gmail.com> Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com> This software is licensed with a Modified BSD License. @@ All of this is supposed to be Free Software, Open Source, DFSG-free, 37,32 37,46 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef PS2_H #define PS2_H #include <stdbool.h> #include <util/delay.h> #include <avr/io.h> /* * Primitive PS/2 Library for AVR * * PS/2 Resources * -------------- * [1] The PS/2 Mouse/Keyboard Protocol * http://www.computer-engineering.org/ps2protocol/ * Concise and thorough primer of PS/2 protocol. * * [2] Keyboard and Auxiliary Device Controller * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf * Signal Timing and Format * * [3] Keyboards(101- and 102-key) * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf * Keyboard Layout, Scan Code Set, POR, and Commands. * * [4] PS/2 Reference Manuals * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf * Collection of IBM Personal System/2 documents. * * [5] TrackPoint Engineering Specifications for version 3E * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html */ /* port settings for clock and data line */ #if !(defined(PS2_CLOCK_PORT) && \ defined(PS2_CLOCK_PIN) && \ defined(PS2_CLOCK_DDR) && \ defined(PS2_CLOCK_BIT)) # error "PS/2 clock port setting is required in config.h" #endif #if !(defined(PS2_DATA_PORT) && \ defined(PS2_DATA_PIN) && \ defined(PS2_DATA_DDR) && \ defined(PS2_DATA_BIT)) # error "PS/2 data port setting is required in config.h" #endif #define PS2_ACK 0xFA #define PS2_RESEND 0xFE #define PS2_SET_LED 0xED #define PS2_ERR_NONE 0 #define PS2_ERR_PARITY 0x10 // TODO: error numbers #define PS2_ERR_NONE 0 #define PS2_ERR_STARTBIT1 1 #define PS2_ERR_STARTBIT2 2 #define PS2_ERR_STARTBIT3 3 #define PS2_ERR_PARITY 0x10 #define PS2_ERR_NODATA 0x20 #define PS2_LED_SCROLL_LOCK 0 @@ #define PS2_LED_NUM_LOCK 1 71,13 85,101 @@ POSSIBILITY OF SUCH DAMAGE. extern uint8_t ps2_error; /* host role */ void ps2_host_init(void); uint8_t ps2_host_send(uint8_t data); uint8_t ps2_host_recv_response(void); uint8_t ps2_host_recv(void); void ps2_host_set_led(uint8_t usb_led); /* device role */ /* Check port settings for clock and data line */ #if !(defined(PS2_CLOCK_PORT) && \ defined(PS2_CLOCK_PIN) && \ defined(PS2_CLOCK_DDR) && \ defined(PS2_CLOCK_BIT)) # error "PS/2 clock port setting is required in config.h" #endif #if !(defined(PS2_DATA_PORT) && \ defined(PS2_DATA_PIN) && \ defined(PS2_DATA_DDR) && \ defined(PS2_DATA_BIT)) # error "PS/2 data port setting is required in config.h" #endif /*-------------------------------------------------------------------- * static functions *------------------------------------------------------------------*/ static inline void clock_lo(void) { PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT); } static inline void clock_hi(void) { /* input with pull up */ PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT); } static inline bool clock_in(void) { PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT); _delay_us(1); return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT); } static inline void data_lo(void) { PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT); PS2_DATA_DDR |= (1<<PS2_DATA_BIT); } static inline void data_hi(void) { /* input with pull up */ PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); PS2_DATA_PORT |= (1<<PS2_DATA_BIT); } static inline bool data_in(void) { PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); PS2_DATA_PORT |= (1<<PS2_DATA_BIT); _delay_us(1); return PS2_DATA_PIN&(1<<PS2_DATA_BIT); } static inline uint16_t wait_clock_lo(uint16_t us) { while (clock_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_clock_hi(uint16_t us) { while (!clock_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_data_lo(uint16_t us) { while (data_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_data_hi(uint16_t us) { while (!data_in() && us) { asm(""); _delay_us(1); us--; } return us; } /* idle state that device can send */ static inline void idle(void) { clock_hi(); data_hi(); } /* inhibit device to send */ static inline void inhibit(void) { clock_lo(); data_hi(); } #endif
A protocol/ps2_busywait.c => protocol/ps2_busywait.c +185 -0
@@ 0,0 1,185 @@ /* Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com> This software is licensed with a Modified BSD License. All of this is supposed to be Free Software, Open Source, DFSG-free, GPL-compatible, and OK to use in both free and proprietary applications. Additions and corrections to this file are welcome. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * PS/2 protocol busywait version */ #include <stdbool.h> #include <util/delay.h> #include "ps2.h" #include "debug.h" #define WAIT(stat, us, err) do { \ if (!wait_##stat(us)) { \ ps2_error = err; \ goto ERROR; \ } \ } while (0) uint8_t ps2_error = PS2_ERR_NONE; void ps2_host_init(void) { // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) _delay_ms(2500); inhibit(); } uint8_t ps2_host_send(uint8_t data) { bool parity = true; ps2_error = PS2_ERR_NONE; /* terminate a transmission if we have */ inhibit(); _delay_us(100); // 100us [4]p.13, [5]p.50 /* 'Request to Send' and Start bit */ data_lo(); clock_hi(); WAIT(clock_lo, 10000, 10); // 10ms [5]p.50 /* Data bit */ for (uint8_t i = 0; i < 8; i++) { _delay_us(15); if (data&(1<<i)) { parity = !parity; data_hi(); } else { data_lo(); } WAIT(clock_hi, 50, 2); WAIT(clock_lo, 50, 3); } /* Parity bit */ _delay_us(15); if (parity) { data_hi(); } else { data_lo(); } WAIT(clock_hi, 50, 4); WAIT(clock_lo, 50, 5); /* Stop bit */ _delay_us(15); data_hi(); /* Ack */ WAIT(data_lo, 50, 6); WAIT(clock_lo, 50, 7); /* wait for idle state */ WAIT(clock_hi, 50, 8); WAIT(data_hi, 50, 9); inhibit(); return ps2_host_recv_response(); ERROR: inhibit(); return 0; } /* receive data when host want else inhibit communication */ uint8_t ps2_host_recv_response(void) { // Command may take 25ms/20ms at most([5]p.46, [3]p.21) // 250 * 100us(wait for start bit in ps2_host_recv) uint8_t data = 0; uint8_t try = 250; do { data = ps2_host_recv(); } while (try-- && ps2_error); return data; } /* called after start bit comes */ uint8_t ps2_host_recv(void) { uint8_t data = 0; bool parity = true; ps2_error = PS2_ERR_NONE; /* release lines(idle state) */ idle(); /* start bit [1] */ WAIT(clock_lo, 100, 1); // TODO: this is enough? WAIT(data_lo, 1, 2); WAIT(clock_hi, 50, 3); /* data [2-9] */ for (uint8_t i = 0; i < 8; i++) { WAIT(clock_lo, 50, 4); if (data_in()) { parity = !parity; data |= (1<<i); } WAIT(clock_hi, 50, 5); } /* parity [10] */ WAIT(clock_lo, 50, 6); if (data_in() != parity) { ps2_error = PS2_ERR_PARITY; goto ERROR; } WAIT(clock_hi, 50, 7); /* stop bit [11] */ WAIT(clock_lo, 50, 8); WAIT(data_hi, 1, 9); WAIT(clock_hi, 50, 10); inhibit(); return data; ERROR: if (ps2_error > PS2_ERR_STARTBIT3) { xprintf("x%02X\n", ps2_error); } inhibit(); return 0; } /* send LED state to keyboard */ void ps2_host_set_led(uint8_t led) { ps2_host_send(0xED); ps2_host_send(led); }
R protocol/ps2.c => protocol/ps2_interrupt.c +80 -254
@@ 35,47 35,15 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * PS/2 protocol Pin interrupt version */ #include <stdbool.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "ps2.h" #include "debug.h" #ifndef PS2_USE_INT static uint8_t recv_data(void); #endif static inline void clock_lo(void); static inline void clock_hi(void); static inline bool clock_in(void); static inline void data_lo(void); static inline void data_hi(void); static inline bool data_in(void); static inline uint16_t wait_clock_lo(uint16_t us); static inline uint16_t wait_clock_hi(uint16_t us); static inline uint16_t wait_data_lo(uint16_t us); static inline uint16_t wait_data_hi(uint16_t us); static inline void idle(void); static inline void inhibit(void); /* Primitive PS/2 Library for AVR ============================== Host side is only supported now. I/O control ----------- High state is asserted by input with pull up. PS/2 References --------------- http://www.computer-engineering.org/ps2protocol/ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf */ #include "print.h" @@ #define WAIT(stat, us, err) do { \ 89,35 57,38 @@ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf uint8_t ps2_error = PS2_ERR_NONE; static inline uint8_t pbuf_dequeue(void); static inline void pbuf_enqueue(uint8_t data); static inline bool pbuf_has_data(void); static inline void pbuf_clear(void); void ps2_host_init(void) { #ifdef PS2_USE_INT idle(); PS2_INT_INIT(); PS2_INT_ON(); idle(); #else inhibit(); #endif // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) //_delay_ms(2500); } // TODO: send using interrupt if available uint8_t ps2_host_send(uint8_t data) { uint8_t res = 0; bool parity = true; ps2_error = PS2_ERR_NONE; #ifdef PS2_USE_INT PS2_INT_OFF(); #endif /* terminate a transmission if we have */ inhibit(); _delay_us(200); // at least 100us _delay_us(100); // 100us [4]p.13, [5]p.50 /* start bit [1] */ /* 'Request to Send' and Start bit */ data_lo(); clock_hi(); WAIT(clock_lo, 20000, 10); // may take 15ms at most until device starts clocking /* data [2-9] */ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50 /* Data bit[2-9] */ for (uint8_t i = 0; i < 8; i++) { _delay_us(15); @@ if (data&(1<<i)) { 129,15 100,18 @@ uint8_t ps2_host_send(uint8_t data) WAIT(clock_hi, 50, 2); WAIT(clock_lo, 50, 3); } /* parity [10] */ /* Parity bit */ _delay_us(15); if (parity) { data_hi(); } else { data_lo(); } WAIT(clock_hi, 50, 4); WAIT(clock_lo, 50, 5); /* stop bit [11] */ /* Stop bit */ _delay_us(15); data_hi(); /* ack [12] */ /* Ack */ WAIT(data_lo, 50, 6); WAIT(clock_lo, 50, 7); @@ 145,116 119,35 @@ uint8_t ps2_host_send(uint8_t data) WAIT(clock_hi, 50, 8); WAIT(data_hi, 50, 9); #ifdef PS2_USE_INT idle(); PS2_INT_ON(); #endif res = ps2_host_recv_response(); return ps2_host_recv_response(); ERROR: #ifdef PS2_USE_INT PS2_INT_ON(); idle(); #else inhibit(); #endif return res; PS2_INT_ON(); return 0; } #ifndef PS2_USE_INT /* receive data when host want else inhibit communication */ uint8_t ps2_host_recv_response(void) { uint8_t data = 0; #ifdef PS2_USE_INT PS2_INT_OFF(); #endif /* terminate a transmission if we have */ inhibit(); _delay_us(100); /* release lines(idle state) */ idle(); /* wait start bit */ wait_clock_lo(25000); // command response may take 20 ms at most data = recv_data(); inhibit(); return data; } #endif #ifndef PS2_USE_INT uint8_t ps2_host_recv(void) { return ps2_host_recv_response(); } #else /* ring buffer to store ps/2 key data */ #define PBUF_SIZE 32 static uint8_t pbuf[PBUF_SIZE]; static uint8_t pbuf_head = 0; static uint8_t pbuf_tail = 0; static inline void pbuf_enqueue(uint8_t data) { uint8_t sreg = SREG; cli(); uint8_t next = (pbuf_head + 1) % PBUF_SIZE; if (next != pbuf_tail) { pbuf[pbuf_head] = data; pbuf_head = next; } 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) { val = pbuf[pbuf_tail]; pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; // Command may take 25ms/20ms at most([5]p.46, [3]p.21) uint8_t retry = 25; while (retry-- && !pbuf_has_data()) { _delay_ms(1); } SREG = sreg; return val; } static inline bool pbuf_has_data(void) { uint8_t sreg = SREG; cli(); bool has_data = (pbuf_head != pbuf_tail); SREG = sreg; return has_data; } static inline void pbuf_clear(void) { uint8_t sreg = SREG; cli(); pbuf_head = pbuf_tail = 0; SREG = sreg; return pbuf_dequeue(); } /* get data received by interrupt */ uint8_t ps2_host_recv(void) { if (ps2_error) { print("x"); phex(ps2_error); ps2_host_send(0xFE); // request to resend if (pbuf_has_data()) { ps2_error = PS2_ERR_NONE; return pbuf_dequeue(); } else { ps2_error = PS2_ERR_NODATA; return 0; } idle(); return pbuf_dequeue(); } uint8_t ps2_host_recv_response(void) { while (!pbuf_has_data()) ; return pbuf_dequeue(); } @@ ISR(PS2_INT_VECT) 309,7 202,6 @@ ISR(PS2_INT_VECT) if (!data_in()) goto ERROR; pbuf_enqueue(data); //phex(data); goto DONE; break; @@ default: 317,7 209,6 @@ ISR(PS2_INT_VECT) } goto RETURN; ERROR: inhibit(); ps2_error = state; DONE: @@ state = INIT; 326,8 217,6 @@ DONE: RETURN: return; } #endif /* send LED state to keyboard */ @@ void ps2_host_set_led(uint8_t led) 337,116 226,53 @@ void ps2_host_set_led(uint8_t led) } #ifndef PS2_USE_INT /* called after start bit comes */ static uint8_t recv_data(void) /*-------------------------------------------------------------------- * Ring buffer to store scan codes from keyboard *------------------------------------------------------------------*/ #define PBUF_SIZE 32 static uint8_t pbuf[PBUF_SIZE]; static uint8_t pbuf_head = 0; static uint8_t pbuf_tail = 0; static inline void pbuf_enqueue(uint8_t data) { uint8_t data = 0; bool parity = true; ps2_error = PS2_ERR_NONE; /* start bit [1] */ WAIT(clock_lo, 1, 1); WAIT(data_lo, 1, 2); WAIT(clock_hi, 50, 3); /* data [2-9] */ for (uint8_t i = 0; i < 8; i++) { WAIT(clock_lo, 50, 4); if (data_in()) { parity = !parity; data |= (1<<i); } WAIT(clock_hi, 50, 5); } /* parity [10] */ WAIT(clock_lo, 50, 6); if (data_in() != parity) { ps2_error = PS2_ERR_PARITY; goto ERROR; uint8_t sreg = SREG; cli(); uint8_t next = (pbuf_head + 1) % PBUF_SIZE; if (next != pbuf_tail) { pbuf[pbuf_head] = data; pbuf_head = next; } else { print("pbuf: full\n"); } WAIT(clock_hi, 50, 7); /* stop bit [11] */ WAIT(clock_lo, 50, 8); WAIT(data_hi, 1, 9); WAIT(clock_hi, 50, 10); return data; ERROR: return 0; } #endif static inline void clock_lo() { PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT); } static inline void clock_hi() { /* input with pull up */ PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT); } static inline bool clock_in() { PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT); _delay_us(1); return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT); } static inline void data_lo() { PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT); PS2_DATA_DDR |= (1<<PS2_DATA_BIT); } static inline void data_hi() { /* input with pull up */ PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); PS2_DATA_PORT |= (1<<PS2_DATA_BIT); SREG = sreg; } static inline bool data_in() static inline uint8_t pbuf_dequeue(void) { PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); PS2_DATA_PORT |= (1<<PS2_DATA_BIT); _delay_us(1); return PS2_DATA_PIN&(1<<PS2_DATA_BIT); } uint8_t val = 0; static inline uint16_t wait_clock_lo(uint16_t us) { while (clock_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_clock_hi(uint16_t us) { while (!clock_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_data_lo(uint16_t us) { while (data_in() && us) { asm(""); _delay_us(1); us--; } return us; uint8_t sreg = SREG; cli(); if (pbuf_head != pbuf_tail) { val = pbuf[pbuf_tail]; pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; } SREG = sreg; return val; } static inline uint16_t wait_data_hi(uint16_t us) static inline bool pbuf_has_data(void) { while (!data_in() && us) { asm(""); _delay_us(1); us--; } return us; uint8_t sreg = SREG; cli(); bool has_data = (pbuf_head != pbuf_tail); SREG = sreg; return has_data; } /* idle state that device can send */ static inline void idle(void) static inline void pbuf_clear(void) { clock_hi(); data_hi(); uint8_t sreg = SREG; cli(); pbuf_head = pbuf_tail = 0; SREG = sreg; } /* inhibit device to send */ static inline void inhibit(void) { clock_lo(); data_hi(); }
M protocol/ps2_usart.c => protocol/ps2_usart.c +38 -136
@@ 36,32 36,14 @@ POSSIBILITY OF SUCH DAMAGE. */ /* Primitive PS/2 Library for AVR ============================== Host side is only supported now. Synchronous USART is used to receive data by hardware process rather than interrupt. During V-USB interrupt runs, CLOCK interrupt cannot interpose. In the result it is prone to lost CLOCK edge. * PS/2 protocol USART version */ I/O control ----------- High state is asserted by internal pull-up. If you have a signaling problem, you may need to have external pull-up resisters on CLOCK and DATA line. PS/2 References --------------- http://www.computer-engineering.org/ps2protocol/ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf */ #include <stdbool.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "ps2.h" #include "debug.h" #include "print.h" @@ #define WAIT(stat, us, err) do { \ 75,18 57,6 @@ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf uint8_t ps2_error = PS2_ERR_NONE; static inline void clock_lo(void); static inline void clock_hi(void); static inline bool clock_in(void); static inline void data_lo(void); static inline void data_hi(void); static inline bool data_in(void); static inline uint16_t wait_clock_lo(uint16_t us); static inline uint16_t wait_clock_hi(uint16_t us); static inline uint16_t wait_data_lo(uint16_t us); static inline uint16_t wait_data_hi(uint16_t us); static inline void idle(void); static inline void inhibit(void); static inline uint8_t pbuf_dequeue(void); static inline void pbuf_enqueue(uint8_t data); @@ static inline bool pbuf_has_data(void); 95,14 65,15 @@ static inline void pbuf_clear(void); void ps2_host_init(void) { idle(); idle(); // without this many USART errors occur when cable is disconnected PS2_USART_INIT(); PS2_USART_RX_INT_ON(); // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) //_delay_ms(2500); } uint8_t ps2_host_send(uint8_t data) { uint8_t res = 0; bool parity = true; ps2_error = PS2_ERR_NONE; @@ 110,13 81,14 @@ uint8_t ps2_host_send(uint8_t data) /* terminate a transmission if we have */ inhibit(); _delay_us(100); _delay_us(100); // [4]p.13 /* start bit [1] */ /* 'Request to Send' and Start bit */ data_lo(); clock_hi(); WAIT(clock_lo, 15000, 1); /* data [2-9] */ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50 /* Data bit[2-9] */ for (uint8_t i = 0; i < 8; i++) { _delay_us(15); @@ if (data&(1<<i)) { 128,15 100,18 @@ uint8_t ps2_host_send(uint8_t data) WAIT(clock_hi, 50, 2); WAIT(clock_lo, 50, 3); } /* parity [10] */ /* Parity bit */ _delay_us(15); if (parity) { data_hi(); } else { data_lo(); } WAIT(clock_hi, 50, 4); WAIT(clock_lo, 50, 5); /* stop bit [11] */ /* Stop bit */ _delay_us(15); data_hi(); /* ack [12] */ /* Ack */ WAIT(data_lo, 50, 6); WAIT(clock_lo, 50, 7); @@ 144,127 119,55 @@ uint8_t ps2_host_send(uint8_t data) WAIT(clock_hi, 50, 8); WAIT(data_hi, 50, 9); idle(); PS2_USART_INIT(); PS2_USART_RX_INT_ON(); res = ps2_host_recv_response(); return ps2_host_recv_response(); ERROR: idle(); PS2_USART_INIT(); PS2_USART_RX_INT_ON(); return res; return 0; } // Do polling data from keyboard to get response to last command. uint8_t ps2_host_recv_response(void) { while (!pbuf_has_data()) { _delay_ms(1); // without this delay it seems to fall into deadlock // Command may take 25ms/20ms at most([5]p.46, [3]p.21) uint8_t retry = 25; while (retry-- && !pbuf_has_data()) { _delay_ms(1); } return pbuf_dequeue(); } uint8_t ps2_host_recv(void) { return pbuf_dequeue(); if (pbuf_has_data()) { ps2_error = PS2_ERR_NONE; return pbuf_dequeue(); } else { ps2_error = PS2_ERR_NODATA; return 0; } } ISR(PS2_USART_RX_VECT) { uint8_t error = PS2_USART_ERROR; // TODO: request RESEND when error occurs? uint8_t error = PS2_USART_ERROR; // USART error should be read before data uint8_t data = PS2_USART_RX_DATA; if (!error) { pbuf_enqueue(data); } else { xprintf("PS2 USART error: %02X data: %02X\n", error, data); } } /* send LED state to keyboard */ void ps2_host_set_led(uint8_t led) { // send 0xED then keyboard keeps waiting for next LED data // and keyboard does not send any scan codes during waiting. // If fail to send LED data keyboard looks like being freezed. uint8_t retry = 3; while (retry-- && ps2_host_send(PS2_SET_LED) != PS2_ACK) ; retry = 3; while (retry-- && ps2_host_send(led) != PS2_ACK) ; } /*-------------------------------------------------------------------- * static functions *------------------------------------------------------------------*/ static inline void clock_lo() { PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT); } static inline void clock_hi() { /* input with pull up */ PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT); } static inline bool clock_in() { PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT); _delay_us(1); return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT); } static inline void data_lo() { PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT); PS2_DATA_DDR |= (1<<PS2_DATA_BIT); } static inline void data_hi() { /* input with pull up */ PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); PS2_DATA_PORT |= (1<<PS2_DATA_BIT); } static inline bool data_in() { PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); PS2_DATA_PORT |= (1<<PS2_DATA_BIT); _delay_us(1); return PS2_DATA_PIN&(1<<PS2_DATA_BIT); } static inline uint16_t wait_clock_lo(uint16_t us) { while (clock_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_clock_hi(uint16_t us) { while (!clock_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_data_lo(uint16_t us) { while (data_in() && us) { asm(""); _delay_us(1); us--; } return us; } static inline uint16_t wait_data_hi(uint16_t us) { while (!data_in() && us) { asm(""); _delay_us(1); us--; } return us; } /* idle state that device can send */ static inline void idle(void) { clock_hi(); data_hi(); } /* inhibit device to send */ static inline void inhibit(void) { clock_lo(); data_hi(); ps2_host_send(0xED); ps2_host_send(led); } @@ 284,11 187,10 @@ static inline void pbuf_enqueue(uint8_t data) pbuf[pbuf_head] = data; pbuf_head = next; } else { debug("pbuf: full\n"); print("pbuf: full\n"); } SREG = sreg; } static inline uint8_t pbuf_dequeue(void) { uint8_t val = 0;