summaryrefslogtreecommitdiffstats
path: root/converter/ibm4704_usb
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ibm4704_usb')
-rw-r--r--converter/ibm4704_usb/Makefile93
-rw-r--r--converter/ibm4704_usb/README.md62
-rw-r--r--converter/ibm4704_usb/config.h61
-rw-r--r--converter/ibm4704_usb/ibm4704.txt181
-rw-r--r--converter/ibm4704_usb/keymap_common.c30
-rw-r--r--converter/ibm4704_usb/keymap_common.h98
-rw-r--r--converter/ibm4704_usb/keymap_hasu.c85
-rw-r--r--converter/ibm4704_usb/keymap_plain.c38
-rw-r--r--converter/ibm4704_usb/led.c24
-rw-r--r--converter/ibm4704_usb/matrix.c165
10 files changed, 837 insertions, 0 deletions
diff --git a/converter/ibm4704_usb/Makefile b/converter/ibm4704_usb/Makefile
new file mode 100644
index 0000000000..b5c97d2d31
--- /dev/null
+++ b/converter/ibm4704_usb/Makefile
@@ -0,0 +1,93 @@
+# Target file name (without extension).
+TARGET = ibm4704_usb
+
+# Directory common source filess exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC = keymap_common.c \
+ matrix.c \
+ led.c \
+ protocol/ibm4704.c
+
+ifdef KEYMAP
+ SRC := keymap_$(KEYMAP).c $(SRC)
+else
+ SRC := keymap_plain.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# 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
+#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TMK_DIR)
+
+include $(TMK_DIR)/protocol.mk
+include $(TMK_DIR)/protocol/lufa.mk
+include $(TMK_DIR)/common.mk
+include $(TMK_DIR)/rules.mk
diff --git a/converter/ibm4704_usb/README.md b/converter/ibm4704_usb/README.md
new file mode 100644
index 0000000000..a3af4ab31d
--- /dev/null
+++ b/converter/ibm4704_usb/README.md
@@ -0,0 +1,62 @@
+IBM 4704 to USB keyboard converter
+==================================
+This firmware converts IBM 4704 keyboard protocol to USB HID.
+
+Keyboard initialization process takes a few seconds at start up. During that you will hear buzzer from the keyboard. **You need to plug USB cable after hooking up your keyboard to the converter.**
+
+
+Supported Keyboard
+------------------
+### IBM capacitive switch models:
+- 6019273 Model 100 50-key (grid layout) http://kishy.dyndns.org/?p=977
+- 6019284 Model 200 62-key Alpha(60% layout) http://kishy.dyndns.org/?p=894
+- 6019303 Model 300 77-key Expanded Alpha http://kbtalking.cool3c.com/article/23272
+- 6020218 Model 400 107-key Full key http://kishy.dyndns.org/?p=980
+
+### Alps switch(vintage Green) models:
+
+- 5954339 Japanese 102-key http://deskthority.net/post87127.html#p87127
+- 6112883 Japanese 102-key http://geekhack.org/index.php?topic=52888.msg1194489#msg1194489
+- 6112884 Japanese 102-key http://geekhack.org/index.php?topic=50437.msg1193047#msg1193047
+- 6341739 Chinese 102-key http://geekhack.org/index.php?topic=52888.msg1176566#msg1176566
+
+
+Connector
+---------
+Keyboard Plug from front:
+
+ DSUB-9
+ -------------
+ \ N 2 3 4 5 /
+ \ N N N N /
+ ---------
+ 2 GND
+ 3 VCC 5V
+ 4 DATA
+ 5 CLOCK
+ N No connection/No pin.
+
+
+Connection
+----------
+In case of using ATMega32U4(Teensy2.0):
+
+1. Supply power with VCC and GND.
+2. Connect CLOCK to PD1 and DATA to PD0. You can change pin with config.h.
+3. Optionally you may need pull-up register. 1KOhm probably work.
+
+
+Build Firmware
+--------------
+Just run `make`:
+
+ $ make
+
+To select keymap:
+
+ $ make KEYMAP=[plain|...]
+
+
+Keymap
+------
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `keymap_<name>.c` and see keymap document(you can find in top README.md) and existent keymap files.
diff --git a/converter/ibm4704_usb/config.h b/converter/ibm4704_usb/config.h
new file mode 100644
index 0000000000..4f267b3b7a
--- /dev/null
+++ b/converter/ibm4704_usb/config.h
@@ -0,0 +1,61 @@
+/*
+Copyright 2014 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <avr/interrupt.h>
+
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x4707
+#define DEVICE_VER 0x0001
+#define MANUFACTURER t.m.k.
+#define PRODUCT IBM 4704 keyboard converter
+#define DESCRIPTION convert IBM 4704 keyboard to USB
+
+
+/* matrix size */
+#define MATRIX_ROWS 16 // keycode bit3-6
+#define MATRIX_COLS 8 // keycode bit0-2
+
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL)) || \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+
+
+/* Pin configuration */
+#define IBM4704_CLOCK_PORT PORTD
+#define IBM4704_CLOCK_PIN PIND
+#define IBM4704_CLOCK_DDR DDRD
+#define IBM4704_CLOCK_BIT 1
+#define IBM4704_DATA_PORT PORTD
+#define IBM4704_DATA_PIN PIND
+#define IBM4704_DATA_DDR DDRD
+#define IBM4704_DATA_BIT 0
+
+/* Pin interrupt on rising edge */
+#define IBM4704_INT_INIT() do { EICRA |= ((1<<ISC11)|(0<<ISC10)); } while (0)
+#define IBM4704_INT_ON() do { EIMSK |= (1<<INT1); } while (0)
+#define IBM4704_INT_OFF() do { EIMSK &= ~(1<<INT1); } while (0)
+#define IBM4704_INT_VECT INT1_vect
+
+
+#endif
diff --git a/converter/ibm4704_usb/ibm4704.txt b/converter/ibm4704_usb/ibm4704.txt
new file mode 100644
index 0000000000..4dc296b2c5
--- /dev/null
+++ b/converter/ibm4704_usb/ibm4704.txt
@@ -0,0 +1,181 @@
+IBM 4704 Keyboard
+=================
+IBM capacitive switch models:
+ 6019273 Model 100 50-key (grid layout) http://kishy.dyndns.org/?p=977
+ 6019284 Model 200 62-key Alpha(60% layout) http://kishy.dyndns.org/?p=894
+ 6019303 Model 300 77-key Expanded Alpha http://kbtalking.cool3c.com/article/23272
+ 6020218 Model 400 107-key Full key http://kishy.dyndns.org/?p=980
+
+Alps switch(vintage Green) models:
+ 5954339 Japanese 102-key http://deskthority.net/post87127.html#p87127
+ 6112883 Japanese 102-key http://geekhack.org/index.php?topic=52888.msg1194489#msg1194489
+ 6112884 Japanese 102-key http://geekhack.org/index.php?topic=50437.msg1193047#msg1193047
+ 6341739 Chinese 102-key http://geekhack.org/index.php?topic=52888.msg1176566#msg1176566
+
+Resourse
+--------
+The IBM 4704: lots of pictures and info
+http://kishy.dyndns.org/?p=648#more-648
+
+Brochure:
+http://ed-thelen.org/comp-hist/IBM-ProdAnn/4700.pdf
+
+
+
+IBM 4704 Keyboard Protocol
+==========================
+On powering up keyboard sends keyboard ID; A3h for 6019284(62-key), for example.
+After that the keyboard enters FC command mode and waits for parameter data from host
+so that it doesn't send any scancode until you send 'FF'(End of FC command mode).
+
+ Keyboard ID
+ -------------------------------
+ Model 100 50-key A2h
+ Model 200 62-key A3h
+ Model 300 77-key A4h
+ Model 400 107-key A5h
+ Japanese/Chinese 102-key A6h
+
+
+Connector
+---------
+ Keyboard Plug from front
+
+ DSUB-9
+ -------------
+ \ N 2 3 4 5 /
+ \ N N N N /
+ ---------
+ 2 GND
+ 3 VCC 5V
+ 4 DATA
+ 5 CLOCK
+ N No connection/No pin.
+
+
+Keyboard to Host
+----------------
+Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
+
+ ____ __ __ __ __ __ __ __ __ __ ________
+ Clock \____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
+ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
+ Data ____/ X____X____X____X____X____X____X____X____X____X________
+ Start 0 1 2 3 4 5 6 7 P Stop
+
+Start bit: can be long as 300-350us.
+Inhibit: Pull Data line down to inhibit keyboard to send.
+Timing: Host reads bit while Clock is hi.
+Stop bit: Keyboard pulls down Data line to lo after 9th clock.
+
+
+Host to Keyboard
+----------------
+Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
+
+ ____ __ __ __ __ __ __ __ __ __ ________
+ Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
+ ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
+ Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
+ | Start 0 1 2 3 4 5 6 7 P Stop
+ Request by host
+
+Start bit: can be long as 300-350us.
+Request: Host pulls Clock line down to request to send a command.
+Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
+ After request host release Clock line once Data line becomes hi.
+ Host wirtes a bit while Clock is hi and Keyboard reads while low.
+Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keybaord pull down the line to lo.
+
+
+Scancodes
+---------
+Keyboard doesn't send Break code for all keys except for Alt by default.
+
+ 6019284 62-key:
+ ,-----------------------------------------------------------.
+ | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|???|BS |
+ |-----------------------------------------------------------|
+ |Tab | Q| W| E| R| T| Y| U| I| O| P| ¢| \| PD2|
+ |-----------------------------------------------------------|
+ |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| {}| PD3|
+ |-----------------------------------------------------------|
+ |Shif| <>| Z| X| C| V| B| N| M| ,| ,| /|???|Shift |
+ |-----------------------------------------------------------|
+ |Reset|blk|Alt | Space |Alt |blk|Enter|
+ `-----------------------------------------------------------'
+ +----------+---------------------+----------+----------+
+ |` 00|PD1 04|Caps 20|LShift 30|Reset 31|
+ |1 18|q 05|a 21|<> 3E|Rblank 41|
+ |2 19|w 06|s 22|z 32|Alt 3F|
+ |3 1A|e 13|d 23|x 33|Space 40|
+ |4 10|r 14|f 24|c 34|Alt 3F|
+ |5 11|t 15|g 25|v 35|Lblank 42|
+ |6 12|y 16|h 26|b 36|Enter 2F|
+ |7 08|u 17|j 27|n 37| |
+ |8 09|i 01|k 28|m 38| |
+ |9 0A|o 02|l 29|, 39| |
+ |0 0F|p 03|; 2A|. 3A| |
+ |- 1F|¢ 1B|' 2B|/ 3B| |
+ |= 0D|\ 1C|{} 2C|??? 3C| |
+ |??? 0C|PD2 1D|PD3 2D|RShift 3D| |
+ |BS 0E| | | | |
+ +----------+---------------------+----------+----------+
+ Bit7 is 'press flag' which set 1 on press and 0 on release when break code is enabled.
+
+NOTE: When break code is enabled the key sends scancode with setting 7th bit on press
+and without it on release. That is, '`' sends 80h on press and 00h on release.
+
+
+Keyboard command
+----------------
+Keyboard accepts these commands from host.
+
+ Description Entry point
+ -----------------------------------------------------------
+ FF Soft Reset 0008h
+ FE Resend 00e8h
+ FD Buzzer(emits a short beep) 00edh
+ FC Set Key Flag 00f6h
+ FB Soft Reset 0008h
+ FA Reset 0000h
+
+
+Keyboard response
+-----------------
+Keyobard sends these bytes to host.
+
+ Description Entry point
+ -----------------------------------------------------------
+ FE Overflow(key event/receive data) 00c5h, 0346h
+ Memory test error 0224h
+ FD Command out of bound 00d8h
+ Key out of bound
+ 7E Read/Parity error in receive from host 00bch
+
+
+Set Key Flag command(FC)
+------------------------
+After 'Power on Reset' firmware enters this command mode and waits for data from host,
+so that you don't need to send 'FC' and it doesn't send any scancode until you send 'FF'.
+
+Data sent from host:
+
+ bit: 7 6 ... 0
+ en | |
+ | `-----`--- scan code
+ `------------- enable bit(0: enable repeat, 1: enable break)
+
+ 00-77 Enable repeat(78-7F: invalid scancode)
+ 80-F7 Enable break(F8-FF: invalid scancode)
+ FE Resend(011ah) no need to use
+ FF End(0114h) exits FC command mode.
+
+Response from keyboard:
+ FD Out of bound - Invalid scancode
+
+Examples:
+ To enable break code of all keys.
+
+ FC 80 81 ... F7 FF
+
diff --git a/converter/ibm4704_usb/keymap_common.c b/converter/ibm4704_usb/keymap_common.c
new file mode 100644
index 0000000000..55a13793cb
--- /dev/null
+++ b/converter/ibm4704_usb/keymap_common.c
@@ -0,0 +1,30 @@
+/*
+Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "keymap_common.h"
+
+
+/* translates key to keycode */
+uint8_t keymap_key_to_keycode(uint8_t layer, keypos_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/ibm4704_usb/keymap_common.h b/converter/ibm4704_usb/keymap_common.h
new file mode 100644
index 0000000000..3321a81a50
--- /dev/null
+++ b/converter/ibm4704_usb/keymap_common.h
@@ -0,0 +1,98 @@
+/*
+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[];
+
+
+/* 77, 107-key From Ellipse@Deskthority
+ * http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478-90.html#p190550
+
+ * 77-key
+ K00,K18,K19,K1A,K10,K11,K12,K08,K09,K0A,K0F,K1F,K0D,K0C,K0E, K44,K45,K46, \
+ K04,K05,K06,K13,K14,K15,K16,K17,K01,K02,K03,K1B,K1C,K1D, K54,K55,K56, \
+ K20,K21,K22,K23,K24,K25,K26,K27,K28,K29,K2A,K2B,K2C,K2D, K64,K65,K66, \
+ K30,K3E,K32,K33,K34,K35,K36,K37,K38,K39,K3A,K3B,K3C,K3D, K74,K75,K76, \
+ K31,K41,K3F, K40, K42,K2F, K77,K67,K71 \
+
+ * 107-key
+ K00,K18, K19,K1A,K10,K11,K12,K08,K09,K0A,K0F,K1F,K0D,K0C,K0E,K46,K64, NO, K6B,K6C, K47,K48,K49,K4A, \
+ K04,K05, K06,K13,K14,K15,K16,K17,K01,K02,K03,K1B,K1C,K1D,K56,K66, K6D,K6E,K6F, K4B,K4C,K4D,K4E, \
+ K20,K21, K22,K23,K24,K25,K26,K27,K28,K29,K2A,K2B,K2C,K2D,K71,K77, K70,K65,K72, K50,K51,K52,K53, \
+ K30, K3E,K32,K33,K34,K35,K36,K37,K38,K39,K3A,K3B,K3C,K3D,K44, K74,K75,K76, K5E,K58,K59,K5A, \
+ K31,K41, K3F,K40,K42, K2F, K54,K55, K78,K67,K79, K5B,K5C,K5D,K57 \
+
+ * IBM4704 scancode 00-79h
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_NO }, \
+ { KC_##K08, KC_##K09, KC_##K0A, KC_NO, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
+ { KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_NO, KC_##K1F }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
+ { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_NO, KC_##K2F }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
+ { KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_NO, KC_##K44, KC_NO, KC_##K46, KC_##K47 }, \
+ { KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_NO }, \
+ { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \
+ { KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_##K64, KC_##K65, KC_##K66, KC_##K67 }, \
+ { KC_NO, KC_NO, KC_NO, KC_##K6B, KC_##K6C, KC_##K6D, KC_##K6E, KC_##K6F }, \
+ { KC_##K70, KC_##K71, KC_##K72, KC_NO, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \
+ { KC_##K78, KC_##K79, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO },
+*/
+/* 62-key */
+#define KEYMAP( \
+ K00,K18,K19,K1A,K10,K11,K12,K08,K09,K0A,K0F,K1F,K0D,K0C,K0E, \
+ K04,K05,K06,K13,K14,K15,K16,K17,K01,K02,K03,K1B,K1C,K1D, \
+ K20,K21,K22,K23,K24,K25,K26,K27,K28,K29,K2A,K2B,K2C,K2D, \
+ K30,K3E,K32,K33,K34,K35,K36,K37,K38,K39,K3A,K3B,K3C,K3D, \
+ K31,K41,K3F, K40, K42,K2F \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_NO }, \
+ { KC_##K08, KC_##K09, KC_##K0A, KC_NO, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
+ { KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_NO, KC_##K1F }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
+ { KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_NO, KC_##K2F }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
+ { KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+ { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
+}
+
+#endif
diff --git a/converter/ibm4704_usb/keymap_hasu.c b/converter/ibm4704_usb/keymap_hasu.c
new file mode 100644
index 0000000000..7545b0923d
--- /dev/null
+++ b/converter/ibm4704_usb/keymap_hasu.c
@@ -0,0 +1,85 @@
+#include "keymap_common.h"
+
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: default
+ * ,-----------------------------------------------------------.
+ * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|???|BS |
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
+ * |-----------------------------------------------------------|
+ * |Ctrl | A| S| D| F| G| H| J| K| L| ;| '|xxx|Ret |
+ * |-----------------------------------------------------------|
+ * |Shif|xxx| Z| X| C| V| B| N| M| ,| ,| /|xxx|Shift |
+ * |-----------------------------------------------------------|
+ * |Ctrl |Gui|Alt | Space |Alt |Gui|Ctrl |
+ * `-----------------------------------------------------------'
+ */
+ KEYMAP(
+ ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
+ LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT,NO, ENT, \
+ LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, FN2, NO, FN0, \
+ LCTL,LGUI,LALT, FN3, RGUI,RCTL \
+ ),
+
+ KEYMAP(
+ ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, BSPC, \
+ LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,NO, ENT, \
+ LSFT,NO, NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,NO, TRNS, \
+ LCTL,LGUI,LALT, SPC, RGUI,RCTL \
+ ),
+
+ KEYMAP(
+ ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,WSTP,WBAK,WFWD,BSPC, \
+ LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,TRNS,NO, NO, ENT, \
+ LSFT,NO, NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, NO, RSFT,\
+ LCTL,LGUI,LALT, BTN1, RGUI,RCTL \
+ ),
+
+ KEYMAP(
+ ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \
+ LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, NO, ENT, \
+ LSFT,NO, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, TRNS,NO, RSFT, \
+ LCTL,LGUI,LALT, SPC, RGUI,RCTL \
+ ),
+
+ KEYMAP(
+ ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,MS_U,WH_U,WH_R,BTN4,BTN5,FN4, \
+ LCTL,VOLD,VOLU,MUTE,NO, NO, BTN2,MS_L,MS_D,MS_R,BTN1,NO, NO, ENT, \
+ LSFT,NO, NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, NO, NO, \
+ LCTL,LGUI,LALT, TRNS, RGUI,RCTL \
+ ),
+};
+
+enum macro_id {
+ ALT_TAB,
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(1),
+ [1] = ACTION_LAYER_TAP_KEY(2, KC_SCLN),
+ [2] = ACTION_LAYER_TAP_KEY(3, KC_SLASH),
+ [3] = ACTION_LAYER_TAP_KEY(4, KC_SPC),
+ [4] = ACTION_MACRO(ALT_TAB),
+};
+
+/*
+ * Macro definition
+ */
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ keyevent_t event = record->event;
+
+ switch (id) {
+ case ALT_TAB:
+ return (event.pressed ?
+ MACRO( D(LALT), D(TAB), END ) :
+ MACRO( U(TAB), END ));
+ }
+ return MACRO_NONE;
+}
diff --git a/converter/ibm4704_usb/keymap_plain.c b/converter/ibm4704_usb/keymap_plain.c
new file mode 100644
index 0000000000..a121634ef7
--- /dev/null
+++ b/converter/ibm4704_usb/keymap_plain.c
@@ -0,0 +1,38 @@
+#include "keymap_common.h"
+
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: default
+ * ,-----------------------------------------------------------.
+ * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|???|BS |
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
+ * |-----------------------------------------------------------|
+ * |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| #|Ret |
+ * |-----------------------------------------------------------|
+ * |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|???|Shift |
+ * |-----------------------------------------------------------|
+ * |Ctrl |Gui|Alt | Space |Alt* |Gui|Ctrl |
+ * `-----------------------------------------------------------'
+ */
+ KEYMAP(
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,BSPC, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
+ LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,NUHS,ENT, \
+ LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, FN0, \
+ LCTL,LGUI,LALT, SPC, RGUI,RCTL \
+ ),
+
+ /* 1: HHKB */
+ KEYMAP(
+ ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, INS, \
+ LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,NO, ENT, \
+ LSFT,NO, NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,NO, TRNS, \
+ LCTL,LGUI,LALT, SPC, RGUI,RCTL \
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(1),
+};
diff --git a/converter/ibm4704_usb/led.c b/converter/ibm4704_usb/led.c
new file mode 100644
index 0000000000..f76545f0ba
--- /dev/null
+++ b/converter/ibm4704_usb/led.c
@@ -0,0 +1,24 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdint.h"
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+}
diff --git a/converter/ibm4704_usb/matrix.c b/converter/ibm4704_usb/matrix.c
new file mode 100644
index 0000000000..5f928d716f
--- /dev/null
+++ b/converter/ibm4704_usb/matrix.c
@@ -0,0 +1,165 @@
+/*
+Copyright 2014 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#include "action.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "ibm4704.h"
+#include "matrix.h"
+
+
+static void matrix_make(uint8_t code);
+static void matrix_break(uint8_t code);
+static void matrix_clear(void);
+
+
+/*
+ * Matrix Array usage:
+ * IBM 4704 scan codes are assigned into 128(16x8)-cell matrix.
+ *
+ * 8bit wide
+ * +---------+
+ * 0| |
+ * :| XX | 00-7F
+ * f| |
+ * +---------+
+ *
+ * Exceptions:
+ */
+static uint8_t matrix[MATRIX_ROWS];
+
+// scan code bits 7654 3210
+// R:row/C:column -RRR RCCC
+#define ROW(code) ((code>>3)&0x0f)
+#define COL(code) (code&0x07)
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+static void enable_break(void)
+{
+ uint8_t ret;
+ print("Enable break: ");
+ // valid scancode: 00-79h
+ for (uint8_t code = 0; code < 0x7A; code++) {
+ while (ibm4704_send(0x80|code)) _delay_ms(1);
+ // get none when ok, get FD when out of bound
+ _delay_ms(5);
+ if ((ret = ibm4704_recv()) != 0xff) {
+ xprintf("c%02X:r%02X ", code, ret);
+ }
+ _delay_ms(1);
+ }
+ _delay_us(1000);
+ while (ibm4704_send(0xFF)) { _delay_ms(1); } // End
+ print("End\n");
+}
+
+void matrix_init(void)
+{
+ debug_enable = true;
+
+ ibm4704_init();
+ matrix_clear();
+
+ _delay_ms(2000); // wait for starting up debug console
+
+ print("IBM 4704 converter\n");
+ while (ibm4704_send(0xFE)) _delay_ms(1); // resend
+ _delay_ms(5);
+ xprintf("Keyboard ID: %02X\n", ibm4704_recv());
+ enable_break();
+}
+
+/*
+ * IBM 4704 Scan Code
+ */
+uint8_t matrix_scan(void)
+{
+ uint8_t code = ibm4704_recv();
+ if (code==0xFF) {
+ // Not receivd
+ return 0;
+ } else if ((code&0x7F) >= 0x7A) {
+ // 0xFF-FA and 0x7F-7A is not scancode
+ xprintf("Error: %02X\n", code);
+ matrix_clear();
+ return 0;
+ } else if (code&0x80) {
+ dprintf("%02X\n", code);
+ matrix_make(code);
+ } else {
+ dprintf("%02X\n", code);
+ matrix_break(code);
+ }
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & (1<<col));
+}
+
+inline
+uint8_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 01234567\n");
+ for (uint8_t row = 0; row < matrix_rows(); row++) {
+ xprintf("%02X: %08b\n", row, bitrev(matrix_get_row(row)));
+ }
+}
+
+
+
+inline
+static void matrix_make(uint8_t code)
+{
+ matrix[ROW(code)] |= 1<<COL(code);
+}
+
+inline
+static void matrix_break(uint8_t code)
+{
+ matrix[ROW(code)] &= ~(1<<COL(code));
+}
+
+inline
+static void matrix_clear(void)
+{
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
+}