diff options
32 files changed, 2111 insertions, 901 deletions
diff --git a/common/action.c b/common/action.c index 485abf81e3..e6938f5a23 100644 --- a/common/action.c +++ b/common/action.c @@ -128,6 +128,17 @@ void process_action(keyrecord_t *record) } break; #endif + case MODS_TAP_TOGGLE: + if (event.pressed) { + if (tap_count <= TAPPING_TOGGLE) { + register_mods(mods); + } + } else { + if (tap_count < TAPPING_TOGGLE) { + unregister_mods(mods); + } + } + break; default: if (event.pressed) { if (tap_count > 0) { diff --git a/common/action_code.h b/common/action_code.h index b08d36124e..8df86b1192 100644 --- a/common/action_code.h +++ b/common/action_code.h @@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. * * ACT_MODS_TAP(001r): * 001r|mods|0000 0000 Modifiers with OneShot + * 001r|mods|0000 0001 Modifiers with tap toggle * 001r|mods|0000 00xx (reserved) * 001r|mods| keycode Modifiers with Tap Key(Dual role) * @@ -205,12 +206,14 @@ enum mods_bit { }; enum mods_codes { MODS_ONESHOT = 0x00, + MODS_TAP_TOGGLE = 0x01, }; #define ACTION_KEY(key) ACTION(ACT_MODS, (key)) #define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | 0) #define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | (key)) #define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | (key)) #define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_ONESHOT) +#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_TAP_TOGGLE) /* diff --git a/converter/ps2_usb/Makefile b/converter/ps2_usb/Makefile index 0c6442374c..04bf28a00c 100644 --- a/converter/ps2_usb/Makefile +++ b/converter/ps2_usb/Makefile @@ -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 diff --git a/converter/ps2_usb/Makefile.pjrc b/converter/ps2_usb/Makefile.pjrc new file mode 100644 index 0000000000..0e175f8b45 --- /dev/null +++ b/converter/ps2_usb/Makefile.pjrc @@ -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 diff --git a/converter/ps2_usb/config.h b/converter/ps2_usb/config.h index 51cd271d78..c9bab1b072 100644 --- a/converter/ps2_usb/config.h +++ b/converter/ps2_usb/config.h @@ -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 diff --git a/converter/ps2_usb/keymap.c b/converter/ps2_usb/keymap.c deleted file mode 100644 index c97783fa53..0000000000 --- a/converter/ps2_usb/keymap.c +++ /dev/null @@ -1,379 +0,0 @@ -/* -Copyright 2011 Jun Wako <wakojun@gmail.com> - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Keymap for PS/2 keyboard - */ -#include <stdint.h> -#include <stdbool.h> -#include <avr/pgmspace.h> -#include "keycode.h" -#include "print.h" -#include "debug.h" -#include "util.h" -#include "keymap.h" - - - - -// Following macros help you to define a keymap with the form of actual keyboard layout. - -/* US layout plus all other various keys */ -#define KEYMAP_ALL( \ - K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ - K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ - K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ - K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ - K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ - K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ - \ - K61, /* for European ISO */ \ - K51, K13, K6A, K64, K67, /* for Japanese JIS */ \ - K08, K10, K18, K20, K28, K30, K38, K40, K48, K50, K57, K5F, /* F13-24 */ \ - KB7, KBF, KDE, /* System Power, Sleep, Wake */ \ - KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \ - KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \ - KC8, KAB, KC0, /* Mail, Calculator, My Computer */ \ - K90, KBA, KB8, KB0, /* WWW Search, Home, Back, Forward */ \ - KA8, KA0, K98 /* WWW Stop, Refresh, Favorites */ \ -) { \ - { KC_NO, KC_##K01, KC_NO, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \ - { KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_NO }, \ - { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_NO }, \ - { KC_##K18, KC_NO, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_NO }, \ - { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO }, \ - { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_NO }, \ - { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_NO }, \ - { KC_##K38, KC_NO, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_NO }, \ - { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_NO }, \ - { KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_NO }, \ - { KC_##K50, KC_##K51, KC_##K52, KC_NO, KC_##K54, KC_##K55, KC_NO, KC_##K57 }, \ - { KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_NO, KC_##K5D, KC_NO, KC_##K5F }, \ - { KC_NO, KC_##K61, KC_NO, KC_NO, KC_##K64, KC_NO, KC_##K66, KC_##K67 }, \ - { KC_NO, KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C, KC_NO, KC_NO, KC_NO }, \ - { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \ - { KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_##K7E, KC_NO }, \ - { KC_NO, KC_NO, KC_NO, KC_##K83, KC_NO, KC_NO, KC_NO, KC_NO }, \ - { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ - { KC_##K90, KC_##K91, KC_NO, KC_NO, KC_##K94, KC_##K95, KC_NO, KC_NO }, \ - { KC_##K98, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_##K9F }, \ - { KC_##KA0, KC_##KA1, KC_NO, KC_##KA3, KC_NO, KC_NO, KC_NO, KC_##KA7 }, \ - { KC_##KA8, KC_NO, KC_NO, KC_##KAB, KC_NO, KC_NO, KC_NO, KC_##KAF }, \ - { KC_##KB0, KC_NO, KC_##KB2, KC_NO, KC_##KB4, KC_NO, KC_NO, KC_##KB7 }, \ - { KC_##KB8, KC_NO, KC_##KBA, KC_##KBB, KC_NO, KC_NO, KC_NO, KC_##KBF }, \ - { KC_##KC0, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ - { KC_##KC8, KC_NO, KC_##KCA, KC_NO, KC_NO, KC_##KCD, KC_NO, KC_NO }, \ - { KC_##KD0, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ - { KC_NO, KC_NO, KC_##KDA, KC_NO, KC_NO, KC_NO, KC_##KDE, KC_NO }, \ - { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ - { KC_NO, KC_##KE9, KC_NO, KC_##KEB, KC_##KEC, KC_NO, KC_NO, KC_NO }, \ - { KC_##KF0, KC_##KF1, KC_##KF2, KC_NO, KC_##KF4, KC_##KF5, KC_NO, KC_NO }, \ - { KC_NO, KC_NO, KC_##KFA, KC_NO, KC_##KFC, KC_##KFD, KC_##KFE, KC_NO }, \ -} - -/* US layout */ -#define KEYMAP( \ - K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ - K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ - K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ - K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ - K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ - K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ -) \ -KEYMAP_ALL( \ - K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ - K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ - K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ - K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ - K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ - K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ - \ - NUBS, \ - RO, KANA, JYEN, HENK, MHEN, \ - F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ - SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ - AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ - MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ - MAIL, CALCULATOR, MY_COMPUTER, \ - WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ - WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ -) - -/* ISO layout */ -#define KEYMAP_ISO( \ - K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ - K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ - K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ - K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,K5A, K6B,K73,K74,K79, \ - K12,K61,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ - K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ -) \ -KEYMAP_ALL( \ - K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ - K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ - K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ - K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ - K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ - K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ - \ - K61, \ - RO, KANA, JYEN, HENK, MHEN, \ - F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ - SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ - AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ - MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ - MAIL, CALCULATOR, MY_COMPUTER, \ - WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ - WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ -) - -/* JIS layout */ -#define KEYMAP_JIS( \ - K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ - K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ - K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ - K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D, K5A, K6B,K73,K74,K79, \ - K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51, K59, KF5, K69,K72,K7A, \ - K14,K9F,K11, K67,K29,K64,K13, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ -) \ -KEYMAP_ALL( \ - K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ - K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ - K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ - K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ - K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ - K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ - \ - NUBS, \ - K51, K13, K6A, K64, K67, \ - F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ - SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ - AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ - MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ - MAIL, CALCULATOR, MY_COMPUTER, \ - WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ - WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ -) - - -// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. -static const uint8_t PROGMEM fn_layer[] = { - 5, // Fn0 - 6, // Fn1 - 0, // Fn2 - 0, // Fn3 - 0, // Fn4 - 0, // Fn5 - 0, // Fn6 - 0 // Fn7 -}; - -// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. -// See layer.c for details. -static const uint8_t PROGMEM fn_keycode[] = { - 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]); -} diff --git a/converter/ps2_usb/keymap_common.c b/converter/ps2_usb/keymap_common.c new file mode 100644 index 0000000000..241d2e33b1 --- /dev/null +++ b/converter/ps2_usb/keymap_common.c @@ -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)]) }; +} diff --git a/converter/ps2_usb/keymap_common.h b/converter/ps2_usb/keymap_common.h new file mode 100644 index 0000000000..216a8dc020 --- /dev/null +++ b/converter/ps2_usb/keymap_common.h @@ -0,0 +1,174 @@ +/* +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/>. +*/ +#ifndef KEYMAP_COMMON_H +#define KEYMAP_COMMON_H + +#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 "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[]; + + +/* 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, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + K61, /* for European ISO */ \ + K51, K13, K6A, K64, K67, /* for Japanese JIS */ \ + K08, K10, K18, K20, K28, K30, K38, K40, K48, K50, K57, K5F, /* F13-24 */ \ + KB7, KBF, KDE, /* System Power, Sleep, Wake */ \ + KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \ + KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \ + KC8, KAB, KC0, /* Mail, Calculator, My Computer */ \ + K90, KBA, KB8, KB0, /* WWW Search, Home, Back, Forward */ \ + KA8, KA0, K98 /* WWW Stop, Refresh, Favorites */ \ +) { \ + { KC_NO, KC_##K01, KC_NO, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \ + { KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_NO }, \ + { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_NO }, \ + { KC_##K18, KC_NO, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_NO }, \ + { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO }, \ + { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_NO }, \ + { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_NO }, \ + { KC_##K38, KC_NO, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_NO }, \ + { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_NO }, \ + { KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_NO }, \ + { KC_##K50, KC_##K51, KC_##K52, KC_NO, KC_##K54, KC_##K55, KC_NO, KC_##K57 }, \ + { KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_NO, KC_##K5D, KC_NO, KC_##K5F }, \ + { KC_NO, KC_##K61, KC_NO, KC_NO, KC_##K64, KC_NO, KC_##K66, KC_##K67 }, \ + { KC_NO, KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C, KC_NO, KC_NO, KC_NO }, \ + { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \ + { KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_##K7E, KC_NO }, \ + { KC_NO, KC_NO, KC_NO, KC_##K83, KC_NO, KC_NO, KC_NO, KC_NO }, \ + { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ + { KC_##K90, KC_##K91, KC_NO, KC_NO, KC_##K94, KC_##K95, KC_NO, KC_NO }, \ + { KC_##K98, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_##K9F }, \ + { KC_##KA0, KC_##KA1, KC_NO, KC_##KA3, KC_NO, KC_NO, KC_NO, KC_##KA7 }, \ + { KC_##KA8, KC_NO, KC_NO, KC_##KAB, KC_NO, KC_NO, KC_NO, KC_##KAF }, \ + { KC_##KB0, KC_NO, KC_##KB2, KC_NO, KC_##KB4, KC_NO, KC_NO, KC_##KB7 }, \ + { KC_##KB8, KC_NO, KC_##KBA, KC_##KBB, KC_NO, KC_NO, KC_NO, KC_##KBF }, \ + { KC_##KC0, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ + { KC_##KC8, KC_NO, KC_##KCA, KC_NO, KC_NO, KC_##KCD, KC_NO, KC_NO }, \ + { KC_##KD0, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ + { KC_NO, KC_NO, KC_##KDA, KC_NO, KC_NO, KC_NO, KC_##KDE, KC_NO }, \ + { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \ + { KC_NO, KC_##KE9, KC_NO, KC_##KEB, KC_##KEC, KC_NO, KC_NO, KC_NO }, \ + { KC_##KF0, KC_##KF1, KC_##KF2, KC_NO, KC_##KF4, KC_##KF5, KC_NO, KC_NO }, \ + { KC_NO, KC_NO, KC_##KFA, KC_NO, KC_##KFC, KC_##KFD, KC_##KFE, KC_NO }, \ +} + +/* US layout */ +#define KEYMAP( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ +) \ +KEYMAP_ALL( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + NUBS, \ + RO, KANA, JYEN, HENK, MHEN, \ + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ + SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ + AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ + MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ + MAIL, CALCULATOR, MY_COMPUTER, \ + WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ + WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ +) + +/* ISO layout */ +#define KEYMAP_ISO( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,K5A, K6B,K73,K74,K79, \ + K12,K61,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ +) \ +KEYMAP_ALL( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + K61, \ + RO, KANA, JYEN, HENK, MHEN, \ + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ + SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ + AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ + MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ + MAIL, CALCULATOR, MY_COMPUTER, \ + WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ + WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ +) + +/* JIS layout */ +#define KEYMAP_JIS( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K67,K29,K64,K13, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ +) \ +KEYMAP_ALL( \ + K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ + K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ + K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ + K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ + K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ + K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ + \ + NUBS, \ + K51, K13, K6A, K64, K67, \ + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ + SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ + AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ + MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ + MAIL, CALCULATOR, MY_COMPUTER, \ + WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ + WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ +) + +#endif diff --git a/converter/ps2_usb/keymap_plain.c b/converter/ps2_usb/keymap_plain.c new file mode 100644 index 0000000000..9c6e7d9ff1 --- /dev/null +++ b/converter/ps2_usb/keymap_plain.c @@ -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[] = { +}; diff --git a/converter/ps2_usb/matrix.c b/converter/ps2_usb/matrix.c index 4187ea0601..45344c0f75 100644 --- a/converter/ps2_usb/matrix.c +++ b/converter/ps2_usb/matrix.c @@ -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; +} diff --git a/converter/terminal_bluefruit/Makefile b/converter/terminal_bluefruit/Makefile new file mode 100644 index 0000000000..83d68fc252 --- /dev/null +++ b/converter/terminal_bluefruit/Makefile @@ -0,0 +1,113 @@ +# Target file name (without extension). +TARGET = terminal_bluefruit + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = keymap.c \ + matrix.c \ + led.c + +CONFIG_H = config.h + +BLUEFRUIT_TRACE_SERIAL=true + +# 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 + + +# +# 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) + +# Interrupt driven control endpoint task +OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT + + +# Boot Section Size in bytes +# Teensy halfKay 512 +# Atmel DFU loader 4096 +# LUFA bootloader 4096 +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(+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 +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA + + +# +# PS/2 protocol implementations +# USART is recommended if it is available, others are for reference purpose. +# INT implementation will drop simultaneous key strokes. +# +#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 + +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 + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + +# Search Path +VPATH += $(TARGET_DIR) +VPATH += $(TOP_DIR) + + +include $(TOP_DIR)/protocol/bluefruit.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/converter/terminal_bluefruit/README b/converter/terminal_bluefruit/README new file mode 100644 index 0000000000..6ff1bc92f3 --- /dev/null +++ b/converter/terminal_bluefruit/README @@ -0,0 +1,37 @@ +Keyboard converter for IBM terminal keyboard +============================================ +It supports PS/2 Scan Code Set 3 and runs on USB AVR chips such like PJRC Teensy. +I tested the converter on ATMega32U4 with 1392595(102keys) and 6110345(122keys). + +Source code: https://github.com/tmk/tmk_keyboard +Article: http://geekhack.org/index.php?topic=27272.0 + + +CONNECTION +---------- +Keyboard ATMega32U4 +---------------------- +Data: PD2 +Clock: PD5 + +And VCC and GND, of course. See RESOURCE for keyboard connector pin assign. + + +BUILD +----- +$ git clone https://github.com/tmk/tmk_keyboard.git +$ cd converter/terminal_usb +$ make + + +RESOURCE +-------- +Soarer's Converter: http://geekhack.org/index.php?topic=17458.0 +102keys(1392595): http://geekhack.org/index.php?topic=10737.0 +122keys(1390876): http://www.seasip.info/VintagePC/ibm_1390876.html +KbdBabel: http://www.kbdbabel.org/ +RJ45 Connector: http://www.kbdbabel.org/conn/kbd_connector_ibmterm.png +DIN Connector: http://www.kbdbabel.org/conn/kbd_connector_ibm3179_318x_319x.png +WinAVR: http://winavr.sourceforge.net/ + +EOF diff --git a/converter/terminal_bluefruit/config.h b/converter/terminal_bluefruit/config.h new file mode 100644 index 0000000000..8bf139d35f --- /dev/null +++ b/converter/terminal_bluefruit/config.h @@ -0,0 +1,112 @@ +/* +Converter for 70% IBM Terminal Keyboard +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6535 +#define DEVICE_VER 0x0100 +#define MANUFACTURER t.m.k. +#define PRODUCT 70% IBM Terminal Keyboard Converter w/ Bluetooth +#define DESCRIPTION USB converter for IBM Terminal Keyboard w/ Bluetooth + + +/* matrix size */ +#define MATRIX_ROWS 17 // keycode bit: 3-0 +#define MATRIX_COLS 8 // keycode bit: 6-4 + + +/* legacy keymap support */ +// #define USE_LEGACY_KEYMAP + + +/* key combination for command */ +#define IS_COMMAND() ( \ + (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) || \ + (keyboard_report->mods == (MOD_BIT(KC_RALT) | MOD_BIT(KC_RCTL))) \ +) + +/* USART configuration + * asynchronous, 9600baud, 8-data bit, non parity, 1-stop bit, no flow control + */ +#ifdef __AVR_ATmega32U4__ + #define SERIAL_UART_BAUD 9600 + #define SERIAL_UART_DATA UDR1 + #define SERIAL_UART_UBRR ((F_CPU/(16UL*SERIAL_UART_BAUD))-1) + #define SERIAL_UART_RXD_VECT USART1_RX_vect + #define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1)) + #define SERIAL_UART_INIT() do { \ + UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \ + UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8); /* baud rate */ \ + UCSR1B = (1<<TXEN1); /* TX: enable */ \ + UCSR1C = (0<<UPM11) | (0<<UPM10) | /* parity: none(00), even(01), odd(11) */ \ + (0<<UCSZ12) | (1<<UCSZ11) | (1<<UCSZ10); /* data-8bit(011) */ \ + sei(); \ + } while(0) +#else +# error "USART configuration is needed." +#endif + +/* + * PS/2 Interrupt configuration + */ +#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 0 + +#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 Busywait configuration + */ +#ifdef PS2_USE_BUSYWAIT +#define PS2_CLOCK_PORT PORTD +#define PS2_CLOCK_PIN PIND +#define PS2_CLOCK_DDR DDRD +#define PS2_CLOCK_BIT 1 + +#define PS2_DATA_PORT PORTD +#define PS2_DATA_PIN PIND +#define PS2_DATA_DDR DDRD +#define PS2_DATA_BIT 0 +#endif + +#endif diff --git a/converter/terminal_bluefruit/keymap.c b/converter/terminal_bluefruit/keymap.c new file mode 100644 index 0000000000..716590a456 --- /dev/null +++ b/converter/terminal_bluefruit/keymap.c @@ -0,0 +1,227 @@ +/* +Converter for 70% IBM Terminal Keyboard +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "keycode.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + + + +/* + * IBM Terminal keyboard 6110345(122keys)/1392595(102keys) + * http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M + * http://www.seasip.info/VintagePC/ibm_1391406.html + * + * Keymap array: + * 8 bytes + * +---------+ + * 0| | + * :| | 0x00-0x87 + * ;| | + * 17| | + * +---------+ + */ +#define KEYMAP( \ + K08,K10,K18,K20,K28,K30,K38,K40,K48,K50,K57,K5F, \ + K07,K0F,K17,K1F,K27,K2F,K37,K3F,K47,K4F,K56,K5E, \ + \ + K05,K06, K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K5D,K66, K67,K6E,K6F, K76,K77,K7E,K84, \ + K04,K0C, K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, K5C, K64,K65,K6D, K6C,K75,K7D,K7C, \ + K03,K0B, K14,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K53,K5A, K63, K6B,K73,K74,K7B, \ + K83,K0A, K12,K13,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K51,K59, K61,K62,K6A, K69,K72,K7A,K79, \ + K01,K09, K11, K19, K29, K39, K58, K60, K68,K70,K71,K78 \ +) { \ + { KC_NO, KC_##K01, KC_NO, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \ + { KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F }, \ + { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \ + { KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F }, \ + { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \ + { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F }, \ + { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \ + { KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \ + { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47 }, \ + { KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_##K4F }, \ + { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \ + { KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_##K5F }, \ + { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67 }, \ + { KC_##K68, KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C, KC_##K6D, KC_##K6E, KC_##K6F }, \ + { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \ + { KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_##K7E, KC_NO }, \ + { KC_NO, KC_NO, KC_NO, KC_##K83, KC_##K84, KC_NO, KC_NO, KC_NO, }, \ +} + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* 0: default + * ,---. ,---------------. ,---------------. ,---------------. ,-----------. + * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| + * `---' `---------------' `---------------' `---------------' `-----------' + * ,-----------------------------------------------------------. ,-----------. ,---------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \|BS | |Ins|Hom|PgU| |NmL| /| *| -| + * |-----------------------------------------------------------| |-----------| |---------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | + * |-----------------------------------------------------------| `-----------' |-----------| +| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #|Retu| | 4| 5| 6| | + * |-----------------------------------------------------------| ,---. |---------------| + * |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------| ,-----------. |-----------|Ent| + * |Ctrl| |Alt | Space |Alt | |Ctrl| |Lef|Dow|Rig| | 0| .| | + * `----' `---------------------------------------' `----' `-----------' `---------------' + */ +/* + KEYMAP( + F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, + F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, + + PSCR,ESC, GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, + SLCK,INT4, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, + PAUS,INT5, CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, UP, P4, P5, P6, PCMM, + APP, INT6, LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RO, RSFT, LEFT,INT2,RGHT, P1, P2, P3, PENT, + RGUI,LGUI, LCTL, LALT, SPC, RALT, RCTL, DOWN, NO, P0, PDOT,NO + ), +*/ + /* + KEYMAP( + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,TRNS,TRNS,TRNS + ), + */ + // pseudo ANSI + + KEYMAP( + FN0, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, + PSCR,PAUS,PGUP,PGDN,HOME,END, INS, DEL, LEFT,DOWN,UP, RGHT, + + NO, NO, ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, GRV, BSPC, NO, NO, NO, NO, NO, NO, NO, + NO, NO, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, NO, NO, NO, NO, NO, NO, NO, + NO, NO, LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT, BSLS,ENT, NO, NO, NO, NO, NO, + NO, NO, LSFT,FN1 ,Z, X, C, V, B, N, M, COMM,DOT, SLSH, FN1, RSFT, NO, NO, NO, NO, NO, NO, NO, + NO, NO, LCTL, LALT, SPC, LGUI, APP, NO, NO, NO, NO, NO + ), + + // Momentary Function Layer + KEYMAP( + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + TRNS,MUTE,VOLD,VOLU,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + + TRNS,TRNS, TRNS,F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,HOME,UP ,END, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,MS_L,MS_D,MS_U,MS_R,LEFT,DOWN, RGHT,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PGUP,PGDN,TRNS, TRNS,RSFT, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, BTN2, TRNS, BTN1, RALT, RCTL, TRNS, TRNS,TRNS,TRNS,TRNS + ), + + // Mouse Layer + KEYMAP( + FN0, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,NO, TRNS, NO, NO, NO, NO, NO, NO, NO, + TRNS,TRNS, TRNS,NO, NO, MS_U,NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, TRNS, NO, NO, NO, NO, NO, NO, NO, + TRNS,TRNS, BTN2,BTN1,MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,NO, NO, NO, ENT, NO, NO, NO, NO, NO, + TRNS,TRNS, TRNS,TRNS,NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, RSFT, NO, NO, NO, NO, NO, NO, NO, + TRNS,TRNS, TRNS, TRNS, BTN1, BTN2, TRNS, NO, NO, NO, NO, NO + ), + + // vi Layer + KEYMAP( + FN0, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,NO, TRNS, NO, NO, NO, NO, NO, NO, NO, + TRNS,TRNS, TRNS,HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, TRNS, NO, NO, NO, NO, NO, NO, NO, + TRNS,TRNS, TRNS,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, NO, ENT, NO, NO, NO, NO, NO, + TRNS,TRNS, TRNS,TRNS,NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, RSFT, NO, NO, NO, NO, NO, NO, NO, + TRNS,TRNS, TRNS, TRNS, SPC, RALT, RCTL, NO, NO, NO, NO, NO + ), + + // num lock layer + KEYMAP( + FN0, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, + + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, + TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,TRNS,TRNS,TRNS + ), + +}; + + +static const uint16_t fn_actions[] PROGMEM = { + [0] = ACTION_DEFAULT_LAYER_SET(0), + [1] = ACTION_LAYER_MOMENTARY(1), + [2] = ACTION_LAYER_MOMENTARY(2), //ACTION_LAYER_ON(2, ON_RELEASE), + [3] = KC_NO, //ACTION_LAYER_ON(3, ON_RELEASE), + [4] = KC_NO, //ACTION_LAYER_ON(4, ON_RELEASE), + [5] = KC_NO, + [6] = KC_NO, + [7] = KC_NO, +}; + +/* +enum macro_id { + MS_UL, + MS_UR, + MS_DL, + MS_DR, +}; + +const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) +{ + keyevent_t event = record->event; + + switch (id) { + case MS_UL: + return (event.pressed ? MACRO( D(MS_L), D(MS_U), END ) : MACRO( U(MS_L), U(MS_U), END ) ); + case MS_UR: + return (event.pressed ? MACRO( D(MS_R), D(MS_U), END ) : MACRO( U(MS_L), U(MS_U), END ) ); + case MS_DL: + return (event.pressed ? MACRO( D(MS_L), D(MS_D), END ) : MACRO( U(MS_L), U(MS_U), END ) ); + case MS_DR: + return (event.pressed ? MACRO( D(MS_R), D(MS_D), END ) : MACRO( U(MS_L), U(MS_U), END ) ); + } + return MACRO_NONE; +} +*/ + +uint8_t keymap_key_to_keycode(uint8_t layer, key_t key) +{ + return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); +} + +action_t keymap_fn_to_action(uint8_t keycode) +{ + action_t action; + action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]); + return action; +} diff --git a/converter/terminal_bluefruit/led.c b/converter/terminal_bluefruit/led.c new file mode 100644 index 0000000000..e5bf41d4ab --- /dev/null +++ b/converter/terminal_bluefruit/led.c @@ -0,0 +1,35 @@ +/* +Converter for 70% IBM Terminal Keyboard +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdint.h" +#include "ps2.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + uint8_t ps2_led = 0; + if (usb_led & (1<<USB_LED_SCROLL_LOCK)) + ps2_led |= (1<<PS2_LED_SCROLL_LOCK); + if (usb_led & (1<<USB_LED_NUM_LOCK)) + ps2_led |= (1<<PS2_LED_NUM_LOCK); + if (usb_led & (1<<USB_LED_CAPS_LOCK)) + ps2_led |= (1<<PS2_LED_CAPS_LOCK); + ps2_host_set_led(ps2_led); +} diff --git a/converter/terminal_bluefruit/matrix.c b/converter/terminal_bluefruit/matrix.c new file mode 100644 index 0000000000..36901536f1 --- /dev/null +++ b/converter/terminal_bluefruit/matrix.c @@ -0,0 +1,262 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "debug.h" +#include "ps2.h" +#include "matrix.h" + + +static void matrix_make(uint8_t code); +static void matrix_break(uint8_t code); +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); +#endif + + +/* + * Matrix Array usage: + * 'Scan Code Set 3' is assigned into 17x8 cell matrix. + * + * 8bit wide + * +---------+ + * 0| | + * :| | 0x00-0x87 + * ;| | + * 17| | + * +---------+ + */ +static uint8_t matrix[MATRIX_ROWS]; +#define ROW(code) (code>>3) +#define COL(code) (code&0x07) + +static bool is_modified = false; + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + debug_enable = true; + //debug_matrix = true; + //debug_keyboard = true; + //debug_mouse = false; + + ps2_host_init(); + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; + + return; +} + +uint8_t matrix_scan(void) +{ + + // scan code reading states + static enum { + RESET, + RESET_RESPONSE, + KBD_ID0, + KBD_ID1, + CONFIG, + READY, + F0, + } state = RESET; + + is_modified = false; + + uint8_t code; + if ((code = ps2_host_recv())) { + debug("r"); debug_hex(code); debug(" "); + } + + switch (state) { + case RESET: + debug("wFF "); + if (ps2_host_send(0xFF) == 0xFA) { + debug("[ack]\nRESET_RESPONSE: "); + state = RESET_RESPONSE; + } + break; + case RESET_RESPONSE: + if (code == 0xAA) { + debug("[ok]\nKBD_ID: "); + state = KBD_ID0; + } else if (code) { + debug("err\nRESET: "); + state = RESET; + } + break; + // after reset receive keyboad ID(2 bytes) + case KBD_ID0: + if (code) { + state = KBD_ID1; + } + break; + case KBD_ID1: + if (code) { + debug("\nCONFIG: "); + state = CONFIG; + } + break; + case CONFIG: + debug("wF8 "); + if (ps2_host_send(0xF8) == 0xFA) { + debug("[ack]\nREADY\n"); + state = READY; + } + break; + case READY: + switch (code) { + case 0x00: + break; + case 0xF0: + state = F0; + debug(" "); + break; + default: // normal key make + if (code < 0x88) { + matrix_make(code); + } else { + debug("unexpected scan code at READY: "); debug_hex(code); debug("\n"); + } + state = READY; + debug("\n"); + } + break; + case F0: // Break code + switch (code) { + case 0x00: + break; + default: + if (code < 0x88) { + matrix_break(code); + } else { + debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); + } + state = READY; + debug("\n"); + } + break; + } + return 1; +} + +bool matrix_is_modified(void) +{ + return is_modified; +} + +inline +bool matrix_has_ghost(void) +{ +#ifdef MATRIX_HAS_GHOST + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + if (matrix_has_ghost_in_row(i)) + return true; + } +#endif + return false; +} + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & (1<<col)); +} + +inline +uint8_t matrix_get_row(uint8_t row) +{ + return matrix[row]; +} + +void matrix_print(void) +{ + print("\nr/c 01234567\n"); + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); + pbin_reverse(matrix_get_row(row)); +#ifdef MATRIX_HAS_GHOST + if (matrix_has_ghost_in_row(row)) { + print(" <ghost"); + } +#endif + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += bitpop(matrix[i]); + } + return count; +} + +#ifdef MATRIX_HAS_GHOST +inline +static bool matrix_has_ghost_in_row(uint8_t row) +{ + // no ghost exists in case less than 2 keys on + if (((matrix[row] - 1) & matrix[row]) == 0) + return false; + + // ghost exists in case same state as other row + for (uint8_t i=0; i < MATRIX_ROWS; i++) { + if (i != row && (matrix[i] & matrix[row]) == matrix[row]) + return true; + } + return false; +} +#endif + + +inline +static void matrix_make(uint8_t code) +{ + if (!matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] |= 1<<COL(code); + is_modified = true; + } +} + +inline +static void matrix_break(uint8_t code) +{ + if (matrix_is_on(ROW(code), COL(code))) { + matrix[ROW(code)] &= ~(1<<COL(code)); + is_modified = true; + } +} diff --git a/doc/keymap.md b/doc/keymap.md index 11e80a9c31..3a549de62e 100644 --- a/doc/keymap.md +++ b/doc/keymap.md @@ -526,6 +526,12 @@ Say you want to type 'The', you have to push and hold Shift key before type 't' Oneshot effect is cancel unless following key is pressed down within `ONESHOT_TIMEOUT` of `config.h`. No timeout when it is `0` or not defined. +### 4.4 Tap Toggle Mods +Similar to layer tap toggle, this works as a momentary modifier when holding, but toggles on with several taps. A single tap will 'unstick' the modifier again. + + ACTION_MODS_TAP_TOGGLE(MOD_LSFT) + + ## 5. Legacy Keymap diff --git a/keyboard/onekey/Makefile.lufa b/keyboard/onekey/Makefile index 60a84ba00d..78732e470d 100644 --- a/keyboard/onekey/Makefile.lufa +++ b/keyboard/onekey/Makefile @@ -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) diff --git a/keyboard/onekey/README.md b/keyboard/onekey/README.md index 6ccc999299..7413f3880e 100644 --- a/keyboard/onekey/README.md +++ b/keyboard/onekey/README.md @@ -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 diff --git a/keyboard/onekey/config.h b/keyboard/onekey/config.h index 1d2e052bf0..bf1d2b1ed3 100644 --- a/keyboard/onekey/config.h +++ b/keyboard/onekey/config.h @@ -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 diff --git a/keyboard/onekey/matrix.c b/keyboard/onekey/matrix.c index a0a14ff821..29df868321 100644 --- a/keyboard/onekey/matrix.c +++ b/keyboard/onekey/matrix.c @@ -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; } } diff --git a/protocol.mk b/protocol.mk index 0d5f06c7ec..7f561e62d6 100644 --- a/protocol.mk +++ b/protocol.mk @@ -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 diff --git a/protocol/bluefruit.mk b/protocol/bluefruit.mk new file mode 100644 index 0000000000..7e6328f6cb --- /dev/null +++ b/protocol/bluefruit.mk @@ -0,0 +1,27 @@ +BLUEFRUIT_DIR = protocol/bluefruit +PJRC_DIR = protocol/pjrc + +SRC += $(BLUEFRUIT_DIR)/main.c \ + $(BLUEFRUIT_DIR)/bluefruit.c \ + serial_uart.c \ + $(PJRC_DIR)/pjrc.c \ + $(PJRC_DIR)/usb_keyboard.c \ + $(PJRC_DIR)/usb_debug.c \ + $(PJRC_DIR)/usb.c + +# Option modules +ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) + SRC += $(PJRC_DIR)/usb_mouse.c +endif + +ifdef EXTRAKEY_ENABLE + SRC += $(PJRC_DIR)/usb_extra.c +endif + +# Search Path +VPATH += $(TOP_DIR)/$(BLUEFRUIT_DIR) +#VPATH += $(TOP_DIR)/$(BLUEFRUIT_DIR)/usb_debug_only +VPATH += $(TOP_DIR)/$(PJRC_DIR) + +OPT_DEFS += -DPROTOCOL_BLUEFRUIT +OPT_DEFS += -DPROTOCOL_PJRC diff --git a/protocol/bluefruit/bluefruit.c b/protocol/bluefruit/bluefruit.c new file mode 100644 index 0000000000..f991e4d04e --- /dev/null +++ b/protocol/bluefruit/bluefruit.c @@ -0,0 +1,202 @@ +/* +Bluefruit Protocol for TMK firmware +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <stdint.h> +#include "host.h" +#include "report.h" +#include "print.h" +#include "debug.h" +#include "host_driver.h" +#include "serial.h" +#include "bluefruit.h" + +#define BLUEFRUIT_TRACE_SERIAL 1 + +static uint8_t bluefruit_keyboard_leds = 0; + +static void bluefruit_serial_send(uint8_t); + +void bluefruit_keyboard_print_report(report_keyboard_t *report) +{ + if (!debug_keyboard) return; + dprintf("keys: "); for (int i = 0; i < REPORT_KEYS; i++) { debug_hex8(report->keys[i]); dprintf(" "); } + dprintf(" mods: "); debug_hex8(report->mods); + dprintf(" reserved: "); debug_hex8(report->reserved); + dprintf("\n"); +} + +#ifdef BLUEFRUIT_TRACE_SERIAL +static void bluefruit_trace_header() +{ + dprintf("+------------------------------------+\n"); + dprintf("| HID report to Bluefruit via serial |\n"); + dprintf("+------------------------------------+\n|"); +} + +static void bluefruit_trace_footer() +{ + dprintf("|\n+------------------------------------+\n\n"); +} +#endif + +static void bluefruit_serial_send(uint8_t data) +{ +#ifdef BLUEFRUIT_TRACE_SERIAL + dprintf(" "); + debug_hex8(data); + dprintf(" "); +#endif + serial_send(data); +} + +/*------------------------------------------------------------------* + * Host driver + *------------------------------------------------------------------*/ + +static uint8_t keyboard_leds(void); +static void send_keyboard(report_keyboard_t *report); +static void send_mouse(report_mouse_t *report); +static void send_system(uint16_t data); +static void send_consumer(uint16_t data); + +static host_driver_t driver = { + keyboard_leds, + send_keyboard, + send_mouse, + send_system, + send_consumer +}; + +host_driver_t *bluefruit_driver(void) +{ + return &driver; +} + +static uint8_t keyboard_leds(void) { + return bluefruit_keyboard_leds; +} + +static void send_keyboard(report_keyboard_t *report) +{ +#ifdef BLUEFRUIT_TRACE_SERIAL + bluefruit_trace_header(); +#endif + bluefruit_serial_send(0xFD); + for (uint8_t i = 0; i < REPORT_SIZE; i++) { + bluefruit_serial_send(report->raw[i]); + } +#ifdef BLUEFRUIT_TRACE_SERIAL + bluefruit_trace_footer(); +#endif +} + +static void send_mouse(report_mouse_t *report) +{ +#ifdef BLUEFRUIT_TRACE_SERIAL + bluefruit_trace_header(); +#endif + bluefruit_serial_send(0xFD); + bluefruit_serial_send(0x00); + bluefruit_serial_send(0x03); + bluefruit_serial_send(report->buttons); + bluefruit_serial_send(report->x); + bluefruit_serial_send(report->y); + bluefruit_serial_send(report->v); // should try sending the wheel v here + bluefruit_serial_send(report->h); // should try sending the wheel h here + bluefruit_serial_send(0x00); +#ifdef BLUEFRUIT_TRACE_SERIAL + bluefruit_trace_footer(); +#endif +} + +static void send_system(uint16_t data) +{ +} + +/* ++-----------------+-------------------+-------+ +| Consumer Key | Bit Map | Hex | ++-----------------+-------------------+-------+ +| Home | 00000001 00000000 | 01 00 | +| KeyboardLayout | 00000010 00000000 | 02 00 | +| Search | 00000100 00000000 | 04 00 | +| Snapshot | 00001000 00000000 | 08 00 | +| VolumeUp | 00010000 00000000 | 10 00 | +| VolumeDown | 00100000 00000000 | 20 00 | +| Play/Pause | 01000000 00000000 | 40 00 | +| Fast Forward | 10000000 00000000 | 80 00 | +| Rewind | 00000000 00000001 | 00 01 | +| Scan Next Track | 00000000 00000010 | 00 02 | +| Scan Prev Track | 00000000 00000100 | 00 04 | +| Random Play | 00000000 00001000 | 00 08 | +| Stop | 00000000 00010000 | 00 10 | ++-------------------------------------+-------+ +*/ +#define CONSUMER2BLUEFRUIT(usage) \ + (usage == AUDIO_MUTE ? 0x0000 : \ + (usage == AUDIO_VOL_UP ? 0x1000 : \ + (usage == AUDIO_VOL_DOWN ? 0x2000 : \ + (usage == TRANSPORT_NEXT_TRACK ? 0x0002 : \ + (usage == TRANSPORT_PREV_TRACK ? 0x0004 : \ + (usage == TRANSPORT_STOP ? 0x0010 : \ + (usage == TRANSPORT_STOP_EJECT ? 0x0000 : \ + (usage == TRANSPORT_PLAY_PAUSE ? 0x4000 : \ + (usage == AL_CC_CONFIG ? 0x0000 : \ + (usage == AL_EMAIL ? 0x0000 : \ + (usage == AL_CALCULATOR ? 0x0000 : \ + (usage == AL_LOCAL_BROWSER ? 0x0000 : \ + (usage == AC_SEARCH ? 0x0400 : \ + (usage == AC_HOME ? 0x0100 : \ + (usage == AC_BACK ? 0x0000 : \ + (usage == AC_FORWARD ? 0x0000 : \ + (usage == AC_STOP ? 0x0000 : \ + (usage == AC_REFRESH ? 0x0000 : \ + (usage == AC_BOOKMARKS ? 0x0000 : 0))))))))))))))))))) + +static void send_consumer(uint16_t data) +{ + static uint16_t last_data = 0; + if (data == last_data) return; + last_data = data; + + uint16_t bitmap = CONSUMER2BLUEFRUIT(data); + +#ifdef BLUEFRUIT_TRACE_SERIAL + dprintf("\nData: "); + debug_hex16(data); + dprintf("; bitmap: "); + debug_hex16(bitmap); + dprintf("\n"); + bluefruit_trace_header(); +#endif + bluefruit_serial_send(0xFD); + bluefruit_serial_send(0x00); + bluefruit_serial_send(0x02); + bluefruit_serial_send((bitmap>>8)&0xFF); + bluefruit_serial_send(bitmap&0xFF); + bluefruit_serial_send(0x00); + bluefruit_serial_send(0x00); + bluefruit_serial_send(0x00); + bluefruit_serial_send(0x00); +#ifdef BLUEFRUIT_TRACE_SERIAL + bluefruit_trace_footer(); +#endif +} + diff --git a/protocol/bluefruit/bluefruit.h b/protocol/bluefruit/bluefruit.h new file mode 100644 index 0000000000..4f9b58836d --- /dev/null +++ b/protocol/bluefruit/bluefruit.h @@ -0,0 +1,28 @@ +/* +Bluefruit Protocol for TMK firmware +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef VUSB_H +#define VUSB_H + +#include "host_driver.h" + + +host_driver_t *bluefruit_driver(void); + +#endif diff --git a/protocol/bluefruit/main.c b/protocol/bluefruit/main.c new file mode 100644 index 0000000000..871062ab11 --- /dev/null +++ b/protocol/bluefruit/main.c @@ -0,0 +1,116 @@ +/* +Bluefruit Protocol for TMK firmware +Author: Benjamin Gould, 2013 +Based on code Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <avr/sleep.h> +#include <util/delay.h> +#include "serial.h" +#include "keyboard.h" +#include "usb.h" +#include "host.h" +#include "timer.h" +#include "print.h" +#include "debug.h" +#include "sendchar.h" +#include "suspend.h" +#include "bluefruit.h" +#include "pjrc.h" + +#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) + +#define HOST_DRIVER_NOT_SET 0 +#define BLUEFRUIT_HOST_DRIVER 1 +#define PJRC_HOST_DRIVER 2 + +int main(void) +{ + + CPU_PRESCALE(0); + + DDRD = _BV(PD5); + DDRB = _BV(PB0); + + PORTD = _BV(PD5); + PORTB = _BV(PB0); + + print_set_sendchar(sendchar); + + usb_init(); + _delay_ms(2000); + // while (!usb_configured()) /* wait */ + + dprintf("Initializing keyboard...\n"); + keyboard_init(); + + // This implementation is pretty simplistic... if the USB connection + // is not configured, choose the Bluefruit, otherwise use USB + // Definitely would prefer to have this driven by an input pin and make + // it switch dynamically - BCG + if (!usb_configured()) { + + // Send power to Bluefruit... Adafruit says it takes 27 mA, I think + // the pins should provide 40 mA, but just in case I switch the + // Bluefruit using a transistor - BCG + DDRB = _BV(PB6); + PORTB |= _BV(PB6); + + dprintf("Setting host driver to bluefruit...\n"); + host_set_driver(bluefruit_driver()); + + dprintf("Initializing serial...\n"); + serial_init(); + + // wait an extra second for the PC's operating system + // to load drivers and do whatever it does to actually + // be ready for input + _delay_ms(1000); + PORTD = ~_BV(PD5); + dprintf("Starting main loop"); + while (1) { + keyboard_task(); + } + + } else { + + // I'm not smart enough to get this done with LUFA - BCG + dprintf("Setting host driver to PJRC...\n"); + host_set_driver(pjrc_driver()); +#ifdef SLEEP_LED_ENABLE + sleep_led_init(); +#endif + // wait an extra second for the PC's operating system + // to load drivers and do whatever it does to actually + // be ready for input + _delay_ms(1000); + PORTB = ~_BV(PB0); + dprintf("Starting main loop"); + while (1) { + while (suspend) { + suspend_power_down(); + if (remote_wakeup && suspend_wakeup_condition()) { + usb_remote_wakeup(); + } + } + keyboard_task(); + } + } + +} diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index 04e8e78f38..eca51c8784 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c @@ -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) diff --git a/protocol/pjrc/usb.c b/protocol/pjrc/usb.c index 84c99972f2..393b36f78e 100644 --- a/protocol/pjrc/usb.c +++ b/protocol/pjrc/usb.c @@ -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); diff --git a/protocol/ps2.h b/protocol/ps2.h index 834165356c..483eea7209 100644 --- a/protocol/ps2.h +++ b/protocol/ps2.h @@ -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 diff --git a/protocol/ps2_busywait.c b/protocol/ps2_busywait.c new file mode 100644 index 0000000000..05dd7b27e6 --- /dev/null +++ b/protocol/ps2_busywait.c @@ -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); +} diff --git a/protocol/ps2.c b/protocol/ps2_interrupt.c index e5873a9bfa..259d254007 100644 --- a/protocol/ps2.c +++ b/protocol/ps2_interrupt.c @@ -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(); -} diff --git a/protocol/ps2_usart.c b/protocol/ps2_usart.c index 40c46c497c..c2d9d0a208 100644 --- a/protocol/ps2_usart.c +++ b/protocol/ps2_usart.c @@ -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; |