Conflicts: common.mk common/keyboard.c keyboard/gh60/Makefile keyboard/gh60/keymap_hasu.c keyboard/gh60/matrix.cled_matrix
ifdef MOUSEKEY_ENABLE | ifdef MOUSEKEY_ENABLE | ||||
SRC += $(COMMON_DIR)/mousekey.c | SRC += $(COMMON_DIR)/mousekey.c | ||||
OPT_DEFS += -DMOUSEKEY_ENABLE | OPT_DEFS += -DMOUSEKEY_ENABLE | ||||
OPT_DEFS += -DMOUSE_ENABLE | |||||
endif | endif | ||||
ifdef EXTRAKEY_ENABLE | ifdef EXTRAKEY_ENABLE | ||||
OPT_DEFS += -DNKRO_ENABLE | OPT_DEFS += -DNKRO_ENABLE | ||||
endif | 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 | ifdef SLEEP_LED_ENABLE | ||||
SRC += $(COMMON_DIR)/sleep_led.c | SRC += $(COMMON_DIR)/sleep_led.c | ||||
OPT_DEFS += -DSLEEP_LED_ENABLE | OPT_DEFS += -DSLEEP_LED_ENABLE |
} | } | ||||
break; | break; | ||||
#endif | #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: | default: | ||||
if (event.pressed) { | if (event.pressed) { | ||||
if (tap_count > 0) { | if (tap_count > 0) { | ||||
#endif | #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) | bool is_tap_key(key_t key) | ||||
{ | { | ||||
action_t action = layer_switch_get_action(key); | action_t action = layer_switch_get_action(key); |
//void set_mods(uint8_t mods); | //void set_mods(uint8_t mods); | ||||
void clear_keyboard(void); | void clear_keyboard(void); | ||||
void clear_keyboard_but_mods(void); | void clear_keyboard_but_mods(void); | ||||
bool sending_anykey(void); | |||||
void layer_switch(uint8_t new_layer); | void layer_switch(uint8_t new_layer); | ||||
bool is_tap_key(key_t key); | bool is_tap_key(key_t key); | ||||
* | * | ||||
* ACT_MODS_TAP(001r): | * ACT_MODS_TAP(001r): | ||||
* 001r|mods|0000 0000 Modifiers with OneShot | * 001r|mods|0000 0000 Modifiers with OneShot | ||||
* 001r|mods|0000 0001 Modifiers with tap toggle | |||||
* 001r|mods|0000 00xx (reserved) | * 001r|mods|0000 00xx (reserved) | ||||
* 001r|mods| keycode Modifiers with Tap Key(Dual role) | * 001r|mods| keycode Modifiers with Tap Key(Dual role) | ||||
* | * | ||||
}; | }; | ||||
enum mods_codes { | enum mods_codes { | ||||
MODS_ONESHOT = 0x00, | MODS_ONESHOT = 0x00, | ||||
MODS_TAP_TOGGLE = 0x01, | |||||
}; | }; | ||||
#define ACTION_KEY(key) ACTION(ACT_MODS, (key)) | #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) | |||||
/* | /* |
#define ACTION_UTIL_H | #define ACTION_UTIL_H | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include "report.h" | |||||
extern report_keyboard_t *keyboard_report; | extern report_keyboard_t *keyboard_report; | ||||
bool keyboard_nkro = false; | bool keyboard_nkro = false; | ||||
#endif | #endif | ||||
report_mouse_t mouse_report = {}; | |||||
static host_driver_t *driver; | static host_driver_t *driver; | ||||
static uint16_t last_system_report = 0; | static uint16_t last_system_report = 0; | ||||
static uint16_t last_consumer_report = 0; | static uint16_t last_consumer_report = 0; | ||||
(*driver->send_consumer)(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) | uint16_t host_last_sysytem_report(void) | ||||
{ | { | ||||
return last_system_report; | return last_system_report; |
extern bool keyboard_nkro; | extern bool keyboard_nkro; | ||||
#endif | #endif | ||||
/* report */ | |||||
extern report_mouse_t mouse_report; | |||||
/* host driver */ | /* host driver */ | ||||
void host_set_driver(host_driver_t *driver); | void host_set_driver(host_driver_t *driver); | ||||
void host_system_send(uint16_t data); | void host_system_send(uint16_t data); | ||||
void host_consumer_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_sysytem_report(void); | ||||
uint16_t host_last_consumer_report(void); | uint16_t host_last_consumer_report(void); | ||||
#include "sendchar.h" | #include "sendchar.h" | ||||
#include "bootmagic.h" | #include "bootmagic.h" | ||||
#include "eeconfig.h" | #include "eeconfig.h" | ||||
#include "mousekey.h" | |||||
#include "backlight.h" | #include "backlight.h" | ||||
#include "keymap_ex.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 | #ifdef MATRIX_HAS_GHOST | ||||
action_exec(TICK); | action_exec(TICK); | ||||
MATRIX_LOOP_END: | MATRIX_LOOP_END: | ||||
#ifdef MOUSEKEY_ENABLE | #ifdef MOUSEKEY_ENABLE | ||||
// mousekey repeat & acceleration | // mousekey repeat & acceleration | ||||
mousekey_task(); | mousekey_task(); | ||||
#endif | #endif | ||||
#ifdef PS2_MOUSE_ENABLE | |||||
ps2_mouse_task(); | |||||
#endif | |||||
// update LED | // update LED | ||||
if (led_status != host_keyboard_leds()) { | if (led_status != host_keyboard_leds()) { | ||||
led_status = host_keyboard_leds(); | led_status = host_keyboard_leds(); |
static report_mouse_t mouse_report = {}; | |||||
static uint8_t mousekey_repeat = 0; | static uint8_t mousekey_repeat = 0; | ||||
static uint8_t mousekey_accel = 0; | static uint8_t mousekey_accel = 0; | ||||
uint8_t matrix_scan(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; | uint16_t codes; | ||||
uint8_t key0, key1; | uint8_t key0, key1; | ||||
is_modified = false; | 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; | key0 = codes>>8; | ||||
key1 = codes&0xFF; | key1 = codes&0xFF; | ||||
} else { | } else { | ||||
register_key(key0); | register_key(key0); | ||||
if (key1 != 0xFF) // key1 is 0xFF when no second key. | 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; | return 1; |
# Target file name (without extension). | # Target file name (without extension). | ||||
TARGET = ps2_usb | |||||
TARGET = ps2_usb_lufa | |||||
# Directory common source filess exist | # Directory common source filess exist | ||||
TOP_DIR = ../.. | TOP_DIR = ../.. | ||||
# Directory keyboard dependent files exist | # Directory keyboard dependent files exist | ||||
TARGET_DIR = . | 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. | # 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 | 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 | # Search Path | ||||
VPATH += $(TARGET_DIR) | VPATH += $(TARGET_DIR) | ||||
VPATH += $(TOP_DIR) | VPATH += $(TOP_DIR) | ||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | include $(TOP_DIR)/protocol.mk | ||||
include $(TOP_DIR)/protocol/lufa.mk | |||||
include $(TOP_DIR)/common.mk | include $(TOP_DIR)/common.mk | ||||
include $(TOP_DIR)/rules.mk | include $(TOP_DIR)/rules.mk |
# 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 |
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 |
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) |
#define VENDOR_ID 0xFEED | #define VENDOR_ID 0xFEED | ||||
#define PRODUCT_ID 0x6512 | #define PRODUCT_ID 0x6512 | ||||
#define DEVICE_VER 0x0001 | |||||
#define MANUFACTURER t.m.k. | #define MANUFACTURER t.m.k. | ||||
#define PRODUCT PS/2 keyboard converter | #define PRODUCT PS/2 keyboard converter | ||||
#define DESCRIPTION convert PS/2 keyboard to USB | #define DESCRIPTION convert PS/2 keyboard to USB | ||||
) | ) | ||||
/* 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 | #ifdef PS2_USE_USART | ||||
#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) | #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) | ||||
/* XCK for clock line and RXD for data line */ | /* XCK for clock line and RXD for data line */ | ||||
#define PS2_DATA_PIN PIND | #define PS2_DATA_PIN PIND | ||||
#define PS2_DATA_DDR DDRD | #define PS2_DATA_DDR DDRD | ||||
#define PS2_DATA_BIT 2 | #define PS2_DATA_BIT 2 | ||||
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | /* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | ||||
/* set DDR of CLOCK as input to be slave */ | /* set DDR of CLOCK as input to be slave */ | ||||
#define PS2_USART_INIT() do { \ | #define PS2_USART_INIT() do { \ | ||||
#define PS2_USART_RX_DATA UDR1 | #define PS2_USART_RX_DATA UDR1 | ||||
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) | #define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) | ||||
#define PS2_USART_RX_VECT USART1_RX_vect | #define PS2_USART_RX_VECT USART1_RX_vect | ||||
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) | ||||
/* XCK for clock line and RXD for data line */ | /* XCK for clock line and RXD for data line */ | ||||
#define PS2_CLOCK_PORT PORTD | #define PS2_CLOCK_PORT PORTD | ||||
#define PS2_DATA_PIN PIND | #define PS2_DATA_PIN PIND | ||||
#define PS2_DATA_DDR DDRD | #define PS2_DATA_DDR DDRD | ||||
#define PS2_DATA_BIT 0 | #define PS2_DATA_BIT 0 | ||||
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | /* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | ||||
/* set DDR of CLOCK as input to be slave */ | /* set DDR of CLOCK as input to be slave */ | ||||
#define PS2_USART_INIT() do { \ | #define PS2_USART_INIT() do { \ | ||||
#endif | #endif | ||||
#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 | #endif |
/* | |||||
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]); | |||||
} |
/* | |||||
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)]) }; | |||||
} |
/* | |||||
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 |
/* | /* | ||||
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 | /* 0: JIS LAYOUT | ||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. | * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. | ||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|Slp|Wak| | * |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|Slp|Wak| | ||||
* |Ctrl |Gui |Alt |MHEN| Space |HENK|KANA|Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| | 0| .| | | * |Ctrl |Gui |Alt |MHEN| Space |HENK|KANA|Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| | 0| .| | | ||||
* `-----------------------------------------------------------' `-----------' `---------------' | * `-----------------------------------------------------------' `-----------' `---------------' | ||||
*/ | */ | ||||
/* | |||||
KEYMAP_JIS( | KEYMAP_JIS( | ||||
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, 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, | GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | ||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RO, RSFT, UP, P1, P2, P3, | 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 | 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[] = { | |||||
}; |
#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[] = { | |||||
}; |
/* | |||||
* 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 | |||||
}; | |||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <avr/io.h> | #include <avr/io.h> | ||||
#include <util/delay.h> | #include <util/delay.h> | ||||
#include "action.h" | |||||
#include "print.h" | #include "print.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
static void matrix_make(uint8_t code); | static void matrix_make(uint8_t code); | ||||
static void matrix_break(uint8_t code); | static void matrix_break(uint8_t code); | ||||
static void matrix_clear(void); | |||||
#ifdef MATRIX_HAS_GHOST | #ifdef MATRIX_HAS_GHOST | ||||
static bool matrix_has_ghost_in_row(uint8_t row); | static bool matrix_has_ghost_in_row(uint8_t row); | ||||
#endif | #endif | ||||
void matrix_init(void) | void matrix_init(void) | ||||
{ | { | ||||
debug_enable = true; | |||||
ps2_host_init(); | ps2_host_init(); | ||||
// initialize matrix state: all keys off | // initialize matrix state: all keys off | ||||
matrix_break(PAUSE); | matrix_break(PAUSE); | ||||
} | } | ||||
uint8_t code; | |||||
while ((code = ps2_host_recv())) { | |||||
uint8_t code = ps2_host_recv(); | |||||
if (!ps2_error) { | |||||
switch (state) { | switch (state) { | ||||
case INIT: | case INIT: | ||||
switch (code) { | switch (code) { | ||||
matrix_make(PRINT_SCREEN); | matrix_make(PRINT_SCREEN); | ||||
state = INIT; | state = INIT; | ||||
break; | break; | ||||
case 0x00: // Overrun [3]p.25 | |||||
matrix_clear(); | |||||
clear_keyboard(); | |||||
print("Overrun\n"); | |||||
state = INIT; | |||||
break; | |||||
default: // normal key make | default: // normal key make | ||||
if (code < 0x80) { | if (code < 0x80) { | ||||
matrix_make(code); | matrix_make(code); | ||||
} else { | } 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; | state = INIT; | ||||
} | } | ||||
if (code < 0x80) { | if (code < 0x80) { | ||||
matrix_make(code|0x80); | matrix_make(code|0x80); | ||||
} else { | } 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; | state = INIT; | ||||
} | } | ||||
matrix_break(PRINT_SCREEN); | matrix_break(PRINT_SCREEN); | ||||
state = INIT; | state = INIT; | ||||
break; | break; | ||||
case 0xF0: | |||||
matrix_clear(); | |||||
clear_keyboard(); | |||||
xprintf("unexpected scan code at F0: F0(clear and cont.)\n"); | |||||
break; | |||||
default: | default: | ||||
if (code < 0x80) { | if (code < 0x80) { | ||||
matrix_break(code); | matrix_break(code); | ||||
} else { | } 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; | state = INIT; | ||||
} | } | ||||
if (code < 0x80) { | if (code < 0x80) { | ||||
matrix_break(code|0x80); | matrix_break(code|0x80); | ||||
} else { | } 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; | state = INIT; | ||||
} | } | ||||
default: | default: | ||||
state = INIT; | 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; | return 1; | ||||
} | } | ||||
is_modified = true; | is_modified = true; | ||||
} | } | ||||
} | } | ||||
inline | |||||
static void matrix_clear(void) | |||||
{ | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||||
} |
# 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 |
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 |
/* | |||||
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 |
/* | |||||
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; | |||||
} |
/* | |||||
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); | |||||
} |
/* | |||||
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; | |||||
} | |||||
} |
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. | 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 | ## 5. Legacy Keymap |
TARGET_DIR = . | TARGET_DIR = . | ||||
# project specific files | # project specific files | ||||
SRC += keymap.c \ | |||||
SRC = keymap_common.c \ | |||||
matrix.c \ | matrix.c \ | ||||
led.c \ | led.c \ | ||||
backlight.c | backlight.c | ||||
ifdef KEYMAP | |||||
SRC := keymap_$(KEYMAP).c $(SRC) | |||||
else | |||||
SRC := keymap_poker.c $(SRC) | |||||
endif | |||||
CONFIG_H = config.h | CONFIG_H = config.h | ||||
F_USB = $(F_CPU) | F_USB = $(F_CPU) | ||||
# Interrupt driven control endpoint task(+60) | # Interrupt driven control endpoint task(+60) | ||||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||||
# Boot Section Size in *bytes* | # Boot Section Size in *bytes* | ||||
include $(TOP_DIR)/protocol/lufa.mk | include $(TOP_DIR)/protocol/lufa.mk | ||||
include $(TOP_DIR)/common.mk | include $(TOP_DIR)/common.mk | ||||
include $(TOP_DIR)/rules.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 |
TARGET_DIR = . | TARGET_DIR = . | ||||
# project specific files | # project specific files | ||||
SRC = keymap.c \ | |||||
SRC = keymap_common.c \ | |||||
matrix.c \ | matrix.c \ | ||||
led.c | led.c | ||||
ifdef KEYMAP | |||||
SRC := keymap_$(KEYMAP).c $(SRC) | |||||
else | |||||
SRC := keymap_poker.c $(SRC) | |||||
endif | |||||
CONFIG_H = config.h | CONFIG_H = config.h | ||||
====================== | ====================== | ||||
DIY compact keyboard designed and run by komar007 and Geekhack community. | 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) | - [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 | ## Build | ||||
Move to this directory then just run `make` like: | 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 | ## 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 | | | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | ||||
|-----------------------------------------------------------| | |-----------------------------------------------------------| | ||||
|-----------------------------------------------------------| | |-----------------------------------------------------------| | ||||
|Ctrl|Gui |Alt | Space |Fn |Gui |App |Ctrl| | |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 | | |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | ||||
|-----------------------------------------------------------| | |-----------------------------------------------------------| | ||||
|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |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 | |||||
/* | |||||
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)]) }; | |||||
} |
/* | |||||
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 |
/* | |||||
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 | /* Keymap 0: Default Layer | ||||
* ,-----------------------------------------------------------. | * ,-----------------------------------------------------------. | ||||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | ||||
/* | /* | ||||
* Fn action definition | * Fn action definition | ||||
*/ | */ | ||||
static const uint16_t PROGMEM fn_actions[] = { | |||||
const uint16_t PROGMEM fn_actions[] = { | |||||
[0] = ACTION_LAYER_MOMENTARY(4), | [0] = ACTION_LAYER_MOMENTARY(4), | ||||
[1] = ACTION_LAYER_TAP_KEY(5, KC_SLASH), | [1] = ACTION_LAYER_TAP_KEY(5, KC_SLASH), | ||||
[2] = ACTION_LAYER_TAP_KEY(6, KC_SCLN), | [2] = ACTION_LAYER_TAP_KEY(6, KC_SCLN), | ||||
[8] = ACTION_DEFAULT_LAYER_SET(3), // set workman layout | [8] = ACTION_DEFAULT_LAYER_SET(3), // set workman layout | ||||
[9] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_GRV), | [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; | |||||
} |
#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), | |||||
}; |
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 */ | /* 0: qwerty */ | ||||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | 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, \ | TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \ | ||||
LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, RSFT, \ | LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, RSFT, \ | ||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL), | LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL), | ||||
}; | }; | ||||
static const uint16_t PROGMEM fn_actions[] = {}; | |||||
const uint16_t PROGMEM fn_actions[] = {}; |
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 */ | /* 0: qwerty */ | ||||
KEYMAP_ANSI( | KEYMAP_ANSI( | ||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | ||||
TRNS,TRNS,TRNS,FN6, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \ | TRNS,TRNS,TRNS,FN6, 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 PROGMEM fn_actions[] = { | |||||
const uint16_t PROGMEM fn_actions[] = { | |||||
/* Poker Layout */ | /* Poker Layout */ | ||||
[0] = ACTION_LAYER_MOMENTARY(6), // to Fn overlay | [0] = ACTION_LAYER_MOMENTARY(6), // to Fn overlay | ||||
[1] = ACTION_LAYER_TOGGLE(4), // toggle arrow overlay | [1] = ACTION_LAYER_TOGGLE(4), // toggle arrow overlay |
#include "keymap_common.h" | |||||
// Poker fix with toggle and bit operation | // Poker fix with toggle and bit operation | ||||
// Fn + Esc = ` | // Fn + Esc = ` | ||||
// Fn + {left, down, up, right} = {home, pgdown, pgup, end} | // 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 */ | /* 0: qwerty */ | ||||
KEYMAP_ANSI( | KEYMAP_ANSI( | ||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | ||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \ | TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \ | ||||
TRNS,TRNS,TRNS, TRNS, TRNS,LEFT,DOWN,RGHT), | TRNS,TRNS,TRNS, TRNS, TRNS,LEFT,DOWN,RGHT), | ||||
}; | }; | ||||
static const uint16_t PROGMEM fn_actions[] = { | |||||
const uint16_t PROGMEM fn_actions[] = { | |||||
/* Poker Layout */ | /* Poker Layout */ | ||||
[0] = ACTION_LAYER_BIT_XOR(1, 0b0101, ON_BOTH), // Poker Fn(with fix for Esc) | [0] = ACTION_LAYER_BIT_XOR(1, 0b0101, ON_BOTH), // Poker Fn(with fix for Esc) | ||||
[1] = ACTION_LAYER_TOGGLE(5), // Poker Arrow toggle | [1] = ACTION_LAYER_TOGGLE(5), // Poker Arrow toggle |
#include "keymap_common.h" | |||||
// Poker fix with set(state transition) | // Poker fix with set(state transition) | ||||
// Fn + Esc = ` | // Fn + Esc = ` | ||||
// Fn + {left, down, up, right} = {home, pgdown, pgup, end} | // 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 */ | /* 0: qwerty */ | ||||
KEYMAP_ANSI( | KEYMAP_ANSI( | ||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | ||||
/* | /* | ||||
* Fn action definition | * Fn action definition | ||||
*/ | */ | ||||
static const uint16_t PROGMEM fn_actions[] = { | |||||
const uint16_t PROGMEM fn_actions[] = { | |||||
/* Poker Layout */ | /* Poker Layout */ | ||||
[0] = ACTION_LAYER_SET(4, ON_PRESS), // FN0 move to Fn'd when press | [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 | [1] = ACTION_LAYER_SET(5, ON_PRESS), // FN1 move to Fn'd arrow when press |
#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 | |||||
}; |
} | } | ||||
/* Column pin configuration | /* 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) | static void init_cols(void) | ||||
{ | { | ||||
PORTD |= (1<<PD7 | 1<<PD6 | 1<<PD4); | PORTD |= (1<<PD7 | 1<<PD6 | 1<<PD4); | ||||
DDRC &= ~(1<<PC7 | 1<<PC6); | DDRC &= ~(1<<PC7 | 1<<PC6); | ||||
PORTC |= (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); | 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); | 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 | #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 | #endif | ||||
} | } | ||||
/* Column pin configuration | /* 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) | static matrix_row_t read_cols(void) | ||||
{ | { | ||||
#if defined(GH60_REV_C) | |||||
#if defined(GH60_REV_CHN) | |||||
return (PINF&(1<<PF0) ? 0 : (1<<0)) | | return (PINF&(1<<PF0) ? 0 : (1<<0)) | | ||||
(PINF&(1<<PF1) ? 0 : (1<<1)) | | (PINF&(1<<PF1) ? 0 : (1<<1)) | | ||||
(PINE&(1<<PE6) ? 0 : (1<<2)) | | (PINE&(1<<PE6) ? 0 : (1<<2)) | | ||||
(PIND&(1<<PD7) ? 0 : (1<<11)) | | (PIND&(1<<PD7) ? 0 : (1<<11)) | | ||||
(PIND&(1<<PD6) ? 0 : (1<<12)) | | (PIND&(1<<PD6) ? 0 : (1<<12)) | | ||||
(PINB&(1<<PB3) ? 0 : (1<<13)); | (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 | #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 | #endif | ||||
} | } | ||||
# List C source files here. (C dependencies are automatically generated.) | # List C source files here. (C dependencies are automatically generated.) | ||||
SRC += keymap.c \ | |||||
SRC += keymap_common.c \ | |||||
matrix.c \ | matrix.c \ | ||||
led.c | led.c | ||||
ifdef KEYMAP | |||||
SRC := keymap_$(KEYMAP).c $(SRC) | |||||
else | |||||
SRC := keymap_hasu.c $(SRC) | |||||
endif | |||||
CONFIG_H = config.h | CONFIG_H = config.h | ||||
#---------------------------------------------------------------------------- | |||||
# 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 |
TARGET_DIR = . | TARGET_DIR = . | ||||
# keyboard dependent files | # keyboard dependent files | ||||
SRC = keymap.c \ | |||||
SRC = keymap_common.c \ | |||||
matrix.c \ | matrix.c \ | ||||
led.c | led.c | ||||
ifdef KEYMAP | |||||
SRC := keymap_$(KEYMAP).c $(SRC) | |||||
else | |||||
SRC := keymap_hasu.c $(SRC) | |||||
endif | |||||
CONFIG_H = config.h | CONFIG_H = config.h | ||||
Alternative Controller for HHKB Pro | 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. | See [this thread][AltController] in geekhack.org. | ||||
Set `MCU`, `BOOTLOADER_SIZE` and other build options in `Makefile` and `config.h`. | Set `MCU`, `BOOTLOADER_SIZE` and other build options in `Makefile` and `config.h`. | ||||
### Build | ### 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 | ### Program | ||||
First, push reset button on board to start bootloader. | First, push reset button on board to start bootloader. | ||||
Use [Teensy Loader] if your controller is Teensy/Teensy++. | 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 | ##Hardware | ||||
See [this post](http://geekhack.org/index.php?topic=12047.msg948923#msg948923). | 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++ | | | Teensy++ | | ||||
| | | | | | ||||
- NOTE: PJRC [Teensy](http://www.pjrc.com/teensy/) | - 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 | [LUFA]: http://www.fourwalledcubicle.com/LUFA.php | ||||
[FLIP]: http://www.atmel.com/tools/FLIP.aspx | [FLIP]: http://www.atmel.com/tools/FLIP.aspx | ||||
[Teensy Loader]: http://www.pjrc.com/teensy/loader.html | [Teensy Loader]: http://www.pjrc.com/teensy/loader.html | ||||
[V-USB]: http://www.obdev.at/products/vusb/index.html | [V-USB]: http://www.obdev.at/products/vusb/index.html | ||||
[USBaspLoader]: http://www.obdev.at/products/vusb/usbasploader.html |
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 |
/* | |||||
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)]) }; | |||||
} |
/* | |||||
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 |
/* | |||||
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 | #ifdef KEYMAP_SECTION_ENABLE | ||||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { | ||||
#else | #else | ||||
static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { | |||||
#endif | #endif | ||||
/* Layer 0: Default Layer | /* Layer 0: Default Layer | ||||
* ,-----------------------------------------------------------. | * ,-----------------------------------------------------------. | ||||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ | 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, \ | 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, \ | 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), | LGUI,LALT, FN6, RALT,RGUI), | ||||
/* Layer 1: HHKB mode (HHKB Fn) | /* Layer 1: HHKB mode (HHKB Fn) | ||||
*/ | */ | ||||
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | 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, \ | 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, \ | LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \ | ||||
LGUI,LALT, SPC, RALT,RGUI), | LGUI,LALT, SPC, RALT,RGUI), | ||||
#ifdef KEYMAP_SECTION_ENABLE | #ifdef KEYMAP_SECTION_ENABLE | ||||
const uint16_t fn_actions[] __attribute__ ((section (".keymap.fn_actions"))) = { | const uint16_t fn_actions[] __attribute__ ((section (".keymap.fn_actions"))) = { | ||||
#else | #else | ||||
static const uint16_t fn_actions[] PROGMEM = { | |||||
const uint16_t fn_actions[] PROGMEM = { | |||||
#endif | #endif | ||||
[0] = ACTION_DEFAULT_LAYER_SET(0), // Default layer(not used) | [0] = ACTION_DEFAULT_LAYER_SET(0), // Default layer(not used) | ||||
[1] = ACTION_LAYER_TAP_TOGGLE(1), // HHKB layer(toggle with 5 taps) | [1] = ACTION_LAYER_TAP_TOGGLE(1), // HHKB layer(toggle with 5 taps) | ||||
[6] = ACTION_LAYER_TAP_KEY(5, KC_SPC), // Mousekey layer with Space | [6] = ACTION_LAYER_TAP_KEY(5, KC_SPC), // Mousekey layer with Space | ||||
[7] = ACTION_LAYER_TOGGLE(3), // Mousekey layer(toggle) | [7] = ACTION_LAYER_TOGGLE(3), // Mousekey layer(toggle) | ||||
[8] = ACTION_MODS_KEY(MOD_LCTL, KC_W), // Close Tab | [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 | // [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 | // [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 '(' | // [13] = ACTION_MACRO_TAP(LSHIFT_PAREN), // Macro: LShift with tap '(' | ||||
// [14] = ACTION_MACRO_TAP(RSHIFT_PAREN), // Macro: RShift with tap ')' | // [14] = ACTION_MACRO_TAP(RSHIFT_PAREN), // Macro: RShift with tap ')' | ||||
// [15] = ACTION_MACRO(HELLO), // Macro: say hello | // [15] = ACTION_MACRO(HELLO), // Macro: say hello | ||||
// NOTE: cant use register_code to avoid conflicting with magic key bind | // NOTE: cant use register_code to avoid conflicting with magic key bind | ||||
if (event.pressed) { | if (event.pressed) { | ||||
if (tap.count == 0 || tap.interrupted) { | if (tap.count == 0 || tap.interrupted) { | ||||
add_mods(MOD_BIT(KC_LSHIFT)); | |||||
//add_mods(MOD_BIT(KC_LSHIFT)); | |||||
layer_on(1); | |||||
} else { | } 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 { | } else { | ||||
if (tap.count == 0 || tap.interrupted) { | if (tap.count == 0 || tap.interrupted) { | ||||
del_mods(MOD_BIT(KC_LSHIFT)); | |||||
//del_mods(MOD_BIT(KC_LSHIFT)); | |||||
layer_off(1); | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
if (tap.count == 0 || tap.interrupted) { | if (tap.count == 0 || tap.interrupted) { | ||||
add_mods(MOD_BIT(KC_RSHIFT)); | add_mods(MOD_BIT(KC_RSHIFT)); | ||||
} else { | } 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 { | } else { | ||||
if (tap.count == 0 || tap.interrupted) { | if (tap.count == 0 || tap.interrupted) { | ||||
break; | 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; | |||||
} |
/* | |||||
* 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), | |||||
}; |
/* | |||||
* 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 | |||||
}; | |||||
F_USB = $(F_CPU) | F_USB = $(F_CPU) | ||||
# Interrupt driven control endpoint task(+60) | # Interrupt driven control endpoint task(+60) | ||||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||||
# Boot Section Size in *bytes* | # Boot Section Size in *bytes* | ||||
# Build Options | # Build Options | ||||
# comment out to disable the 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) | 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 | #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 | # Search Path | ||||
VPATH += $(TARGET_DIR) | VPATH += $(TARGET_DIR) | ||||
VPATH += $(TOP_DIR) | VPATH += $(TOP_DIR) | ||||
include $(TOP_DIR)/protocol/lufa.mk | |||||
include $(TOP_DIR)/common.mk | include $(TOP_DIR)/common.mk | ||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/protocol/lufa.mk | |||||
include $(TOP_DIR)/rules.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 |
# Build Options | # Build Options | ||||
# comment out to disable the 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 | 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 | # Search Path | ||||
VPATH += $(TARGET_DIR) | VPATH += $(TARGET_DIR) | ||||
VPATH += $(TOP_DIR) | VPATH += $(TOP_DIR) | ||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/common.mk | include $(TOP_DIR)/common.mk | ||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/rules.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 |
Onekey | 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 | https://github.com/tmk/tmk_keyboard/issues/56 |
//#define NO_ACTION_MACRO | //#define NO_ACTION_MACRO | ||||
//#define NO_ACTION_FUNCTION | //#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 | #endif |
{ | { | ||||
debug_enable = true; | debug_enable = true; | ||||
debug_matrix = true; | debug_matrix = true; | ||||
debug_mouse = true; | |||||
// initialize row and col | // initialize row and col | ||||
unselect_rows(); | unselect_rows(); | ||||
init_cols(); | init_cols(); | ||||
/* Column pin configuration | /* Column pin configuration | ||||
* col: 0 | * col: 0 | ||||
* pin: D0 | |||||
* pin: B0 | |||||
*/ | */ | ||||
static void init_cols(void) | static void init_cols(void) | ||||
{ | { | ||||
// Input with pull-up(DDR:0, PORT:1) | // 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) | 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 pin configuration | ||||
* row: 0 | * row: 0 | ||||
* pin: D1 | |||||
* pin: B1 | |||||
*/ | */ | ||||
static void unselect_rows(void) | static void unselect_rows(void) | ||||
{ | { | ||||
// Hi-Z(DDR:0, PORT:0) to unselect | // Hi-Z(DDR:0, PORT:0) to unselect | ||||
DDRD &= ~0b00000010; | |||||
PORTD &= ~0b00000010; | |||||
DDRB &= ~0b00000010; | |||||
PORTB &= ~0b00000010; | |||||
} | } | ||||
static void select_row(uint8_t row) | static void select_row(uint8_t row) | ||||
// Output low(DDR:1, PORT:0) to select | // Output low(DDR:1, PORT:0) to select | ||||
switch (row) { | switch (row) { | ||||
case 0: | case 0: | ||||
DDRD |= (1<<1); | |||||
PORTD &= ~(1<<1); | |||||
DDRB |= (1<<1); | |||||
PORTB &= ~(1<<1); | |||||
break; | break; | ||||
} | } | ||||
} | } |
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 | # Search Path | ||||
VPATH += $(TOP_DIR)/protocol | VPATH += $(TOP_DIR)/protocol |
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 |
/* | |||||
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 | |||||
} | |||||
/* | |||||
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 |
/* | |||||
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(); | |||||
} | |||||
} | |||||
} |
*/ | */ | ||||
void EVENT_USB_Device_Connect(void) | void EVENT_USB_Device_Connect(void) | ||||
{ | { | ||||
led_set(0x1f); // all on | |||||
} | } | ||||
void EVENT_USB_Device_Disconnect(void) | void EVENT_USB_Device_Disconnect(void) | ||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
sleep_led_disable(); | sleep_led_disable(); | ||||
#endif | |||||
// NOTE: converters may not accept this | |||||
led_set(host_keyboard_leds()); | led_set(host_keyboard_leds()); | ||||
#endif | |||||
} | } | ||||
void EVENT_USB_Device_StartOfFrame(void) | void EVENT_USB_Device_StartOfFrame(void) | ||||
{ | { | ||||
SetupHardware(); | SetupHardware(); | ||||
sei(); | sei(); | ||||
/* wait for USB startup & debug output */ | |||||
while (USB_DeviceState != DEVICE_STATE_Configured) { | |||||
#if defined(INTERRUPT_CONTROL_ENDPOINT) | #if defined(INTERRUPT_CONTROL_ENDPOINT) | ||||
while (USB_DeviceState != DEVICE_STATE_Configured) ; | |||||
; | |||||
#else | |||||
USB_USBTask(); | |||||
#endif | #endif | ||||
} | |||||
print("USB configured.\n"); | print("USB configured.\n"); | ||||
/* init modules */ | |||||
keyboard_init(); | keyboard_init(); | ||||
host_set_driver(&lufa_driver); | host_set_driver(&lufa_driver); | ||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE |
$(PJRC_DIR)/usb.c | $(PJRC_DIR)/usb.c | ||||
# Option modules | # 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 | SRC += $(PJRC_DIR)/usb_mouse.c | ||||
endif | endif | ||||
suspend_wakeup_init(); | suspend_wakeup_init(); | ||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
sleep_led_disable(); | sleep_led_disable(); | ||||
#endif | |||||
// NOTE: converters may not accept this | |||||
led_set(host_keyboard_leds()); | led_set(host_keyboard_leds()); | ||||
#endif | |||||
UDIEN |= (1<<SUSPE); | UDIEN |= (1<<SUSPE); | ||||
UDIEN &= ~(1<<WAKEUPE); | UDIEN &= ~(1<<WAKEUPE); |
/* | /* | ||||
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. | This software is licensed with a Modified BSD License. | ||||
All of this is supposed to be Free Software, Open Source, DFSG-free, | All of this is supposed to be Free Software, Open Source, DFSG-free, | ||||
#ifndef PS2_H | #ifndef PS2_H | ||||
#define PS2_H | #define PS2_H | ||||
#include <stdbool.h> | |||||
#include <util/delay.h> | |||||
#include <avr/io.h> | |||||
/* | /* | ||||
* Primitive PS/2 Library for AVR | * 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_ACK 0xFA | ||||
#define PS2_RESEND 0xFE | #define PS2_RESEND 0xFE | ||||
#define PS2_SET_LED 0xED | #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_SCROLL_LOCK 0 | ||||
#define PS2_LED_NUM_LOCK 1 | #define PS2_LED_NUM_LOCK 1 | ||||
extern uint8_t ps2_error; | extern uint8_t ps2_error; | ||||
/* host role */ | |||||
void ps2_host_init(void); | void ps2_host_init(void); | ||||
uint8_t ps2_host_send(uint8_t data); | uint8_t ps2_host_send(uint8_t data); | ||||
uint8_t ps2_host_recv_response(void); | uint8_t ps2_host_recv_response(void); | ||||
uint8_t ps2_host_recv(void); | uint8_t ps2_host_recv(void); | ||||
void ps2_host_set_led(uint8_t usb_led); | 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 | #endif |
/* | |||||
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); | |||||
} |
/* | /* | ||||
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. | This software is licensed with a Modified BSD License. | ||||
All of this is supposed to be Free Software, Open Source, DFSG-free, | All of this is supposed to be Free Software, Open Source, DFSG-free, | ||||
POSSIBILITY OF SUCH DAMAGE. | POSSIBILITY OF SUCH DAMAGE. | ||||
*/ | */ | ||||
/* | |||||
* PS/2 protocol Pin interrupt version | |||||
*/ | |||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <avr/io.h> | |||||
#include <avr/interrupt.h> | #include <avr/interrupt.h> | ||||
#include <util/delay.h> | #include <util/delay.h> | ||||
#include "ps2.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 { \ | #define WAIT(stat, us, err) do { \ | ||||
uint8_t ps2_error = PS2_ERR_NONE; | 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) | void ps2_host_init(void) | ||||
{ | { | ||||
#ifdef PS2_USE_INT | |||||
idle(); | |||||
PS2_INT_INIT(); | PS2_INT_INIT(); | ||||
PS2_INT_ON(); | 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 ps2_host_send(uint8_t data) | ||||
{ | { | ||||
uint8_t res = 0; | |||||
bool parity = true; | bool parity = true; | ||||
ps2_error = PS2_ERR_NONE; | ps2_error = PS2_ERR_NONE; | ||||
#ifdef PS2_USE_INT | |||||
PS2_INT_OFF(); | PS2_INT_OFF(); | ||||
#endif | |||||
/* terminate a transmission if we have */ | /* terminate a transmission if we have */ | ||||
inhibit(); | 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(); | data_lo(); | ||||
clock_hi(); | 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++) { | for (uint8_t i = 0; i < 8; i++) { | ||||
_delay_us(15); | _delay_us(15); | ||||
if (data&(1<<i)) { | if (data&(1<<i)) { | ||||
WAIT(clock_hi, 50, 2); | WAIT(clock_hi, 50, 2); | ||||
WAIT(clock_lo, 50, 3); | WAIT(clock_lo, 50, 3); | ||||
} | } | ||||
/* parity [10] */ | |||||
/* Parity bit */ | |||||
_delay_us(15); | _delay_us(15); | ||||
if (parity) { data_hi(); } else { data_lo(); } | if (parity) { data_hi(); } else { data_lo(); } | ||||
WAIT(clock_hi, 50, 4); | WAIT(clock_hi, 50, 4); | ||||
WAIT(clock_lo, 50, 5); | WAIT(clock_lo, 50, 5); | ||||
/* stop bit [11] */ | |||||
/* Stop bit */ | |||||
_delay_us(15); | _delay_us(15); | ||||
data_hi(); | data_hi(); | ||||
/* ack [12] */ | |||||
/* Ack */ | |||||
WAIT(data_lo, 50, 6); | WAIT(data_lo, 50, 6); | ||||
WAIT(clock_lo, 50, 7); | WAIT(clock_lo, 50, 7); | ||||
WAIT(clock_hi, 50, 8); | WAIT(clock_hi, 50, 8); | ||||
WAIT(data_hi, 50, 9); | WAIT(data_hi, 50, 9); | ||||
res = ps2_host_recv_response(); | |||||
ERROR: | |||||
#ifdef PS2_USE_INT | |||||
idle(); | |||||
PS2_INT_ON(); | PS2_INT_ON(); | ||||
return ps2_host_recv_response(); | |||||
ERROR: | |||||
idle(); | 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 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 */ | /* get data received by interrupt */ | ||||
uint8_t ps2_host_recv(void) | 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; | 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) | ISR(PS2_INT_VECT) | ||||
{ | { | ||||
static enum { | static enum { | ||||
} | } | ||||
state++; | state++; | ||||
DEBUGP(state); | |||||
switch (state) { | switch (state) { | ||||
case START: | case START: | ||||
if (data_in()) | if (data_in()) | ||||
} | } | ||||
goto RETURN; | goto RETURN; | ||||
ERROR: | ERROR: | ||||
DEBUGP(0x0F); | |||||
inhibit(); | |||||
ps2_error = state; | ps2_error = state; | ||||
DONE: | DONE: | ||||
state = INIT; | state = INIT; | ||||
RETURN: | RETURN: | ||||
return; | return; | ||||
} | } | ||||
#endif | |||||
static void ps2_reset(void) | |||||
{ | |||||
ps2_host_send(0xFF); | |||||
} | |||||
/* send LED state to keyboard */ | /* send LED state to keyboard */ | ||||
void ps2_host_set_led(uint8_t led) | 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(); | |||||
} |
/* | /* | ||||
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 | 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 | it under the terms of the GNU General Public License as published by | ||||
#include<util/delay.h> | #include<util/delay.h> | ||||
#include "ps2.h" | #include "ps2.h" | ||||
#include "ps2_mouse.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 ps2_mouse_init(void) { | ||||
uint8_t rcv; | uint8_t rcv; | ||||
if (!ps2_mouse_enable) return 1; | |||||
ps2_host_init(); | 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"); | 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: "); | print("ps2_mouse_init: read BAT: "); | ||||
phex(rcv); phex(ps2_error); print("\n"); | 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: "); | print("ps2_mouse_init: read DevID: "); | ||||
phex(rcv); phex(ps2_error); print("\n"); | 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: "); | 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"); | phex(rcv); phex(ps2_error); print("\n"); | ||||
ERROR_RETURN(); | |||||
return 0; | 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; | 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); | _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; | 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 | |||||
*/ |
#include <stdbool.h> | #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_MASK 0x07 | ||||
#define PS2_MOUSE_BTN_LEFT 0 | #define PS2_MOUSE_BTN_LEFT 0 | ||||
#define PS2_MOUSE_BTN_RIGHT 1 | #define PS2_MOUSE_BTN_RIGHT 1 | ||||
#define PS2_MOUSE_X_OVFLW 6 | #define PS2_MOUSE_X_OVFLW 6 | ||||
#define PS2_MOUSE_Y_OVFLW 7 | #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_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 | #endif |
/* | /* | ||||
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. | This software is licensed with a Modified BSD License. | ||||
All of this is supposed to be Free Software, Open Source, DFSG-free, | All of this is supposed to be Free Software, Open Source, DFSG-free, | ||||
*/ | */ | ||||
/* | /* | ||||
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 <stdbool.h> | ||||
#include <avr/io.h> | |||||
#include <avr/interrupt.h> | #include <avr/interrupt.h> | ||||
#include <util/delay.h> | #include <util/delay.h> | ||||
#include "ps2.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 { \ | #define WAIT(stat, us, err) do { \ | ||||
if (!wait_##stat(us)) { \ | if (!wait_##stat(us)) { \ | ||||
uint8_t ps2_error = PS2_ERR_NONE; | 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 uint8_t pbuf_dequeue(void); | ||||
static inline void pbuf_enqueue(uint8_t data); | 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) | 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_INIT(); | ||||
PS2_USART_RX_INT_ON(); | 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 ps2_host_send(uint8_t data) | ||||
{ | { | ||||
uint8_t res = 0; | |||||
bool parity = true; | bool parity = true; | ||||
ps2_error = PS2_ERR_NONE; | ps2_error = PS2_ERR_NONE; | ||||
DEBUGP(0x6); | |||||
PS2_USART_OFF(); | PS2_USART_OFF(); | ||||
/* terminate a transmission if we have */ | /* terminate a transmission if we have */ | ||||
inhibit(); | inhibit(); | ||||
_delay_us(100); | |||||
_delay_us(100); // [4]p.13 | |||||
/* start bit [1] */ | |||||
/* 'Request to Send' and Start bit */ | |||||
data_lo(); | data_lo(); | ||||
clock_hi(); | 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++) { | for (uint8_t i = 0; i < 8; i++) { | ||||
_delay_us(15); | _delay_us(15); | ||||
if (data&(1<<i)) { | if (data&(1<<i)) { | ||||
WAIT(clock_hi, 50, 2); | WAIT(clock_hi, 50, 2); | ||||
WAIT(clock_lo, 50, 3); | WAIT(clock_lo, 50, 3); | ||||
} | } | ||||
/* parity [10] */ | |||||
/* Parity bit */ | |||||
_delay_us(15); | _delay_us(15); | ||||
if (parity) { data_hi(); } else { data_lo(); } | if (parity) { data_hi(); } else { data_lo(); } | ||||
WAIT(clock_hi, 50, 4); | WAIT(clock_hi, 50, 4); | ||||
WAIT(clock_lo, 50, 5); | WAIT(clock_lo, 50, 5); | ||||
/* stop bit [11] */ | |||||
/* Stop bit */ | |||||
_delay_us(15); | _delay_us(15); | ||||
data_hi(); | data_hi(); | ||||
/* ack [12] */ | |||||
/* Ack */ | |||||
WAIT(data_lo, 50, 6); | WAIT(data_lo, 50, 6); | ||||
WAIT(clock_lo, 50, 7); | WAIT(clock_lo, 50, 7); | ||||
WAIT(clock_hi, 50, 8); | WAIT(clock_hi, 50, 8); | ||||
WAIT(data_hi, 50, 9); | 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: | ERROR: | ||||
idle(); | idle(); | ||||
PS2_USART_INIT(); | PS2_USART_INIT(); | ||||
PS2_USART_RX_INT_ON(); | 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 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) | 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) | 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; | uint8_t data = PS2_USART_RX_DATA; | ||||
if (error) { | |||||
DEBUGP(error>>2); | |||||
} else { | |||||
if (!error) { | |||||
pbuf_enqueue(data); | pbuf_enqueue(data); | ||||
} else { | |||||
xprintf("PS2 USART error: %02X data: %02X\n", error, data); | |||||
} | } | ||||
DEBUGP(0x8); | |||||
} | } | ||||
/* send LED state to keyboard */ | /* send LED state to keyboard */ | ||||
void ps2_host_set_led(uint8_t led) | 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); | |||||
} | } | ||||
static uint8_t pbuf_tail = 0; | static uint8_t pbuf_tail = 0; | ||||
static inline void pbuf_enqueue(uint8_t data) | static inline void pbuf_enqueue(uint8_t data) | ||||
{ | { | ||||
if (!data) | |||||
return; | |||||
uint8_t sreg = SREG; | uint8_t sreg = SREG; | ||||
cli(); | cli(); | ||||
uint8_t next = (pbuf_head + 1) % PBUF_SIZE; | uint8_t next = (pbuf_head + 1) % PBUF_SIZE; | ||||
pbuf[pbuf_head] = data; | pbuf[pbuf_head] = data; | ||||
pbuf_head = next; | pbuf_head = next; | ||||
} else { | } else { | ||||
debug("pbuf: full\n"); | |||||
print("pbuf: full\n"); | |||||
} | } | ||||
SREG = sreg; | SREG = sreg; | ||||
} | } | ||||
static inline uint8_t pbuf_dequeue(void) | static inline uint8_t pbuf_dequeue(void) | ||||
{ | { | ||||
uint8_t val = 0; | uint8_t val = 0; | ||||
return val; | 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; | |||||
} |