Conflicts: common.mk common/keyboard.c keyboard/gh60/Makefile keyboard/gh60/keymap_hasu.c keyboard/gh60/matrix.cled_matrix
@@ -25,6 +25,7 @@ endif | |||
ifdef MOUSEKEY_ENABLE | |||
SRC += $(COMMON_DIR)/mousekey.c | |||
OPT_DEFS += -DMOUSEKEY_ENABLE | |||
OPT_DEFS += -DMOUSE_ENABLE | |||
endif | |||
ifdef EXTRAKEY_ENABLE | |||
@@ -47,20 +48,6 @@ ifdef NKRO_ENABLE | |||
OPT_DEFS += -DNKRO_ENABLE | |||
endif | |||
ifdef PS2_MOUSE_ENABLE | |||
SRC += $(COMMON_DIR)/ps2.c \ | |||
$(COMMON_DIR)/ps2_mouse.c | |||
OPT_DEFS += -DPS2_MOUSE_ENABLE | |||
endif | |||
ifdef MOUSEKEY_ENABLE | |||
OPT_DEFS += -DMOUSE_ENABLE | |||
endif | |||
ifdef PS4_MOUSE_ENABLE | |||
OPT_DEFS += -DMOUSE_ENABLE | |||
endif | |||
ifdef SLEEP_LED_ENABLE | |||
SRC += $(COMMON_DIR)/sleep_led.c | |||
OPT_DEFS += -DSLEEP_LED_ENABLE |
@@ -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) { | |||
@@ -485,12 +496,6 @@ void clear_keyboard_but_mods(void) | |||
#endif | |||
} | |||
bool sending_anykey(void) | |||
{ | |||
return (has_anykey() || host_mouse_in_use() || | |||
host_last_sysytem_report() || host_last_consumer_report()); | |||
} | |||
bool is_tap_key(key_t key) | |||
{ | |||
action_t action = layer_switch_get_action(key); |
@@ -64,7 +64,6 @@ void unregister_mods(uint8_t mods); | |||
//void set_mods(uint8_t mods); | |||
void clear_keyboard(void); | |||
void clear_keyboard_but_mods(void); | |||
bool sending_anykey(void); | |||
void layer_switch(uint8_t new_layer); | |||
bool is_tap_key(key_t key); | |||
@@ -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(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) | |||
/* |
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#define ACTION_UTIL_H | |||
#include <stdint.h> | |||
#include "report.h" | |||
extern report_keyboard_t *keyboard_report; | |||
@@ -27,9 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
bool keyboard_nkro = false; | |||
#endif | |||
report_mouse_t mouse_report = {}; | |||
static host_driver_t *driver; | |||
static uint16_t last_system_report = 0; | |||
static uint16_t last_consumer_report = 0; | |||
@@ -89,11 +86,6 @@ void host_consumer_send(uint16_t report) | |||
(*driver->send_consumer)(report); | |||
} | |||
uint8_t host_mouse_in_use(void) | |||
{ | |||
return (mouse_report.buttons | mouse_report.x | mouse_report.y | mouse_report.v | mouse_report.h); | |||
} | |||
uint16_t host_last_sysytem_report(void) | |||
{ | |||
return last_system_report; |
@@ -32,9 +32,6 @@ extern "C" { | |||
extern bool keyboard_nkro; | |||
#endif | |||
/* report */ | |||
extern report_mouse_t mouse_report; | |||
/* host driver */ | |||
void host_set_driver(host_driver_t *driver); | |||
@@ -47,9 +44,6 @@ void host_mouse_send(report_mouse_t *report); | |||
void host_system_send(uint16_t data); | |||
void host_consumer_send(uint16_t data); | |||
/* mouse report utils */ | |||
uint8_t host_mouse_in_use(void); | |||
uint16_t host_last_sysytem_report(void); | |||
uint16_t host_last_consumer_report(void); | |||
@@ -30,9 +30,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "sendchar.h" | |||
#include "bootmagic.h" | |||
#include "eeconfig.h" | |||
#include "mousekey.h" | |||
#include "backlight.h" | |||
#include "keymap_ex.h" | |||
#ifdef MOUSEKEY_ENABLE | |||
# include "mousekey.h" | |||
#endif | |||
#ifdef PS2_MOUSE_ENABLE | |||
# include "ps2_mouse.h" | |||
#endif | |||
#ifdef MATRIX_HAS_GHOST | |||
@@ -116,10 +121,16 @@ void keyboard_task(void) | |||
action_exec(TICK); | |||
MATRIX_LOOP_END: | |||
#ifdef MOUSEKEY_ENABLE | |||
// mousekey repeat & acceleration | |||
mousekey_task(); | |||
#endif | |||
#ifdef PS2_MOUSE_ENABLE | |||
ps2_mouse_task(); | |||
#endif | |||
// update LED | |||
if (led_status != host_keyboard_leds()) { | |||
led_status = host_keyboard_leds(); |
@@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
static report_mouse_t mouse_report = {}; | |||
static uint8_t mousekey_repeat = 0; | |||
static uint8_t mousekey_accel = 0; | |||
@@ -88,12 +88,26 @@ void matrix_init(void) | |||
uint8_t matrix_scan(void) | |||
{ | |||
/* extra_key is volatile and more convoluted than necessary because gcc refused | |||
to generate valid code otherwise. Making extra_key uint8_t and constructing codes | |||
here via codes = extra_key<<8 | 0xFF; would consistently fail to even LOAD | |||
extra_key from memory, and leave garbage in the high byte of codes. I tried | |||
dozens of code variations and it kept generating broken assembly output. So | |||
beware if attempting to make extra_key code more logical and efficient. */ | |||
static volatile uint16_t extra_key = 0xFFFF; | |||
uint16_t codes; | |||
uint8_t key0, key1; | |||
is_modified = false; | |||
_delay_ms(12); // delay for preventing overload of poor ADB keyboard controller | |||
codes = adb_host_kbd_recv(); | |||
codes = extra_key; | |||
extra_key = 0xFFFF; | |||
if ( codes == 0xFFFF ) | |||
{ | |||
_delay_ms(12); // delay for preventing overload of poor ADB keyboard controller | |||
codes = adb_host_kbd_recv(); | |||
} | |||
key0 = codes>>8; | |||
key1 = codes&0xFF; | |||
@@ -113,7 +127,7 @@ uint8_t matrix_scan(void) | |||
} else { | |||
register_key(key0); | |||
if (key1 != 0xFF) // key1 is 0xFF when no second key. | |||
register_key(key1); | |||
extra_key = key1<<8 | 0xFF; // process in a separate call | |||
} | |||
return 1; |
@@ -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 | |||
# 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 | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_plain.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
# 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 |
@@ -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 |
@@ -1,122 +0,0 @@ | |||
PS/2 to USB keyboard converter | |||
============================== | |||
This firmware converts PS/2 keyboard protocol to USB and supports only Scan Code Set 2. | |||
This will works on USB AVR(ATMega32U4, AT90USB) or V-USB(ATMega168, 328...). | |||
Features | |||
-------- | |||
Mouse keys | |||
You can emulates mouse move and button click using keyboard. | |||
System/Media control | |||
You can sends Power event, Volume down/up and Mute. | |||
USB NKRO(actually 120KRO+8Modifiers) | |||
You can tolggles NKRO feature. | |||
Keymap customization | |||
You can customize keymaps easily by editing source code. See keymap.c. | |||
PS/2 signal handling implementations | |||
------------------------------------ | |||
Following three methods are used to implement PS/2 signal handling. | |||
a. Simple and stupid busy-wait(ps2.c) | |||
This is expected to implemented with portable C code for reference. | |||
b. Interrupt driven(ps2.c) | |||
Uses external interrupt to detect falling edge of clock line. | |||
c. USART hardware module(ps2_usart.c) | |||
Uses AVR USART engine to recevie PS/2 signal. Recomended and default. | |||
This is required to work with V-USB, preceding two methods tend to | |||
miss signal edges while V-USB handles USB. | |||
To select method edit Makefile. | |||
Connect Wires | |||
------------- | |||
In case of Teensy2.0(ATMega32U4): | |||
0. Connect Vcc and GND. | |||
1. Connect Clock and Data line. | |||
For a. Clock is on PF0 and Data on PF1. | |||
For b. Clock is on PD1 and Data on PD2. | |||
For c. Clock is on PD5 and Data on PD2. | |||
2. Optionally you need pull-up register. 1K-10K Ohm is OK. | |||
To change pin configuration edit config.h. | |||
Build Frimware | |||
-------------- | |||
1. Edit Makefile for build options and MCU setting. | |||
Use 'atmega32u4' for Teensy 2.0 or 'at90usb1286' for Teensy++ 2.0. | |||
2. make | |||
Just type `make` in a terminal. | |||
Use `-f Makefile.vusb` option to build V-USB converter. | |||
Use `-f Makefile.jis` option to use JIS keyboard. | |||
3. program MCU. | |||
In case of Teensy use `Teensy Loader`.(http://www.pjrc.com/teensy/loader.html) | |||
Otherwise you want to use `avrdude` or `dfu-programmer`. | |||
Demonstration of Features | |||
------------------------- | |||
In default configuration, you can try several keymaps, mousekeys and USB NKRO. | |||
Use following magic key combinations to enable some features. | |||
keymaps and NKRO: | |||
Magic+0: Qwerty with mousekeys(default) | |||
Magic+1: Qwerty without mousekeys | |||
Magic+2: Colemak | |||
Magic+3: Dvorak | |||
Magic+4: Workman | |||
Magic+N: toggles NKRO/6KRO(6KRO by default) | |||
Magic+Esc: sends Power Event(Power button) | |||
where Magic=(LShift+RShift) or (LControl+RShift) | |||
Fn layer function: | |||
Fn0+(hjkl): Mousekey move(vi cursor like) | |||
Fn0+(yuio): Mouse wheel(left,down,up,right) | |||
Fn0+space: Mouse left button | |||
Fn0+(mnb): Mouse buttons(m=left, n=right, b=middle) | |||
Fn0+(zxc): Media control(Volup, Voldown, Mute) | |||
Fn1+(hjkl): Cursor move(vi cursor like) | |||
Fn1+(nm,.): Cursor move(Home,PageDown,PageUp,End) | |||
where Fn0=;, Fn1=/ | |||
Keymap | |||
------ | |||
You can change a keymap by editing code of keymap. See common/keycode.h for key symbols. | |||
V-USB Support | |||
------------- | |||
You can also use this converter on ATmega(168/328) with V-USB instead of Teensy. | |||
The converter on V-USB lacks some features for now: USB NKRO and System/Media control. | |||
Circuit | |||
------- | |||
+---+ +---------------+ | |||
USB GND | | ATmega168 | | |||
=== C3 | | | |||
5V <-------+--------+---|Vcc,AVCC | PS/2 | |||
R1 | | ==== | |||
D- <----+--+-----R2-----|INT1 RXD|------->DATA | |||
D+ <----|---+----R3-----|INT0 XCK|------->CLOCK | |||
Z1 Z2 | | ->5V | |||
GND<----+---+--+--+-----|GND | ->GND | |||
| | | | | |||
| C2-+--|XTAL1 | | |||
| X1 | | | |||
+--C3-+--|XTAL2 | | |||
+---------------+ | |||
R1: 1.5K Ohm | |||
R2,R3: 68 Ohm | |||
Z1,Z2: Zenner 3.6V | |||
C1,C2: 22pF | |||
C3: 0.1uF | |||
X1: Crystal 20MHz(16MHz/12MHz) | |||
EOF |
@@ -0,0 +1,76 @@ | |||
PS/2 to USB keyboard converter | |||
============================== | |||
This firmware converts PS/2 keyboard protocol to USB and supports only Scan Code Set 2. | |||
PS/2 signal handling implementations | |||
------------------------------------ | |||
Following three methods are used to implement PS/2 signal handling. | |||
### Simple and stupid busy-wait(ps2_busywait.c) | |||
This is expected to implemented with portable C code for reference. | |||
### Interrupt driven(ps2_interrupt.c) | |||
Uses pin interrupt to detect falling edge of clock line. | |||
### USART hardware module(ps2_usart.c) | |||
Uses AVR USART engine to recevie PS/2 signal. | |||
To select method edit Makefile. | |||
Connect Wires | |||
------------- | |||
In case of Teensy2.0(ATMega32U4): | |||
1. Connect Vcc and GND. | |||
2. Connect Clock and Data line. | |||
- Busywait: Clock is on PD5 and Data on PD2. | |||
- Interrupt: Clock is on PD1 and Data on PD2. | |||
- USART: Clock is on PD5 and Data on PD2. | |||
3. Optionally you need pull-up register. 1K-10K Ohm is OK. | |||
To change pin configuration edit config.h. | |||
Build Frimware | |||
-------------- | |||
Just run `make`: | |||
$ make | |||
To select keymap: | |||
$ make KEYMAP=[plain|jis|spacefn|...] | |||
Keymap | |||
------ | |||
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `keymap_<name>.c` and see keymap document(you can find in top README.md) and existent keymap files. | |||
V-USB Support | |||
------------- | |||
You can also use this converter on ATmega(168/328) with V-USB instead of Teensy. | |||
The converter on V-USB lacks some features for now: USB NKRO and System/Media control. | |||
Circuit: | |||
+---+ +---------------+ | |||
USB GND | | ATmega168 | | |||
=== C3 | | | |||
5V <-------+--------+---|Vcc,AVCC | PS/2 | |||
R1 | | ==== | |||
D- <----+--+-----R2-----|INT1 RXD|------->DATA | |||
D+ <----|---+----R3-----|INT0 XCK|------->CLOCK | |||
Z1 Z2 | | ->5V | |||
GND<----+---+--+--+-----|GND | ->GND | |||
| | | | | |||
| C2-+--|XTAL1 | | |||
| X1 | | | |||
+--C3-+--|XTAL2 | | |||
+---------------+ | |||
R1: 1.5K Ohm | |||
R2,R3: 68 Ohm | |||
Z1,Z2: Zenner 3.6V | |||
C1,C2: 22pF | |||
C3: 0.1uF | |||
X1: Crystal 20MHz(16MHz/12MHz) |
@@ -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 |
@@ -1,379 +0,0 @@ | |||
/* | |||
Copyright 2011 Jun Wako <[email protected]> | |||
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]); | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
Copyright 2011,2012,2013 Jun Wako <[email protected]> | |||
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)]) }; | |||
} |
@@ -0,0 +1,174 @@ | |||
/* | |||
Copyright 2011,2012,2013 Jun Wako <[email protected]> | |||
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 |
@@ -1,175 +1,9 @@ | |||
/* | |||
Copyright 2011 Jun Wako <[email protected]> | |||
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 | |||
* JIS layout Japanese 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 }, \ | |||
} | |||
/* 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 \ | |||
) | |||
#define KEYMAP_JIS_COMPACT( \ | |||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, \ | |||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, \ | |||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D, K5A, \ | |||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51, K59, \ | |||
K14,K9F,K11, K67,K29,K64,K13, K91,KA7,KAF,K94 \ | |||
) \ | |||
KEYMAP_ALL( \ | |||
ESC,F1, F2, F3, F4, F5, F6, F7, F8, F9, F10,F11,F12, PSCR,SLCK,BRK, \ | |||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, \ | |||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, DEL, END, PGDN, P7, P8, P9, \ | |||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, P4, P5, P6, PPLS, \ | |||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, UP, P1, P2, P3, \ | |||
K14,K9F,K11, K29, K91,KA7,KAF,K94, LEFT,DOWN,RGHT, P0, PDOT,PENT, \ | |||
\ | |||
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[] = { | |||
1, // Fn0 | |||
2, // Fn1 | |||
1, // Fn2 | |||
2, // Fn3 | |||
3, // Fn4 | |||
4, // 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_BSPC, // Fn2 | |||
KC_NO, // Fn3 | |||
KC_NO, // Fn4 | |||
KC_SPC, // Fn5 | |||
KC_NO, // Fn6 | |||
KC_NO // Fn7 | |||
}; | |||
#include "keymap_common.h" | |||
// 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] = { | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* 0: JIS LAYOUT | |||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. | |||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|Slp|Wak| | |||
@@ -186,7 +20,6 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
* |Ctrl |Gui |Alt |MHEN| Space |HENK|KANA|Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| | 0| .| | | |||
* `-----------------------------------------------------------' `-----------' `---------------' | |||
*/ | |||
/* | |||
KEYMAP_JIS( | |||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||
@@ -195,103 +28,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RO, RSFT, UP, P1, P2, P3, | |||
LCTL,LGUI,LALT, MHEN,SPC, HENK,KANA, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||
), | |||
*/ | |||
/* 0: HHKB-wise | |||
* ,-----------------------------------------------------------. | |||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| | |||
* |-----------------------------------------------------------| | |||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| Bsp | | |||
* |------------------------------------------------------` | | |||
* |Ctrl | A| S| D| F| G| H| J| K| L| ;| :|Ret| | | |||
* |-----------------------------------------------------------| | |||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /| RO|Shift | | |||
* |-----------------------------------------------------------| | |||
* |Ctrl |Gui |Alt |MHEN| Space |HENK|KANA|Alt |Gui |Menu|Ctrl| | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP_JIS_COMPACT( | |||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,BSPC, | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, | |||
LCTL,A, S, D, F, G, H, J, K, L, FN0, QUOT,GRV, ENT, | |||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN1, RSFT, FN4, | |||
LCTL,LGUI,LALT, LALT,FN5, FN2, FN3, RALT,RGUI,APP, LGUI | |||
), | |||
/* 1: Mouse keys | |||
* ,-----------------------------------------------------------. | |||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| | |||
* |-----------------------------------------------------------| | |||
* |Tab |MwL|MwU|McU|WwU|WwR|MwL|MwD|MwU|MwR| | | | \| | |||
* |-----------------------------------------------------------| | |||
* |CapsLo| |McL|McD|McR| |McL|McD|McU|McR|Fn0| |Return | | |||
* |-----------------------------------------------------------| | |||
* |Shift |VoD|VoU|Mut|Mb2|Mb3|Mb2|Mb1|VoD|VoU|Mut|Shift | | |||
* |-----------------------------------------------------------| | |||
* |Ctrl |Gui |Alt | Mb1 |Alt |Gui |Menu|Ctrl| | |||
* `-----------------------------------------------------------' | |||
* Mc = mouse cursor, Mw = mouse wheel, Mb = mouse button | |||
* Vo = Volume, Mut = Mute | |||
*/ | |||
KEYMAP_JIS_COMPACT( | |||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, INS, DEL, | |||
TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, | |||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, NO, ENT, | |||
LSFT,NO, NO, BTN1,BTN2,BTN3,BTN2,BTN1,BTN2,BTN3,NO, RSFT, RSFT, | |||
LCTL,LGUI,LALT, LALT,BTN1,FN2, RALT, RALT,RGUI,APP, LGUI | |||
), | |||
/* 2: Cursor keys | |||
* ,-----------------------------------------------------------. | |||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| | |||
* |-----------------------------------------------------------| | |||
* |Tab |Hom|PgU| Up|PgU|End|Hom|PgD|PgU|End| | | | \| | |||
* |-----------------------------------------------------------| | |||
* |CapsLo| |Lef|Dow|Rig| |Lef|Dow| Up|Rig| | |Return | | |||
* |-----------------------------------------------------------| | |||
* |Shift | | | | | |Hom|PgD|PgU|End|Fn1|Shift | | |||
* |-----------------------------------------------------------| | |||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP_JIS_COMPACT( | |||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, INS, DEL, | |||
TAB, HOME,PGUP,UP, PGDN,END, HOME,PGDN,PGUP,END, NO, NO, NO, | |||
LCTL,HOME,LEFT,DOWN,RGHT,END, LEFT,DOWN,UP, RGHT,NO, NO, NO, ENT, | |||
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN1, RSFT, RSFT, | |||
LCTL,LGUI,LALT, LALT,BTN1,BSPC,FN3, RALT,RGUI,APP, LGUI | |||
), | |||
/* 3: HHKB Fn layer */ | |||
KEYMAP_JIS_COMPACT( | |||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, INS, DEL, | |||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, | |||
LCTL,VOLD,VOLU,MUTE,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT,NO, ENT, | |||
LSFT,NO, NO, NO, NO, NO, NO, NO, END, PGDN,DOWN,RSFT, FN4, | |||
LCTL,LGUI,LALT, LALT,SPC, BSPC,NO, RALT,RGUI,APP, LGUI | |||
), | |||
/* 4: Number */ | |||
KEYMAP_JIS_COMPACT( | |||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, INS, DEL, | |||
TAB, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, | |||
LCTL,1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, ENT, | |||
LSFT,NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, RSFT, RSFT, | |||
LCTL,LGUI,LALT, LALT,FN5, BSPC,NO, RALT,RGUI,APP, LGUI | |||
), | |||
}; | |||
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]); | |||
} | |||
const uint16_t PROGMEM fn_actions[] = { | |||
}; |
@@ -0,0 +1,32 @@ | |||
#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| .| | | |||
* `-----------------------------------------------------------' `-----------' `---------------' | |||
*/ | |||
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[] = { | |||
}; |
@@ -0,0 +1,61 @@ | |||
/* | |||
* SpaceFN layout | |||
* http://geekhack.org/index.php?topic=51069.0 | |||
*/ | |||
#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| .| | | |||
* `-----------------------------------------------------------' `-----------' `---------------' | |||
*/ | |||
KEYMAP( | |||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||
ESC, 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, FN0, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||
), | |||
/* 1: SpaceFN | |||
* ,-----------------------------------------------------------. | |||
* |` | F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | |Hom|Up |End|Psc|Slk|Pau|Ins | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | |PgU|Lef|Dow|Rig| | | | | |||
* |-----------------------------------------------------------| | |||
* | | | | | |Spc|PgD|` |~ | | | | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | | | | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP( | |||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||
TRNS,TRNS,TRNS,ESC, TRNS,TRNS,TRNS,HOME,UP, END, PSCR,SLCK,PAUS,INS, DEL, END, PGDN, P7, P8, P9, | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PGUP,LEFT,DOWN,RGHT,TRNS,TRNS, TRNS, P4, P5, P6, PPLS, | |||
TRNS,TRNS,TRNS,TRNS,TRNS,SPC, PGDN,GRV, FN1, TRNS,TRNS, TRNS, UP, P1, P2, P3, | |||
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||
), | |||
}; | |||
const uint16_t PROGMEM fn_actions[] = { | |||
[0] = ACTION_LAYER_TAP_KEY(1, KC_SPACE), | |||
[1] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV), // tilde | |||
}; | |||
@@ -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; | |||
} |
@@ -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 |
@@ -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 |
@@ -0,0 +1,112 @@ | |||
/* | |||
Converter for 70% IBM Terminal Keyboard | |||
Author: Benjamin Gould, 2013 | |||
Based on code Copyright 2011 Jun Wako <[email protected]> | |||
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 |
@@ -0,0 +1,227 @@ | |||
/* | |||
Converter for 70% IBM Terminal Keyboard | |||
Author: Benjamin Gould, 2013 | |||
Based on code Copyright 2011 Jun Wako <[email protected]> | |||
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; | |||
} |
@@ -0,0 +1,35 @@ | |||
/* | |||
Converter for 70% IBM Terminal Keyboard | |||
Author: Benjamin Gould, 2013 | |||
Based on code Copyright 2011 Jun Wako <[email protected]> | |||
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); | |||
} |
@@ -0,0 +1,262 @@ | |||
/* | |||
Copyright 2011 Jun Wako <[email protected]> | |||
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; | |||
} | |||
} |
@@ -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 |
@@ -48,11 +48,17 @@ TOP_DIR = ../.. | |||
TARGET_DIR = . | |||
# project specific files | |||
SRC += keymap.c \ | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c \ | |||
backlight.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_poker.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
@@ -94,7 +100,7 @@ ARCH = AVR8 | |||
F_USB = $(F_CPU) | |||
# Interrupt driven control endpoint task(+60) | |||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# Boot Section Size in *bytes* | |||
@@ -132,18 +138,3 @@ VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk | |||
plain: OPT_DEFS += -DKEYMAP_PLAIN | |||
plain: all | |||
poker: OPT_DEFS += -DKEYMAP_POKER | |||
poker: all | |||
poker_set: OPT_DEFS += -DKEYMAP_POKER_SET | |||
poker_set: all | |||
poker_bit: OPT_DEFS += -DKEYMAP_POKER_BIT | |||
poker_bit: all | |||
poker2: OPT_DEFS += -DKEYMAP_POKER2 -DBACKLIGHT_CUSTOM -DGH60_REV_C -DDEBUG | |||
poker2: all |
@@ -48,10 +48,16 @@ TOP_DIR = ../.. | |||
TARGET_DIR = . | |||
# project specific files | |||
SRC = keymap.c \ | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_poker.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
@@ -2,57 +2,40 @@ GH60 keyboard firmware | |||
====================== | |||
DIY compact keyboard designed and run by komar007 and Geekhack community. | |||
## Threads on Geekhack.org | |||
- Both Rev.A and Rev.B PCB are supported by one firmware binary(issue #64) | |||
## GH60 Resources | |||
- [KOMAR's project page](http://blog.komar.be/projects/gh60-programmable-keyboard/) | |||
- [Prototyping](http://geekhack.org/index.php?topic=34959.0) | |||
- [Beta-test](http://geekhack.org/index.php?topic=37570.0) | |||
- [Rev.A PCB test](http://geekhack.org/index.php?topic=37570.0) | |||
- [Rev.B PCB test](http://geekhack.org/index.php?topic=50685.0) | |||
- [Group buy](http://geekhack.org/index.php?topic=41464.0) | |||
## Build | |||
Move to this directory then just run `make` like: | |||
$ make -f Makfile.[pjrc|lufa] | |||
Use `Makefile.pjrc` if you want to use PJRC stack or use `Makefile.lufa` for LUFA stack. | |||
$ make | |||
## Boot Magic | |||
Plugin pressing these `Boot Magic` key. | |||
- `Fn` key for bootloader kick up. | |||
- `D` key for Debug enable. | |||
Use `make -f Makefile.pjrc` if you want to use PJRC stack but I find no reason to do so now. | |||
## Keymap | |||
Two version of keymap are available. `Plan`, `Poker` and `Funky`(default). | |||
See keymap.c to define your own favourite keymap. | |||
$ make -f Makefile.[pjrc|lufa] [plain|poker] | |||
### 1. Plain keymap | |||
This will be useful if you want to use key mapping tool like AHK. | |||
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `keymap_<name>.c` and see keymap document(you can find in top README.md) and existent keymap files. | |||
See [keymap_plain.h](keymap_plain.h) for detail. | |||
To build firmware binary hex file with a certain keymap just do `make` with `KEYMAP` option like: | |||
#### 1.0 Plain Default Layer | |||
,-----------------------------------------------------------. | |||
|Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||
|-----------------------------------------------------------| | |||
|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||
|-----------------------------------------------------------| | |||
|Caps | 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 |App |Ctrl| | |||
`-----------------------------------------------------------' | |||
$ make KEYMAP=[poker|poker_set|poker_bit|plain|hasu|spacefn|hhkb|<name>] | |||
### 2 Poker keymap | |||
See [keymap_poker.h](keymap_poker.h) for Poker layer emulation, [keymap_poker_bit.h](keymap_poker_bit.h) and [keymap_poker_set.h](keymap_poker_set.h) for better support of Esc and arrow. | |||
### 1 Poker | |||
[keymap_poker.c](keymap_poker.c) emulates original Poker layers | |||
while both [keymap_poker_bit.c](keymap_poker_bit.c) and [keymap_poker_set.c](keymap_poker_set.c) implements same layout in different way and they fix a minor issue of original Poker and enhance arrow keys. | |||
These keymap supports Colemak, Dvorak and Workmans, use `Magic` + {`1`, `2`, `3`} to switch and `Magic` + `0` to return to Qwerty. | |||
Fn + Esc = ` | |||
Fn + {left, down, up, right} = {home, pgdown, pgup, end} | |||
#### 2.0 Poker Default Layer | |||
#### 1.0 Default layer | |||
,-----------------------------------------------------------. | |||
| `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||
|-----------------------------------------------------------| | |||
@@ -64,102 +47,95 @@ See [keymap_poker.h](keymap_poker.h) for Poker layer emulation, [keymap_poker_bi | |||
|-----------------------------------------------------------| | |||
|Ctrl|Gui |Alt | Space |Fn |Gui |App |Ctrl| | |||
`-----------------------------------------------------------' | |||
#### 2.1 Poker Arrow Layer | |||
#### 1.1 Poker Fn layer | |||
,-----------------------------------------------------------. | |||
| | | | | | | | | | | | | | | | |||
|Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| | | |||
|-----------------------------------------------------------| | |||
| | | | | | | | | | | | | | | | |||
| |FnQ| Up| | | | | | |Cal| |Hom|Ins| | | |||
|-----------------------------------------------------------| | |||
| | | | | | | | | | | | | | | |||
| |Lef|Dow|Rig| | |Psc|Slk|Pau| |Tsk|End| | | |||
|-----------------------------------------------------------| | |||
| | | | | | | | | | | | Up | | |||
| |Del| |Web|Mut|VoU|VoD| |PgU|PgD|Del| Up | | |||
|-----------------------------------------------------------| | |||
| | | | |Fn |Left|Down|Righ| | |||
| | | | FnS |Fn |Left|Down|Righ| | |||
`-----------------------------------------------------------' | |||
#### 2.2 Poker Esc Layer | |||
,-----------------------------------------------------------. | |||
|Esc| | | | | | | | | | | | | | | |||
|-----------------------------------------------------------| | |||
| | | | | | | | | | | | | | | | |||
|-----------------------------------------------------------| | |||
| | | | | | | | | | | | | | | |||
|-----------------------------------------------------------| | |||
| | | | | | | | | | | | | | |||
|-----------------------------------------------------------| | |||
| | | | |Fn | | | | | |||
`-----------------------------------------------------------' | |||
#### 2.1 Poker Fn Layer | |||
### 2. Plain | |||
Without any Fn layer this will be useful if you want to use key remapping tool like AHK on host. | |||
See [keymap_plain.c](keymap_plain.c) for detail. | |||
#### 1.0 Plain Default layer | |||
,-----------------------------------------------------------. | |||
|Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| | | |||
|Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||
|-----------------------------------------------------------| | |||
| |FnQ| Up| | | | | | |Cal| |Hom|Ins| | | |||
|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||
|-----------------------------------------------------------| | |||
| |Lef|Dow|Rig| | |Psc|Slk|Pau| |Tsk|End| | | |||
|Caps | A| S| D| F| G| H| J| K| L| ;| '|Return | | |||
|-----------------------------------------------------------| | |||
| |Del| |Web|Mut|VoU|VoD| |PgU|PgD|Del| | | |||
|Shift | Z| X| C| V| B| N| M| ,| .| /|Shift | | |||
|-----------------------------------------------------------| | |||
| | | | FnS |Fn | | | | | |||
|Ctrl|Gui |Alt | Space |Alt |Gui |App |Ctrl| | |||
`-----------------------------------------------------------' | |||
### 3. Hasu | |||
This is my favourite keymap with HHKB Fn, Vi cursor and Mousekey layer. See [keymap_hasu.c](keymap_hasu.c) for detail. | |||
### 3. Funky keymap | |||
This is my keymap(default) with HHKB, Vi cursor and Mousekey layer. | |||
See [keymap.c](keymap.c) for detail. | |||
### 4. SpaceFN | |||
This layout proposed by spiceBar uses space bar to change layer with using Dual role key technique. See [keymap_spacefn.c](keymap_spacefn.c) and [SpaceFN discussion](http://geekhack.org/index.php?topic=51069.0). | |||
#### 3.0 Funky Default Layer | |||
#### 4.0 Default layer | |||
,-----------------------------------------------------------. | |||
|Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||
|-----------------------------------------------------------| | |||
|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||
|-----------------------------------------------------------| | |||
|Caps | A| S| D| F| G| H| J| K| L|*L3| '|Return | | |||
|Caps | A| S| D| F| G| H| J| K| L| ;| '|Return | | |||
|-----------------------------------------------------------| | |||
|Shift | Z| X| C| V| B| N| M| ,| .|*L2|Shift | | |||
|Shift | Z| X| C| V| B| N| M| ,| .| /|Shift | | |||
|-----------------------------------------------------------| | |||
|Ctrl|Gui |Alt | Space |Alt |*L3 |*L3 |*L1 | | |||
|Ctrl|Gui |Alt | Space/Fn |Alt |Gui |App |Ctrl| | |||
`-----------------------------------------------------------' | |||
#### 3.1 Funky HHKB mode | |||
#### 4.1 SpaceFN layer | |||
,-----------------------------------------------------------. | |||
|Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||
|` | F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||
|-----------------------------------------------------------| | |||
|Caps | | | | | | | |Psc|Slk|Pus|Up | |Inser| | |||
| | | | | | | |Hom|Up |End|Psc|Slk|Pau|Ins | | |||
|-----------------------------------------------------------| | |||
|Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | | |||
| | | | | | |PgU|Lef|Dow|Rig| | | | | |||
|-----------------------------------------------------------| | |||
|Shift | | | | | | +| -|End|PgD|Dow|Shift | | |||
| | | | | |Spc|PgD|` |~ | | | | | |||
|-----------------------------------------------------------| | |||
|Ctrl|Gui |Alt | Space |Alt |Gui |App |*L0 | | |||
| | | | Fn | | | | | | |||
`-----------------------------------------------------------' | |||
#### 3.2 Funky Vi mode | |||
### 5. HHKB | |||
[keymap_hhkb.c](keymap_hhkb.c) emulates original HHKB layers. | |||
#### 5.0: Default layer | |||
,-----------------------------------------------------------. | |||
| `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backsp | | |||
|Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| | |||
|-----------------------------------------------------------| | |||
|Tab |Hom|PgD|Up |PgU|End|Hom|PgD|PgU|End| | | | | | |||
|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Bspc | | |||
|-----------------------------------------------------------| | |||
|Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return | | |||
|Ctrl | A| S| D| F| G| H| J| K| L|Fn3| '|Return | | |||
|-----------------------------------------------------------| | |||
|Shift | | | | | |Hom|PgD|PgU|End|*L0|Shift | | |||
|Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn | | |||
|-----------------------------------------------------------| | |||
|Ctrl|Gui |Alt | Space |Alt |Gui |App |Ctrl| | |||
| |Gui |Alt | Space | |Alt |Gui | | | |||
`-----------------------------------------------------------' | |||
#### 3.3 Funky Mouse mode | |||
#### 5.1: HHKB Fn layer | |||
,-----------------------------------------------------------. | |||
| `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backsp | | |||
|Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||
|-----------------------------------------------------------| | |||
|Tab |MwL|MwD|McU|MwU|MwR|MwL|MwD|MwU|MwR| | | | | | |||
|Caps | | | | | | | |Psc|Slk|Pus|Up | | | | |||
|-----------------------------------------------------------| | |||
|Contro| |McL|McD|McR| |McL|McD|McU|McR|*L0| |Return | | |||
| |VoD|VoU|Mut|Ejc| | *| /|Hom|PgU|Lef|Rig|Enter | | |||
|-----------------------------------------------------------| | |||
|Shift | | |Mb1|Mb2|Mb3|Mb2|Mb1| | | |Shift | | |||
| | | | | | | +| -|End|PgD|Dow| | | | |||
|-----------------------------------------------------------| | |||
|Ctrl|Gui |Alt | Space |Alt |*L0 |*L0 |Ctrl| | |||
| | | | | | | | | | |||
`-----------------------------------------------------------' | |||
Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel | |||
@@ -0,0 +1,30 @@ | |||
/* | |||
Copyright 2012,2013 Jun Wako <[email protected]> | |||
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)]) }; | |||
} |
@@ -0,0 +1,84 @@ | |||
/* | |||
Copyright 2012,2013 Jun Wako <[email protected]> | |||
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 "host.h" | |||
#include "print.h" | |||
#include "debug.h" | |||
#include "keymap.h" | |||
extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; | |||
extern const uint16_t fn_actions[]; | |||
/* GH60 keymap definition macro | |||
* K2C, K31 and K3C are extra keys for ISO | |||
*/ | |||
#define KEYMAP( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, \ | |||
K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \ | |||
K40, K41, K42, K45, K49, K4A, K4B, K4C, K4D \ | |||
) { \ | |||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \ | |||
{ 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_##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_##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_##K40, KC_##K41, KC_##K42, KC_NO, KC_NO, KC_##K45, KC_NO, KC_NO, KC_NO, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D } \ | |||
} | |||
/* ANSI valiant. No extra keys for ISO */ | |||
#define KEYMAP_ANSI( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D, \ | |||
K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, \ | |||
K40, K41, K42, K45, K4A, K4B, K4C, K4D \ | |||
) KEYMAP( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO, K2D, \ | |||
K30, NO, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, NO, K3D, \ | |||
K40, K41, K42, K45, NO, K4A, K4B, K4C, K4D \ | |||
) | |||
#define KEYMAP_HHKB( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K49,\ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D, \ | |||
K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, K3C, \ | |||
K40, K41, K42, K45, K4A, K4B, K4C, K4D \ | |||
) KEYMAP( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO, K2D, \ | |||
K30, NO, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \ | |||
K40, K41, K42, K45, K49, K4A, K4B, K4C, K4D \ | |||
) | |||
#endif |
@@ -1,81 +1,9 @@ | |||
/* | |||
Copyright 2012,2013 Jun Wako <[email protected]> | |||
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 "action.h" | |||
#include "action_macro.h" | |||
#include "report.h" | |||
#include "host.h" | |||
#include "print.h" | |||
#include "debug.h" | |||
#include "keymap.h" | |||
#include "keymap_ex.h" | |||
#include "keymap_common.h" | |||
/* GH60 keymap definition macro | |||
* K2C, K31 and K3C are extra keys for ISO | |||
/* | |||
* Hasu | |||
*/ | |||
#define KEYMAP( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, \ | |||
K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \ | |||
K40, K41, K42, K45, K49, K4A, K4B, K4C, K4D \ | |||
) { \ | |||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \ | |||
{ 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_##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_##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_##K40, KC_##K41, KC_##K42, KC_NO, KC_NO, KC_##K45, KC_NO, KC_NO, KC_NO, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D } \ | |||
} | |||
/* ANSI valiant. No extra keys for ISO */ | |||
#define KEYMAP_ANSI( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D, \ | |||
K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, \ | |||
K40, K41, K42, K45, K4A, K4B, K4C, K4D \ | |||
) KEYMAP( \ | |||
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \ | |||
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \ | |||
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO, K2D, \ | |||
K30, NO, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, NO, K3D, \ | |||
K40, K41, K42, K45, NO, K4A, K4B, K4C, K4D \ | |||
) | |||
#if defined(KEYMAP_PLAIN) | |||
#include "keymap_plain.h" | |||
#elif defined(KEYMAP_POKER) | |||
#include "keymap_poker.h" | |||
#elif defined(KEYMAP_POKER_SET) | |||
#include "keymap_poker_set.h" | |||
#elif defined(KEYMAP_POKER_BIT) | |||
#include "keymap_poker_bit.h" | |||
#elif defined(KEYMAP_POKER2) | |||
#include "keymap_poker2.h" | |||
#else | |||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* | |||
* Funky | |||
*/ | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* Keymap 0: Default Layer | |||
* ,-----------------------------------------------------------. | |||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||
@@ -203,7 +131,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* | |||
* Fn action definition | |||
*/ | |||
static const uint16_t PROGMEM fn_actions[] = { | |||
const uint16_t PROGMEM fn_actions[] = { | |||
[0] = ACTION_LAYER_MOMENTARY(4), | |||
[1] = ACTION_LAYER_TAP_KEY(5, KC_SLASH), | |||
[2] = ACTION_LAYER_TAP_KEY(6, KC_SCLN), | |||
@@ -215,62 +143,3 @@ static const uint16_t PROGMEM fn_actions[] = { | |||
[8] = ACTION_DEFAULT_LAYER_SET(3), // set workman layout | |||
[9] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_GRV), | |||
}; | |||
#endif | |||
#define KEYMAPS_SIZE (sizeof(keymaps) / sizeof(keymaps[0])) | |||
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0])) | |||
#ifdef KEYMAP_EX_ENABLE | |||
const uint8_t* keymaps_pointer(void) { | |||
return (const uint8_t*)keymaps; | |||
} | |||
const uint16_t* fn_actions_pointer(void) { | |||
return fn_actions; | |||
} | |||
uint16_t keys_count(void) { | |||
return KEYMAPS_SIZE * MATRIX_ROWS * MATRIX_COLS; | |||
} | |||
uint16_t fn_actions_count(void) { | |||
return FN_ACTIONS_SIZE; | |||
} | |||
#endif | |||
/* translates key to keycode */ | |||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key) | |||
{ | |||
if (layer < KEYMAPS_SIZE) { | |||
#ifndef KEYMAP_EX_ENABLE | |||
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); | |||
#else | |||
return eeconfig_read_keymap_key(layer, key.row, key.col); | |||
#endif | |||
} else { | |||
// XXX: this may cuaes bootlaoder_jump inconsistent fail. | |||
//debug("key_to_keycode: base "); debug_dec(layer); debug(" is invalid.\n"); | |||
// fall back to layer 0 | |||
#ifndef KEYMAP_EX_ENABLE | |||
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]); | |||
#else | |||
return eeconfig_read_keymap_key(0, key.row, key.col); | |||
#endif | |||
} | |||
} | |||
/* translates Fn keycode to action */ | |||
action_t keymap_fn_to_action(uint8_t keycode) | |||
{ | |||
action_t action; | |||
if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) { | |||
#ifndef KEYMAP_EX_ENABLE | |||
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]); | |||
#else | |||
action.code = eeconfig_read_keymap_fn_action(FN_INDEX(keycode)); | |||
#endif | |||
} else { | |||
action.code = ACTION_NO; | |||
} | |||
return action; | |||
} |
@@ -0,0 +1,52 @@ | |||
#include "keymap_common.h" | |||
/* | |||
* HHKB Layout | |||
*/ | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* 0: Default layer | |||
* ,-----------------------------------------------------------. | |||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| | |||
* |-----------------------------------------------------------| | |||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Bspc | | |||
* |-----------------------------------------------------------| | |||
* |Ctrl | A| S| D| F| G| H| J| K| L|Fn3| '|Return | | |||
* |-----------------------------------------------------------| | |||
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn | | |||
* |-----------------------------------------------------------| | |||
* | |Gui |Alt | Space | |Alt |Gui | | | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP_HHKB( | |||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS, GRV, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ | |||
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \ | |||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT,FN0, \ | |||
NO, LGUI,LALT, SPC, NO, RALT,RGUI,NO), | |||
/* 1: HHKB Fn layer | |||
* ,-----------------------------------------------------------. | |||
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||
* |-----------------------------------------------------------| | |||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | | | | |||
* |-----------------------------------------------------------| | |||
* | |VoD|VoU|Mut|Ejc| | *| /|Hom|PgU|Lef|Rig|Enter | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | +| -|End|PgD|Dow| | | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | | | | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP_HHKB( | |||
PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, TRNS,TRNS, \ | |||
TRNS,VOLD,VOLU,MUTE,EJCT,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT, PENT, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN, TRNS,TRNS, \ | |||
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS), | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
const uint16_t PROGMEM fn_actions[] = { | |||
[0] = ACTION_LAYER_MOMENTARY(1), | |||
}; |
@@ -1,4 +1,6 @@ | |||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
#include "keymap_common.h" | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* 0: qwerty */ | |||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \ | |||
@@ -6,4 +8,4 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, RSFT, \ | |||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL), | |||
}; | |||
static const uint16_t PROGMEM fn_actions[] = {}; | |||
const uint16_t PROGMEM fn_actions[] = {}; |
@@ -1,4 +1,6 @@ | |||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
#include "keymap_common.h" | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* 0: qwerty */ | |||
KEYMAP_ANSI( | |||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | |||
@@ -88,7 +90,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
TRNS,TRNS,TRNS,FN6, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \ | |||
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS), | |||
}; | |||
static const uint16_t PROGMEM fn_actions[] = { | |||
const uint16_t PROGMEM fn_actions[] = { | |||
/* Poker Layout */ | |||
[0] = ACTION_LAYER_MOMENTARY(6), // to Fn overlay | |||
[1] = ACTION_LAYER_TOGGLE(4), // toggle arrow overlay |
@@ -1,7 +1,9 @@ | |||
#include "keymap_common.h" | |||
// Poker fix with toggle and bit operation | |||
// Fn + Esc = ` | |||
// Fn + {left, down, up, right} = {home, pgdown, pgup, end} | |||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* 0: qwerty */ | |||
KEYMAP_ANSI( | |||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | |||
@@ -38,7 +40,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \ | |||
TRNS,TRNS,TRNS, TRNS, TRNS,LEFT,DOWN,RGHT), | |||
}; | |||
static const uint16_t PROGMEM fn_actions[] = { | |||
const uint16_t PROGMEM fn_actions[] = { | |||
/* Poker Layout */ | |||
[0] = ACTION_LAYER_BIT_XOR(1, 0b0101, ON_BOTH), // Poker Fn(with fix for Esc) | |||
[1] = ACTION_LAYER_TOGGLE(5), // Poker Arrow toggle |
@@ -1,7 +1,9 @@ | |||
#include "keymap_common.h" | |||
// Poker fix with set(state transition) | |||
// Fn + Esc = ` | |||
// Fn + {left, down, up, right} = {home, pgdown, pgup, end} | |||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* 0: qwerty */ | |||
KEYMAP_ANSI( | |||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | |||
@@ -63,7 +65,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* | |||
* Fn action definition | |||
*/ | |||
static const uint16_t PROGMEM fn_actions[] = { | |||
const uint16_t PROGMEM fn_actions[] = { | |||
/* Poker Layout */ | |||
[0] = ACTION_LAYER_SET(4, ON_PRESS), // FN0 move to Fn'd when press | |||
[1] = ACTION_LAYER_SET(5, ON_PRESS), // FN1 move to Fn'd arrow when press |
@@ -0,0 +1,55 @@ | |||
#include "keymap_common.h" | |||
/* | |||
* SpaceFN | |||
* http://geekhack.org/index.php?topic=51069.0 | |||
*/ | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* Keymap 0: Default Layer | |||
* ,-----------------------------------------------------------. | |||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||
* |-----------------------------------------------------------| | |||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||
* |-----------------------------------------------------------| | |||
* |Caps | 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 |App |Ctrl| | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP_ANSI( | |||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \ | |||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \ | |||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, \ | |||
LCTL,LGUI,LALT, FN0, RALT,RGUI,APP, RCTL), | |||
/* Overlay 1: SpaceFN | |||
* ,-----------------------------------------------------------. | |||
* |` | F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | |Hom|Up |End|Psc|Slk|Pau|Ins | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | |PgU|Lef|Dow|Rig| | | | | |||
* |-----------------------------------------------------------| | |||
* | | | | | |Spc|PgD|` |~ | | | | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | | | | |||
* `-----------------------------------------------------------' | |||
*/ | |||
KEYMAP_ANSI( | |||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, \ | |||
TRNS,TRNS,TRNS,ESC, TRNS,TRNS,TRNS,HOME,UP, END, PSCR,SLCK,PAUS,INS, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PGUP,LEFT,DOWN,RGHT,TRNS,TRNS, TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,SPC, PGDN,GRV, FN1, TRNS,TRNS, TRNS, \ | |||
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS), | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
const uint16_t PROGMEM fn_actions[] = { | |||
[0] = ACTION_LAYER_TAP_KEY(1, KC_SPACE), | |||
[1] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV), // tilde | |||
}; |
@@ -135,9 +135,9 @@ uint8_t matrix_key_count(void) | |||
} | |||
/* Column pin configuration | |||
* revC pin: F1 F0 E6 D7 D6 D4 C7 C6 B7 B5 B4 B3 B1 B0 | |||
* revB pin: F1 F0 E6 D7 D6 D4 C7 C6 B7 B6 B5 B4 B3 B1 | |||
* revA pin: F1 F0 E6 D7 D6 D4 C7 C6 B6 B5 B4 B3 B1 B0 | |||
* pin: F1 F0 E6 D7 D6 D4 C7 C6 B6 B5 B4 B3 B1 B0 (Rev.A) | |||
* pin: F1 F0 E6 D7 D6 D4 C7 C6 B7 B6 B5 B4 B3 B1 (Rev.B) | |||
* pin: F1 F0 E6 D7 D6 D4 C7 C6 B7 B5 B4 B3 B1 B0 (Rev.CHN) | |||
*/ | |||
static void init_cols(void) | |||
{ | |||
@@ -150,27 +150,24 @@ static void init_cols(void) | |||
PORTD |= (1<<PD7 | 1<<PD6 | 1<<PD4); | |||
DDRC &= ~(1<<PC7 | 1<<PC6); | |||
PORTC |= (1<<PC7 | 1<<PC6); | |||
#if defined(GH60_REV_C) | |||
#if defined(GH60_REV_CHN) | |||
DDRB &= ~(1<<PB7 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
PORTB |= (1<<PB7 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
#elif defined(GH60_REV_B) | |||
DDRB &= ~(1<<PB7 | 1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1); | |||
PORTB |= (1<<PB7 | 1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1); | |||
#else | |||
DDRB &= ~(1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
PORTB |= (1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
DDRB &= ~(1<<PB7 | 1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
PORTB |= (1<<PB7 | 1<<PB6 | 1<<PB5 | 1<<PB4 | 1<<PB3 | 1<<PB1 | 1<<PB0); | |||
#endif | |||
} | |||
/* Column pin configuration | |||
* col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |||
* revC pin: F0 F1 E6 C7 C6 B7 D4 B1 B0 B5 B4 D7 D6 B3 | |||
* revB pin: F0 F1 E6 C7 C6 B6 D4 B1 B7 B5 B4 D7 D6 B3 | |||
* revA pin: F0 F1 E6 C7 C6 B6 D4 B1 B0 B5 B4 D7 D6 B3 | |||
* col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |||
* pin: F0 F1 E6 C7 C6 B6 D4 B1 B0 B5 B4 D7 D6 B3 (Rev.A) | |||
* pin: F0 F1 E6 C7 C6 B6 D4 B1 B7 B5 B4 D7 D6 B3 (Rev.B) | |||
* pin: F0 F1 E6 C7 C6 B7 D4 B1 B0 B5 B4 D7 D6 B3 (Rev.CHN) | |||
*/ | |||
static matrix_row_t read_cols(void) | |||
{ | |||
#if defined(GH60_REV_C) | |||
#if defined(GH60_REV_CHN) | |||
return (PINF&(1<<PF0) ? 0 : (1<<0)) | | |||
(PINF&(1<<PF1) ? 0 : (1<<1)) | | |||
(PINE&(1<<PE6) ? 0 : (1<<2)) | | |||
@@ -185,36 +182,21 @@ static matrix_row_t read_cols(void) | |||
(PIND&(1<<PD7) ? 0 : (1<<11)) | | |||
(PIND&(1<<PD6) ? 0 : (1<<12)) | | |||
(PINB&(1<<PB3) ? 0 : (1<<13)); | |||
#elif defined(GH60_REV_B) | |||
return (PINF&(1<<PF0) ? 0 : (1<<0)) | | |||
(PINF&(1<<PF1) ? 0 : (1<<1)) | | |||
(PINE&(1<<PE6) ? 0 : (1<<2)) | | |||
(PINC&(1<<PC7) ? 0 : (1<<3)) | | |||
(PINC&(1<<PC6) ? 0 : (1<<4)) | | |||
(PINB&(1<<PB6) ? 0 : (1<<5)) | | |||
(PIND&(1<<PD4) ? 0 : (1<<6)) | | |||
(PINB&(1<<PB1) ? 0 : (1<<7)) | | |||
(PINB&(1<<PB7) ? 0 : (1<<8)) | | |||
(PINB&(1<<PB5) ? 0 : (1<<9)) | | |||
(PINB&(1<<PB4) ? 0 : (1<<10)) | | |||
(PIND&(1<<PD7) ? 0 : (1<<11)) | | |||
(PIND&(1<<PD6) ? 0 : (1<<12)) | | |||
(PINB&(1<<PB3) ? 0 : (1<<13)); | |||
#else | |||
return (PINF&(1<<PF0) ? 0 : (1<<0)) | | |||
(PINF&(1<<PF1) ? 0 : (1<<1)) | | |||
(PINE&(1<<PF6) ? 0 : (1<<2)) | | |||
(PINC&(1<<PC7) ? 0 : (1<<3)) | | |||
(PINC&(1<<PC6) ? 0 : (1<<4)) | | |||
(PINB&(1<<PB6) ? 0 : (1<<5)) | | |||
(PIND&(1<<PD4) ? 0 : (1<<6)) | | |||
(PINB&(1<<PB1) ? 0 : (1<<7)) | | |||
(PINB&(1<<PB0) ? 0 : (1<<8)) | | |||
(PINB&(1<<PB5) ? 0 : (1<<9)) | | |||
(PINB&(1<<PB4) ? 0 : (1<<10)) | | |||
(PIND&(1<<PF7) ? 0 : (1<<11)) | | |||
(PIND&(1<<PF6) ? 0 : (1<<12)) | | |||
(PINB&(1<<PF3) ? 0 : (1<<13)); | |||
return (PINF&(1<<0) ? 0 : (1<<0)) | | |||
(PINF&(1<<1) ? 0 : (1<<1)) | | |||
(PINE&(1<<6) ? 0 : (1<<2)) | | |||
(PINC&(1<<7) ? 0 : (1<<3)) | | |||
(PINC&(1<<6) ? 0 : (1<<4)) | | |||
(PINB&(1<<6) ? 0 : (1<<5)) | | |||
(PIND&(1<<4) ? 0 : (1<<6)) | | |||
(PINB&(1<<1) ? 0 : (1<<7)) | | |||
((PINB&(1<<0) && PINB&(1<<7)) ? 0 : (1<<8)) | // Rev.A and B | |||
(PINB&(1<<5) ? 0 : (1<<9)) | | |||
(PINB&(1<<4) ? 0 : (1<<10)) | | |||
(PIND&(1<<7) ? 0 : (1<<11)) | | |||
(PIND&(1<<6) ? 0 : (1<<12)) | | |||
(PINB&(1<<3) ? 0 : (1<<13)); | |||
#endif | |||
} | |||
@@ -49,10 +49,16 @@ TARGET_DIR = . | |||
# List C source files here. (C dependencies are automatically generated.) | |||
SRC += keymap.c \ | |||
SRC += keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_hasu.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
@@ -0,0 +1,141 @@ | |||
#---------------------------------------------------------------------------- | |||
# On command line: | |||
# | |||
# make all = Make software. | |||
# | |||
# make clean = Clean out built project files. | |||
# | |||
# make coff = Convert ELF to AVR COFF. | |||
# | |||
# make extcoff = Convert ELF to AVR Extended COFF. | |||
# | |||
# make program = Download the hex file to the device. | |||
# Please customize your programmer settings(PROGRAM_CMD) | |||
# | |||
# make teensy = Download the hex file to the device, using teensy_loader_cli. | |||
# (must have teensy_loader_cli installed). | |||
# | |||
# make dfu = Download the hex file to the device, using dfu-programmer (must | |||
# have dfu-programmer installed). | |||
# | |||
# make flip = Download the hex file to the device, using Atmel FLIP (must | |||
# have Atmel FLIP installed). | |||
# | |||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer | |||
# (must have dfu-programmer installed). | |||
# | |||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP | |||
# (must have Atmel FLIP installed). | |||
# | |||
# make debug = Start either simulavr or avarice as specified for debugging, | |||
# with avr-gdb or avr-insight as the front end for debugging. | |||
# | |||
# make filename.s = Just compile filename.c into the assembler code only. | |||
# | |||
# make filename.i = Create a preprocessed source file for use in submitting | |||
# bug reports to the GCC project. | |||
# | |||
# To rebuild project do "make clean" then "make all". | |||
#---------------------------------------------------------------------------- | |||
# Target file name (without extension). | |||
TARGET = hhkb_lufa | |||
# Directory common source filess exist | |||
TOP_DIR = ../.. | |||
# Directory keyboard dependent files exist | |||
TARGET_DIR = . | |||
# List C source files here. (C dependencies are automatically generated.) | |||
SRC += keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_hasu.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
# MCU name | |||
# PJRC Teensy++ 2.0 | |||
#MCU = at90usb1286 | |||
# TMK Alt Controller or PJRC Teensy 2.0 | |||
MCU = atmega32u4 | |||
# Processor frequency. | |||
# 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 | |||
# | |||
# 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 | |||
# Teensy++ halfKay 1024 | |||
# Atmel DFU loader 4096 (TMK Alt Controller) | |||
# 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 | |||
MOUSEKEY_ENABLE = yes # Mouse keys | |||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||
#CONSOLE_ENABLE = yes # Console for debug | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||
#KEYMAP_SECTION_ENABLE = yes # fixed address keymap for keymap editor | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/rules.mk | |||
debug-on: EXTRAFLAGS += -DDEBUG -DDEBUG_ACTION | |||
debug-on: all | |||
debug-off: EXTRAFLAGS += -DNO_DEBUG -DNO_PRINT | |||
debug-off: all |
@@ -13,10 +13,16 @@ TOP_DIR = ../.. | |||
TARGET_DIR = . | |||
# keyboard dependent files | |||
SRC = keymap.c \ | |||
SRC = keymap_common.c \ | |||
matrix.c \ | |||
led.c | |||
ifdef KEYMAP | |||
SRC := keymap_$(KEYMAP).c $(SRC) | |||
else | |||
SRC := keymap_hasu.c $(SRC) | |||
endif | |||
CONFIG_H = config.h | |||
@@ -1,8 +1,8 @@ | |||
Alternative Controller for HHKB Pro | |||
=================================== | |||
I wanted to add some features like vi cursor and mouse keys to my [HHKB][HHKB] but its controller is not programmable and | |||
firmware source code is not open, of course. This means customizing this keyboard needs to replace original | |||
controller with programmable one. This controller can work with HHKB Professional and Professional 2 model. | |||
I wanted to add some features like vi cursor and mouse keys to my [HHKB][HHKB] but its controller is not programmable and firmware source code is not open, of course. This means customizing this keyboard needs to replace original controller with programmable one. | |||
This controller can work with HHKB **Professional**, **Professional** 2 and **Type-S**. | |||
See [this thread][AltController] in geekhack.org. | |||
@@ -46,16 +46,10 @@ See [this document](../../doc/build.md) first. | |||
Set `MCU`, `BOOTLOADER_SIZE` and other build options in `Makefile` and `config.h`. | |||
### Build | |||
Just run make after intall tools. | |||
$ make | |||
Use `Makefile.pjrc` if you want to use PJRC stack instead of LUFA.(LUFA is recommended.) | |||
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. Just `make` with `KEYMAP` option like: | |||
$ make -f Makefile.pjrc | |||
$ make KEYMAP=[hasu|hhkb|spacefn|<name>] | |||
Use `Makefile.vusb` for [V-USB] controller.(not supported actively any more.) | |||
$ make -f Makefile.vusb | |||
### Program | |||
First, push reset button on board to start bootloader. | |||
@@ -71,8 +65,8 @@ Or you can also use [FLIP] command to program. Also the tool should be intalled | |||
Use [Teensy Loader] if your controller is Teensy/Teensy++. | |||
##How to Customize | |||
See [tmk_keyboard] documents. | |||
##Keymap | |||
To define your own keymap create file named `keymap_<name>.c` and see keymap document(you can find in top README.md) and existent keymap files. | |||
##Hardware | |||
@@ -83,7 +77,7 @@ TMK designed [Keyboard Controller Board for HHKB Pro2(KiCad project)](https://gi | |||
See [this post](http://geekhack.org/index.php?topic=12047.msg948923#msg948923). | |||
###2. PJRC Teensy++ 2.0 connection | |||
###2. PJRC Teensy++ 2.0 version | |||
+---------------+ | |||
| Teensy++ | | |||
| | | |||
@@ -101,32 +95,8 @@ See [this post](http://geekhack.org/index.php?topic=12047.msg948923#msg948923). | |||
- NOTE: PJRC [Teensy](http://www.pjrc.com/teensy/) | |||
###3. V-USB connection | |||
+---+ +---------------+ | |||
USB GND | | ATmega328p | | |||
~~~ C3 | | | |||
5V <-------+--------+---|Vcc,AVCC | HHKB pro pro2 | |||
R1 | | ~~~~~~~~ ~~~~ | |||
D- <----+--+-----R2-----|INT1 PB2-4|------->ROW (6-8) (5-7) | |||
D+ <----|---+----R3-----|INT0 PC0-2|------->COL (9-11) (8-10) | |||
Z1 Z2 | PC3|------->ENABLE (12) (11) | |||
GND<----+---+-----------|GND PB0|<-------KEY (4) (3) | |||
| PB1|------->PREV (5) (4) | |||
| | | |||
GND+-C2--+--|XTAL1 RXD|------->Debug Console | |||
X1 | TXD|<-------Debug Console | |||
GND+-C3--+--|XTAL2 RST|---SW--+GND | |||
+---------------+ | |||
R1: 1.5K Ohm | |||
R2,R3: 68 Ohm | |||
Z1,Z2: Zener 3.6V | |||
C1,C2: 22pF | |||
C3: 0.1uF | |||
X1: Crystal 12MHz | |||
SW: Push Switch(for bootloader) | |||
- NOTE: See [V-USB] documentation for more detail of hardware and the USB stack. | |||
- NOTE: [USBaspLoader] is very useful for firmware update. | |||
###3. V-USB version | |||
See [V-USB controller for HHKB](doc/V-USB.md) | |||
[LUFA]: http://www.fourwalledcubicle.com/LUFA.php | |||
@@ -135,4 +105,3 @@ See [this post](http://geekhack.org/index.php?topic=12047.msg948923#msg948923). | |||
[FLIP]: http://www.atmel.com/tools/FLIP.aspx | |||
[Teensy Loader]: http://www.pjrc.com/teensy/loader.html | |||
[V-USB]: http://www.obdev.at/products/vusb/index.html | |||
[USBaspLoader]: http://www.obdev.at/products/vusb/usbasploader.html |
@@ -0,0 +1,39 @@ | |||
V-USB controller for HHKB | |||
========================= | |||
Not supported actively any more. | |||
## Build | |||
Use `Makefile.vusb` for [V-USB] controller. | |||
$ make -f Makefile.vusb | |||
##Hardware | |||
###3. V-USB connection | |||
+---+ +---------------+ | |||
USB GND | | ATmega328p | | |||
~~~ C3 | | | |||
5V <-------+--------+---|Vcc,AVCC | HHKB pro pro2 | |||
R1 | | ~~~~~~~~ ~~~~ | |||
D- <----+--+-----R2-----|INT1 PB2-4|------->ROW (6-8) (5-7) | |||
D+ <----|---+----R3-----|INT0 PC0-2|------->COL (9-11) (8-10) | |||
Z1 Z2 | PC3|------->ENABLE (12) (11) | |||
GND<----+---+-----------|GND PB0|<-------KEY (4) (3) | |||
| PB1|------->PREV (5) (4) | |||
| | | |||
GND+-C2--+--|XTAL1 RXD|------->Debug Console | |||
X1 | TXD|<-------Debug Console | |||
GND+-C3--+--|XTAL2 RST|---SW--+GND | |||
+---------------+ | |||
R1: 1.5K Ohm | |||
R2,R3: 68 Ohm | |||
Z1,Z2: Zener 3.6V | |||
C1,C2: 22pF | |||
C3: 0.1uF | |||
X1: Crystal 12MHz | |||
SW: Push Switch(for bootloader) | |||
- NOTE: See [V-USB] documentation for more detail of hardware and the USB stack. | |||
- NOTE: [USBaspLoader] is very useful for firmware update. | |||
[V-USB]: http://www.obdev.at/products/vusb/index.html | |||
[USBaspLoader]: http://www.obdev.at/products/vusb/usbasploader.html |
@@ -0,0 +1,33 @@ | |||
/* | |||
Copyright 2012,2013 Jun Wako <[email protected]> | |||
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 "action.h" | |||
#include <avr/pgmspace.h> | |||
#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)]) }; | |||
} |
@@ -0,0 +1,57 @@ | |||
/* | |||
Copyright 2012,2013 Jun Wako <[email protected]> | |||
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 "keycode.h" | |||
#include "action.h" | |||
#include "action_code.h" | |||
#include "action_layer.h" | |||
#include "action_macro.h" | |||
#include "action_util.h" | |||
#include "report.h" | |||
#include "host.h" | |||
#include "print.h" | |||
#include "debug.h" | |||
#include "keymap.h" | |||
extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; | |||
extern const uint16_t fn_actions[]; | |||
#define KEYMAP( \ | |||
K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \ | |||
K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \ | |||
K33, K04, K03, K14, K15, K24, K25, K45, K44, K65, K64, K74, K53, \ | |||
K34, K05, K06, K07, K16, K17, K26, K46, K66, K76, K75, K55, K54, \ | |||
K35, K36, K37, K57, K56 \ | |||
) \ | |||
{ \ | |||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \ | |||
{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \ | |||
{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO }, \ | |||
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \ | |||
{ KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_NO }, \ | |||
{ KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \ | |||
{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_NO }, \ | |||
{ KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \ | |||
} | |||
#endif |
@@ -1,57 +1,13 @@ | |||
/* | |||
Copyright 2011,2012,2013 Jun Wako <[email protected]> | |||
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 PFU HHKB Pro | |||
* Hasu: my personal keymap | |||
*/ | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#include <avr/pgmspace.h> | |||
#include "keycode.h" | |||
#include "action.h" | |||
#include "action_macro.h" | |||
#include "report.h" | |||
#include "host.h" | |||
#include "debug.h" | |||
#include "keymap.h" | |||
#include "keymap_common.h" | |||
#define KEYMAP( \ | |||
K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \ | |||
K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \ | |||
K33, K04, K03, K14, K15, K24, K25, K45, K44, K65, K64, K74, K53, \ | |||
K34, K05, K06, K07, K16, K17, K26, K46, K66, K76, K75, K55, K54, \ | |||
K35, K36, K37, K57, K56 \ | |||
) \ | |||
{ \ | |||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \ | |||
{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \ | |||
{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO }, \ | |||
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \ | |||
{ KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_NO }, \ | |||
{ KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \ | |||
{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_NO }, \ | |||
{ KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \ | |||
} | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | |||
#else | |||
static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
#endif | |||
/* Layer 0: Default Layer | |||
* ,-----------------------------------------------------------. | |||
@@ -69,7 +25,7 @@ static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ | |||
LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,FN4, \ | |||
FN5,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ | |||
FN5, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ | |||
LGUI,LALT, FN6, RALT,RGUI), | |||
/* Layer 1: HHKB mode (HHKB Fn) | |||
@@ -87,7 +43,7 @@ static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
*/ | |||
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, BSPC, \ | |||
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ | |||
LCTL,VOLD,VOLU,MUTE,NO, FN9, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ | |||
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \ | |||
LGUI,LALT, SPC, RALT,RGUI), | |||
@@ -192,7 +148,7 @@ enum macro_id { | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint16_t fn_actions[] __attribute__ ((section (".keymap.fn_actions"))) = { | |||
#else | |||
static const uint16_t fn_actions[] PROGMEM = { | |||
const uint16_t fn_actions[] PROGMEM = { | |||
#endif | |||
[0] = ACTION_DEFAULT_LAYER_SET(0), // Default layer(not used) | |||
[1] = ACTION_LAYER_TAP_TOGGLE(1), // HHKB layer(toggle with 5 taps) | |||
@@ -203,11 +159,12 @@ static const uint16_t fn_actions[] PROGMEM = { | |||
[6] = ACTION_LAYER_TAP_KEY(5, KC_SPC), // Mousekey layer with Space | |||
[7] = ACTION_LAYER_TOGGLE(3), // Mousekey layer(toggle) | |||
[8] = ACTION_MODS_KEY(MOD_LCTL, KC_W), // Close Tab | |||
[9] = ACTION_MODS_KEY(MOD_LSFT, KC_4), // Shift stuck test | |||
// [8] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // LControl with tap Backspace | |||
// [9] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC), // LControl with tap Esc | |||
// [11] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // Function: LShift with tap '(' | |||
// [12] = ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // Function: RShift with tap ')' | |||
[11] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // Function: LShift with tap '(' | |||
[12] = ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // Function: RShift with tap ')' | |||
// [13] = ACTION_MACRO_TAP(LSHIFT_PAREN), // Macro: LShift with tap '(' | |||
// [14] = ACTION_MACRO_TAP(RSHIFT_PAREN), // Macro: RShift with tap ')' | |||
// [15] = ACTION_MACRO(HELLO), // Macro: say hello | |||
@@ -268,18 +225,20 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) | |||
// NOTE: cant use register_code to avoid conflicting with magic key bind | |||
if (event.pressed) { | |||
if (tap.count == 0 || tap.interrupted) { | |||
add_mods(MOD_BIT(KC_LSHIFT)); | |||
//add_mods(MOD_BIT(KC_LSHIFT)); | |||
layer_on(1); | |||
} else { | |||
host_add_mods(MOD_BIT(KC_LSHIFT)); | |||
host_add_key(KC_9); | |||
host_send_keyboard_report(); | |||
host_del_mods(MOD_BIT(KC_LSHIFT)); | |||
host_del_key(KC_9); | |||
host_send_keyboard_report(); | |||
add_mods(MOD_BIT(KC_LSHIFT)); | |||
add_key(KC_9); | |||
send_keyboard_report(); | |||
del_mods(MOD_BIT(KC_LSHIFT)); | |||
del_key(KC_9); | |||
send_keyboard_report(); | |||
} | |||
} else { | |||
if (tap.count == 0 || tap.interrupted) { | |||
del_mods(MOD_BIT(KC_LSHIFT)); | |||
//del_mods(MOD_BIT(KC_LSHIFT)); | |||
layer_off(1); | |||
} | |||
} | |||
break; | |||
@@ -289,12 +248,12 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) | |||
if (tap.count == 0 || tap.interrupted) { | |||
add_mods(MOD_BIT(KC_RSHIFT)); | |||
} else { | |||
host_add_mods(MOD_BIT(KC_RSHIFT)); | |||
host_add_key(KC_0); | |||
host_send_keyboard_report(); | |||
host_del_mods(MOD_BIT(KC_RSHIFT)); | |||
host_del_key(KC_0); | |||
host_send_keyboard_report(); | |||
add_mods(MOD_BIT(KC_RSHIFT)); | |||
add_key(KC_0); | |||
send_keyboard_report(); | |||
del_mods(MOD_BIT(KC_RSHIFT)); | |||
del_key(KC_0); | |||
send_keyboard_report(); | |||
} | |||
} else { | |||
if (tap.count == 0 || tap.interrupted) { | |||
@@ -304,19 +263,3 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) | |||
break; | |||
} | |||
} | |||
/* 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 index to action */ | |||
action_t keymap_fn_to_action(uint8_t keycode) | |||
{ | |||
action_t action; | |||
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]); | |||
return action; | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* HHKB Layout | |||
*/ | |||
#include "keymap_common.h" | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | |||
#else | |||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||
#endif | |||
/* Layer 0: Default Layer | |||
* ,-----------------------------------------------------------. | |||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| | |||
* |-----------------------------------------------------------| | |||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs| | |||
* |-----------------------------------------------------------| | |||
* |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter | | |||
* |-----------------------------------------------------------| | |||
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0| | |||
* `-----------------------------------------------------------' | |||
* |Gui|Alt | Space |Alt |Gui| | |||
* `-------------------------------------------' | |||
*/ | |||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ | |||
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, \ | |||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN0, \ | |||
LGUI,LALT, SPC, RALT,RGUI), | |||
/* Layer 1: HHKB mode (HHKB Fn) | |||
* ,-----------------------------------------------------------. | |||
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||
* |-----------------------------------------------------------| | |||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs| | |||
* |-----------------------------------------------------------| | |||
* | |VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | +| -|End|PgD|Dow| | | | |||
* `-----------------------------------------------------------' | |||
* | | | | | | | |||
* `-------------------------------------------' | |||
*/ | |||
KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, BSPC, \ | |||
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,PENT, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,TRNS,TRNS, \ | |||
TRNS,TRNS, TRNS, TRNS,TRNS), | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
#ifdef KEYMAP_SECTION_ENABLE | |||
const uint16_t fn_actions[] __attribute__ ((section (".keymap.fn_actions"))) = { | |||
#else | |||
const uint16_t fn_actions[] PROGMEM = { | |||
#endif | |||
[0] = ACTION_LAYER_MOMENTARY(1), | |||
}; |
@@ -0,0 +1,75 @@ | |||
/* | |||
* SpaceFN | |||
* http://geekhack.org/index.php?topic=51069.0 | |||
*/ | |||
#include "keymap_common.h" | |||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* Layer 0: Default Layer | |||
* ,-----------------------------------------------------------. | |||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| `|BSp| | |||
* |-----------------------------------------------------------| | |||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||
* |-----------------------------------------------------------| | |||
* |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter | | |||
* |-----------------------------------------------------------| | |||
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0| | |||
* `-----------------------------------------------------------' | |||
* |Gui|Alt | SpaceFN |Alt |Gui| | |||
* `-------------------------------------------' | |||
*/ | |||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, GRV, BSPC, \ | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \ | |||
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, \ | |||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN0, \ | |||
LGUI,LALT, FN1, RALT,RGUI), | |||
/* Layer 1: HHKB mode (HHKB Fn) | |||
* ,-----------------------------------------------------------. | |||
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||
* |-----------------------------------------------------------| | |||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs| | |||
* |-----------------------------------------------------------| | |||
* | |VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | | +| -|End|PgD|Dow| | | | |||
* `-----------------------------------------------------------' | |||
* | | | | | | | |||
* `-------------------------------------------' | |||
*/ | |||
KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, BSPC, \ | |||
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,PENT, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,TRNS,TRNS, \ | |||
TRNS,TRNS, SPC, TRNS,TRNS), | |||
/* Layer 2: SpaceFN | |||
* ,-----------------------------------------------------------. | |||
* |` | F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| |Del| | |||
* |-----------------------------------------------------------| | |||
* | | | |Esc| | | |Hom|Up |End|Psc|Slk|Pau|Ins | | |||
* |-----------------------------------------------------------| | |||
* | | | | | | |PgU|Lef|Dow|Rig| | | | | |||
* |-----------------------------------------------------------| | |||
* | | | | | |Spc|PgD|` |~ | | | | | | |||
* `-----------------------------------------------------------' | |||
* | | | | | | | |||
* `-------------------------------------------' | |||
*/ | |||
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS,DEL, \ | |||
TRNS,TRNS,TRNS,ESC, TRNS,TRNS,TRNS,HOME,UP, END, PSCR,SLCK,PAUS,INS, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PGUP,LEFT,DOWN,RGHT,TRNS,TRNS,TRNS, \ | |||
TRNS,TRNS,TRNS,TRNS,TRNS,SPC, PGDN,GRV, FN2, TRNS,TRNS,TRNS,NO, \ | |||
TRNS,TRNS, TRNS, TRNS,TRNS), | |||
}; | |||
/* | |||
* Fn action definition | |||
*/ | |||
const uint16_t PROGMEM fn_actions[] = { | |||
[0] = ACTION_LAYER_MOMENTARY(1), | |||
[1] = ACTION_LAYER_TAP_KEY(2, KC_SPACE), | |||
[2] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV), // tilde | |||
}; | |||
@@ -93,7 +93,7 @@ ARCH = AVR8 | |||
F_USB = $(F_CPU) | |||
# Interrupt driven control endpoint task(+60) | |||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
# Boot Section Size in *bytes* | |||
@@ -108,34 +108,25 @@ 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) | |||
#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 | |||
#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 | |||
#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) | |||
# 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/lufa.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/protocol.mk | |||
include $(TOP_DIR)/protocol/lufa.mk | |||
include $(TOP_DIR)/rules.mk | |||
plain: OPT_DEFS += -DKEYMAP_PLAIN | |||
plain: all | |||
poker: OPT_DEFS += -DKEYMAP_POKER | |||
poker: all | |||
poker_set: OPT_DEFS += -DKEYMAP_POKER_SET | |||
poker_set: all | |||
poker_bit: OPT_DEFS += -DKEYMAP_POKER_BIT | |||
poker_bit: all |
@@ -79,32 +79,25 @@ 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(+5000) | |||
EXTRAKEY_ENABLE = yes # Audio control and System control(+600) | |||
#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
#MOUSEKEY_ENABLE = yes # Mouse keys(+5000) | |||
#EXTRAKEY_ENABLE = yes # Audio control and System control(+600) | |||
CONSOLE_ENABLE = yes # Console for debug | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
NKRO_ENABLE = yes # USB Nkey Rollover(+500) | |||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||
#COMMAND_ENABLE = yes # Commands for debug and configuration | |||
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||
#NKRO_ENABLE = yes # USB Nkey Rollover(+500) | |||
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) | |||
# Search Path | |||
VPATH += $(TARGET_DIR) | |||
VPATH += $(TOP_DIR) | |||
include $(TOP_DIR)/protocol/pjrc.mk | |||
include $(TOP_DIR)/common.mk | |||
include $(TOP_DIR)/protocol.mk | |||
include $(TOP_DIR)/protocol/pjrc.mk | |||
include $(TOP_DIR)/rules.mk | |||
plain: OPT_DEFS += -DKEYMAP_PLAIN | |||
plain: all | |||
poker: OPT_DEFS += -DKEYMAP_POKER | |||
poker: all | |||
poker_set: OPT_DEFS += -DKEYMAP_POKER_SET | |||
poker_set: all | |||
poker_bit: OPT_DEFS += -DKEYMAP_POKER_BIT | |||
poker_bit: all |
@@ -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 |
@@ -67,4 +67,90 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
//#define NO_ACTION_MACRO | |||
//#define NO_ACTION_FUNCTION | |||
/* PS/2 mouse */ | |||
#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 2 | |||
#endif | |||
/* PS/2 mouse interrupt version */ | |||
#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 mouse USART version */ | |||
#ifdef PS2_USE_USART | |||
#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) | |||
/* XCK for clock line and RXD for data line */ | |||
#define PS2_CLOCK_PORT PORTD | |||
#define PS2_CLOCK_PIN PIND | |||
#define PS2_CLOCK_DDR DDRD | |||
#define PS2_CLOCK_BIT 5 | |||
#define PS2_DATA_PORT PORTD | |||
#define PS2_DATA_PIN PIND | |||
#define PS2_DATA_DDR DDRD | |||
#define PS2_DATA_BIT 2 | |||
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | |||
/* set DDR of CLOCK as input to be slave */ | |||
#define PS2_USART_INIT() do { \ | |||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ | |||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ | |||
UCSR1C = ((1 << UMSEL10) | \ | |||
(3 << UPM10) | \ | |||
(0 << USBS1) | \ | |||
(3 << UCSZ10) | \ | |||
(0 << UCPOL1)); \ | |||
UCSR1A = 0; \ | |||
UBRR1H = 0; \ | |||
UBRR1L = 0; \ | |||
} while (0) | |||
#define PS2_USART_RX_INT_ON() do { \ | |||
UCSR1B = ((1 << RXCIE1) | \ | |||
(1 << RXEN1)); \ | |||
} while (0) | |||
#define PS2_USART_RX_POLL_ON() do { \ | |||
UCSR1B = (1 << RXEN1); \ | |||
} while (0) | |||
#define PS2_USART_OFF() do { \ | |||
UCSR1C = 0; \ | |||
UCSR1B &= ~((1 << RXEN1) | \ | |||
(1 << TXEN1)); \ | |||
} while (0) | |||
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1)) | |||
#define PS2_USART_RX_DATA UDR1 | |||
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) | |||
#define PS2_USART_RX_VECT USART1_RX_vect | |||
#endif | |||
#endif | |||
#endif |
@@ -59,6 +59,7 @@ void matrix_init(void) | |||
{ | |||
debug_enable = true; | |||
debug_matrix = true; | |||
debug_mouse = true; | |||
// initialize row and col | |||
unselect_rows(); | |||
init_cols(); | |||
@@ -138,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) | |||
@@ -168,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; | |||
} | |||
} |
@@ -1,2 +1,27 @@ | |||
PROTOCOL_DIR = protocol | |||
ifdef PS2_MOUSE_ENABLE | |||
SRC += $(PROTOCOL_DIR)/ps2_mouse.c | |||
OPT_DEFS += -DPS2_MOUSE_ENABLE | |||
OPT_DEFS += -DMOUSE_ENABLE | |||
endif | |||
ifdef PS2_USE_BUSYWAIT | |||
SRC += protocol/ps2_busywait.c | |||
OPT_DEFS += -DPS2_USE_BUSYWAIT | |||
endif | |||
ifdef PS2_USE_INT | |||
SRC += protocol/ps2_interrupt.c | |||
OPT_DEFS += -DPS2_USE_INT | |||
endif | |||
ifdef PS2_USE_USART | |||
SRC += protocol/ps2_usart.c | |||
OPT_DEFS += -DPS2_USE_USART | |||
endif | |||
# Search Path | |||
VPATH += $(TOP_DIR)/protocol |
@@ -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 |
@@ -0,0 +1,202 @@ | |||
/* | |||
Bluefruit Protocol for TMK firmware | |||
Author: Benjamin Gould, 2013 | |||
Based on code Copyright 2011 Jun Wako <[email protected]> | |||
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 | |||
} | |||
@@ -0,0 +1,28 @@ | |||
/* | |||
Bluefruit Protocol for TMK firmware | |||
Author: Benjamin Gould, 2013 | |||
Based on code Copyright 2011 Jun Wako <[email protected]> | |||
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 |
@@ -0,0 +1,116 @@ | |||
/* | |||
Bluefruit Protocol for TMK firmware | |||
Author: Benjamin Gould, 2013 | |||
Based on code Copyright 2011 Jun Wako <[email protected]> | |||
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(); | |||
} | |||
} | |||
} |
@@ -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) | |||
@@ -539,11 +539,18 @@ int main(void) | |||
{ | |||
SetupHardware(); | |||
sei(); | |||
/* wait for USB startup & debug output */ | |||
while (USB_DeviceState != DEVICE_STATE_Configured) { | |||
#if defined(INTERRUPT_CONTROL_ENDPOINT) | |||
while (USB_DeviceState != DEVICE_STATE_Configured) ; | |||
; | |||
#else | |||
USB_USBTask(); | |||
#endif | |||
} | |||
print("USB configured.\n"); | |||
/* init modules */ | |||
keyboard_init(); | |||
host_set_driver(&lufa_driver); | |||
#ifdef SLEEP_LED_ENABLE |
@@ -7,7 +7,11 @@ SRC += $(PJRC_DIR)/main.c \ | |||
$(PJRC_DIR)/usb.c | |||
# Option modules | |||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||
ifdef MOUSEKEY_ENABLE | |||
SRC += $(PJRC_DIR)/usb_mouse.c | |||
endif | |||
ifdef PS2_MOUSE_ENABLE | |||
SRC += $(PJRC_DIR)/usb_mouse.c | |||
endif | |||
@@ -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); |
@@ -1,5 +1,5 @@ | |||
/* | |||
Copyright 2010,2011 Jun WAKO <[email protected]> | |||
Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> | |||
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 |
@@ -0,0 +1,185 @@ | |||
/* | |||
Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> | |||
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); | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
Copyright 2010,2011 Jun WAKO <[email protected]> | |||
Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> | |||
This software is licensed with a Modified BSD License. | |||
All of this is supposed to be Free Software, Open Source, DFSG-free, | |||
@@ -35,45 +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" | |||
static uint8_t recv_data(void); | |||
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 { \ | |||
@@ -87,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(100); | |||
_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, 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)) { | |||
@@ -127,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); | |||
@@ -143,99 +119,37 @@ uint8_t ps2_host_send(uint8_t data) | |||
WAIT(clock_hi, 50, 8); | |||
WAIT(data_hi, 50, 9); | |||
res = ps2_host_recv_response(); | |||
ERROR: | |||
#ifdef PS2_USE_INT | |||
idle(); | |||
PS2_INT_ON(); | |||
return ps2_host_recv_response(); | |||
ERROR: | |||
idle(); | |||
#else | |||
inhibit(); | |||
#endif | |||
return res; | |||
PS2_INT_ON(); | |||
return 0; | |||
} | |||
/* receive data when host want else inhibit communication */ | |||
uint8_t ps2_host_recv_response(void) | |||
{ | |||
uint8_t data = 0; | |||
/* terminate a transmission if we have */ | |||
inhibit(); | |||
_delay_us(100); | |||
/* release lines(idle state) */ | |||
idle(); | |||
/* wait start bit */ | |||
wait_clock_lo(2000); | |||
data = recv_data(); | |||
inhibit(); | |||
return data; | |||
} | |||
#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) | |||
{ | |||
if (!data) | |||
return; | |||
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; | |||
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(); | |||
} | |||
#if 0 | |||
#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0) | |||
#define DEBUGP(x) do { PORTC = x; } while (0) | |||
#else | |||
#define DEBUGP_INIT() | |||
#define DEBUGP(x) | |||
#endif | |||
ISR(PS2_INT_VECT) | |||
{ | |||
static enum { | |||
@@ -256,7 +170,6 @@ ISR(PS2_INT_VECT) | |||
} | |||
state++; | |||
DEBUGP(state); | |||
switch (state) { | |||
case START: | |||
if (data_in()) | |||
@@ -296,8 +209,6 @@ ISR(PS2_INT_VECT) | |||
} | |||
goto RETURN; | |||
ERROR: | |||
DEBUGP(0x0F); | |||
inhibit(); | |||
ps2_error = state; | |||
DONE: | |||
state = INIT; | |||
@@ -306,13 +217,6 @@ DONE: | |||
RETURN: | |||
return; | |||
} | |||
#endif | |||
static void ps2_reset(void) | |||
{ | |||
ps2_host_send(0xFF); | |||
} | |||
/* send LED state to keyboard */ | |||
void ps2_host_set_led(uint8_t led) | |||
@@ -322,114 +226,53 @@ void ps2_host_set_led(uint8_t led) | |||
} | |||
/* 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; | |||
} | |||
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(); | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
Copyright 2011 Jun Wako <[email protected]> | |||
Copyright 2011,2013 Jun Wako <[email protected]> | |||
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 | |||
@@ -20,199 +20,196 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include<util/delay.h> | |||
#include "ps2.h" | |||
#include "ps2_mouse.h" | |||
#include "usb_mouse.h" | |||
#include "report.h" | |||
#include "host.h" | |||
#include "timer.h" | |||
#include "print.h" | |||
#include "debug.h" | |||
#define PS2_MOUSE_DEBUG | |||
#ifdef PS2_MOUSE_DEBUG | |||
# include "print.h" | |||
# include "debug.h" | |||
#else | |||
# define print(s) | |||
# define phex(h) | |||
# define phex16(h) | |||
#endif | |||
// disable when errors occur 255 times. | |||
#define ERROR_RETURN() do { \ | |||
if (ps2_error) { \ | |||
if (ps2_mouse_error_count < 255) { \ | |||
ps2_mouse_error_count++; \ | |||
} else { \ | |||
ps2_mouse_error_count = 0; \ | |||
ps2_mouse_enable = false; \ | |||
} \ | |||
return ps2_error; \ | |||
} \ | |||
} while (0) | |||
static report_mouse_t mouse_report = {}; | |||
/* | |||
TODO | |||
---- | |||
- Stream mode | |||
- Tracpoint command support: needed | |||
- Middle button + move = Wheel traslation | |||
*/ | |||
bool ps2_mouse_enable = true; | |||
uint8_t ps2_mouse_x = 0; | |||
uint8_t ps2_mouse_y = 0; | |||
uint8_t ps2_mouse_btn = 0; | |||
uint8_t ps2_mouse_error_count = 0; | |||
static uint8_t ps2_mouse_btn_prev = 0; | |||
static void print_usb_data(void); | |||
/* supports only 3 button mouse at this time */ | |||
uint8_t ps2_mouse_init(void) { | |||
uint8_t rcv; | |||
if (!ps2_mouse_enable) return 1; | |||
ps2_host_init(); | |||
// Reset | |||
rcv = ps2_host_send(0xFF); | |||
print("ps2_mouse_init: send 0xFF: "); | |||
phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
_delay_ms(1000); // wait for powering up | |||
// ACK | |||
rcv = ps2_host_recv(); | |||
print("ps2_mouse_init: read ACK: "); | |||
// send Reset | |||
rcv = ps2_host_send(0xFF); | |||
print("ps2_mouse_init: send Reset: "); | |||
phex(rcv); phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
// BAT takes some time | |||
_delay_ms(100); | |||
rcv = ps2_host_recv(); | |||
// read completion code of BAT | |||
rcv = ps2_host_recv_response(); | |||
print("ps2_mouse_init: read BAT: "); | |||
phex(rcv); phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
// Device ID | |||
rcv = ps2_host_recv(); | |||
// read Device ID | |||
rcv = ps2_host_recv_response(); | |||
print("ps2_mouse_init: read DevID: "); | |||
phex(rcv); phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
// Enable data reporting | |||
ps2_host_send(0xF4); | |||
print("ps2_mouse_init: send 0xF4: "); | |||
phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
// ACK | |||
rcv = ps2_host_recv(); | |||
print("ps2_mouse_init: read ACK: "); | |||
phex(rcv); phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
// Set Remote mode | |||
ps2_host_send(0xF0); | |||
// send Set Remote mode | |||
rcv = ps2_host_send(0xF0); | |||
print("ps2_mouse_init: send 0xF0: "); | |||
phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
// ACK | |||
rcv = ps2_host_recv(); | |||
print("ps2_mouse_init: read ACK: "); | |||
phex(rcv); phex(ps2_error); print("\n"); | |||
ERROR_RETURN(); | |||
return 0; | |||
} | |||
/* | |||
Data format: | |||
bit: 7 6 5 4 3 2 1 0 | |||
----------------------------------------------------------------------- | |||
0 btn: Yovflw Xovflw Ysign Xsign 1 Middle Right Left | |||
1 x: X movement(0-255) | |||
2 y: Y movement(0-255) | |||
*/ | |||
uint8_t ps2_mouse_read(void) | |||
#define X_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_X_SIGN)) | |||
#define Y_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_Y_SIGN)) | |||
#define X_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_X_OVFLW)) | |||
#define Y_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_Y_OVFLW)) | |||
void ps2_mouse_task(void) | |||
{ | |||
enum { SCROLL_NONE, SCROLL_BTN, SCROLL_SENT }; | |||
static uint8_t scroll_state = SCROLL_NONE; | |||
static uint8_t buttons_prev = 0; | |||
/* receives packet from mouse */ | |||
uint8_t rcv; | |||
rcv = ps2_host_send(PS2_MOUSE_READ_DATA); | |||
if (rcv == PS2_ACK) { | |||
mouse_report.buttons = ps2_host_recv_response(); | |||
mouse_report.x = ps2_host_recv_response(); | |||
mouse_report.y = ps2_host_recv_response(); | |||
} else { | |||
if (!debug_mouse) print("ps2_mouse: fail to get mouse packet\n"); | |||
return; | |||
} | |||
if (!ps2_mouse_enable) return 1; | |||
/* if mouse moves or buttons state changes */ | |||
if (mouse_report.x || mouse_report.y || | |||
((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) { | |||
ps2_host_send(0xEB); | |||
ERROR_RETURN(); | |||
#ifdef PS2_MOUSE_DEBUG | |||
print("ps2_mouse raw: ["); | |||
phex(mouse_report.buttons); print("|"); | |||
print_hex8((uint8_t)mouse_report.x); print(" "); | |||
print_hex8((uint8_t)mouse_report.y); print("]\n"); | |||
#endif | |||
rcv=ps2_host_recv(); | |||
ERROR_RETURN(); | |||
buttons_prev = mouse_report.buttons; | |||
// PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value. | |||
// bit: 8 7 ... 0 | |||
// sign \8-bit/ | |||
// | |||
// Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used. | |||
// | |||
// This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit. | |||
mouse_report.x = X_IS_NEG ? | |||
((!X_IS_OVF && -127 <= mouse_report.x && mouse_report.x <= -1) ? mouse_report.x : -127) : | |||
((!X_IS_OVF && 0 <= mouse_report.x && mouse_report.x <= 127) ? mouse_report.x : 127); | |||
mouse_report.y = Y_IS_NEG ? | |||
((!Y_IS_OVF && -127 <= mouse_report.y && mouse_report.y <= -1) ? mouse_report.y : -127) : | |||
((!Y_IS_OVF && 0 <= mouse_report.y && mouse_report.y <= 127) ? mouse_report.y : 127); | |||
// remove sign and overflow flags | |||
mouse_report.buttons &= PS2_MOUSE_BTN_MASK; | |||
// invert coordinate of y to conform to USB HID mouse | |||
mouse_report.y = -mouse_report.y; | |||
#if PS2_MOUSE_SCROLL_BTN_MASK | |||
static uint16_t scroll_button_time = 0; | |||
if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == (PS2_MOUSE_SCROLL_BTN_MASK)) { | |||
if (scroll_state == SCROLL_NONE) { | |||
scroll_button_time = timer_read(); | |||
scroll_state = SCROLL_BTN; | |||
} | |||
if(rcv==0xFA) { | |||
ps2_mouse_btn = ps2_host_recv(); | |||
ERROR_RETURN(); | |||
ps2_mouse_x = ps2_host_recv(); | |||
ERROR_RETURN(); | |||
ps2_mouse_y = ps2_host_recv(); | |||
ERROR_RETURN(); | |||
} | |||
return 0; | |||
} | |||
// doesn't send Scroll Button | |||
//mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK); | |||
bool ps2_mouse_changed(void) | |||
{ | |||
return (ps2_mouse_x || ps2_mouse_y || (ps2_mouse_btn & PS2_MOUSE_BTN_MASK) != ps2_mouse_btn_prev); | |||
} | |||
if (mouse_report.x || mouse_report.y) { | |||
scroll_state = SCROLL_SENT; | |||
#define PS2_MOUSE_SCROLL_BUTTON 0x04 | |||
void ps2_mouse_usb_send(void) | |||
{ | |||
static bool scrolled = false; | |||
if (!ps2_mouse_enable) return; | |||
if (ps2_mouse_changed()) { | |||
int8_t x, y, v, h; | |||
x = y = v = h = 0; | |||
// convert scale of X, Y: PS/2(-256/255) -> USB(-127/127) | |||
if (ps2_mouse_btn & (1<<PS2_MOUSE_X_SIGN)) | |||
x = ps2_mouse_x > 128 ? (int8_t)ps2_mouse_x : -127; | |||
else | |||
x = ps2_mouse_x < 128 ? (int8_t)ps2_mouse_x : 127; | |||
if (ps2_mouse_btn & (1<<PS2_MOUSE_Y_SIGN)) | |||
y = ps2_mouse_y > 128 ? (int8_t)ps2_mouse_y : -127; | |||
else | |||
y = ps2_mouse_y < 128 ? (int8_t)ps2_mouse_y : 127; | |||
// Y is needed to reverse | |||
y = -y; | |||
if (ps2_mouse_btn & PS2_MOUSE_SCROLL_BUTTON) { | |||
// scroll | |||
if (x > 0 || x < 0) h = (x > 64 ? 64 : (x < -64 ? -64 :x)); | |||
if (y > 0 || y < 0) v = (y > 64 ? 64 : (y < -64 ? -64 :y)); | |||
if (h || v) { | |||
scrolled = true; | |||
usb_mouse_send(0,0, -v/16, h/16, 0); | |||
mouse_report.v = -mouse_report.y/(PS2_MOUSE_SCROLL_DIVISOR_V); | |||
mouse_report.h = mouse_report.x/(PS2_MOUSE_SCROLL_DIVISOR_H); | |||
mouse_report.x = 0; | |||
mouse_report.y = 0; | |||
//host_mouse_send(&mouse_report); | |||
} | |||
} | |||
else if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == 0) { | |||
#if PS2_MOUSE_SCROLL_BTN_SEND | |||
if (scroll_state == SCROLL_BTN && | |||
TIMER_DIFF_16(timer_read(), scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { | |||
// send Scroll Button(down and up at once) when not scrolled | |||
mouse_report.buttons |= (PS2_MOUSE_SCROLL_BTN_MASK); | |||
host_mouse_send(&mouse_report); | |||
_delay_ms(100); | |||
mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK); | |||
} | |||
} else if (!scrolled && (ps2_mouse_btn_prev & PS2_MOUSE_SCROLL_BUTTON)) { | |||
usb_mouse_send(0,0,0,0, PS2_MOUSE_SCROLL_BUTTON); | |||
_delay_ms(100); | |||
usb_mouse_send(0,0,0,0, 0); | |||
} else { | |||
scrolled = false; | |||
usb_mouse_send(x, y, 0, 0, ps2_mouse_btn & PS2_MOUSE_BTN_MASK); | |||
#endif | |||
scroll_state = SCROLL_NONE; | |||
} | |||
// doesn't send Scroll Button | |||
mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK); | |||
#endif | |||
ps2_mouse_btn_prev = (ps2_mouse_btn & PS2_MOUSE_BTN_MASK); | |||
ps2_mouse_print(); | |||
host_mouse_send(&mouse_report); | |||
print_usb_data(); | |||
} | |||
ps2_mouse_x = 0; | |||
ps2_mouse_y = 0; | |||
ps2_mouse_btn = 0; | |||
// clear report | |||
mouse_report.x = 0; | |||
mouse_report.y = 0; | |||
mouse_report.v = 0; | |||
mouse_report.h = 0; | |||
mouse_report.buttons = 0; | |||
} | |||
void ps2_mouse_print(void) | |||
static void print_usb_data(void) | |||
{ | |||
if (!debug_mouse) return; | |||
print("ps2_mouse[btn|x y]: "); | |||
phex(ps2_mouse_btn); print("|"); | |||
phex(ps2_mouse_x); print(" "); | |||
phex(ps2_mouse_y); print("\n"); | |||
print("ps2_mouse usb: ["); | |||
phex(mouse_report.buttons); print("|"); | |||
print_hex8((uint8_t)mouse_report.x); print(" "); | |||
print_hex8((uint8_t)mouse_report.y); print(" "); | |||
print_hex8((uint8_t)mouse_report.v); print(" "); | |||
print_hex8((uint8_t)mouse_report.h); print("]\n"); | |||
} | |||
/* PS/2 Mouse Synopsis | |||
* http://www.computer-engineering.org/ps2mouse/ | |||
* | |||
* Command: | |||
* 0xFF: Reset | |||
* 0xF6: Set Defaults Sampling; rate=100, resolution=4cnt/mm, scaling=1:1, reporting=disabled | |||
* 0xF5: Disable Data Reporting | |||
* 0xF4: Enable Data Reporting | |||
* 0xF3: Set Sample Rate | |||
* 0xF2: Get Device ID | |||
* 0xF0: Set Remote Mode | |||
* 0xEB: Read Data | |||
* 0xEA: Set Stream Mode | |||
* 0xE9: Status Request | |||
* 0xE8: Set Resolution | |||
* 0xE7: Set Scaling 2:1 | |||
* 0xE6: Set Scaling 1:1 | |||
* | |||
* Mode: | |||
* Stream Mode: devices sends the data when it changs its state | |||
* Remote Mode: host polls the data periodically | |||
* | |||
* This code uses Remote Mode and polls the data with Read Data(0xEB). | |||
* | |||
* Data format: | |||
* byte|7 6 5 4 3 2 1 0 | |||
* ----+-------------------------------------------------------------- | |||
* 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left | |||
* 1| X movement | |||
* 2| Y movement | |||
*/ |
@@ -20,6 +20,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include <stdbool.h> | |||
#define PS2_MOUSE_READ_DATA 0xEB | |||
/* | |||
* Data format: | |||
* byte|7 6 5 4 3 2 1 0 | |||
* ----+-------------------------------------------------------------- | |||
* 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left | |||
* 1| X movement(0-255) | |||
* 2| Y movement(0-255) | |||
*/ | |||
#define PS2_MOUSE_BTN_MASK 0x07 | |||
#define PS2_MOUSE_BTN_LEFT 0 | |||
#define PS2_MOUSE_BTN_RIGHT 1 | |||
@@ -29,16 +39,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#define PS2_MOUSE_X_OVFLW 6 | |||
#define PS2_MOUSE_Y_OVFLW 7 | |||
bool ps2_mouse_enable; | |||
extern uint8_t ps2_mouse_x; | |||
extern uint8_t ps2_mouse_y; | |||
extern uint8_t ps2_mouse_btn; | |||
extern uint8_t ps2_mouse_error_count; | |||
/* | |||
* Scroll by mouse move with pressing button | |||
*/ | |||
/* mouse button to start scrolling; set 0 to disable scroll */ | |||
#ifndef PS2_MOUSE_SCROLL_BTN_MASK | |||
#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE) | |||
#endif | |||
/* send button event when button is released within this value(ms); set 0 to disable */ | |||
#ifndef PS2_MOUSE_SCROLL_BTN_SEND | |||
#define PS2_MOUSE_SCROLL_BTN_SEND 300 | |||
#endif | |||
/* divide virtical and horizontal mouse move by this to convert to scroll move */ | |||
#ifndef PS2_MOUSE_SCROLL_DIVISOR_V | |||
#define PS2_MOUSE_SCROLL_DIVISOR_V 2 | |||
#endif | |||
#ifndef PS2_MOUSE_SCROLL_DIVISOR_H | |||
#define PS2_MOUSE_SCROLL_DIVISOR_H 2 | |||
#endif | |||
uint8_t ps2_mouse_init(void); | |||
uint8_t ps2_mouse_read(void); | |||
bool ps2_mouse_changed(void); | |||
void ps2_mouse_usb_send(void); | |||
void ps2_mouse_print(void); | |||
void ps2_mouse_task(void); | |||
#endif |
@@ -1,5 +1,5 @@ | |||
/* | |||
Copyright 2010,2011 Jun WAKO <[email protected]> | |||
Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]> | |||
This software is licensed with a Modified BSD License. | |||
All of this is supposed to be Free Software, Open Source, DFSG-free, | |||
@@ -36,41 +36,15 @@ 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" | |||
#if 0 | |||
#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0) | |||
#define DEBUGP(x) do { PORTC = x; } while (0) | |||
#else | |||
#define DEBUGP_INIT() | |||
#define DEBUGP(x) | |||
#endif | |||
#define WAIT(stat, us, err) do { \ | |||
if (!wait_##stat(us)) { \ | |||
@@ -83,49 +57,38 @@ 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); | |||
static inline void pbuf_clear(void); | |||
void ps2_host_init(void) | |||
{ | |||
DEBUGP_INIT(); | |||
DEBUGP(0x1); | |||
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; | |||
DEBUGP(0x6); | |||
PS2_USART_OFF(); | |||
/* 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)) { | |||
@@ -137,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); | |||
@@ -153,134 +119,55 @@ uint8_t ps2_host_send(uint8_t data) | |||
WAIT(clock_hi, 50, 8); | |||
WAIT(data_hi, 50, 9); | |||
res = ps2_host_recv_response(); | |||
idle(); | |||
PS2_USART_INIT(); | |||
PS2_USART_RX_INT_ON(); | |||
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) | |||
{ | |||
uint8_t data = 0; | |||
PS2_USART_INIT(); | |||
PS2_USART_RX_POLL_ON(); | |||
while (!PS2_USART_RX_READY) | |||
; | |||
data = PS2_USART_RX_DATA; | |||
PS2_USART_OFF(); | |||
DEBUGP(0x9); | |||
return data; | |||
// 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) | |||
{ | |||
DEBUGP(0x7); | |||
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) { | |||
DEBUGP(error>>2); | |||
} else { | |||
if (!error) { | |||
pbuf_enqueue(data); | |||
} else { | |||
xprintf("PS2 USART error: %02X data: %02X\n", error, data); | |||
} | |||
DEBUGP(0x8); | |||
} | |||
/* 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); | |||
} | |||
@@ -293,9 +180,6 @@ static uint8_t pbuf_head = 0; | |||
static uint8_t pbuf_tail = 0; | |||
static inline void pbuf_enqueue(uint8_t data) | |||
{ | |||
if (!data) | |||
return; | |||
uint8_t sreg = SREG; | |||
cli(); | |||
uint8_t next = (pbuf_head + 1) % PBUF_SIZE; | |||
@@ -303,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; | |||
@@ -322,3 +205,18 @@ static inline uint8_t pbuf_dequeue(void) | |||
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; | |||
} |