commit
38bbe976e0
@ -0,0 +1,201 @@
|
||||
#include <stdint.h>
|
||||
#include "keyboard.h"
|
||||
#include "action.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include "layer_switch.h"
|
||||
|
||||
|
||||
/*
|
||||
* Default Layer (0-15)
|
||||
*/
|
||||
uint8_t default_layer = 0;
|
||||
|
||||
void default_layer_set(uint8_t layer)
|
||||
{
|
||||
debug("default_layer_set: ");
|
||||
debug_dec(default_layer); debug(" to ");
|
||||
|
||||
default_layer = layer;
|
||||
|
||||
debug_dec(default_layer); debug("\n");
|
||||
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Keymap Layer (0-15)
|
||||
*/
|
||||
uint16_t keymap_stat = 0;
|
||||
|
||||
/* return highest layer whose state is on */
|
||||
uint8_t keymap_get_layer(void)
|
||||
{
|
||||
return biton16(keymap_stat);
|
||||
}
|
||||
|
||||
static void keymap_stat_set(uint16_t stat)
|
||||
{
|
||||
debug("keymap: ");
|
||||
keymap_debug(); debug(" to ");
|
||||
|
||||
keymap_stat = stat;
|
||||
|
||||
keymap_debug(); debug("\n");
|
||||
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
}
|
||||
|
||||
void keymap_clear(void)
|
||||
{
|
||||
keymap_stat_set(0);
|
||||
}
|
||||
|
||||
|
||||
void keymap_set(uint16_t stat)
|
||||
{
|
||||
keymap_stat_set(stat);
|
||||
}
|
||||
|
||||
void keymap_move(uint8_t layer)
|
||||
{
|
||||
keymap_stat_set(1<<layer);
|
||||
}
|
||||
|
||||
void keymap_on(uint8_t layer)
|
||||
{
|
||||
keymap_stat_set(keymap_stat | (1<<layer));
|
||||
}
|
||||
|
||||
void keymap_off(uint8_t layer)
|
||||
{
|
||||
keymap_stat_set(keymap_stat & ~(1<<layer));
|
||||
}
|
||||
|
||||
void keymap_invert(uint8_t layer)
|
||||
{
|
||||
keymap_stat_set(keymap_stat ^ (1<<layer));
|
||||
}
|
||||
|
||||
void keymap_or(uint16_t stat)
|
||||
{
|
||||
keymap_stat_set(keymap_stat | stat);
|
||||
}
|
||||
void keymap_and(uint16_t stat)
|
||||
{
|
||||
keymap_stat_set(keymap_stat & stat);
|
||||
}
|
||||
void keymap_xor(uint16_t stat)
|
||||
{
|
||||
keymap_stat_set(keymap_stat ^ stat);
|
||||
}
|
||||
|
||||
void keymap_debug(void)
|
||||
{
|
||||
debug_hex16(keymap_stat); debug("("); debug_dec(keymap_get_layer()); debug(")");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Overlay Layer (16-31 = 0-15|0x10)
|
||||
*/
|
||||
uint16_t overlay_stat = 0;
|
||||
|
||||
/* return highest layer whose state is on */
|
||||
uint8_t overlay_get_layer(void)
|
||||
{
|
||||
return biton16(overlay_stat);
|
||||
}
|
||||
|
||||
static void overlay_stat_set(uint16_t stat)
|
||||
{
|
||||
debug("overlay: ");
|
||||
overlay_debug(); debug(" to ");
|
||||
|
||||
overlay_stat = stat;
|
||||
|
||||
overlay_debug(); debug("\n");
|
||||
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
}
|
||||
|
||||
void overlay_clear(void)
|
||||
{
|
||||
overlay_stat_set(0);
|
||||
}
|
||||
|
||||
|
||||
void overlay_set(uint16_t stat)
|
||||
{
|
||||
overlay_stat_set(stat);
|
||||
}
|
||||
|
||||
void overlay_move(uint8_t layer)
|
||||
{
|
||||
overlay_stat_set(1<<layer);
|
||||
}
|
||||
|
||||
void overlay_on(uint8_t layer)
|
||||
{
|
||||
overlay_stat_set(overlay_stat | (1<<layer));
|
||||
}
|
||||
|
||||
void overlay_off(uint8_t layer)
|
||||
{
|
||||
overlay_stat_set(overlay_stat & ~(1<<layer));
|
||||
}
|
||||
|
||||
void overlay_invert(uint8_t layer)
|
||||
{
|
||||
overlay_stat_set(overlay_stat ^ (1<<layer));
|
||||
}
|
||||
|
||||
void overlay_or(uint16_t stat)
|
||||
{
|
||||
overlay_stat_set(overlay_stat | stat);
|
||||
}
|
||||
void overlay_and(uint16_t stat)
|
||||
{
|
||||
overlay_stat_set(overlay_stat & stat);
|
||||
}
|
||||
void overlay_xor(uint16_t stat)
|
||||
{
|
||||
overlay_stat_set(overlay_stat ^ stat);
|
||||
}
|
||||
|
||||
void overlay_debug(void)
|
||||
{
|
||||
debug_hex16(overlay_stat); debug("("); debug_dec(overlay_get_layer()); debug(")");
|
||||
}
|
||||
|
||||
action_t layer_switch_get_action(key_t key)
|
||||
{
|
||||
action_t action;
|
||||
action.code = ACTION_TRANSPARENT;
|
||||
|
||||
/* overlay: top layer first */
|
||||
for (int8_t i = 15; i >= 0; i--) {
|
||||
if (overlay_stat & (1<<i)) {
|
||||
action = action_for_key(i | OVERLAY_BIT, key);
|
||||
if (action.code != ACTION_TRANSPARENT) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* keymap: top layer first */
|
||||
for (int8_t i = 15; i >= 0; i--) {
|
||||
if (keymap_stat & (1<<i)) {
|
||||
action = action_for_key(i, key);
|
||||
if (action.code != ACTION_TRANSPARENT) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* default layer */
|
||||
action = action_for_key(default_layer, key);
|
||||
return action;
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright 2013 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LAYER_SWITCH_H
|
||||
#define LAYER_SWITCH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "keyboard.h"
|
||||
#include "action.h"
|
||||
|
||||
|
||||
/* overlays are asigned at layer 16-31 */
|
||||
#define OVERLAY_BIT 0x10
|
||||
#define OVERLAY_MASK 0x0F
|
||||
|
||||
|
||||
/*
|
||||
* Default Layer
|
||||
*/
|
||||
/* base layer to fall back */
|
||||
extern uint8_t default_layer;
|
||||
void default_layer_set(uint8_t layer);
|
||||
|
||||
|
||||
/*
|
||||
* Keymap Layer
|
||||
*/
|
||||
extern uint16_t keymap_stat;
|
||||
/* return current active layer */
|
||||
uint8_t keymap_get_layer(void);
|
||||
void keymap_clear(void);
|
||||
void keymap_set(uint16_t stat);
|
||||
void keymap_move(uint8_t layer);
|
||||
void keymap_on(uint8_t layer);
|
||||
void keymap_off(uint8_t layer);
|
||||
void keymap_invert(uint8_t layer);
|
||||
/* bitwise operation */
|
||||
void keymap_or(uint16_t stat);
|
||||
void keymap_and(uint16_t stat);
|
||||
void keymap_xor(uint16_t stat);
|
||||
void keymap_debug(void);
|
||||
|
||||
|
||||
/*
|
||||
* Overlay Layer
|
||||
*/
|
||||
extern uint16_t overlay_stat;
|
||||
/* return current active layer */
|
||||
uint8_t overlay_get_layer(void);
|
||||
void overlay_clear(void);
|
||||
void overlay_set(uint16_t stat);
|
||||
void overlay_move(uint8_t layer);
|
||||
void overlay_on(uint8_t layer);
|
||||
void overlay_off(uint8_t layer);
|
||||
void overlay_invert(uint8_t layer);
|
||||
/* bitwise operation */
|
||||
void overlay_or(uint16_t stat);
|
||||
void overlay_and(uint16_t stat);
|
||||
void overlay_xor(uint16_t stat);
|
||||
void overlay_debug(void);
|
||||
|
||||
|
||||
|
||||
/* return action depending on current layer status */
|
||||
action_t layer_switch_get_action(key_t key);
|
||||
|
||||
#endif
|
@ -0,0 +1,91 @@
|
||||
# Target file name (without extension).
|
||||
TARGET = m0110_lufa
|
||||
|
||||
# Directory common source filess exist
|
||||
TOP_DIR = ../..
|
||||
|
||||
# Directory keyboard dependent files exist
|
||||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
SRC = keymap.c \
|
||||
matrix.c \
|
||||
led.c \
|
||||
m0110.c
|
||||
|
||||
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
|
||||
|
||||
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
# Build Options
|
||||
# *Comment out* to disable the options.
|
||||
#
|
||||
MOUSEKEY_ENABLE = yes # Mouse keys
|
||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
|
||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
||||
CONSOLE_ENABLE = yes # Console for debug
|
||||
#NKRO_ENABLE = yes # USB Nkey Rollover
|
||||
|
||||
|
||||
# Boot Section Size in bytes
|
||||
# Teensy halfKay 512
|
||||
# Atmel DFU loader 4096
|
||||
# LUFA bootloader 4096
|
||||
OPT_DEFS += -DBOOT_SIZE=4096
|
||||
|
||||
|
||||
|
||||
#---------------- 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/lufa.mk
|
||||
include $(TOP_DIR)/protocol.mk
|
||||
include $(TOP_DIR)/common.mk
|
||||
include $(TOP_DIR)/rules.mk
|
||||
|
||||
hasu: EXTRAFLAGS += -DHASU
|
||||
hasu: all
|
@ -0,0 +1,83 @@
|
||||
# Target file name (without extension).
|
||||
TARGET = pc98_usb
|
||||
|
||||
# Directory common source filess exist
|
||||
TOP_DIR = ../..
|
||||
|
||||
# Directory keyboard dependent files exist
|
||||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
SRC = keymap.c \
|
||||
matrix.c \
|
||||
led.c \
|
||||
protocol/serial_uart.c
|
||||
# protocol/serial_soft.c
|
||||
|
||||
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
|
||||
|
||||
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
# Build Options
|
||||
# *Comment out* to disable the options.
|
||||
#
|
||||
MOUSEKEY_ENABLE = yes # Mouse keys
|
||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
||||
CONSOLE_ENABLE = yes # Console for debug
|
||||
#NKRO_ENABLE = yes # USB Nkey Rollover
|
||||
|
||||
|
||||
# Boot Section Size in bytes
|
||||
# Teensy halfKay 512
|
||||
# Atmel DFU loader 4096
|
||||
# LUFA bootloader 4096
|
||||
OPT_DEFS += -DBOOT_SIZE=4096
|
||||
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TARGET_DIR)
|
||||
VPATH += $(TOP_DIR)
|
||||
|
||||
|
||||
include $(TOP_DIR)/protocol/lufa.mk
|
||||
include $(TOP_DIR)/protocol.mk
|
||||
include $(TOP_DIR)/common.mk
|
||||
include $(TOP_DIR)/rules.mk
|
@ -0,0 +1,70 @@
|
||||
PC98 to USB keyboard protocol converter
|
||||
=======================================
|
||||
Target MCU is ATMega32u4 but other USB capable AVR will also work.
|
||||
|
||||
|
||||
Connector
|
||||
---------
|
||||
|
||||
8Pin mini DIN
|
||||
___ ___
|
||||
/ |_| \
|
||||
/ 8 7 6 \
|
||||
| 5 4 3 |
|
||||
\_ 2 1 _/
|
||||
\_____/
|
||||
(receptacle)
|
||||
|
||||
|
||||
Wiring: You can change this with ediging config.h.
|
||||
|
||||
Pin mini DIN MCU
|
||||
----------------------------------
|
||||
1 ~RST PD1
|
||||
2 GND GND
|
||||
3 ~RDY PD4
|
||||
4 RXD PD2
|
||||
5 ~RTY PD5
|
||||
6 NC
|
||||
7 NC
|
||||
8 5V VCC
|
||||
|
||||
|
||||
|
||||
|
||||
Protocol
|
||||
--------
|
||||
Singnal: Asynchronous, Positive logic, 19200baud, Least bit first
|
||||
Frame format: 1-Start bit(Lo), 8-Data bits, Odd-Parity, 1-Stop bit
|
||||
|
||||
This converter uses software method for testing purpose. AVR UART engine will work better.
|
||||
|
||||
|
||||
|
||||
|
||||
Build Firmware
|
||||
--------------
|
||||
Just use 'make'
|
||||
|
||||
$ cd pc98_usb
|
||||
$ make
|
||||
|
||||
Then, load the binary to MCU with your favorite programmer.
|
||||
|
||||
|
||||
|
||||
Other PC98 converter projects and resource
|
||||
------------------------------------------
|
||||
PC98 to USB
|
||||
http://davy.nyacom.net/kbd98usb/
|
||||
|
||||
PC98 to PS/2
|
||||
http://www.tsp.ne.jp/~sawada/mago/c_gka98at.htm
|
||||
http://www.tsp.ne.jp/~sawada/mago/src/gka98at.asm
|
||||
|
||||
PC98 keyboard commands
|
||||
http://www.webtech.co.jp/company/doc/undocumented_mem/io_kb.txt
|
||||
|
||||
|
||||
Inhibit repeating key:
|
||||
0x9C, 0x70
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x9898
|
||||
#define DEVICE_VER 0x0100
|
||||
#define MANUFACTURER t.m.k.
|
||||
#define PRODUCT PC98 keyboard converter
|
||||
#define DESCRIPTION converts PC98 keyboard protocol into USB
|
||||
|
||||
|
||||
/* matrix size */
|
||||
#define MATRIX_ROWS 16
|
||||
#define MATRIX_COLS 8
|
||||
|
||||
/* To use new keymap framework */
|
||||
#define USE_KEYMAP_V2
|
||||
|
||||
/* key combination for command */
|
||||
#define IS_COMMAND() ( \
|
||||
host_get_first_key() == KC_CANCEL \
|
||||
)
|
||||
|
||||
|
||||
/* PC98 Reset Port shared with TXD */
|
||||
#define PC98_RST_DDR DDRD
|
||||
#define PC98_RST_PORT PORTD
|
||||
#define PC98_RST_BIT 3
|
||||
/* PC98 Ready Port */
|
||||
#define PC98_RDY_DDR DDRD
|
||||
#define PC98_RDY_PORT PORTD
|
||||
#define PC98_RDY_BIT 4
|
||||
/* PC98 Retry Port */
|
||||
#define PC98_RTY_DDR DDRD
|
||||
#define PC98_RTY_PORT PORTD
|
||||
#define PC98_RTY_BIT 5
|
||||
|
||||
/*
|
||||
* PC98 Serial(USART) configuration
|
||||
* asynchronous, positive logic, 19200baud, bit order: LSB first
|
||||
* 1-start bit, 8-data bit, odd parity, 1-stop bit
|
||||
*/
|
||||
/*
|
||||
* Software Serial
|
||||
*/
|
||||
#define SERIAL_SOFT_BAUD 19200
|
||||
#define SERIAL_SOFT_PARITY_ODD
|
||||
#define SERIAL_SOFT_BIT_ORDER_LSB
|
||||
#define SERIAL_SOFT_LOGIC_POSITIVE
|
||||
/* RXD Port */
|
||||
#define SERIAL_SOFT_RXD_DDR DDRD
|
||||
#define SERIAL_SOFT_RXD_PORT PORTD
|
||||
#define SERIAL_SOFT_RXD_PIN PIND
|
||||
#define SERIAL_SOFT_RXD_BIT 2
|
||||
#define SERIAL_SOFT_RXD_READ() (SERIAL_SOFT_RXD_PIN&(1<<SERIAL_SOFT_RXD_BIT))
|
||||
/* RXD Interupt */
|
||||
#define SERIAL_SOFT_RXD_VECT INT2_vect
|
||||
#define SERIAL_SOFT_RXD_INIT() do { \
|
||||
/* pin configuration: input with pull-up */ \
|
||||
SERIAL_SOFT_RXD_DDR &= ~(1<<SERIAL_SOFT_RXD_BIT); \
|
||||
SERIAL_SOFT_RXD_PORT |= (1<<SERIAL_SOFT_RXD_BIT); \
|
||||
/* enable interrupt: INT2(falling edge) */ \
|
||||
EICRA |= ((1<<ISC21)|(0<<ISC20)); \
|
||||
EIMSK |= (1<<INT2); \
|
||||
sei(); \
|
||||
} while (0)
|
||||
#define SERIAL_SOFT_RXD_INT_ENTER()
|
||||
#define SERIAL_SOFT_RXD_INT_EXIT() do { \
|
||||
/* clear interrupt flag */ \
|
||||
EIFR = (1<<INTF2); \
|
||||
} while (0)
|
||||
/* TXD Port */
|
||||
#define SERIAL_SOFT_TXD_DDR DDRD
|
||||
#define SERIAL_SOFT_TXD_PORT PORTD
|
||||
#define SERIAL_SOFT_TXD_PIN PIND
|
||||
#define SERIAL_SOFT_TXD_BIT 3
|
||||
#define SERIAL_SOFT_TXD_HI() do { SERIAL_SOFT_TXD_PORT |= (1<<SERIAL_SOFT_TXD_BIT); } while (0)
|
||||
#define SERIAL_SOFT_TXD_LO() do { SERIAL_SOFT_TXD_PORT &= ~(1<<SERIAL_SOFT_TXD_BIT); } while (0)
|
||||
#define SERIAL_SOFT_TXD_INIT() do { \
|
||||
/* pin configuration: output */ \
|
||||
SERIAL_SOFT_TXD_DDR |= (1<<SERIAL_SOFT_TXD_BIT); \
|
||||
/* idle */ \
|
||||
SERIAL_SOFT_TXD_ON(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Hardware Serial(UART)
|
||||
*/
|
||||
#ifdef __AVR_ATmega32U4__
|
||||
#define SERIAL_UART_BAUD 19200
|
||||
#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<<RXCIE1) | (1<<RXEN1); /* RX interrupt, RX: enable */ \
|
||||
UCSR1B |= (0<<TXCIE1) | (1<<TXEN1); /* TX interrupt, TX: enable */ \
|
||||
UCSR1C |= (1<<UPM11) | (1<<UPM10); /* parity: none(00), even(01), odd(11) */ \
|
||||
sei(); \
|
||||
} while(0)
|
||||
#else
|
||||
#error "USART configuration is needed."
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "keycode.h"
|
||||
#include "action.h"
|
||||
#include "action_macro.h"
|
||||
#include "layer_switch.h"
|
||||
#include "util.h"
|
||||
#include "keymap.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* PC-9801-98-S02 Raku Raku keyboard(Luckyboard) Normal Mode
|
||||
,---------------------------------------------------------------.
|
||||
| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 6A| 6B| 36| 37| 3F| 3E|
|
||||
`---------------------------------------------------------------'
|
||||
,---------------------------------------------------------------.
|
||||
| 00| 01| 02| 03| 04| 05| 58| 71| 06| 07| 08| 09| 0A| 0E|
|
||||
|---------------------------------------------------------------|
|
||||
| 0F| 10| 11| 12| 13| 14| 3A | 15| 16| 17| 18| 19| 1C|
|
||||
|---------------------------------------------------------'. |
|
||||
| 74| 20| 21| 22| 23| 24| 3B | 3C | 25| 26| 27| 28| 29| |
|
||||
|---------------------------------------------------------------|
|
||||
| 70| 2A| 2B| 2C| 2D| 2E| 38| 3D | 39| 2F| 30| 31| 32| 33| 70|
|
||||
`---------------------------------------------------------------'
|
||||
| 73| 51| 5B| 59| 34| 5A| 35| xx|
|
||||
`-----------------------------------------------'
|
||||
xx: 74 35 F4 B5
|
||||
*/
|
||||
#define KEYMAP( \
|
||||
K60, K61, K62, K63, K64, K65, K66, K67, K68, K69, K6A, K6B, K36, K37, K3F, K3E, \
|
||||
K00, K01, K02, K03, K04, K05, K58, K71, K06, K07, K08, K09, K0A, K0E, \
|
||||
K0F, K10, K11, K12, K13, K14, K3A, K15, K16, K17, K18, K19, K1C, \
|
||||
K74, K20, K21, K22, K23, K24, K3B, K3C, K25, K26, K27, K28, K29, \
|
||||
K70,K2A, K2B, K2C, K2D, K2E, K38, K3D, K39, K2F, K30, K31, K32, K33, \
|
||||
K73, K51, K5B, K59, K34, K5A, K35 \
|
||||
) { \
|
||||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
|
||||
{ KC_##K08, KC_##K09, KC_##K0A, KC_NO, KC_NO, KC_NO, 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_NO, KC_NO, KC_##K1C, KC_NO, KC_NO, KC_NO }, \
|
||||
{ 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_NO, 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_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_##K51, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ 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_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_##K70, KC_##K71, KC_NO, KC_##K73, KC_##K74, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO } \
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/*
|
||||
,---------------------------------------------------------------.
|
||||
| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 6A| 6B| 36| 37| 3F| 3E|
|
||||
`---------------------------------------------------------------'
|
||||
,---------------------------------------------------------------.
|
||||
| 00| 01| 02| 03| 04| 05| 58| 71| 06| 07| 08| 09| 0A| 0E|
|
||||
|---------------------------------------------------------------|
|
||||
| 0F| 10| 11| 12| 13| 14| 3A | 15| 16| 17| 18| 19| 1C|
|
||||
|---------------------------------------------------------------|
|
||||
| 74| 20| 21| 22| 23| 24| MINS| EQL| 25| 26| 27| 28| 29| |
|
||||
|---------------------------------------------------------------|
|
||||
| 70| 2A| 2B| 2C| 2D| 2E| 38| 3D | 39| 2F| 30| 31| 32| 33| 70|
|
||||
`---------------------------------------------------------------'
|
||||
| 73| 51| 5B| 59| 34| 5A| 35| xx|
|
||||
`-----------------------------------------------'
|
||||
*/
|
||||
KEYMAP(
|
||||
CANCEL,COPY, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, FN6,
|
||||
ESC, 1, 2, 3, 4, 5, FN4, FN5, 6, 7, 8, 9, 0, BSPC,
|
||||
TAB, Q, W, E, R, T, UP, Y, U, I, O, P, ENT,
|
||||
LCTL, A, S, D, F, G, MINS, EQL, H, J, K, L, FN2,
|
||||
LSFT, Z, X, C, V, B, GRV, BSLS, QUOT, N, M,COMM, DOT, FN1,
|
||||
LGUI, LALT, LCTL, LSFT, SPC, SPC, RALT
|
||||
),
|
||||
KEYMAP(
|
||||
PAUS,COPY, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14,
|
||||
GRV, F1, F2, F3, F4, F5, NO, NO, F6, F7, F8, F9, F10, DEL,
|
||||
TAB, Q, W, E, R, T, UP, HOME,PGDN,PGUP, END, P, ENT,
|
||||
LCTL, A, S, D, F, G, MINS, EQL, LEFT,DOWN, UP,RGHT,SCLN,
|
||||
LSFT, Z, X, C, V, B, INS, DOWN, DEL,HOME,PGDN,PGUP, END,TRNS,
|
||||
LGUI, LALT, LCTL, LSFT, SPC, SPC, RALT
|
||||
),
|
||||
KEYMAP(
|
||||
PAUS,COPY, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14,
|
||||
GRV, F1, F2, F3, F4, F5, NO, NO, F6, F7, F8, F9, F10, DEL,
|
||||
TAB, Q, W, E, R, T, UP, WH_L,WH_D,WH_U,WH_R, P, ENT,
|
||||
LCTL, A, S, D, F, G, MINS, EQL, MS_L,MS_D,MS_U,MS_R,TRNS,
|
||||
LSFT, Z, X, C, V, B, INS, DOWN, BTN3,BTN2,BTN1,BTN4,BTN5,TRNS,
|
||||
LGUI, LALT, LCTL, LSFT, SPC, SPC, RALT
|
||||
),
|
||||
};
|
||||
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {};
|
||||
|
||||
/*
|
||||
* Macro definition
|
||||
*/
|
||||
enum macro_id {
|
||||
LBRACKET,
|
||||
RBRACKET,
|
||||
DUMMY,
|
||||
};
|
||||
|
||||
const prog_macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
keyevent_t event = record->event;
|
||||
//uint8_t tap_count = record->tap_count;
|
||||
|
||||
switch (id) {
|
||||
case LBRACKET:
|
||||
return (event.pressed ?
|
||||
MACRO( T(LBRC), END ) :
|
||||
MACRO( T(LBRC), END ) );
|
||||
case RBRACKET:
|
||||
return (event.pressed ?
|
||||
MACRO( T(RBRC), END ) :
|
||||
MACRO( T(RBRC), END ) );
|
||||
}
|
||||
return MACRO_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Action function
|
||||
*/
|
||||
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
/*
|
||||
keyevent_t event = record->event;
|
||||
uint8_t tap_count = record->tap_count;
|
||||
switch (id) {
|
||||
case 0xFF:
|
||||
action_macro_play(get_macro(opt, event.pressed));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fn actions
|
||||
*/
|
||||
static const uint16_t PROGMEM fn_actions[] = {
|
||||
ACTION_KEYMAP_TAP_TOGGLE(0), // FN0
|
||||
ACTION_KEYMAP_TAP_KEY(1, KC_SLASH), // FN1
|
||||
ACTION_KEYMAP_TAP_KEY(2, KC_SCLN), // FN2
|
||||
ACTION_KEYMAP_MOMENTARY(2), // FN3
|
||||
ACTION_MACRO(LBRACKET), // FN4
|
||||
ACTION_MACRO(RBRACKET), // FN5
|
||||
ACTION_MACRO(DUMMY), // FN6
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* No need to edit.
|
||||
*/
|
||||
#define KEYMAPS_SIZE (sizeof(keymaps) / sizeof(keymaps[0]))
|
||||
#define OVERLAYS_SIZE (sizeof(overlays) / sizeof(overlays[0]))
|
||||
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0]))
|
||||
|
||||
/* translates key to keycode */
|
||||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
|
||||
{
|
||||
/* Overlay: 16-31(OVERLAY_BIT(0x10) | overlay_layer) */
|
||||
if (layer & OVERLAY_BIT) {
|
||||
layer &= OVERLAY_MASK;
|
||||
if (layer < OVERLAYS_SIZE) {
|
||||
return pgm_read_byte(&overlays[(layer)][(key.row)][(key.col)]);
|
||||
} else {
|
||||
return KC_TRANSPARENT;
|
||||
}
|
||||
}
|
||||
/* Keymap: 0-15 */
|
||||
else {
|
||||
if (layer < KEYMAPS_SIZE) {
|
||||
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
|
||||
} else {
|
||||
// fall back to layer 0
|
||||
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* translates Fn keycode to action */
|
||||
action_t keymap_fn_to_action(uint8_t keycode)
|
||||
{
|
||||
action_t action;
|
||||
if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
|
||||
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
|
||||
} else {
|
||||
action.code = ACTION_NO;
|
||||
}
|
||||
return action;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
#include "serial.h"
|
||||
#include "led.h"
|
||||
|
||||
|
||||
void led_set(uint8_t usb_led)
|
||||
{
|
||||
uint8_t sun_led = 0;
|
||||
if (usb_led & (1<<USB_LED_NUM_LOCK)) sun_led |= (1<<0);
|
||||
if (usb_led & (1<<USB_LED_COMPOSE)) sun_led |= (1<<1);
|
||||
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) sun_led |= (1<<2);
|
||||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) sun_led |= (1<<3);
|
||||
|
||||
serial_send(0x0E);
|
||||
serial_send(sun_led);
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include "print.h"
|
||||
#include "util.h"
|
||||
#include "matrix.h"
|
||||
#include "debug.h"
|
||||
#include "protocol/serial.h"
|
||||
|
||||
|
||||
/*
|
||||
* Matrix Array usage:
|
||||
*
|
||||
* ROW: 16(4bits)
|
||||
* COL: 8(3bits)
|
||||
*
|
||||
* 8bit wide
|
||||
* +---------+
|
||||
* 0|00 ... 07|
|
||||
* 1|08 ... 0F|
|
||||
* :| ... |
|
||||
* :| ... |
|
||||
* E|70 ... 77|
|
||||
* F|78 ... 7F|
|
||||
* +---------+
|
||||
*/
|
||||
static uint8_t matrix[MATRIX_ROWS];
|
||||
#define ROW(code) ((code>>3)&0xF)
|
||||
#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;
|
||||
}
|
||||
|
||||
static void pc98_inhibit_repeat(void)
|
||||
{
|
||||
uint8_t code;
|
||||
|
||||
while (serial_recv()) ;
|
||||
RETRY:
|
||||
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
|
||||
_delay_ms(500);
|
||||
serial_send(0x9C);
|
||||
|
||||
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
|
||||
_delay_ms(100);
|
||||
while (!(code = serial_recv())) ;
|
||||
print("PC98: send 9C: "); print_hex8(code); print("\n");
|
||||
if (code != 0xFA) goto RETRY;
|
||||
|
||||
|
||||
|
||||
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
|
||||
_delay_ms(100);
|
||||
serial_send(0x70);
|
||||
|
||||
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
|
||||
_delay_ms(100);
|
||||
//code = serial_recv();
|
||||
while (!(code = serial_recv())) ;
|
||||
print("PC98: send 70: "); print_hex8(code); print("\n");
|
||||
if (code != 0xFA) goto RETRY;
|
||||
}
|
||||
|
||||
void matrix_init(void)
|
||||
{
|
||||
print_enable = true;
|
||||
// debug_enable = true;
|
||||
// debug_matrix = true;
|
||||
|
||||
PC98_RST_DDR |= (1<<PC98_RST_BIT);
|
||||
PC98_RDY_DDR |= (1<<PC98_RDY_BIT);
|
||||
PC98_RTY_DDR |= (1<<PC98_RTY_BIT);
|
||||
PC98_RST_PORT |= (1<<PC98_RST_BIT);
|
||||
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
|
||||
PC98_RTY_PORT |= (1<<PC98_RTY_BIT);
|
||||
|
||||
|
||||
serial_init();
|
||||
|
||||
// PC98 reset
|
||||
/*
|
||||
PC98_RST_PORT &= ~(1<<PC98_RST_BIT);
|
||||
_delay_us(15);
|
||||
PC98_RST_PORT |= (1<<PC98_RST_BIT);
|
||||
_delay_us(13);
|
||||
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
|
||||
*/
|
||||
|
||||
_delay_ms(500);
|
||||
pc98_inhibit_repeat();
|
||||
|
||||
|
||||
// PC98 ready
|
||||
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
|
||||
|
||||
debug("init\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t matrix_scan(void)
|
||||
{
|
||||
is_modified = false;
|
||||
|
||||
uint16_t code;
|
||||
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
|
||||
_delay_us(30);
|
||||
code = serial_recv2();
|
||||
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
|
||||
if (code == -1) return 0;
|
||||
|
||||
if (code == 0x60) {
|
||||
pc98_inhibit_repeat();
|
||||
|
||||
/*
|
||||
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
|
||||
_delay_ms(100);
|
||||
serial_send(0x96);
|
||||
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
print_hex8(code); print(" ");
|
||||
|
||||
if (code&0x80) {
|
||||
// break code
|
||||
if (matrix_is_on(ROW(code), COL(code))) {
|
||||
matrix[ROW(code)] &= ~(1<<COL(code));
|
||||
is_modified = true;
|
||||
}
|
||||
} else {
|
||||
// make code
|
||||
if (!matrix_is_on(ROW(code), COL(code))) {
|
||||
matrix[ROW(code)] |= (1<<COL(code));
|
||||
is_modified = true;
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
bool matrix_is_modified(void)
|
||||
{
|
||||
return is_modified;
|
||||
}
|
||||
|
||||
inline
|
||||
bool matrix_has_ghost(void)
|
||||
{
|
||||
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));
|
||||
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;
|
||||
}
|
@ -0,0 +1,514 @@
|
||||
Keymap framework - how to define your keymap
|
||||
============================================
|
||||
***NOTE: This is not final version, may be inconsistent with source code and changed occasionally for a while.***
|
||||
|
||||
## 0. Keymap and layers
|
||||
**Keymap** is comprised of multiple layers of key layout, you can define **16** layers at most.
|
||||
**Layer** is an array of **keycodes** to define **actions** on each physical keys.
|
||||
respective layers can be validated simultaneously. Layers are indexed with 0 to 15 and higher layer has precedence.
|
||||
|
||||
Keymap with 16 Layers Layer: array of Keycodes
|
||||
--------------------- ------------------------
|
||||
stack of layers content of layer
|
||||
____________ precedence _______________________
|
||||
/ / | high / ESC / F1 / F2 / F3 ....
|
||||
15 /___________// | /-----/-----/-----/-----
|
||||
14 /___________// | / TAB / / / ....
|
||||
13 /___________/_ | /-----/-----/-----/-----
|
||||
: / : : : : : / | /LCtrl/ / / ....
|
||||
3 /___________// | : / : : : :
|
||||
2 /___________// | 2 `--------------------------
|
||||
1 /___________// | 1 `--------------------------
|
||||
0 /___________/ V low 0 `--------------------------
|
||||
|
||||
|
||||
|
||||
### 0.1 Keymap status
|
||||
Keymap has its state in two parameters:
|
||||
**`default_layer`** indicates a base keymap layer(0-15) which is always valid and to be referred, **`keymap_stat`** is 16bit variable which has current on/off status of layers on its each bit.
|
||||
|
||||
Keymap layer '0' is usually `default_layer` and which is the only valid layer and other layers is initially off after boot up firmware, though, you can configured them in `config.h`.
|
||||
To change `default_layer` will be useful when you want to switch key layout completely, say you use Colmak instead of Qwerty.
|
||||
|
||||
Initial state of Keymap Change base layout
|
||||
----------------------- ------------------
|
||||
|
||||
15 15
|
||||
14 14
|
||||
13 13
|
||||
: :
|
||||
3 3 ____________
|
||||
2 ____________ 2 / /
|
||||
1 / / ,->1 /___________/
|
||||
,->0 /___________/ | 0
|
||||
| |
|
||||
`--- default_layer = 0 `--- default_layer = 1
|
||||
keymap_stat = 0x0001 keymap_stat = 0x0002
|
||||
|
||||
On the other hand, you shall change `keymap_state` to overlay base layer with some layers for feature such as navigation keys, function key(F1-F12), media keys or special actions.
|
||||
|
||||
Overlay feature layer
|
||||
--------------------- bit|status
|
||||
____________ ---+------
|
||||
15 / / 15 | 0
|
||||
14 /___________// -----> 14 | 1
|
||||
13 /___________/ -----> 13 | 1
|
||||
: : |
|
||||
3 ____________ 3 | 0
|
||||
2 / / 2 | 0
|
||||
,->1 /___________/ -----> 1 | 1
|
||||
| 0 0 | 0
|
||||
| |
|
||||
`--- default_layer = 1 |
|
||||
keymap_stat = 0x6002 <-----'
|
||||
|
||||
|
||||
|
||||
### 0.2 Layer Precedence and Transparency
|
||||
Note that ***higher layer has higher priority on stack of layers***, namely firmware falls down from top layer to bottom to look up keycode. Once it spots keycode other than **`KC_TRNS`**(transparent) on a layer it stops searching and lower layers aren't referred.
|
||||
|
||||
You can place `KC_TRNS` on overlay layer changes just part of layout to fall back on lower or base layer.
|
||||
Key with `KC_TRANS` doen't has its own keycode and refers to lower valid layers for keycode, instead.
|
||||
See example below.
|
||||
|
||||
|
||||
### 0.3 Keymap Example
|
||||
Keymap is **`keymaps[]`** C array in fact and you can define layers in it with **`KEYMAP()`** C macro and keycodes. To use complex actions you need to define `Fn` keycode in **`fn_actions[]`** array.
|
||||
|
||||
This is a keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard.
|
||||
This example has three layers, 'Qwerty' as base layer, 'Cursor' and 'Mousekey'.
|
||||
In this example,
|
||||
|
||||
`Fn0` is a **momentary layer switching** key, you can use keys on Cursor layer while holding the key.
|
||||
|
||||
`Fn1` is a momentary layer switching key with tapping feature, you can get semicolon **';'** with taping the key and switch layers while holding the key. The word **'tap'** or **'tapping'** mean to press and release a key quickly.
|
||||
|
||||
`Fn2` is a **toggle layer switch** key, you can stay switched layer after releasing the key unlike momentary switching.
|
||||
|
||||
You can find other keymap definitions in file `keymap.c` located on project directories.
|
||||
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* 0: Qwerty
|
||||
* ,-----------------------------------------------------------.
|
||||
* |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|Fn1| '|Enter |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
|
||||
* `-----------------------------------------------------------'
|
||||
* |Gui|Alt |Space |Alt |Fn2|
|
||||
* `-------------------------------------------'
|
||||
*/
|
||||
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, FN1, QUOT,ENT, \
|
||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN0, \
|
||||
LGUI,LALT, SPC, RALT,FN2),
|
||||
/* 1: Cursor(HHKB mode)
|
||||
* ,-----------------------------------------------------------.
|
||||
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Shift | | | | | | +| -|End|PgD|Dow|Shift | |
|
||||
* `-----------------------------------------------------------'
|
||||
* |Gui |Alt |Space |Alt |Gui|
|
||||
* `--------------------------------------------'
|
||||
*/
|
||||
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, \
|
||||
LCTL,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
|
||||
LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
|
||||
LGUI,LALT, SPC, RALT,RGUI),
|
||||
/* 2: Mousekey
|
||||
* ,-----------------------------------------------------------.
|
||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Contro| | | | | |McL|McD|McU|McR| | |Return |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
|
||||
* `-----------------------------------------------------------'
|
||||
* |Gui |Alt |Mb1 |Alt | |
|
||||
* `--------------------------------------------'
|
||||
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
|
||||
*/
|
||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
|
||||
TAB, TRNS,TRNS,TRNS,TRNS,TRNS,WH_L,WH_D,WH_U,WH_R,TRNS,TRNS,TRNS,BSPC, \
|
||||
LCTL,TRNS,ACL0,ACL1,ACL2,TRNS,MS_L,MS_D,MS_U,MS_R,TRNS,QUOT,ENT, \
|
||||
LSFT,TRNS,TRNS,TRNS,TRNS,BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,TRNS, \
|
||||
LGUI,LALT, BTN1, RALT,TRNS),
|
||||
};
|
||||
|
||||
static const uint16_t PROGMEM fn_actions[] = {
|
||||
ACTION_KEYMAP_MOMENTARY(1), // FN0
|
||||
ACTION_KEYMAP_TAP_KEY(2, KC_SCLN), // FN1
|
||||
ACTION_KEYMAP_TOGGLE(2), // FN2
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
## 1. Keycode
|
||||
See [`common/keycode.h`](../common/keycode.h) or keycode table below for the detail. Keycode is internal **8bit code** to inidicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action registers key to host on press and unregister on release, while some of other keycodes has some special actions like `Fn` keys, Media contorl keys, System control keys and Mousekeys.
|
||||
|
||||
***In `KEYMAP()` macro you should omit prefix part `KC_` of keycode to keep keymap compact.*** For example, just use `A` instead you place `KC_A` in `KEYMAP()`. Some keycodes has 4-letter **short name** in addition to descriptive name, you'll prefer short one in `KEYMAP()`.
|
||||
|
||||
### 1.0 Other key
|
||||
- `KC_NO` for no aciton
|
||||
- `KC_TRNS` for layer transparency (See above)
|
||||
|
||||
### 1.1 Normal key
|
||||
- `KC_A` to `KC_Z`, `KC_1` to `KC_0` for alpha numeric key
|
||||
- `KC_MINS`, `KC_EQL`, `KC_GRV`, `KC_RBRC`, `KC_LBRC`, `KC_COMM`, `KC_DOT`, `KC_BSLS`, `KC_SLSH`, `KC_SCLN`, `KC_QUOT`
|
||||
- `KC_ESC`, `KC_TAB`, `KC_SPC`, `KC_BSPC`, `KC_ENT`, `KC_DEL`, `KC_INS`
|
||||
- `KC_UP`, `KC_DOWN`, `KC_RGHT`, `KC_LEFT`, `KC_PGUP`, `KC_PGDN`, `KC_HOME`, `KC_END`
|
||||
- `KC_CAPS`, `KC_NLCK`, `KC_SLCK`, `KC_PSCR`, `KC_PAUS`, `KC_APP`, `KC_F1` to `KC_F24`
|
||||
- `KC_P1` to `KC_P0`, `KC_PDOT`, `KC_PCMM`, `KC_PSLS`, `KC_PAST`, `KC_PMNS`, `KC_PPLS`, `KC_PEQL`, `KC_PENT` for keypad.
|
||||
|
||||
### 1.2 Modifier
|
||||
There are 8 modifiers which has discrimination between left and right.
|
||||
|
||||
- `KC_LCTL` and `KC_RCTL` for Control
|
||||
- `KC_LSFT` and `KC_RSFT` for Shift
|
||||
- `KC_LALT` and `KC_RALT` for Alt
|
||||
- `KC_LGUI` and `KC_RGUI` for Windows key or Command key in Mac
|
||||
|
||||
### 1.3 Mousekey
|
||||
- `KC_MS_U`, `KC_MS_D`, `KC_MS_L`, `KC_MS_R` for mouse cursor
|
||||
- `KC_WH_U`, `KC_WH_D`, `KC_WH_L`, `KC_WH_R` for mouse wheel
|
||||
- `KC_BTN1`, `KC_BTN2`, `KC_BTN3`, `KC_BTN4`, `KC_BTN5` for mouse buttons
|
||||
|
||||
### 1.4 System & Media key
|
||||
- `KC_PWR`, `KC_SLEP`, `KC_WAKE` for Power, Sleep, Wake
|
||||
- `KC_MUTE`, `KC_VOLU`, `KC_VOLD` for audio volume control
|
||||
- `KC_MNXT`, `KC_MPRV`, `KC_MSTP`, `KC_MPLY`, `KC_MSEL` for media control
|
||||
- `KC_MAIL`, `KC_CALC`, `KC_MYCM` for application launch
|
||||
- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation
|
||||
|
||||
### 1.5 Fn key
|
||||
`KC_FNnn` are keycodes for `Fn` key which not given any actions at the beginning unlike most of keycodes has its own inborn action. To use these keycodes in `KEYMAP` you need to assign action you want at first. Action of `Fn` key is defined in `fn_actions[]` and its index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` keyocde indicates the action defined in first element of the array. ***32 `Fn` keys can be defined at most.***
|
||||
|
||||
### 1.6 Keycode Table
|
||||
See keycode table in [`doc/keycode.txt`](./keycode.txt) for description of keycodes.
|
||||
|
||||
In regard to implementation side most of keycodes are identical with [HID usage][HID_usage](pdf) sent to host for real and some virtual keycodes are defined to support special actions.
|
||||
[HID_usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf
|
||||
|
||||
|
||||
|
||||
## 2. Action
|
||||
See [`common/action.h`](../common/action.h). Action is a **16bit code** and defines function to perform on events of a key like press, release, holding and tapping.
|
||||
|
||||
Most of keys just register 8bit scancode to host, but to support other complex features needs 16bit extended action codes internally. However, using 16bit action codes in keymap results in double size in memory against using jsut keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP` instead of action codes.
|
||||
|
||||
***You can just use keycodes of `Normal key`, `Modifier`, `Mousekey` and `System & Media key` in keymap*** to indicate corresponding actions instead of using action codes. While ***to use other special actions you should use keycode of `Fn` key defined in `fn_actions[]`.***
|
||||
|
||||
Usually action codes are needed only when you want to use layer switching, or
|
||||
|
||||
### 2.1 Key action
|
||||
This is a simple action that registers scancodes(HID usage in fact) to host on press event of key and unregister on release.
|
||||
|
||||
#### 2.1.1 Normal key and Modifier
|
||||
This action usually won't be used expressly because you can use keycodes in `KEYMAP()` instead.
|
||||
You can define `Key` action on *'A'* key and *'left shift'* modifier with:
|
||||
|
||||
ACTION_KEY(KC_A)
|
||||
ACTION_KEY(KC_LSHIFT)
|
||||
|
||||
#### 2.1.2 Key with modifiers
|
||||
This action is comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes.
|
||||
Say you want to assign a key to `Shift + 1` to get charactor *'!'* or `Alt + Tab` to switch application windows.
|
||||
|
||||
ACTION_LMOD_KEY(KC_LSHIFT, KC_1)
|
||||
ACTION_LMOD_KEY(KC_LALT, KC_TAB)
|
||||
|
||||
Or `Alt,Shift + Tab` can be defined. `ACTION_LMODS_KEY()` requires **4-bit modifier state** and a **keycode** as arguments. See `keycode.h` for `MOD_BIT()` macro.
|
||||
|
||||
ACTION_LMODS_KEY((MOD_BIT(KC_LALT) | MOD_BIT(KC_LSHIFT)), KC_TAB)
|
||||
|
||||
|
||||
|
||||
### 2.2 Layer Action
|
||||
These actions operate layers of keymap.
|
||||
|
||||
Parameters:
|
||||
- layer: 0-15
|
||||
- on: { press | release | both }
|
||||
|
||||
|
||||
#### 2.2.0 Default Layer
|
||||
`default_layer` is layer which always is valid and referred to when actions is not defined on other layers.
|
||||
|
||||
##### Return to Default Layer
|
||||
Turns on only `default layer` with clearing other all layers.
|
||||
|
||||
ACTION_DEFAULT_LAYER
|
||||
|
||||
##### Set Default Layer
|
||||
Sets 'default layer' to layer and turn it on.
|
||||
|
||||
ACTION_DEFAULT_LAYER_SET_TO(layer)
|
||||
ACTION_DEFAULT_LAYER_SET(layer, on)
|
||||
|
||||
|
||||
#### 2.2.1 Keymap
|
||||
These actions operate layer status of keymap.
|
||||
|
||||
##### Momentary Switch
|
||||
Turns on layer momentary while holding, in other words turn on when key is pressed and off when released.
|
||||
|
||||
ACTION_KEYMAP_MOMENTARY(layer)
|
||||
|
||||
|
||||
##### Toggle Switch
|
||||
Turns on layer on first type and turns off on next.
|
||||
|
||||
ACTION_KEYMAP_TOGGLE(layer)
|
||||
|
||||
|
||||
##### Momentary Switch with tap key
|
||||
Turns on layer momentary while holding but registers key on tap.
|
||||
|
||||
ACTION_KEYMAP_TAP_KEY(layer, key)
|
||||
|
||||
|
||||
##### Momentary Switch with tap toggle
|
||||
Turns on layer momentary while holding but toggles it with serial taps.
|
||||
|
||||
ACTION_KEYMAP_TAP_TOGGLE(layer)
|
||||
|
||||
|
||||
##### Invert layer
|
||||
Inverts current layer state. If the layer is on it becomes off with this action.
|
||||
|
||||
ACTION_KEYMAP_INV(layer, on)
|
||||
|
||||
|
||||
##### Turn On layer
|
||||
Turns on layer state.
|
||||
|
||||
ACTION_KEYMAP_ON(layer, on)
|
||||
|
||||
Turns on layer state on press and turn off on release. This is identical to **'Switch to layer'** action.
|
||||
|
||||
ACTION_KEYMAP_ON_OFF(layer)
|
||||
|
||||
|
||||
##### Turn Off layer
|
||||
Turns off layer state.
|
||||
|
||||
ACTION_KEYMAP_OFF(layer, on)
|
||||
|
||||
|
||||
##### Set layer
|
||||
Turn on layer only.
|
||||
`keymap_stat = (1<<layer) [layer: 0-15]`
|
||||
|
||||
ACTION_KEYMAP_SET(layer, on)
|
||||
|
||||
Turns on layer only and clear all layer on release..
|
||||
|
||||
ACTION_KEYMAP_SET_CLEAR(layer)
|
||||
|
||||
|
||||
#### 2.2.2 Overlay
|
||||
***TBD***
|
||||
|
||||
In addition to actions of `Keymap` above these actions are also available.
|
||||
|
||||
##### Invert 4bit layer states
|
||||
Invert 4bits out of 16bits of overlay status on both press and release.
|
||||
`overlay_stat = (overlay_stat ^ bits<<(shift*4)) [bits: 0-15, shift: 0-3]`
|
||||
|
||||
ACTION_OVERLAY_INV4(bits, shift)
|
||||
|
||||
|
||||
|
||||
### 2.3 Macro action
|
||||
***TBD***
|
||||
|
||||
`Macro` action indicates complex key strokes.
|
||||
|
||||
MACRO( MD(LSHIFT), D(D), END )
|
||||
MACRO( U(D), MU(LSHIFT), END )
|
||||
MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )
|
||||
|
||||
#### 2.3.1 Normal mode
|
||||
- **I()** change interavl of stroke.
|
||||
- **D()** press key
|
||||
- **U()** release key
|
||||
- **T()** type key(press and release)
|
||||
- **W()** wait
|
||||
- **MD()** modifier down
|
||||
- **MU()** modifier up
|
||||
- **END** end mark
|
||||
|
||||
#### 2.3.2 Extended mode
|
||||
|
||||
***TODO: sample impl***
|
||||
See `keyboard/hhkb/keymap.c` for sample.
|
||||
|
||||
|
||||
### 2.4 Function action
|
||||
***TBD***
|
||||
|
||||
There are two type of action, normal `Function` and tappable `Function`.
|
||||
These actions call user defined function with `id`, `opt`, and key event information as arguments.
|
||||
|
||||
#### 2.4.1 Function
|
||||
To define normal `Function` action in keymap use this.
|
||||
|
||||
ACTION_FUNCTION(id, opt)
|
||||
|
||||
#### 2.4.2 Function with tap
|
||||
To define tappable `Function` action in keymap use this.
|
||||
|
||||
ACTION_FUNCTION_TAP(id, opt)
|
||||
|
||||
#### 2.4.3 Implement user function
|
||||
`Function` actions can be defined freely with C by user in callback function:
|
||||
|
||||
void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)
|
||||
|
||||
This C function is called every time key is operated, argument `id` selects action to be performed and `opt` can be used for option. Functon `id` can be 0-255 and `opt` can be 0-15.
|
||||
|
||||
`keyrecord_t` is comprised of key event and tap count. `keyevent_t` indicates which and when key is pressed or released. From `tap_count` you can know tap state, 0 means no tap. These information will be used in user function to decide how action of key is performed.
|
||||
|
||||
typedef struct {
|
||||
keyevent_t event;
|
||||
uint8_t tap_count;
|
||||
} keyrecord_t;
|
||||
|
||||
typedef struct {
|
||||
key_t key;
|
||||
bool pressed;
|
||||
uint16_t time;
|
||||
} keyevent_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t col;
|
||||
uint8_t row;
|
||||
} key_t;
|
||||
|
||||
***TODO: sample impl***
|
||||
See `keyboard/hhkb/keymap.c` for sample.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 4. Layer switching Example
|
||||
There are some ways to switch layer with 'Layer' actions.
|
||||
|
||||
### 4.1 Momentary switching
|
||||
Momentary switching changes layer only while holding Fn key.
|
||||
|
||||
This action makes 'Layer 1' active(valid) on key press event and inactive on release event. Namely you can overlay a layer on base layer temporarily with this.
|
||||
|
||||
ACTION_KEYMAP_MOMENTARY(1)
|
||||
|
||||
|
||||
After switch actions of destination layer are perfomed.
|
||||
***Thus you shall need to place action to come back on destination layer***, or you will be stuck in destination layer without way to get back. Usually you need to palce same action or 'KC_TRNS` on destination layer to get back.
|
||||
|
||||
|
||||
### 4.2 Toggle switching
|
||||
Toggle switching changes layer after press then release. With this you can keep staying on the layer until you press the key again to return.
|
||||
|
||||
This is toggle action of 'Layer 2'.
|
||||
|
||||
ACTION_KEYMAP_TOGGLE(2)
|
||||
|
||||
|
||||
|
||||
### 4.3 Momentary switching with Tap key
|
||||
These actions switch layer only while holding `Fn` key and register key on tap. **Tap** means to press and release key quickly.
|
||||
|
||||
ACTION_KEYMAP_TAP_KEY(2, KC_SCLN)
|
||||
|
||||
With this you can place layer switching function on normal key like ';' without losing its original key register function.
|
||||
|
||||
|
||||
|
||||
### 4.4 Momentary switching with Tap Toggle
|
||||
This switches layer only while holding `Fn` key and toggle layer after several taps. **Tap** means to press and release key quickly.
|
||||
|
||||
ACTION_KEYMAP_TAP_TOGGLE(1)
|
||||
|
||||
Number of taps can be defined with `TAPPING_TOGGLE` in `config.h`, `5` by default.
|
||||
|
||||
|
||||
|
||||
## Tapping
|
||||
Tapping is to press and release key quickly. Tapping speed is determined with setting of `TAPPING_TERM`, which can be defined in `config.h`, 200ms by default.
|
||||
|
||||
### Tap Key
|
||||
This is feature to assign normal key action and modifier including `Fn` to just one physical key. This is a kind of [Dual role modifier][dual_role]. It works as modifier or `Fn` when holding a key but registers normal key when tapping.
|
||||
|
||||
Action for modifier with tap key.
|
||||
|
||||
ACTION_LMODS_TAP_KEY(mods, key)
|
||||
|
||||
Action for `Fn` with tap key.
|
||||
|
||||
ACTION_KEYMAP_TAP_KEY(layer, key)
|
||||
|
||||
[dual_role]: http://en.wikipedia.org/wiki/Modifier_key#Dual-role_modifier_keys
|
||||
|
||||
|
||||
### Tap Toggle
|
||||
This is feature to assign both toggle layer and momentary switch layer action to just one physical key. It works as mementary switch when holding a key but toggle switch when tapping.
|
||||
|
||||
ACTION_KEYMAP_TAP_TOGGLE(layer)
|
||||
|
||||
|
||||
### One Shot Modifier
|
||||
This adds oneshot feature to modifier key. 'One Shot Modifier' is one time modifier which has effect only on following one alpha key.
|
||||
It works as normal modifier key when holding but oneshot modifier when tapping.
|
||||
|
||||
ACTION_LMODS_ONESHOT(mods)
|
||||
|
||||
Say you want to type 'The', you have to push and hold Shift before type 't' then release Shift before type 'h' and 'e' or you'll get 'THe'. With One Shot Modifier you can tap Shift then type 't', 'h' and 'e' normally, you don't need to holding Shift key properly here.
|
||||
|
||||
|
||||
|
||||
|
||||
## Legacy Keymap
|
||||
This was used in prior version and still works due to legacy support code in `common/keymap.c`. Legacy keymap doesn't support many of features that new keymap offers.
|
||||
|
||||
In comparison with new keymap how to define Fn key is different. It uses two arrays `fn_layer[]` and `fn_keycode[]`. The index of arrays corresponds with postfix number of `Fn` key. Array `fn_layer[]` indicates destination layer to switch and `fn_keycode[]` has keycodes to send when tapping `Fn` key.
|
||||
|
||||
In following setting example, `Fn0`, `Fn1` and `Fn2` switch layer to 1, 2 and 2 respectively. `Fn2` registers `Space` key when tap while `Fn0` and `Fn1` doesn't send any key.
|
||||
|
||||
static const uint8_t PROGMEM fn_layer[] = {
|
||||
1, // Fn0
|
||||
2, // Fn1
|
||||
2, // Fn2
|
||||
};
|
||||
|
||||
static const uint8_t PROGMEM fn_keycode[] = {
|
||||
KC_NO, // Fn0
|
||||
KC_NO, // Fn1
|
||||
KC_SPC, // Fn2
|
||||
};
|
||||
|
||||
|
||||
## Terminology
|
||||
- keymap
|
||||
- layer
|
||||
- layout
|
||||
- key
|
||||
- keycode
|
||||
- scancode
|
||||
- action
|
||||
- layer transparency
|
||||
- layer precedence
|
||||
- register
|
||||
- tap
|
||||
- Fn key
|
Before Width: | Height: | Size: 322 KiB After Width: | Height: | Size: 322 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
@ -1,24 +1,10 @@
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/*
|
||||
* Plain
|
||||
*/
|
||||
/* Layer 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 0: qwerty */
|
||||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
|
||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,NO, ENT, \
|
||||
LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, RSFT, \
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL),
|
||||
};
|
||||
|
||||
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {};
|
||||
static const uint16_t PROGMEM fn_actions[] = {};
|
||||
|
@ -0,0 +1,50 @@
|
||||
// Poker fix with toggle and bit operation
|
||||
// Fn + Esc = `
|
||||
// Fn + {left, down, up, right} = {home, pgdown, pgup, end}
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Keymap 0: qwerty */
|
||||
KEYMAP_ANSI(
|
||||
GRV, 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, \
|
||||
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, \
|
||||
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
|
||||
};
|
||||
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Overlay 0: Poker Default + Fn'd */
|
||||
KEYMAP_ANSI(
|
||||
TRNS,F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
|
||||
CAPS,FN2, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
|
||||
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN4, END, TRNS, \
|
||||
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
|
||||
TRNS,TRNS,TRNS, FN1, TRNS,TRNS,TRNS,TRNS),
|
||||
/* Overlay 1: Poker with Arrow */
|
||||
KEYMAP_ANSI(
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, PGUP, \
|
||||
TRNS,TRNS,TRNS, TRNS, FN3, HOME,PGDN,END),
|
||||
/* Overlay 2: Poker with Esc */
|
||||
KEYMAP_ANSI(
|
||||
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
|
||||
/* Overlay 3: Poker with Arrow + Fn'd */
|
||||
KEYMAP_ANSI(
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
|
||||
TRNS,TRNS,TRNS, TRNS, TRNS,LEFT,DOWN,RGHT),
|
||||
};
|
||||
static const uint16_t PROGMEM fn_actions[] = {
|
||||
/* Poker Layout */
|
||||
[0] = ACTION_OVERLAY_INV4(0b0101, 0), // Poker Fn(with fix for Esc)
|
||||
[1] = ACTION_OVERLAY_TOGGLE(1), // Poker Arrow toggle
|
||||
[2] = ACTION_OVERLAY_TOGGLE(2), // Poker Esc toggle
|
||||
[3] = ACTION_OVERLAY_INV4(0b1101, 0), // Poker Fn(with fix for Arrow)
|
||||
[4] = ACTION_RMODS_KEY(MOD_BIT(KC_RCTL)|MOD_BIT(KC_RSFT), KC_ESC), // FN3 Task(RControl,RShift+Esc)
|
||||
};
|
@ -0,0 +1,81 @@
|
||||
// Poker fix with set(state transition)
|
||||
// Fn + Esc = `
|
||||
// Fn + {left, down, up, right} = {home, pgdown, pgup, end}
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Keymap 0: qwerty */
|
||||
KEYMAP_ANSI(
|
||||
GRV, 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, \
|
||||
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, \
|
||||
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
|
||||
};
|
||||
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Overlay 0: Poker with Arrow */
|
||||
KEYMAP_ANSI(
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
|
||||
TRNS,TRNS,TRNS, TRNS, FN1, LEFT,DOWN,RGHT),
|
||||
/* Overlay 1: Poker with Esc */
|
||||
KEYMAP_ANSI(
|
||||
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS, TRNS, FN2, TRNS,TRNS,TRNS),
|
||||
/* Overlay 2: Poker with Arrow and Esc */
|
||||
KEYMAP_ANSI(
|
||||
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
|
||||
TRNS,TRNS,TRNS, TRNS, FN3, LEFT,DOWN,RGHT),
|
||||
/* Overlay 3: Poker Fn'd */
|
||||
KEYMAP_ANSI(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
|
||||
TRNS,FN6, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
|
||||
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
|
||||
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
|
||||
TRNS,TRNS,TRNS, FN5, FN4, TRNS,TRNS,TRNS),
|
||||
/* Overlay 4: Poker Fn'd arrow */
|
||||
KEYMAP_ANSI(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
|
||||
TRNS,FN7, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
|
||||
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
|
||||
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, PGUP, \
|
||||
TRNS,TRNS,TRNS, FN4, FN5, HOME,PGDN,END),
|
||||
/* Overlay 5: Poker Fn'd Esc */
|
||||
KEYMAP_ANSI(
|
||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
|
||||
TRNS,FN4, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
|
||||
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
|
||||
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
|
||||
TRNS,TRNS,TRNS, FN7, FN6, TRNS,TRNS,TRNS),
|
||||
/* Overlay 6: Poker Fn'd Arrow + Esc */
|
||||
KEYMAP_ANSI(
|
||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
|
||||
TRNS,FN5, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
|
||||
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
|
||||
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, PGUP, \
|
||||
TRNS,TRNS,TRNS, FN6, FN7, HOME,PGDN,END),
|
||||
};
|
||||
|
||||
/*
|
||||
* Fn action definition
|
||||
*/
|
||||
static const uint16_t PROGMEM fn_actions[] = {
|
||||
/* Poker Layout */
|
||||
[0] = ACTION_OVERLAY_SET(3, ON_PRESS), // FN0 move to Fn'd when press
|
||||
[1] = ACTION_OVERLAY_SET(4, ON_PRESS), // FN1 move to Fn'd arrow when press
|
||||
[2] = ACTION_OVERLAY_SET(5, ON_PRESS), // FN2 move to Fn'd Esc when press
|
||||
[3] = ACTION_OVERLAY_SET(6, ON_PRESS), // FN3 move to Fn'd arrow + Esc when press
|
||||
|
||||
[4] = ACTION_OVERLAY_CLEAR(ON_RELEASE), // FN4 clear overlay when release
|
||||
[5] = ACTION_OVERLAY_SET(0, ON_RELEASE), // FN5 move to arrow when release
|
||||
[6] = ACTION_OVERLAY_SET(1, ON_RELEASE), // FN6 move to Esc when release
|
||||
[7] = ACTION_OVERLAY_SET(2, ON_RELEASE), // FN7 move to arrow + Esc when release
|
||||
|
||||
[8] = ACTION_RMODS_KEY(MOD_BIT(KC_RCTL)|MOD_BIT(KC_RSFT), KC_ESC), // FN8 Task(RControl,RShift+Esc)
|
||||
};
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright 2013 Jun WAKO <wakojun@gmail.com>
|
||||
|
||||
This software is licensed with a Modified BSD License.
|
||||
All of this is supposed to be Free Software, Open Source, DFSG-free,
|
||||
GPL-compatible, and OK to use in both free and proprietary applications.
|
||||
Additions and corrections to this file are welcome.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
void serial_init(void)
|
||||
{
|
||||
SERIAL_UART_INIT();
|
||||
}
|
||||
|
||||
// RX ring buffer
|
||||
#define RBUF_SIZE 8
|
||||
static uint8_t rbuf[RBUF_SIZE];
|
||||
static uint8_t rbuf_head = 0;
|
||||
static uint8_t rbuf_tail = 0;
|
||||
|
||||
uint8_t serial_recv(void)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
if (rbuf_head == rbuf_tail) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = rbuf[rbuf_tail];
|
||||
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
|
||||
return data;
|
||||
}
|
||||
|
||||
int16_t serial_recv2(void)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
if (rbuf_head == rbuf_tail) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data = rbuf[rbuf_tail];
|
||||
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
|
||||
return data;
|
||||
}
|
||||
|
||||
void serial_send(uint8_t data)
|
||||
{
|
||||
while (!SERIAL_UART_TXD_READY) ;
|
||||
SERIAL_UART_DATA = data;
|
||||
}
|
||||
|
||||
// USART RX complete interrupt
|
||||
ISR(SERIAL_UART_RXD_VECT)
|
||||
{
|
||||
uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
|
||||
if (next != rbuf_tail) {
|
||||
rbuf[rbuf_head] = SERIAL_UART_DATA;
|
||||
rbuf_head = next;
|
||||
}
|
||||
}
|
Loading…
Reference in new issue