]> git.donarmstrong.com Git - tmk_firmware.git/commitdiff
Merge branch 'ps2_keyboard_fix'
authortmk <nobody@nowhere>
Thu, 28 Nov 2013 07:02:29 +0000 (16:02 +0900)
committertmk <nobody@nowhere>
Thu, 28 Nov 2013 07:02:29 +0000 (16:02 +0900)
21 files changed:
converter/ps2_usb/Makefile
converter/ps2_usb/Makefile.pjrc [new file with mode: 0644]
converter/ps2_usb/config.h
converter/ps2_usb/keymap.c [deleted file]
converter/ps2_usb/keymap_common.c [new file with mode: 0644]
converter/ps2_usb/keymap_common.h [new file with mode: 0644]
converter/ps2_usb/keymap_plain.c [new file with mode: 0644]
converter/ps2_usb/matrix.c
keyboard/onekey/Makefile [new file with mode: 0644]
keyboard/onekey/Makefile.lufa [deleted file]
keyboard/onekey/README.md
keyboard/onekey/config.h
keyboard/onekey/matrix.c
protocol.mk
protocol/lufa/lufa.c
protocol/pjrc/usb.c
protocol/ps2.c [deleted file]
protocol/ps2.h
protocol/ps2_busywait.c [new file with mode: 0644]
protocol/ps2_interrupt.c [new file with mode: 0644]
protocol/ps2_usart.c

index 0c6442374c4cca13cbff297148aa92b2a7c04d3c..04bf28a00c5c995c020654a9ce3d71502089fd73 100644 (file)
@@ -1,5 +1,5 @@
 # Target file name (without extension).
-TARGET = ps2_usb
+TARGET = ps2_usb_lufa
 
 # Directory common source filess exist
 TOP_DIR = ../..
@@ -7,69 +7,96 @@ TOP_DIR = ../..
 # Directory keyboard dependent files exist
 TARGET_DIR = .
 
+# project specific files
+SRC =  keymap_common.c \
+       matrix.c \
+       led.c
+
+ifdef KEYMAP
+    SRC := keymap_$(KEYMAP).c $(SRC)
+else
+    SRC := keymap_plain.c $(SRC)
+endif
+
+CONFIG_H = config.h
 
-# MCU name, you MUST set this to match the board you are using
-# type "make clean" after changing this, so all files will be rebuilt
-#MCU = at90usb162       # Teensy 1.0
-MCU = atmega32u4       # Teensy 2.0
-#MCU = at90usb646       # Teensy++ 1.0
-#MCU = at90usb1286      # Teensy++ 2.0
 
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
 
 # Processor frequency.
-#   Normally the first thing your program should do is set the clock prescaler,
-#   so your program will run at the correct speed.  You should also set this
-#   variable to same clock speed.  The _delay_ms() macro uses this, and many
-#   examples use this variable to calculate timings.  Do not add a "UL" here.
+#     This will define a symbol, F_CPU, in all source code files equal to the
+#     processor frequency in Hz. You can then use this symbol in your source code to
+#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+#     automatically to create a 32-bit value in your source code.
+#
+#     This will be an integer division of F_USB below, as it is sourced by
+#     F_USB after it has run through any CPU prescalers. Note that this value
+#     does not *change* the processor frequency - it should merely be updated to
+#     reflect the processor speed set externally so that the code can use accurate
+#     software delays.
 F_CPU = 16000000
 
 
-# Build Options
-#   *Comment out* to disable the options.
 #
-MOUSEKEY_ENABLE = yes  # Mouse keys
-EXTRAKEY_ENABLE = yes  # Audio control and System control
-NKRO_ENABLE = yes      # USB Nkey Rollover
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+#     This will define a symbol, F_USB, in all source code files equal to the
+#     input clock frequency (before any prescaling is performed) in Hz. This value may
+#     differ from F_CPU if prescaling is used on the latter, and is required as the
+#     raw input clock is fed directly to the PLL sections of the AVR for high speed
+#     clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+#     at the end, this will be done automatically to create a 32-bit value in your
+#     source code.
+#
+#     If no clock division is performed on the input clock inside the AVR (via the
+#     CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
 
-PS2_USE_USART = yes    # uses hardware USART engine for PS/2 signal receive(recomened)
-#PS2_USE_INT = yes     # uses external interrupt for falling edge of PS/2 clock pin
-#PS2_USE_BUSYWAIT = yes        # uses primitive reference code
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
 
 
-# keyboard dependent files
-SRC =   keymap.c \
-       matrix.c \
-       led.c
-
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Teensy++ halfKay 1024
+#   Atmel DFU loader 4096
+#   LUFA bootloader  4096
+#   USBaspLoader     2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
 
-ifdef PS2_USE_USART
-    SRC += protocol/ps2_usart.c
-    OPT_DEFS += -DPS2_USE_USART
-endif
-ifdef PS2_USE_INT
-    SRC += protocol/ps2.c
-    OPT_DEFS += -DPS2_USE_INT
-endif
-ifdef PS2_USE_BUSYWAIT
-    SRC += protocol/ps2.c
-    OPT_DEFS += -DPS2_USE_BUSYWAIT
-endif
 
+# Build Options
+#   comment out to disable the options.
+#
+#BOOTMAGIC_ENABLE = yes        # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes  # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes  # Audio control and System control(+450)
+CONSOLE_ENABLE = yes   # Console for debug(+400)
+COMMAND_ENABLE = yes    # Commands for debug and configuration
+NKRO_ENABLE = yes      # USB Nkey Rollover - not yet supported in LUFA
 
-#CONFIG_H = config_pjrc_usart.h
-CONFIG_H = config.h
 
+# PS/2 Options
+#
+#PS2_USE_USART = yes   # uses hardware USART engine for PS/2 signal receive(recomened)
+#PS2_USE_INT = yes     # uses external interrupt for falling edge of PS/2 clock pin
+PS2_USE_BUSYWAIT = yes # uses primitive reference code
 
-#---------------- Programming Options --------------------------
-PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
 
+# Optimize size but this may cause error "relocation truncated to fit"
+#EXTRALDFLAGS = -Wl,--relax
 
 # Search Path
 VPATH += $(TARGET_DIR)
 VPATH += $(TOP_DIR)
 
-
-include $(TOP_DIR)/protocol/pjrc.mk
 include $(TOP_DIR)/protocol.mk
+include $(TOP_DIR)/protocol/lufa.mk
 include $(TOP_DIR)/common.mk
 include $(TOP_DIR)/rules.mk
diff --git a/converter/ps2_usb/Makefile.pjrc b/converter/ps2_usb/Makefile.pjrc
new file mode 100644 (file)
index 0000000..0e175f8
--- /dev/null
@@ -0,0 +1,75 @@
+# Target file name (without extension).
+TARGET = ps2_usb_pjrc
+
+# Directory common source filess exist
+TOP_DIR = ../..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# keyboard dependent files
+SRC =   keymap_common.c \
+       matrix.c \
+       led.c
+
+ifdef KEYMAP
+    SRC := keymap_$(KEYMAP).c $(SRC)
+else
+    SRC := keymap_plain.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+
+# MCU name, you MUST set this to match the board you are using
+# type "make clean" after changing this, so all files will be rebuilt
+#MCU = at90usb162       # Teensy 1.0
+MCU = atmega32u4       # Teensy 2.0
+#MCU = at90usb646       # Teensy++ 1.0
+#MCU = at90usb1286      # Teensy++ 2.0
+
+
+# Processor frequency.
+#   Normally the first thing your program should do is set the clock prescaler,
+#   so your program will run at the correct speed.  You should also set this
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
+F_CPU = 16000000
+
+
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Teensy++ halfKay 1024
+#   Atmel DFU loader 4096
+#   LUFA bootloader  4096
+#   USBaspLoader     2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+#   *Comment out* to disable the options.
+#
+#BOOTMAGIC_ENABLE = yes        # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes  # Mouse keys
+EXTRAKEY_ENABLE = yes  # Audio control and System control
+CONSOLE_ENABLE = yes   # Console for debug(+400)
+COMMAND_ENABLE = yes    # Commands for debug and configuration
+NKRO_ENABLE = yes      # USB Nkey Rollover
+
+
+# PS/2 Options
+#
+#PS2_USE_USART = yes   # uses hardware USART engine for PS/2 signal receive(recomened)
+#PS2_USE_INT = yes     # uses external interrupt for falling edge of PS/2 clock pin
+PS2_USE_BUSYWAIT = yes # uses primitive reference code
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TOP_DIR)
+
+
+include $(TOP_DIR)/protocol.mk
+include $(TOP_DIR)/protocol/pjrc.mk
+include $(TOP_DIR)/common.mk
+include $(TOP_DIR)/rules.mk
index 51cd271d7826b3ef4d2f90b572c12e3f6c3cd99f..c9bab1b0724d65d23ae61d4fd62d589a106817de 100644 (file)
@@ -22,6 +22,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #define VENDOR_ID       0xFEED
 #define PRODUCT_ID      0x6512
+#define DEVICE_VER      0x0001
 #define MANUFACTURER    t.m.k.
 #define PRODUCT         PS/2 keyboard converter
 #define DESCRIPTION     convert PS/2 keyboard to USB
@@ -39,10 +40,52 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 )
 
 
-/* legacy keymap support */
-#define USE_LEGACY_KEYMAP
+//#define NO_SUSPEND_POWER_DOWN
 
 
+/*
+ * PS/2 Busywait
+ */
+#ifdef PS2_USE_BUSYWAIT
+#define PS2_CLOCK_PORT  PORTD
+#define PS2_CLOCK_PIN   PIND
+#define PS2_CLOCK_DDR   DDRD
+#define PS2_CLOCK_BIT   5
+#define PS2_DATA_PORT   PORTD
+#define PS2_DATA_PIN    PIND
+#define PS2_DATA_DDR    DDRD
+#define PS2_DATA_BIT    2
+#endif
+
+/*
+ * PS/2 Pin interrupt
+ */
+#ifdef PS2_USE_INT
+/* uses INT1 for clock line(ATMega32U4) */
+#define PS2_CLOCK_PORT  PORTD
+#define PS2_CLOCK_PIN   PIND
+#define PS2_CLOCK_DDR   DDRD
+#define PS2_CLOCK_BIT   1
+#define PS2_DATA_PORT   PORTD
+#define PS2_DATA_PIN    PIND
+#define PS2_DATA_DDR    DDRD
+#define PS2_DATA_BIT    2
+#define PS2_INT_INIT()  do {    \
+    EICRA |= ((1<<ISC11) |      \
+              (0<<ISC10));      \
+} while (0)
+#define PS2_INT_ON()  do {      \
+    EIMSK |= (1<<INT1);         \
+} while (0)
+#define PS2_INT_OFF() do {      \
+    EIMSK &= ~(1<<INT1);        \
+} while (0)
+#define PS2_INT_VECT    INT1_vect
+#endif
+
+/*
+ * PS/2 USART
+ */
 #ifdef PS2_USE_USART
 #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
 /* XCK for clock line and RXD for data line */
@@ -54,7 +97,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define PS2_DATA_PIN    PIND
 #define PS2_DATA_DDR    DDRD
 #define PS2_DATA_BIT    2
-
 /* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */
 /* set DDR of CLOCK as input to be slave */
 #define PS2_USART_INIT() do {   \
@@ -85,7 +127,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define PS2_USART_RX_DATA       UDR1
 #define PS2_USART_ERROR         (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1)))
 #define PS2_USART_RX_VECT       USART1_RX_vect
-
 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
 /* XCK for clock line and RXD for data line */
 #define PS2_CLOCK_PORT  PORTD
@@ -96,7 +137,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define PS2_DATA_PIN    PIND
 #define PS2_DATA_DDR    DDRD
 #define PS2_DATA_BIT    0
-
 /* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */
 /* set DDR of CLOCK as input to be slave */
 #define PS2_USART_INIT() do {   \
@@ -130,41 +170,4 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #endif
 #endif
 
-
-#ifdef PS2_USE_INT
-/* uses INT1 for clock line(ATMega32U4) */
-#define PS2_CLOCK_PORT  PORTD
-#define PS2_CLOCK_PIN   PIND
-#define PS2_CLOCK_DDR   DDRD
-#define PS2_CLOCK_BIT   1
-#define PS2_DATA_PORT   PORTD
-#define PS2_DATA_PIN    PIND
-#define PS2_DATA_DDR    DDRD
-#define PS2_DATA_BIT    2
-
-#define PS2_INT_INIT()  do {    \
-    EICRA |= ((1<<ISC11) |      \
-              (0<<ISC10));      \
-} while (0)
-#define PS2_INT_ON()  do {      \
-    EIMSK |= (1<<INT1);         \
-} while (0)
-#define PS2_INT_OFF() do {      \
-    EIMSK &= ~(1<<INT1);        \
-} while (0)
-#define PS2_INT_VECT    INT1_vect
-#endif
-
-
-#ifdef PS2_USE_BUSYWAIT
-#define PS2_CLOCK_PORT  PORTF
-#define PS2_CLOCK_PIN   PINF
-#define PS2_CLOCK_DDR   DDRF
-#define PS2_CLOCK_BIT   0
-#define PS2_DATA_PORT   PORTF
-#define PS2_DATA_PIN    PINF
-#define PS2_DATA_DDR    DDRF
-#define PS2_DATA_BIT    1
-#endif
-
 #endif
diff --git a/converter/ps2_usb/keymap.c b/converter/ps2_usb/keymap.c
deleted file mode 100644 (file)
index c97783f..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
-Copyright 2011 Jun Wako <wakojun@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/* 
- * Keymap for PS/2 keyboard
- */
-#include <stdint.h>
-#include <stdbool.h>
-#include <avr/pgmspace.h>
-#include "keycode.h"
-#include "print.h"
-#include "debug.h"
-#include "util.h"
-#include "keymap.h"
-
-
-
-
-// Following macros help you to define a keymap with the form of actual keyboard layout.
-
-/* US layout plus all other various keys */
-#define KEYMAP_ALL( \
-    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
-    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
-    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
-    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
-    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
-    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
-                                                                                            \
-    K61,                     /* for European ISO */                                         \
-    K51, K13, K6A, K64, K67, /* for Japanese JIS */                                         \
-    K08, K10, K18, K20, K28, K30, K38, K40, K48, K50, K57, K5F, /* F13-24 */                \
-    KB7, KBF, KDE,           /* System Power, Sleep, Wake */                                \
-    KA3, KB2, KA1,           /* Mute, Volume Up, Volume Down */                             \
-    KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */                \
-    KC8, KAB, KC0,           /* Mail, Calculator, My Computer */                            \
-    K90, KBA, KB8, KB0,      /* WWW Search, Home, Back, Forward */                          \
-    KA8, KA0, K98            /* WWW Stop, Refresh, Favorites */                             \
-) { \
-    { KC_NO,    KC_##K01, KC_NO,    KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
-    { KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_NO    }, \
-    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_NO    }, \
-    { KC_##K18, KC_NO,    KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_NO    }, \
-    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO    }, \
-    { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_NO    }, \
-    { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_NO    }, \
-    { KC_##K38, KC_NO,    KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_NO    }, \
-    { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_NO    }, \
-    { KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_NO    }, \
-    { KC_##K50, KC_##K51, KC_##K52, KC_NO,    KC_##K54, KC_##K55, KC_NO,    KC_##K57 }, \
-    { KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_NO,    KC_##K5D, KC_NO,    KC_##K5F }, \
-    { KC_NO,    KC_##K61, KC_NO,    KC_NO,    KC_##K64, KC_NO,    KC_##K66, KC_##K67 }, \
-    { KC_NO,    KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C, KC_NO,    KC_NO,    KC_NO    }, \
-    { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \
-    { KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_##K7E, KC_NO    }, \
-    { KC_NO,    KC_NO,    KC_NO,    KC_##K83, KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
-    { KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
-    { KC_##K90, KC_##K91, KC_NO,    KC_NO,    KC_##K94, KC_##K95, KC_NO,    KC_NO    }, \
-    { KC_##K98, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_##K9F }, \
-    { KC_##KA0, KC_##KA1, KC_NO,    KC_##KA3, KC_NO,    KC_NO,    KC_NO,    KC_##KA7 }, \
-    { KC_##KA8, KC_NO,    KC_NO,    KC_##KAB, KC_NO,    KC_NO,    KC_NO,    KC_##KAF }, \
-    { KC_##KB0, KC_NO,    KC_##KB2, KC_NO,    KC_##KB4, KC_NO,    KC_NO,    KC_##KB7 }, \
-    { KC_##KB8, KC_NO,    KC_##KBA, KC_##KBB, KC_NO,    KC_NO,    KC_NO,    KC_##KBF }, \
-    { KC_##KC0, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
-    { KC_##KC8, KC_NO,    KC_##KCA, KC_NO,    KC_NO,    KC_##KCD, KC_NO,    KC_NO    }, \
-    { KC_##KD0, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
-    { KC_NO,    KC_NO,    KC_##KDA, KC_NO,    KC_NO,    KC_NO,    KC_##KDE, KC_NO    }, \
-    { KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
-    { KC_NO,    KC_##KE9, KC_NO,    KC_##KEB, KC_##KEC, KC_NO,    KC_NO,    KC_NO    }, \
-    { KC_##KF0, KC_##KF1, KC_##KF2, KC_NO,    KC_##KF4, KC_##KF5, KC_NO,    KC_NO    }, \
-    { KC_NO,    KC_NO,    KC_##KFA, KC_NO,    KC_##KFC, KC_##KFD, KC_##KFE, KC_NO    }, \
-}
-
-/* US layout */
-#define KEYMAP( \
-    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
-    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
-    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
-    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
-    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
-    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA  \
-) \
-KEYMAP_ALL( \
-    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
-    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
-    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
-    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
-    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
-    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
-                                                                                            \
-    NUBS,                                                                                   \
-    RO, KANA, JYEN, HENK, MHEN,                                                             \
-    F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,                             \
-    SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE,                                                \
-    AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN,                                               \
-    MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT,         \
-    MAIL, CALCULATOR, MY_COMPUTER,                                                          \
-    WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD,                                            \
-    WWW_STOP, WWW_REFRESH, WWW_FAVORITES                                                    \
-)
-
-/* ISO layout */
-#define KEYMAP_ISO( \
-    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
-    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
-    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,     KF1,KE9,KFA,  K6C,K75,K7D,     \
-    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,K5A,               K6B,K73,K74,K79, \
-    K12,K61,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,    K59,     KF5,      K69,K72,K7A,     \
-    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA  \
-) \
-KEYMAP_ALL( \
-    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
-    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
-    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
-    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
-    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
-    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
-                                                                                            \
-    K61,                                                                                    \
-    RO, KANA, JYEN, HENK, MHEN,                                                             \
-    F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,                             \
-    SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE,                                                \
-    AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN,                                               \
-    MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT,         \
-    MAIL, CALCULATOR, MY_COMPUTER,                                                          \
-    WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD,                                            \
-    WWW_STOP, WWW_REFRESH, WWW_FAVORITES                                                    \
-)
-
-/* JIS layout */
-#define KEYMAP_JIS( \
-    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,         KFC,K7E,KFE,                   \
-    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
-    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,         KF1,KE9,KFA,  K6C,K75,K7D,     \
-    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,    K5A,               K6B,K73,K74,K79, \
-    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51,        K59,     KF5,      K69,K72,K7A,     \
-    K14,K9F,K11,    K67,K29,K64,K13,            K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA  \
-) \
-KEYMAP_ALL( \
-    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
-    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
-    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
-    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
-    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
-    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
-                                                                                            \
-    NUBS,                                                                                   \
-    K51, K13, K6A, K64, K67,                                                                \
-    F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,                             \
-    SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE,                                                \
-    AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN,                                               \
-    MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT,         \
-    MAIL, CALCULATOR, MY_COMPUTER,                                                          \
-    WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD,                                            \
-    WWW_STOP, WWW_REFRESH, WWW_FAVORITES                                                    \
-)
-
-
-// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
-static const uint8_t PROGMEM fn_layer[] = {
-    5,              // Fn0
-    6,              // Fn1
-    0,              // Fn2
-    0,              // Fn3
-    0,              // Fn4
-    0,              // Fn5
-    0,              // Fn6
-    0               // Fn7
-};
-
-// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer.
-// See layer.c for details.
-static const uint8_t PROGMEM fn_keycode[] = {
-    KC_SCLN,        // Fn0
-    KC_SLSH,        // Fn1
-    KC_NO,          // Fn2
-    KC_NO,          // Fn3
-    KC_NO,          // Fn4
-    KC_NO,          // Fn5
-    KC_NO,          // Fn6
-    KC_NO           // Fn7
-};
-
-
-// The keymap is a 32*8 byte array which convert a PS/2 scan code into a USB keycode.
-// See keycode.h for USB keycodes. You should omit a 'KC_' prefix of USB keycodes in keymap macro.
-// Use KEYMAP_ISO() or KEYMAP_JIS() instead of KEYMAP() if your keyboard is ISO or JIS.
-static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
-    /* 0: default
-     * ,---.   ,---------------. ,---------------. ,---------------. ,-----------.     ,-----------.
-     * |Esc|   |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau|     |Pwr|Slp|Wak|
-     * `---'   `---------------' `---------------' `---------------' `-----------'     `-----------'
-     * ,-----------------------------------------------------------. ,-----------. ,---------------.
-     * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backspa| |Ins|Hom|PgU| |NmL|  /|  *|  -|
-     * |-----------------------------------------------------------| |-----------| |---------------|
-     * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|    \| |Del|End|PgD| |  7|  8|  9|   |
-     * |-----------------------------------------------------------| `-----------' |-----------|  +|
-     * |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return  |               |  4|  5|  6|   |
-     * |-----------------------------------------------------------|     ,---.     |---------------|
-     * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shift     |     |Up |     |  1|  2|  3|   |
-     * |-----------------------------------------------------------| ,-----------. |-----------|Ent|
-     * |Ctrl |Gui |Alt |         Space         |Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| |      0|  .|   |
-     * `-----------------------------------------------------------' `-----------' `---------------'
-     * ; = Fn0(to Layer 5)
-     * / = Fn1(to Layer 6)
-     */
-    KEYMAP(
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
-    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
-    TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   FN0, QUOT,     ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, FN1,           RSFT,          UP,           P1,  P2,  P3,
-    LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
-    ),
-
-    /* 1: plain Qwerty without layer switching
-     * ,-----------------------------------------------------------.
-     * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backspa|
-     * |-----------------------------------------------------------|
-     * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|    \|
-     * |-----------------------------------------------------------|
-     * |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return  |
-     * |-----------------------------------------------------------|
-     * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shift     |
-     * |-----------------------------------------------------------|
-     * |Ctrl |Gui |Alt |         Space         |Alt |Gui |Menu|Ctrl|
-     * `-----------------------------------------------------------'
-     */
-    KEYMAP(
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
-    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
-    TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,          RSFT,          UP,           P1,  P2,  P3,
-    LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
-    ),
-
-    /* 2: Colemak http://colemak.com
-     * ,-----------------------------------------------------------.
-     * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backspa|
-     * |-----------------------------------------------------------|
-     * |Tab  |  Q|  W|  F|  P|  G|  J|  L|  U|  Y|  ;|  [|  ]|    \|
-     * |-----------------------------------------------------------|
-     * |BackSp|  A|  R|  S|  T|  D|  H|  N|  E|  I|  O|  '|Return  |
-     * |-----------------------------------------------------------|
-     * |Shift   |  Z|  X|  C|  V|  B|  K|  M|  ,|  ,|  /|Shift     |
-     * |-----------------------------------------------------------|
-     * |Ctrl |Gui |Alt |         Space         |Alt |Gui |Menu|Ctrl|
-     * `----------------------------------------------------------'
-     */
-    KEYMAP(
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
-    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
-    TAB, Q,   W,   F,   P,   G,   J,   L,   U,   Y,   SCLN,LBRC,RBRC,BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    BSPC,A,   R,   S,   T,   D,   H,   N,   E,   I,   O,   QUOT,     ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,Z,   X,   C,   V,   B,   K,   M,   COMM,DOT, SLSH,          RSFT,          UP,           P1,  P2,  P3,
-    LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
-    ),
-
-    /* 3: Dvorak http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard
-     * ,-----------------------------------------------------------.
-     * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  [|  ]|Backspa|
-     * |-----------------------------------------------------------|
-     * |Tab  |  '|  ,|  .|  P|  Y|  F|  G|  C|  R|  L|  /|  =|    \|
-     * |-----------------------------------------------------------|
-     * |BackSp|  A|  O|  E|  U|  I|  D|  H|  T|  N|  S|  -|Return  |
-     * |-----------------------------------------------------------|
-     * |Shift   |  ;|  Q|  J|  K|  X|  B|  M|  Wl  V|  Z|Shift     |
-     * |-----------------------------------------------------------|
-     * |Ctrl |Gui |Alt |         Space         |Alt |Gui |Menu|Ctrl|
-     * `-----------------------------------------------------------'
-     */
-    KEYMAP(
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
-    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   LBRC,RBRC,BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
-    TAB, QUOT,COMM,DOT, P,   Y,   F,   G,   C,   R,   L,   SLSH,EQL, BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    CAPS,A,   O,   E,   U,   I,   D,   H,   T,   N,   S,   MINS,     ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,SCLN,Q,   J,   K,   X,   B,   M,   W,   V,   Z,             RSFT,          UP,           P1,  P2,  P3,
-    LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
-    ),
-
-    /* 4: Workman http://viralintrospection.wordpress.com/2010/09/06/a-different-philosophy-in-designing-keyboard-layouts/
-     * ,-----------------------------------------------------------.
-     * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backspa|
-     * |-----------------------------------------------------------|
-     * |Tab  |  Q|  D|  R|  W|  B|  J|  F|  U|  P|  ;|  [|  ]|    \|
-     * |-----------------------------------------------------------|
-     * |CapsLo|  A|  S|  H|  T|  G|  Y|  N|  E|  O|  I|  '|Return  |
-     * |-----------------------------------------------------------|
-     * |Shift   |  Z|  X|  M|  C|  V|  K|  L|  ,|  ,|  /|Shift     |
-     * |-----------------------------------------------------------|
-     * |Ctrl |Gui |Alt |         Space         |Alt |Gui |Menu|Ctrl|
-     * `-----------------------------------------------------------'
-     */
-    KEYMAP(
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
-    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
-    TAB, Q,   D,   R,   W,   B,   J,   F,   U,   P,   SCLN,LBRC,RBRC,BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    BSPC,A,   S,   H,   T,   G,   Y,   N,   E,   O,   I,   QUOT,     ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,Z,   X,   M,   C,   V,   K,   L,   COMM,DOT, SLSH,          RSFT,          UP,           P1,  P2,  P3,
-    LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
-    ),
-
-    /* 5: Mouse keys
-     * ,-----------------------------------------------------------.
-     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa|
-     * |-----------------------------------------------------------|
-     * |Tab  |MwL|MwU|McU|WwU|WwR|MwL|MwD|MwU|MwR|   |   |   |    \|
-     * |-----------------------------------------------------------|
-     * |CapsLo|   |McL|McD|McR|   |McL|McD|McU|McR|Fn0|   |Return  |
-     * |-----------------------------------------------------------|
-     * |Shift   |VoD|VoU|Mut|Mb2|Mb3|Mb2|Mb1|VoD|VoU|Mut|Shift     |
-     * |-----------------------------------------------------------|
-     * |Ctrl |Gui |Alt |         Mb1           |Alt |Gui |Menu|Ctrl|
-     * `-----------------------------------------------------------'
-     * Mc = mouse cursor, Mw = mouse wheel, Mb = mouse button
-     * Vo = Volume, Mut = Mute
-     */
-    KEYMAP(
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F8,  F10, F11, F12, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
-    TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO,  NO,  NO,  BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    CAPS,NO,  MS_L,MS_D,MS_R,NO,  MS_L,MS_D,MS_U,MS_R,FN0, NO,       ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE,          RSFT,          UP,           P1,  P2,  P3,
-    LCTL,LGUI,LALT,          BTN1,                    RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
-    ),
-
-    /* 6: Cursor keys
-     * ,-----------------------------------------------------------.
-     * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa|
-     * |-----------------------------------------------------------|
-     * |Tab  |Hom|PgU| Up|PgU|End|Hom|PgD|PgU|End|   |   |   |    \|
-     * |-----------------------------------------------------------|
-     * |CapsLo|   |Lef|Dow|Rig|   |Lef|Dow| Up|Rig|   |   |Return  |
-     * |-----------------------------------------------------------|
-     * |Shift   |   |   |   |   |   |Hom|PgD|PgU|End|Fn1|Shift     |
-     * |-----------------------------------------------------------|
-     * |Ctrl |Gui |Alt |         Space         |Alt |Gui |Menu|Ctrl|
-     * `-----------------------------------------------------------'
-     */
-    KEYMAP(
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
-    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F8,  F10, F11, F12, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
-    TAB, NO,  NO,  NO,  NO,  NO,  HOME,PGDN,PGUP,END, NO,  NO,  NO,  BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
-    CAPS,NO,  NO,  NO,  NO,  NO,  LEFT,DOWN,UP,  RGHT,NO,  NO,       ENT,                         P4,  P5,  P6,  PPLS,
-    LSFT,VOLD,VOLU,MUTE,NO,  NO,  HOME,PGDN,PGUP,END, FN1,           RSFT,          UP,           P1,  P2,  P3,
-    LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
-    ),
-};
-
-
-uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
-{
-    return pgm_read_byte(&keymaps[(layer)][(row)][(col)]);
-}
-
-uint8_t keymap_fn_layer(uint8_t index)
-{
-    return pgm_read_byte(&fn_layer[index]);
-}
-
-uint8_t keymap_fn_keycode(uint8_t index)
-{
-    return pgm_read_byte(&fn_keycode[index]);
-}
diff --git a/converter/ps2_usb/keymap_common.c b/converter/ps2_usb/keymap_common.c
new file mode 100644 (file)
index 0000000..241d2e3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "keymap_common.h"
+
+
+/* translates key to keycode */
+uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
+{
+    return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
+}
+
+/* translates Fn keycode to action */
+action_t keymap_fn_to_action(uint8_t keycode)
+{
+    return (action_t){ .code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) };
+}
diff --git a/converter/ps2_usb/keymap_common.h b/converter/ps2_usb/keymap_common.h
new file mode 100644 (file)
index 0000000..216a8dc
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef KEYMAP_COMMON_H
+#define KEYMAP_COMMON_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/pgmspace.h>
+#include "keycode.h"
+#include "action.h"
+#include "action_macro.h"
+#include "report.h"
+#include "print.h"
+#include "debug.h"
+#include "keymap.h"
+
+
+// 32*8(256) byte array which converts PS/2 code into USB code
+extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
+extern const uint16_t fn_actions[];
+
+
+/* All keys */
+#define KEYMAP_ALL( \
+    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
+    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
+    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
+    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
+    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
+    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
+                                                                                            \
+    K61,                     /* for European ISO */                                         \
+    K51, K13, K6A, K64, K67, /* for Japanese JIS */                                         \
+    K08, K10, K18, K20, K28, K30, K38, K40, K48, K50, K57, K5F, /* F13-24 */                \
+    KB7, KBF, KDE,           /* System Power, Sleep, Wake */                                \
+    KA3, KB2, KA1,           /* Mute, Volume Up, Volume Down */                             \
+    KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */                \
+    KC8, KAB, KC0,           /* Mail, Calculator, My Computer */                            \
+    K90, KBA, KB8, KB0,      /* WWW Search, Home, Back, Forward */                          \
+    KA8, KA0, K98            /* WWW Stop, Refresh, Favorites */                             \
+) { \
+    { KC_NO,    KC_##K01, KC_NO,    KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
+    { KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_NO    }, \
+    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_NO    }, \
+    { KC_##K18, KC_NO,    KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_NO    }, \
+    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO    }, \
+    { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_NO    }, \
+    { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_NO    }, \
+    { KC_##K38, KC_NO,    KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_NO    }, \
+    { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_NO    }, \
+    { KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_NO    }, \
+    { KC_##K50, KC_##K51, KC_##K52, KC_NO,    KC_##K54, KC_##K55, KC_NO,    KC_##K57 }, \
+    { KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_NO,    KC_##K5D, KC_NO,    KC_##K5F }, \
+    { KC_NO,    KC_##K61, KC_NO,    KC_NO,    KC_##K64, KC_NO,    KC_##K66, KC_##K67 }, \
+    { KC_NO,    KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C, KC_NO,    KC_NO,    KC_NO    }, \
+    { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \
+    { KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_##K7E, KC_NO    }, \
+    { KC_NO,    KC_NO,    KC_NO,    KC_##K83, KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
+    { KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
+    { KC_##K90, KC_##K91, KC_NO,    KC_NO,    KC_##K94, KC_##K95, KC_NO,    KC_NO    }, \
+    { KC_##K98, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_##K9F }, \
+    { KC_##KA0, KC_##KA1, KC_NO,    KC_##KA3, KC_NO,    KC_NO,    KC_NO,    KC_##KA7 }, \
+    { KC_##KA8, KC_NO,    KC_NO,    KC_##KAB, KC_NO,    KC_NO,    KC_NO,    KC_##KAF }, \
+    { KC_##KB0, KC_NO,    KC_##KB2, KC_NO,    KC_##KB4, KC_NO,    KC_NO,    KC_##KB7 }, \
+    { KC_##KB8, KC_NO,    KC_##KBA, KC_##KBB, KC_NO,    KC_NO,    KC_NO,    KC_##KBF }, \
+    { KC_##KC0, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
+    { KC_##KC8, KC_NO,    KC_##KCA, KC_NO,    KC_NO,    KC_##KCD, KC_NO,    KC_NO    }, \
+    { KC_##KD0, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
+    { KC_NO,    KC_NO,    KC_##KDA, KC_NO,    KC_NO,    KC_NO,    KC_##KDE, KC_NO    }, \
+    { KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO    }, \
+    { KC_NO,    KC_##KE9, KC_NO,    KC_##KEB, KC_##KEC, KC_NO,    KC_NO,    KC_NO    }, \
+    { KC_##KF0, KC_##KF1, KC_##KF2, KC_NO,    KC_##KF4, KC_##KF5, KC_NO,    KC_NO    }, \
+    { KC_NO,    KC_NO,    KC_##KFA, KC_NO,    KC_##KFC, KC_##KFD, KC_##KFE, KC_NO    }, \
+}
+
+/* US layout */
+#define KEYMAP( \
+    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
+    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
+    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
+    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
+    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
+    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA  \
+) \
+KEYMAP_ALL( \
+    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
+    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
+    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
+    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
+    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
+    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
+                                                                                            \
+    NUBS,                                                                                   \
+    RO, KANA, JYEN, HENK, MHEN,                                                             \
+    F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,                             \
+    SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE,                                                \
+    AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN,                                               \
+    MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT,         \
+    MAIL, CALCULATOR, MY_COMPUTER,                                                          \
+    WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD,                                            \
+    WWW_STOP, WWW_REFRESH, WWW_FAVORITES                                                    \
+)
+
+/* ISO layout */
+#define KEYMAP_ISO( \
+    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
+    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
+    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,     KF1,KE9,KFA,  K6C,K75,K7D,     \
+    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,K5A,               K6B,K73,K74,K79, \
+    K12,K61,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,    K59,     KF5,      K69,K72,K7A,     \
+    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA  \
+) \
+KEYMAP_ALL( \
+    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
+    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
+    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
+    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
+    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
+    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
+                                                                                            \
+    K61,                                                                                    \
+    RO, KANA, JYEN, HENK, MHEN,                                                             \
+    F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,                             \
+    SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE,                                                \
+    AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN,                                               \
+    MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT,         \
+    MAIL, CALCULATOR, MY_COMPUTER,                                                          \
+    WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD,                                            \
+    WWW_STOP, WWW_REFRESH, WWW_FAVORITES                                                    \
+)
+
+/* JIS layout */
+#define KEYMAP_JIS( \
+    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,         KFC,K7E,KFE,                   \
+    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
+    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,         KF1,KE9,KFA,  K6C,K75,K7D,     \
+    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,    K5A,               K6B,K73,K74,K79, \
+    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51,        K59,     KF5,      K69,K72,K7A,     \
+    K14,K9F,K11,    K67,K29,K64,K13,            K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA  \
+) \
+KEYMAP_ALL( \
+    K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07,     KFC,K7E,KFE,                   \
+    K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD,  K77,KCA,K7C,K7B, \
+    K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA,  K6C,K75,K7D,     \
+    K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,    K5A,               K6B,K73,K74,K79, \
+    K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,        K59,     KF5,      K69,K72,K7A,     \
+    K14,K9F,K11,        K29,                K91,KA7,KAF,K94, KEB,KF2,KF4,  K70,    K71,KDA, \
+                                                                                            \
+    NUBS,                                                                                   \
+    K51, K13, K6A, K64, K67,                                                                \
+    F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,                             \
+    SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE,                                                \
+    AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN,                                               \
+    MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT,         \
+    MAIL, CALCULATOR, MY_COMPUTER,                                                          \
+    WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD,                                            \
+    WWW_STOP, WWW_REFRESH, WWW_FAVORITES                                                    \
+)
+
+#endif
diff --git a/converter/ps2_usb/keymap_plain.c b/converter/ps2_usb/keymap_plain.c
new file mode 100644 (file)
index 0000000..9c6e7d9
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "keymap_common.h"
+
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+    /* 0: default
+     * ,---.   ,---------------. ,---------------. ,---------------. ,-----------.     ,-----------.
+     * |Esc|   |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau|     |Pwr|Slp|Wak|
+     * `---'   `---------------' `---------------' `---------------' `-----------'     `-----------'
+     * ,-----------------------------------------------------------. ,-----------. ,---------------.
+     * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backspa| |Ins|Hom|PgU| |NmL|  /|  *|  -|
+     * |-----------------------------------------------------------| |-----------| |---------------|
+     * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|    \| |Del|End|PgD| |  7|  8|  9|   |
+     * |-----------------------------------------------------------| `-----------' |-----------|  +|
+     * |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return  |               |  4|  5|  6|   |
+     * |-----------------------------------------------------------|     ,---.     |---------------|
+     * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shift     |     |Up |     |  1|  2|  3|   |
+     * |-----------------------------------------------------------| ,-----------. |-----------|Ent|
+     * |Ctrl |Gui |Alt |         Space         |Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| |      0|  .|   |
+     * `-----------------------------------------------------------' `-----------' `---------------'
+     * ; = Fn0(to Layer 5)
+     * / = Fn1(to Layer 6)
+     */
+    KEYMAP(
+    ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,           PSCR,SLCK,BRK,
+    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,     INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS,
+    TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,     DEL, END, PGDN,    P7,  P8,  P9,
+    CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     ENT,                         P4,  P5,  P6,  PPLS,
+    LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,          RSFT,          UP,           P1,  P2,  P3,
+    LCTL,LGUI,LALT,          SPC,                     RALT,RGUI,APP, RCTL,     LEFT,DOWN,RGHT,    P0,       PDOT,PENT
+    ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
index 4187ea060122455adc0cb863f2a92cd885f5059d..45344c0f759c20aa3491bd7972bce228efddbe6b 100644 (file)
@@ -19,6 +19,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdbool.h>
 #include <avr/io.h>
 #include <util/delay.h>
+#include "action.h"
 #include "print.h"
 #include "util.h"
 #include "debug.h"
@@ -28,6 +29,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 static void matrix_make(uint8_t code);
 static void matrix_break(uint8_t code);
+static void matrix_clear(void);
 #ifdef MATRIX_HAS_GHOST
 static bool matrix_has_ghost_in_row(uint8_t row);
 #endif
@@ -83,6 +85,7 @@ uint8_t matrix_cols(void)
 
 void matrix_init(void)
 {
+    debug_enable = true;
     ps2_host_init();
 
     // initialize matrix state: all keys off
@@ -185,8 +188,8 @@ uint8_t matrix_scan(void)
         matrix_break(PAUSE);
     }
 
-    uint8_t code;
-    while ((code = ps2_host_recv())) {
+    uint8_t code = ps2_host_recv();
+    if (!ps2_error) {
         switch (state) {
             case INIT:
                 switch (code) {
@@ -207,11 +210,19 @@ uint8_t matrix_scan(void)
                         matrix_make(PRINT_SCREEN);
                         state = INIT;
                         break;
+                    case 0x00:  // Overrun [3]p.25
+                        matrix_clear();
+                        clear_keyboard();
+                        print("Overrun\n");
+                        state = INIT;
+                        break;
                     default:    // normal key make
                         if (code < 0x80) {
                             matrix_make(code);
                         } else {
-                            debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n");
+                            matrix_clear();
+                            clear_keyboard();
+                            xprintf("unexpected scan code at INIT: %02X\n", code);
                         }
                         state = INIT;
                 }
@@ -232,7 +243,9 @@ uint8_t matrix_scan(void)
                         if (code < 0x80) {
                             matrix_make(code|0x80);
                         } else {
-                            debug("unexpected scan code at E0: "); debug_hex(code); debug("\n");
+                            matrix_clear();
+                            clear_keyboard();
+                            xprintf("unexpected scan code at E0: %02X\n", code);
                         }
                         state = INIT;
                 }
@@ -247,11 +260,18 @@ uint8_t matrix_scan(void)
                         matrix_break(PRINT_SCREEN);
                         state = INIT;
                         break;
+                    case 0xF0:
+                        matrix_clear();
+                        clear_keyboard();
+                        xprintf("unexpected scan code at F0: F0(clear and cont.)\n");
+                        break;
                     default:
                     if (code < 0x80) {
                         matrix_break(code);
                     } else {
-                        debug("unexpected scan code at F0: "); debug_hex(code); debug("\n");
+                        matrix_clear();
+                        clear_keyboard();
+                        xprintf("unexpected scan code at F0: %02X\n", code);
                     }
                     state = INIT;
                 }
@@ -266,7 +286,9 @@ uint8_t matrix_scan(void)
                         if (code < 0x80) {
                             matrix_break(code|0x80);
                         } else {
-                            debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n");
+                            matrix_clear();
+                            clear_keyboard();
+                            xprintf("unexpected scan code at E0_F0: %02X\n", code);
                         }
                         state = INIT;
                 }
@@ -357,8 +379,15 @@ uint8_t matrix_scan(void)
             default:
                 state = INIT;
         }
-        phex(code);
     }
+
+    // TODO: request RESEND when error occurs?
+/*
+    if (PS2_IS_FAILED(ps2_error)) {
+        uint8_t ret = ps2_host_send(PS2_RESEND);
+        xprintf("Resend: %02X\n", ret);
+    }
+*/
     return 1;
 }
 
@@ -450,3 +479,9 @@ static void matrix_break(uint8_t code)
         is_modified = true;
     }
 }
+
+inline
+static void matrix_clear(void)
+{
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
+}
diff --git a/keyboard/onekey/Makefile b/keyboard/onekey/Makefile
new file mode 100644 (file)
index 0000000..78732e4
--- /dev/null
@@ -0,0 +1,132 @@
+#----------------------------------------------------------------------------
+# 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 = onekey_lufa
+
+# Directory common source filess exist
+TOP_DIR = ../..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC =  keymap.c \
+       matrix.c \
+       led.c
+
+CONFIG_H = config.h
+
+
+# MCU name
+#MCU = at90usb1287
+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(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# 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(+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
+
+#PS2_MOUSE_ENABLE = yes  # PS/2 mouse(TrackPoint) support
+#PS2_USE_BUSYWAIT = yes # uses primitive reference code
+#PS2_USE_INT = yes      # uses external interrupt for falling edge of PS/2 clock pin
+#PS2_USE_USART = yes     # uses hardware USART engine for PS/2 signal receive(recomened)
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TOP_DIR)
+
+include $(TOP_DIR)/common.mk
+include $(TOP_DIR)/protocol.mk
+include $(TOP_DIR)/protocol/lufa.mk
+include $(TOP_DIR)/rules.mk
diff --git a/keyboard/onekey/Makefile.lufa b/keyboard/onekey/Makefile.lufa
deleted file mode 100644 (file)
index 60a84ba..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-#----------------------------------------------------------------------------
-# 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 = onekey_lufa
-
-# Directory common source filess exist
-TOP_DIR = ../..
-
-# Directory keyboard dependent files exist
-TARGET_DIR = .
-
-# project specific files
-SRC =  keymap.c \
-       matrix.c \
-       led.c
-
-CONFIG_H = config.h
-
-
-# MCU name
-#MCU = at90usb1287
-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(+60)
-OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
-
-
-# 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(+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
-
-PS2_MOUSE_ENABLE = yes  # PS/2 mouse(TrackPoint) support
-PS2_USE_BUSYWAIT = yes # uses primitive reference code
-#PS2_USE_INT = yes      # uses external interrupt for falling edge of PS/2 clock pin
-#PS2_USE_USART = yes     # uses hardware USART engine for PS/2 signal receive(recomened)
-
-
-# Search Path
-VPATH += $(TARGET_DIR)
-VPATH += $(TOP_DIR)
-
-include $(TOP_DIR)/common.mk
-include $(TOP_DIR)/protocol.mk
-include $(TOP_DIR)/protocol/lufa.mk
-include $(TOP_DIR)/rules.mk
index 6ccc999299f82f6f9c787bcfb977e5d341256cdc..7413f3880eba54a081b0e16158f81320ae42632a 100644 (file)
@@ -1,5 +1,5 @@
 Onekey
 ======
-Just one key keyboard for example. It sends 'a' key if pins PD0 and PD1 are short-circuited.
+Just one key keyboard for example. It sends 'a' key if pins PB0 and PB1 are short-circuited.
 
 https://github.com/tmk/tmk_keyboard/issues/56
index 1d2e052bf0961ced26e0aac96ca2bf62c07afa98..bf1d2b1ed3aaee62b087ae5eea3ef7e83429c13e 100644 (file)
@@ -73,7 +73,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #   define PS2_CLOCK_PORT  PORTD
 #   define PS2_CLOCK_PIN   PIND
 #   define PS2_CLOCK_DDR   DDRD
-#   define PS2_CLOCK_BIT   5
+#   define PS2_CLOCK_BIT   1
 #   define PS2_DATA_PORT   PORTD
 #   define PS2_DATA_PIN    PIND
 #   define PS2_DATA_DDR    DDRD
@@ -87,7 +87,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define PS2_CLOCK_PORT  PORTD
 #define PS2_CLOCK_PIN   PIND
 #define PS2_CLOCK_DDR   DDRD
-#define PS2_CLOCK_BIT   5
+#define PS2_CLOCK_BIT   1
 #define PS2_DATA_PORT   PORTD
 #define PS2_DATA_PIN    PIND
 #define PS2_DATA_DDR    DDRD
index a0a14ff82191476781d1620cab604de35cc5ab99..29df868321955daf5327eef9f61855011c35d05e 100644 (file)
@@ -139,29 +139,29 @@ uint8_t matrix_key_count(void)
 
 /* Column pin configuration
  * col: 0
- * pin: D0
+ * pin: B0
  */
 static void  init_cols(void)
 {
     // Input with pull-up(DDR:0, PORT:1)
-    DDRD  &= ~(1<<0);
-    PORTD |=  (1<<0);
+    DDRB  &= ~(1<<0);
+    PORTB |=  (1<<0);
 }
 
 static matrix_row_t read_cols(void)
 {
-    return (PIND&(1<<0) ? 0 : (1<<0));
+    return (PINB&(1<<0) ? 0 : (1<<0));
 }
 
 /* Row pin configuration
  * row: 0
- * pin: D1
+ * pin: B1
  */
 static void unselect_rows(void)
 {
     // Hi-Z(DDR:0, PORT:0) to unselect
-    DDRD  &= ~0b00000010;
-    PORTD &= ~0b00000010;
+    DDRB  &= ~0b00000010;
+    PORTB &= ~0b00000010;
 }
 
 static void select_row(uint8_t row)
@@ -169,8 +169,8 @@ static void select_row(uint8_t row)
     // Output low(DDR:1, PORT:0) to select
     switch (row) {
         case 0:
-            DDRD  |= (1<<1);
-            PORTD &= ~(1<<1);
+            DDRB  |= (1<<1);
+            PORTB &= ~(1<<1);
             break;
     }
 }
index 0d5f06c7ecbb05008ae44bf8a3245af0c1ab25b4..7f561e62d60dc0a5dc7c49ca0cb9a9fee25d781e 100644 (file)
@@ -8,12 +8,12 @@ ifdef PS2_MOUSE_ENABLE
 endif
 
 ifdef PS2_USE_BUSYWAIT
-    SRC += protocol/ps2.c
+    SRC += protocol/ps2_busywait.c
     OPT_DEFS += -DPS2_USE_BUSYWAIT
 endif
 
 ifdef PS2_USE_INT
-    SRC += protocol/ps2.c
+    SRC += protocol/ps2_interrupt.c
     OPT_DEFS += -DPS2_USE_INT
 endif
 
index 04e8e78f381fd9f821be2a45aea3b9bcab4cee2a..eca51c8784f2f37dd54301ee3c4822a42abd8e08 100644 (file)
@@ -148,7 +148,6 @@ static void Console_Task(void)
 */
 void EVENT_USB_Device_Connect(void)
 {
-    led_set(0x1f);  // all on
 }
 
 void EVENT_USB_Device_Disconnect(void)
@@ -172,8 +171,9 @@ void EVENT_USB_Device_WakeUp()
 
 #ifdef SLEEP_LED_ENABLE
     sleep_led_disable();
-#endif
+    // NOTE: converters may not accept this
     led_set(host_keyboard_leds());
+#endif
 }
 
 void EVENT_USB_Device_StartOfFrame(void)
index 84c99972f201bd165051798a2b70fdd96ccb7a15..393b36f78e04048a87ec1a6c49e92e1927c03a5f 100644 (file)
@@ -662,8 +662,9 @@ ISR(USB_GEN_vect)
             suspend_wakeup_init();
 #ifdef SLEEP_LED_ENABLE
             sleep_led_disable();
-#endif
+            // NOTE: converters may not accept this
             led_set(host_keyboard_leds());
+#endif
 
             UDIEN |= (1<<SUSPE);
             UDIEN &= ~(1<<WAKEUPE);
diff --git a/protocol/ps2.c b/protocol/ps2.c
deleted file mode 100644 (file)
index e5873a9..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
-Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
-
-This software is licensed with a Modified BSD License.
-All of this is supposed to be Free Software, Open Source, DFSG-free,
-GPL-compatible, and OK to use in both free and proprietary applications.
-Additions and corrections to this file are welcome.
-
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
-  notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright
-  notice, this list of conditions and the following disclaimer in
-  the documentation and/or other materials provided with the
-  distribution.
-
-* Neither the name of the copyright holders nor the names of
-  contributors may be used to endorse or promote products derived
-  from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdbool.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include "ps2.h"
-#include "debug.h"
-
-
-#ifndef PS2_USE_INT
-static uint8_t recv_data(void);
-#endif
-static inline void clock_lo(void);
-static inline void clock_hi(void);
-static inline bool clock_in(void);
-static inline void data_lo(void);
-static inline void data_hi(void);
-static inline bool data_in(void);
-static inline uint16_t wait_clock_lo(uint16_t us);
-static inline uint16_t wait_clock_hi(uint16_t us);
-static inline uint16_t wait_data_lo(uint16_t us);
-static inline uint16_t wait_data_hi(uint16_t us);
-static inline void idle(void);
-static inline void inhibit(void);
-
-
-/*
-Primitive PS/2 Library for AVR
-==============================
-Host side is only supported now.
-
-
-I/O control
------------
-High state is asserted by input with pull up.
-
-
-PS/2 References
----------------
-http://www.computer-engineering.org/ps2protocol/
-http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
-*/
-
-
-#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)
-{
-#ifdef PS2_USE_INT
-    PS2_INT_INIT();
-    PS2_INT_ON();
-    idle();
-#else
-    inhibit();
-#endif
-}
-
-// TODO: send using interrupt if available
-uint8_t ps2_host_send(uint8_t data)
-{
-    uint8_t res = 0;
-    bool parity = true;
-    ps2_error = PS2_ERR_NONE;
-#ifdef PS2_USE_INT
-    PS2_INT_OFF();
-#endif
-    /* terminate a transmission if we have */
-    inhibit();
-    _delay_us(200); // at least 100us
-
-    /* start bit [1] */
-    data_lo();
-    clock_hi();
-    WAIT(clock_lo, 20000, 10);   // may take 15ms at most until device starts clocking
-    /* data [2-9] */
-    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 [10] */
-    _delay_us(15);
-    if (parity) { data_hi(); } else { data_lo(); }
-    WAIT(clock_hi, 50, 4);
-    WAIT(clock_lo, 50, 5);
-    /* stop bit [11] */
-    _delay_us(15);
-    data_hi();
-    /* ack [12] */
-    WAIT(data_lo, 50, 6);
-    WAIT(clock_lo, 50, 7);
-
-    /* wait for idle state */
-    WAIT(clock_hi, 50, 8);
-    WAIT(data_hi, 50, 9);
-
-#ifdef PS2_USE_INT
-    PS2_INT_ON();
-#endif
-    res = ps2_host_recv_response();
-ERROR:
-#ifdef PS2_USE_INT
-    PS2_INT_ON();
-    idle();
-#else
-    inhibit();
-#endif
-    return res;
-}
-
-#ifndef PS2_USE_INT
-/* receive data when host want else inhibit communication */
-uint8_t ps2_host_recv_response(void)
-{
-    uint8_t data = 0;
-
-#ifdef PS2_USE_INT
-    PS2_INT_OFF();
-#endif
-    /* terminate a transmission if we have */
-    inhibit();
-    _delay_us(100);
-
-    /* release lines(idle state) */
-    idle();
-
-    /* wait start bit */
-    wait_clock_lo(25000);    // command response may take 20 ms at most
-    data = recv_data();
-
-    inhibit();
-    return data;
-}
-#endif
-
-#ifndef PS2_USE_INT
-uint8_t ps2_host_recv(void)
-{
-    return ps2_host_recv_response();
-}
-#else
-/* ring buffer to store ps/2 key data */
-#define PBUF_SIZE 32
-static uint8_t pbuf[PBUF_SIZE];
-static uint8_t pbuf_head = 0;
-static uint8_t pbuf_tail = 0;
-static inline void pbuf_enqueue(uint8_t data)
-{
-    uint8_t sreg = SREG;
-    cli();
-    uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
-    if (next != pbuf_tail) {
-        pbuf[pbuf_head] = data;
-        pbuf_head = next;
-    } else {
-        debug("pbuf: full\n");
-    }
-    SREG = sreg;
-}
-static inline uint8_t pbuf_dequeue(void)
-{
-    uint8_t val = 0;
-
-    uint8_t sreg = SREG;
-    cli();
-    if (pbuf_head != pbuf_tail) {
-        val = pbuf[pbuf_tail];
-        pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
-    }
-    SREG = sreg;
-
-    return val;
-}
-static inline bool pbuf_has_data(void)
-{
-    uint8_t sreg = SREG;
-    cli();
-    bool has_data = (pbuf_head != pbuf_tail);
-    SREG = sreg;
-    return has_data;
-}
-static inline void pbuf_clear(void)
-{
-    uint8_t sreg = SREG;
-    cli();
-    pbuf_head = pbuf_tail = 0;
-    SREG = sreg;
-}
-
-/* get data received by interrupt */
-uint8_t ps2_host_recv(void)
-{
-    if (ps2_error) {
-        print("x");
-        phex(ps2_error);
-        ps2_host_send(0xFE);    // request to resend
-        ps2_error = PS2_ERR_NONE;
-    }
-    idle();
-    return pbuf_dequeue();
-}
-
-uint8_t ps2_host_recv_response(void)
-{
-    while (!pbuf_has_data()) ;
-    return pbuf_dequeue();
-}
-
-ISR(PS2_INT_VECT)
-{
-    static enum {
-        INIT,
-        START,
-        BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
-        PARITY,
-        STOP,
-    } state = INIT;
-    static uint8_t data = 0;
-    static uint8_t parity = 1;
-
-    // TODO: abort if elapse 100us from previous interrupt
-
-    // return unless falling edge
-    if (clock_in()) {
-        goto RETURN;
-    }
-
-    state++;
-    switch (state) {
-        case START:
-            if (data_in())
-                goto ERROR;
-            break;
-        case BIT0:
-        case BIT1:
-        case BIT2:
-        case BIT3:
-        case BIT4:
-        case BIT5:
-        case BIT6:
-        case BIT7:
-            data >>= 1;
-            if (data_in()) {
-                data |= 0x80;
-                parity++;
-            }
-            break;
-        case PARITY:
-            if (data_in()) {
-                if (!(parity & 0x01))
-                    goto ERROR;
-            } else {
-                if (parity & 0x01)
-                    goto ERROR;
-            }
-            break;
-        case STOP:
-            if (!data_in())
-                goto ERROR;
-            pbuf_enqueue(data);
-//phex(data);
-            goto DONE;
-            break;
-        default:
-            goto ERROR;
-    }
-    goto RETURN;
-ERROR:
-    inhibit();
-    ps2_error = state;
-DONE:
-    state = INIT;
-    data = 0;
-    parity = 1;
-RETURN:
-    return;
-}
-#endif
-
-
-/* send LED state to keyboard */
-void ps2_host_set_led(uint8_t led)
-{
-    ps2_host_send(0xED);
-    ps2_host_send(led);
-}
-
-
-#ifndef PS2_USE_INT
-/* called after start bit comes */
-static uint8_t recv_data(void)
-{
-    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;
-    }
-    WAIT(clock_hi, 50, 7);
-
-    /* stop bit [11] */
-    WAIT(clock_lo, 50, 8);
-    WAIT(data_hi, 1, 9);
-    WAIT(clock_hi, 50, 10);
-
-    return data;
-ERROR:
-    return 0;
-}
-#endif
-
-static inline void clock_lo()
-{
-    PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
-    PS2_CLOCK_DDR  |=  (1<<PS2_CLOCK_BIT);
-}
-static inline void clock_hi()
-{
-    /* input with pull up */
-    PS2_CLOCK_DDR  &= ~(1<<PS2_CLOCK_BIT);
-    PS2_CLOCK_PORT |=  (1<<PS2_CLOCK_BIT);
-}
-static inline bool clock_in()
-{
-    PS2_CLOCK_DDR  &= ~(1<<PS2_CLOCK_BIT);
-    PS2_CLOCK_PORT |=  (1<<PS2_CLOCK_BIT);
-    _delay_us(1);
-    return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
-}
-static inline void data_lo()
-{
-    PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
-    PS2_DATA_DDR  |=  (1<<PS2_DATA_BIT);
-}
-static inline void data_hi()
-{
-    /* input with pull up */
-    PS2_DATA_DDR  &= ~(1<<PS2_DATA_BIT);
-    PS2_DATA_PORT |=  (1<<PS2_DATA_BIT);
-}
-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();
-}
index 834165356c249ebedfd88509637a5c390559e131..483eea7209a769d10790f19952728f974ab72ccf 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright 2010,2011 Jun WAKO <wakojun@gmail.com>
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
 
 This software is licensed with a Modified BSD License.
 All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -37,32 +37,46 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef PS2_H
 #define PS2_H
+
+#include <stdbool.h>
+#include <util/delay.h>
+#include <avr/io.h>
+
 /*
  * Primitive PS/2 Library for AVR
+ *
+ * PS/2 Resources
+ * --------------
+ * [1] The PS/2 Mouse/Keyboard Protocol
+ * http://www.computer-engineering.org/ps2protocol/
+ * Concise and thorough primer of PS/2 protocol.
+ *
+ * [2] Keyboard and Auxiliary Device Controller
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Signal Timing and Format
+ *
+ * [3] Keyboards(101- and 102-key)
+ * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
+ * Keyboard Layout, Scan Code Set, POR, and Commands.
+ *
+ * [4] PS/2 Reference Manuals
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Collection of IBM Personal System/2 documents.
+ *
+ * [5] TrackPoint Engineering Specifications for version 3E
+ * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
  */
-
-
-/* port settings for clock and data line */
-#if !(defined(PS2_CLOCK_PORT) && \
-      defined(PS2_CLOCK_PIN) && \
-      defined(PS2_CLOCK_DDR) && \
-      defined(PS2_CLOCK_BIT))
-#   error "PS/2 clock port setting is required in config.h"
-#endif
-
-#if !(defined(PS2_DATA_PORT) && \
-      defined(PS2_DATA_PIN) && \
-      defined(PS2_DATA_DDR) && \
-      defined(PS2_DATA_BIT))
-#   error "PS/2 data port setting is required in config.h"
-#endif
-
 #define PS2_ACK         0xFA
 #define PS2_RESEND      0xFE
 #define PS2_SET_LED     0xED
 
-#define PS2_ERR_NONE    0
-#define PS2_ERR_PARITY  0x10
+// TODO: error numbers
+#define PS2_ERR_NONE        0
+#define PS2_ERR_STARTBIT1   1
+#define PS2_ERR_STARTBIT2   2
+#define PS2_ERR_STARTBIT3   3
+#define PS2_ERR_PARITY      0x10
+#define PS2_ERR_NODATA      0x20
 
 #define PS2_LED_SCROLL_LOCK 0
 #define PS2_LED_NUM_LOCK    1
@@ -71,13 +85,101 @@ POSSIBILITY OF SUCH DAMAGE.
 
 extern uint8_t ps2_error;
 
-/* host role */
 void ps2_host_init(void);
 uint8_t ps2_host_send(uint8_t data);
 uint8_t ps2_host_recv_response(void);
 uint8_t ps2_host_recv(void);
 void ps2_host_set_led(uint8_t usb_led);
 
-/* device role */
+
+/* Check port settings for clock and data line */
+#if !(defined(PS2_CLOCK_PORT) && \
+      defined(PS2_CLOCK_PIN) && \
+      defined(PS2_CLOCK_DDR) && \
+      defined(PS2_CLOCK_BIT))
+#   error "PS/2 clock port setting is required in config.h"
+#endif
+
+#if !(defined(PS2_DATA_PORT) && \
+      defined(PS2_DATA_PIN) && \
+      defined(PS2_DATA_DDR) && \
+      defined(PS2_DATA_BIT))
+#   error "PS/2 data port setting is required in config.h"
+#endif
+
+/*--------------------------------------------------------------------
+ * static functions
+ *------------------------------------------------------------------*/
+static inline void clock_lo(void)
+{
+    PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
+    PS2_CLOCK_DDR  |=  (1<<PS2_CLOCK_BIT);
+}
+static inline void clock_hi(void)
+{
+    /* input with pull up */
+    PS2_CLOCK_DDR  &= ~(1<<PS2_CLOCK_BIT);
+    PS2_CLOCK_PORT |=  (1<<PS2_CLOCK_BIT);
+}
+static inline bool clock_in(void)
+{
+    PS2_CLOCK_DDR  &= ~(1<<PS2_CLOCK_BIT);
+    PS2_CLOCK_PORT |=  (1<<PS2_CLOCK_BIT);
+    _delay_us(1);
+    return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
+}
+static inline void data_lo(void)
+{
+    PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
+    PS2_DATA_DDR  |=  (1<<PS2_DATA_BIT);
+}
+static inline void data_hi(void)
+{
+    /* input with pull up */
+    PS2_DATA_DDR  &= ~(1<<PS2_DATA_BIT);
+    PS2_DATA_PORT |=  (1<<PS2_DATA_BIT);
+}
+static inline bool data_in(void)
+{
+    PS2_DATA_DDR  &= ~(1<<PS2_DATA_BIT);
+    PS2_DATA_PORT |=  (1<<PS2_DATA_BIT);
+    _delay_us(1);
+    return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
+}
+
+static inline uint16_t wait_clock_lo(uint16_t us)
+{
+    while (clock_in()  && us) { asm(""); _delay_us(1); us--; }
+    return us;
+}
+static inline uint16_t wait_clock_hi(uint16_t us)
+{
+    while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
+    return us;
+}
+static inline uint16_t wait_data_lo(uint16_t us)
+{
+    while (data_in() && us)  { asm(""); _delay_us(1); us--; }
+    return us;
+}
+static inline uint16_t wait_data_hi(uint16_t us)
+{
+    while (!data_in() && us)  { asm(""); _delay_us(1); us--; }
+    return us;
+}
+
+/* idle state that device can send */
+static inline void idle(void)
+{
+    clock_hi();
+    data_hi();
+}
+
+/* inhibit device to send */
+static inline void inhibit(void)
+{
+    clock_lo();
+    data_hi();
+}
 
 #endif
diff --git a/protocol/ps2_busywait.c b/protocol/ps2_busywait.c
new file mode 100644 (file)
index 0000000..05dd7b2
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+* Neither the name of the copyright holders nor the names of
+  contributors may be used to endorse or promote products derived
+  from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * PS/2 protocol busywait version
+ */
+
+#include <stdbool.h>
+#include <util/delay.h>
+#include "ps2.h"
+#include "debug.h"
+
+
+#define WAIT(stat, us, err) do { \
+    if (!wait_##stat(us)) { \
+        ps2_error = err; \
+        goto ERROR; \
+    } \
+} while (0)
+
+
+uint8_t ps2_error = PS2_ERR_NONE;
+
+
+void ps2_host_init(void)
+{
+    // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+    _delay_ms(2500);
+
+    inhibit();
+}
+
+uint8_t ps2_host_send(uint8_t data)
+{
+    bool parity = true;
+    ps2_error = PS2_ERR_NONE;
+
+    /* terminate a transmission if we have */
+    inhibit();
+    _delay_us(100); // 100us [4]p.13, [5]p.50
+
+    /* 'Request to Send' and Start bit */
+    data_lo();
+    clock_hi();
+    WAIT(clock_lo, 10000, 10);   // 10ms [5]p.50
+
+    /* Data bit */
+    for (uint8_t i = 0; i < 8; i++) {
+        _delay_us(15);
+        if (data&(1<<i)) {
+            parity = !parity;
+            data_hi();
+        } else {
+            data_lo();
+        }
+        WAIT(clock_hi, 50, 2);
+        WAIT(clock_lo, 50, 3);
+    }
+
+    /* Parity bit */
+    _delay_us(15);
+    if (parity) { data_hi(); } else { data_lo(); }
+    WAIT(clock_hi, 50, 4);
+    WAIT(clock_lo, 50, 5);
+
+    /* Stop bit */
+    _delay_us(15);
+    data_hi();
+
+    /* Ack */
+    WAIT(data_lo, 50, 6);
+    WAIT(clock_lo, 50, 7);
+
+    /* wait for idle state */
+    WAIT(clock_hi, 50, 8);
+    WAIT(data_hi, 50, 9);
+
+    inhibit();
+    return ps2_host_recv_response();
+ERROR:
+    inhibit();
+    return 0;
+}
+
+/* receive data when host want else inhibit communication */
+uint8_t ps2_host_recv_response(void)
+{
+    // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+    // 250 * 100us(wait for start bit in ps2_host_recv)
+    uint8_t data = 0;
+    uint8_t try = 250;
+    do {
+        data = ps2_host_recv();
+    } while (try-- && ps2_error);
+    return data;
+}
+
+/* called after start bit comes */
+uint8_t ps2_host_recv(void)
+{
+    uint8_t data = 0;
+    bool parity = true;
+    ps2_error = PS2_ERR_NONE;
+
+    /* release lines(idle state) */
+    idle();
+
+    /* start bit [1] */
+    WAIT(clock_lo, 100, 1); // TODO: this is enough?
+    WAIT(data_lo, 1, 2);
+    WAIT(clock_hi, 50, 3);
+
+    /* data [2-9] */
+    for (uint8_t i = 0; i < 8; i++) {
+        WAIT(clock_lo, 50, 4);
+        if (data_in()) {
+            parity = !parity;
+            data |= (1<<i);
+        }
+        WAIT(clock_hi, 50, 5);
+    }
+
+    /* parity [10] */
+    WAIT(clock_lo, 50, 6);
+    if (data_in() != parity) {
+        ps2_error = PS2_ERR_PARITY;
+        goto ERROR;
+    }
+    WAIT(clock_hi, 50, 7);
+
+    /* stop bit [11] */
+    WAIT(clock_lo, 50, 8);
+    WAIT(data_hi, 1, 9);
+    WAIT(clock_hi, 50, 10);
+
+    inhibit();
+    return data;
+ERROR:
+    if (ps2_error > PS2_ERR_STARTBIT3) {
+        xprintf("x%02X\n", ps2_error);
+    }
+    inhibit();
+    return 0;
+}
+
+/* send LED state to keyboard */
+void ps2_host_set_led(uint8_t led)
+{
+    ps2_host_send(0xED);
+    ps2_host_send(led);
+}
diff --git a/protocol/ps2_interrupt.c b/protocol/ps2_interrupt.c
new file mode 100644 (file)
index 0000000..259d254
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+* Neither the name of the copyright holders nor the names of
+  contributors may be used to endorse or promote products derived
+  from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * PS/2 protocol Pin interrupt version
+ */
+
+#include <stdbool.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "ps2.h"
+#include "print.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;
+
+
+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)
+{
+    idle();
+    PS2_INT_INIT();
+    PS2_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)
+{
+    bool parity = true;
+    ps2_error = PS2_ERR_NONE;
+
+    PS2_INT_OFF();
+
+    /* 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[2-9] */
+    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);
+
+    idle();
+    PS2_INT_ON();
+    return ps2_host_recv_response();
+ERROR:
+    idle();
+    PS2_INT_ON();
+    return 0;
+}
+
+uint8_t ps2_host_recv_response(void)
+{
+    // 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();
+}
+
+/* get data received by interrupt */
+uint8_t ps2_host_recv(void)
+{
+    if (pbuf_has_data()) {
+        ps2_error = PS2_ERR_NONE;
+        return pbuf_dequeue();
+    } else {
+        ps2_error = PS2_ERR_NODATA;
+        return 0;
+    }
+}
+
+ISR(PS2_INT_VECT)
+{
+    static enum {
+        INIT,
+        START,
+        BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
+        PARITY,
+        STOP,
+    } state = INIT;
+    static uint8_t data = 0;
+    static uint8_t parity = 1;
+
+    // TODO: abort if elapse 100us from previous interrupt
+
+    // return unless falling edge
+    if (clock_in()) {
+        goto RETURN;
+    }
+
+    state++;
+    switch (state) {
+        case START:
+            if (data_in())
+                goto ERROR;
+            break;
+        case BIT0:
+        case BIT1:
+        case BIT2:
+        case BIT3:
+        case BIT4:
+        case BIT5:
+        case BIT6:
+        case BIT7:
+            data >>= 1;
+            if (data_in()) {
+                data |= 0x80;
+                parity++;
+            }
+            break;
+        case PARITY:
+            if (data_in()) {
+                if (!(parity & 0x01))
+                    goto ERROR;
+            } else {
+                if (parity & 0x01)
+                    goto ERROR;
+            }
+            break;
+        case STOP:
+            if (!data_in())
+                goto ERROR;
+            pbuf_enqueue(data);
+            goto DONE;
+            break;
+        default:
+            goto ERROR;
+    }
+    goto RETURN;
+ERROR:
+    ps2_error = state;
+DONE:
+    state = INIT;
+    data = 0;
+    parity = 1;
+RETURN:
+    return;
+}
+
+/* send LED state to keyboard */
+void ps2_host_set_led(uint8_t led)
+{
+    ps2_host_send(0xED);
+    ps2_host_send(led);
+}
+
+
+/*--------------------------------------------------------------------
+ * 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 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");
+    }
+    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;
+    }
+    SREG = sreg;
+
+    return val;
+}
+static inline bool pbuf_has_data(void)
+{
+    uint8_t sreg = SREG;
+    cli();
+    bool has_data = (pbuf_head != pbuf_tail);
+    SREG = sreg;
+    return has_data;
+}
+static inline void pbuf_clear(void)
+{
+    uint8_t sreg = SREG;
+    cli();
+    pbuf_head = pbuf_tail = 0;
+    SREG = sreg;
+}
+
index 40c46c497c54459bf4dbd7bb17ff99a334943111..c2d9d0a208d301cc71d8b2bdfcce6f652615fa5a 100644 (file)
@@ -36,32 +36,14 @@ POSSIBILITY OF SUCH DAMAGE.
 */
 
 /*
-Primitive PS/2 Library for AVR
-==============================
-Host side is only supported now.
-Synchronous USART is used to receive data by hardware process
-rather than interrupt. During V-USB interrupt runs, CLOCK interrupt
-cannot interpose. In the result it is prone to lost CLOCK edge.
+ * PS/2 protocol USART version
+ */
 
-
-I/O control
------------
-High state is asserted by internal pull-up.
-If you have a signaling problem, you may need to have
-external pull-up resisters on CLOCK and DATA line.
-
-
-PS/2 References
----------------
-http://www.computer-engineering.org/ps2protocol/
-http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
-*/
 #include <stdbool.h>
-#include <avr/io.h>
 #include <avr/interrupt.h>
 #include <util/delay.h>
 #include "ps2.h"
-#include "debug.h"
+#include "print.h"
 
 
 #define WAIT(stat, us, err) do { \
@@ -75,18 +57,6 @@ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
 uint8_t ps2_error = PS2_ERR_NONE;
 
 
-static inline void clock_lo(void);
-static inline void clock_hi(void);
-static inline bool clock_in(void);
-static inline void data_lo(void);
-static inline void data_hi(void);
-static inline bool data_in(void);
-static inline uint16_t wait_clock_lo(uint16_t us);
-static inline uint16_t wait_clock_hi(uint16_t us);
-static inline uint16_t wait_data_lo(uint16_t us);
-static inline uint16_t wait_data_hi(uint16_t us);
-static inline void idle(void);
-static inline void inhibit(void);
 static inline uint8_t pbuf_dequeue(void);
 static inline void pbuf_enqueue(uint8_t data);
 static inline bool pbuf_has_data(void);
@@ -95,14 +65,15 @@ static inline void pbuf_clear(void);
 
 void ps2_host_init(void)
 {
-    idle();
+    idle(); // without this many USART errors occur when cable is disconnected
     PS2_USART_INIT();
     PS2_USART_RX_INT_ON();
+    // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+    //_delay_ms(2500);
 }
 
 uint8_t ps2_host_send(uint8_t data)
 {
-    uint8_t res = 0;
     bool parity = true;
     ps2_error = PS2_ERR_NONE;
 
@@ -110,13 +81,14 @@ uint8_t ps2_host_send(uint8_t data)
 
     /* terminate a transmission if we have */
     inhibit();
-    _delay_us(100);
+    _delay_us(100); // [4]p.13
 
-    /* start bit [1] */
+    /* 'Request to Send' and Start bit */
     data_lo();
     clock_hi();
-    WAIT(clock_lo, 15000, 1);
-    /* data [2-9] */
+    WAIT(clock_lo, 10000, 10);   // 10ms [5]p.50
+
+    /* Data bit[2-9] */
     for (uint8_t i = 0; i < 8; i++) {
         _delay_us(15);
         if (data&(1<<i)) {
@@ -128,15 +100,18 @@ uint8_t ps2_host_send(uint8_t data)
         WAIT(clock_hi, 50, 2);
         WAIT(clock_lo, 50, 3);
     }
-    /* parity [10] */
+
+    /* Parity bit */
     _delay_us(15);
     if (parity) { data_hi(); } else { data_lo(); }
     WAIT(clock_hi, 50, 4);
     WAIT(clock_lo, 50, 5);
-    /* stop bit [11] */
+
+    /* Stop bit */
     _delay_us(15);
     data_hi();
-    /* ack [12] */
+
+    /* Ack */
     WAIT(data_lo, 50, 6);
     WAIT(clock_lo, 50, 7);
 
@@ -144,127 +119,55 @@ uint8_t ps2_host_send(uint8_t data)
     WAIT(clock_hi, 50, 8);
     WAIT(data_hi, 50, 9);
 
+    idle();
     PS2_USART_INIT();
     PS2_USART_RX_INT_ON();
-    res = ps2_host_recv_response();
+    return ps2_host_recv_response();
 ERROR:
     idle();
     PS2_USART_INIT();
     PS2_USART_RX_INT_ON();
-    return res;
+    return 0;
 }
 
-// Do polling data from keyboard to get response to last command.
 uint8_t ps2_host_recv_response(void)
 {
-    while (!pbuf_has_data()) {
-        _delay_ms(1);   // without this delay it seems to fall into deadlock
+    // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+    uint8_t retry = 25;
+    while (retry-- && !pbuf_has_data()) {
+        _delay_ms(1);
     }
     return pbuf_dequeue();
 }
 
 uint8_t ps2_host_recv(void)
 {
-    return pbuf_dequeue();
+    if (pbuf_has_data()) {
+        ps2_error = PS2_ERR_NONE;
+        return pbuf_dequeue();
+    } else {
+        ps2_error = PS2_ERR_NODATA;
+        return 0;
+    }
 }
 
 ISR(PS2_USART_RX_VECT)
 {
-    uint8_t error = PS2_USART_ERROR;
+    // TODO: request RESEND when error occurs?
+    uint8_t error = PS2_USART_ERROR;    // USART error should be read before data
     uint8_t data = PS2_USART_RX_DATA;
     if (!error) {
         pbuf_enqueue(data);
+    } else {
+        xprintf("PS2 USART error: %02X data: %02X\n", error, data);
     }
 }
 
 /* send LED state to keyboard */
 void ps2_host_set_led(uint8_t led)
 {
-    // send 0xED then keyboard keeps waiting for next LED data
-    // and keyboard does not send any scan codes during waiting.
-    // If fail to send LED data keyboard looks like being freezed.
-    uint8_t retry = 3;
-    while (retry-- && ps2_host_send(PS2_SET_LED) != PS2_ACK)
-        ;
-    retry = 3;
-    while (retry-- && ps2_host_send(led) != PS2_ACK)
-        ;
-}
-
-
-/*--------------------------------------------------------------------
- * static functions
- *------------------------------------------------------------------*/
-static inline void clock_lo()
-{
-    PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
-    PS2_CLOCK_DDR  |=  (1<<PS2_CLOCK_BIT);
-}
-static inline void clock_hi()
-{
-    /* input with pull up */
-    PS2_CLOCK_DDR  &= ~(1<<PS2_CLOCK_BIT);
-    PS2_CLOCK_PORT |=  (1<<PS2_CLOCK_BIT);
-}
-static inline bool clock_in()
-{
-    PS2_CLOCK_DDR  &= ~(1<<PS2_CLOCK_BIT);
-    PS2_CLOCK_PORT |=  (1<<PS2_CLOCK_BIT);
-    _delay_us(1);
-    return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
-}
-static inline void data_lo()
-{
-    PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
-    PS2_DATA_DDR  |=  (1<<PS2_DATA_BIT);
-}
-static inline void data_hi()
-{
-    /* input with pull up */
-    PS2_DATA_DDR  &= ~(1<<PS2_DATA_BIT);
-    PS2_DATA_PORT |=  (1<<PS2_DATA_BIT);
-}
-static inline bool data_in()
-{
-    PS2_DATA_DDR  &= ~(1<<PS2_DATA_BIT);
-    PS2_DATA_PORT |=  (1<<PS2_DATA_BIT);
-    _delay_us(1);
-    return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
-}
-
-static inline uint16_t wait_clock_lo(uint16_t us)
-{
-    while (clock_in()  && us) { asm(""); _delay_us(1); us--; }
-    return us;
-}
-static inline uint16_t wait_clock_hi(uint16_t us)
-{
-    while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
-    return us;
-}
-static inline uint16_t wait_data_lo(uint16_t us)
-{
-    while (data_in() && us)  { asm(""); _delay_us(1); us--; }
-    return us;
-}
-static inline uint16_t wait_data_hi(uint16_t us)
-{
-    while (!data_in() && us)  { asm(""); _delay_us(1); us--; }
-    return us;
-}
-
-/* idle state that device can send */
-static inline void idle(void)
-{
-    clock_hi();
-    data_hi();
-}
-
-/* inhibit device to send */
-static inline void inhibit(void)
-{
-    clock_lo();
-    data_hi();
+    ps2_host_send(0xED);
+    ps2_host_send(led);
 }
 
 
@@ -284,11 +187,10 @@ static inline void pbuf_enqueue(uint8_t data)
         pbuf[pbuf_head] = data;
         pbuf_head = next;
     } else {
-        debug("pbuf: full\n");
+        print("pbuf: full\n");
     }
     SREG = sreg;
 }
-
 static inline uint8_t pbuf_dequeue(void)
 {
     uint8_t val = 0;