summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2014-02-13 09:45:54 +0900
committertmk <nobody@nowhere>2014-02-13 09:45:54 +0900
commit188ab49dd3467217a59fea59995259df69bbb78e (patch)
tree1eb8a3a88d3cfe5cabfe5e4d5088f6164978e15b
parentcb3a547ebff8e09401c7d635ed24585a7521bb19 (diff)
parent428b23646129aeee5eda20f34d22846fc54a86d4 (diff)
Merge branch 'ibm4704'
-rw-r--r--README.md2
-rw-r--r--converter/ibm4704_usb/Makefile93
-rw-r--r--converter/ibm4704_usb/README.md46
-rw-r--r--converter/ibm4704_usb/config.h73
-rw-r--r--converter/ibm4704_usb/ibm4704.txt160
-rw-r--r--converter/ibm4704_usb/keymap_common.c30
-rw-r--r--converter/ibm4704_usb/keymap_common.h73
-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.c170
-rw-r--r--protocol/ibm4704.c169
-rw-r--r--protocol/ibm4704.h110
13 files changed, 1073 insertions, 0 deletions
diff --git a/README.md b/README.md
index b76b7fb9ed..a561b38eb3 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
* [pc98_usb](converter/pc98_usb/) - [PC98] to USB
* [usb_usb](converter/usb_usb/) - USB to USB(experimental)
* [ascii_usb](converter/ascii_usb/) - ASCII(Serial console terminal) to USB
+* [ibm4704_usb](converter/ibm4704_usb) - [IBM 4704 keyboard Converter][GH_ibm4704]
### keyboard
* [hhkb](keyboard/hhkb/) - [Happy Hacking Keyboard pro][GH_hhkb] **my main board**
@@ -62,6 +63,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272
[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060
[GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483
+[GH_ibm4704]: http://geekhack.org/index.php?topic=54706.0
[HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions
[Phantom]: http://geekhack.org/index.php?topic=26742
[GH60]: http://geekhack.org/index.php?topic=34959
diff --git a/converter/ibm4704_usb/Makefile b/converter/ibm4704_usb/Makefile
new file mode 100644
index 0000000000..112b00129d
--- /dev/null
+++ b/converter/ibm4704_usb/Makefile
@@ -0,0 +1,93 @@
+# Target file name (without extension).
+TARGET = ibm4704_usb
+
+# Directory common source filess exist
+TOP_DIR = ../..
+
+# 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 += $(TOP_DIR)
+
+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/ibm4704_usb/README.md b/converter/ibm4704_usb/README.md
new file mode 100644
index 0000000000..6541dd6d0c
--- /dev/null
+++ b/converter/ibm4704_usb/README.md
@@ -0,0 +1,46 @@
+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.**
+
+
+4704 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..befed0d530
--- /dev/null
+++ b/converter/ibm4704_usb/config.h
@@ -0,0 +1,73 @@
+/*
+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_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+
+
+/*
+ * Busywait
+ */
+#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
+ */
+#ifdef IBM4704_USE_INT
+#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
+
+
+#endif
diff --git a/converter/ibm4704_usb/ibm4704.txt b/converter/ibm4704_usb/ibm4704.txt
new file mode 100644
index 0000000000..c17d172af1
--- /dev/null
+++ b/converter/ibm4704_usb/ibm4704.txt
@@ -0,0 +1,160 @@
+4704 Keyboard
+=============
+Keyboard Models:
+ Model 100 6019273 50-key (grid layout)
+ Model 200 6019284 62-key Alpha(60% layout)
+ Model 300 6019303 77-key Expanded Alpha
+ Model 400 6020218 107-key Full key
+
+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
+
+
+
+4704 Keyboard Protocol
+======================
+On powering up the keyboard sends keyboard id; A3h for 6019284(62-key), for example.
+After that firmware 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).
+
+
+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
+----------------
+ FF Soft Reset(0008h)
+ FE Resend(00e8h)
+ FD Buzzer stop?(00edh)
+ FC Set Key flag(00f6h)
+ FB Soft Reset(0008h)
+ FA Reset(0000h)
+
+
+Keyboard response
+-----------------
+ FF Not exist. [Outgoing buffer cannot have FFh(00h in fact)]
+ FE Overflow(key event/receive data) at 00c5h, 0346h
+ FE Memory test error at 0224h
+ FD Command out of bound at 00d8h
+ Key out of bound
+ 7E Read/Parity error in receive from host at 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..241d2e33b1
--- /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, 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/ibm4704_usb/keymap_common.h b/converter/ibm4704_usb/keymap_common.h
new file mode 100644
index 0000000000..c55a817205
--- /dev/null
+++ b/converter/ibm4704_usb/keymap_common.h
@@ -0,0 +1,73 @@
+/*
+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[];
+
+
+/* Original keys */
+#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
+
+/*
+ { K48, K49, K4A, K4B, K4C, K4D, K4E, K4F }, \
+ { K50, K51, K52, K53, K54, K55, K56, K57 }, \
+ { K58, K59, K5A, K5B, K5C, K5D, K5E, K5F }, \
+ { K60, K61, K62, K63, K64, K65, K66, K67 }, \
+ { K68, K69, K6A, K6B, K6C, K6D, K6E, K6F }, \
+ { K70, K71, K72, K73, K74, K75, K76, K77 }, \
+ { K78, K79, K7A, K7B, K7C, K7D, K7E, K7F }, \
+*/
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..0bfda2b158
--- /dev/null
+++ b/converter/ibm4704_usb/matrix.c
@@ -0,0 +1,170 @@
+/*
+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-77h
+ for (uint8_t code = 0; code < 0x78; code++) {
+ while (ibm4704_send(0x80|code) != 0) {
+ print("z");
+ _delay_us(500);
+ }
+ _delay_us(2000);
+ ret = ibm4704_recv();
+ if (ret != 0xff) {
+ xprintf("c%02X:r%02X ", code, ret);
+ }
+ _delay_us(1000);
+ }
+ _delay_us(1000);
+ while (ibm4704_send(0xFF) != 0) { _delay_us(500); } // End
+ print("End\n");
+}
+
+void matrix_init(void)
+{
+ uint8_t ret;
+ debug_enable = true;
+
+ ibm4704_init();
+ matrix_clear();
+
+ // read keyboard id
+ while ((ret = ibm4704_recv()) == 0xFF) {
+ ibm4704_send(0xFE);
+ _delay_us(100);
+ }
+
+ _delay_ms(2000); // wait for starting up debug console
+ print("IBM 4704 converter\n");
+ xprintf("Keyboard ID: %02X\n", ret);
+ 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&0x78)==0x78) {
+ // 0xFF-F8 and 0x7F-78 is not scancode
+ xprintf("Error: %0X\n", code);
+ matrix_clear();
+ return 0;
+ } else if (code&0x80) {
+ matrix_make(code);
+ } else {
+ 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;
+}
diff --git a/protocol/ibm4704.c b/protocol/ibm4704.c
new file mode 100644
index 0000000000..10e229fd15
--- /dev/null
+++ b/protocol/ibm4704.c
@@ -0,0 +1,169 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+*/
+#include <stdbool.h>
+#include <util/delay.h>
+#include "debug.h"
+#include "ibm4704.h"
+
+
+#define WAIT(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ ibm4704_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+
+uint8_t ibm4704_error = 0;
+
+
+void ibm4704_init(void)
+{
+ inhibit();
+}
+
+/*
+Host to Keyboard
+----------------
+Data bits are LSB first and Parity 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 writes 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 keyboard pull down the line to lo.
+*/
+uint8_t ibm4704_send(uint8_t data)
+{
+ bool parity = true; // odd parity
+ ibm4704_error = 0;
+
+ /* Request to send */
+ idle();
+ clock_lo();
+
+ /* wait for Start bit(Clock:lo/Data:hi) */
+ WAIT(data_hi, 300, 0x30);
+
+ /* Data bit */
+ for (uint8_t i = 0; i < 8; i++) {
+ WAIT(clock_hi, 100, 0x40+i);
+ //_delay_us(5);
+ if (data&(1<<i)) {
+ parity = !parity;
+ data_hi();
+ } else {
+ data_lo();
+ }
+ WAIT(clock_lo, 100, 0x48+i);
+ }
+
+ /* Parity bit */
+ WAIT(clock_hi, 100, 0x34);
+ if (parity) { data_hi(); } else { data_lo(); }
+ WAIT(clock_lo, 100, 0x35);
+
+ /* Stop bit */
+ WAIT(clock_hi, 100, 0x34);
+ data_hi();
+
+ /* End */
+ WAIT(data_lo, 100, 0x36);
+
+ inhibit();
+ _delay_us(200); // wait to recover clock to hi
+ return 0;
+ERROR:
+ inhibit();
+ if (ibm4704_error >= 0x30) {
+ xprintf("x%02X ", ibm4704_error);
+ }
+ _delay_us(200); // wait to recover clock to hi
+ return -1;
+}
+
+/* receive data when host want else inhibit communication */
+uint8_t ibm4704_recv_response(void)
+{
+ // 250 * 100us(wait start bit in ibm4704_recv)
+ uint8_t data = 0;
+ uint8_t try = 250;
+ do {
+ data = ibm4704_recv();
+ } while (try-- && ibm4704_error);
+ return data;
+}
+
+/*
+Keyboard to Host
+----------------
+Data bits are LSB first and Parity 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.
+*/
+uint8_t ibm4704_recv(void)
+{
+ uint8_t data = 0;
+ bool parity = true; // odd parity
+ ibm4704_error = IBM4704_ERR_NONE;
+
+ idle();
+ _delay_us(5); // wait for line settles
+
+ /* start bit */
+ WAIT(clock_lo, 100, 0x11); // wait for keyboard to send
+ WAIT(data_hi, 100, 0x12); // can be delayed that long
+
+ WAIT(clock_hi, 100, 0x13); // first rising edge which can take longer
+ /* data */
+ for (uint8_t i = 0; i < 8; i++) {
+ WAIT(clock_hi, 100, 0x20+i);
+ //_delay_us(5);
+ if (data_in()) {
+ parity = !parity;
+ data |= (1<<i);
+ }
+ WAIT(clock_lo, 150, 0x28+i);
+ }
+
+ /* parity */
+ WAIT(clock_hi, 100, 0x17);
+ if (data_in() != parity) {
+ ibm4704_error = IBM4704_ERR_PARITY;
+ goto ERROR;
+ }
+ WAIT(clock_lo, 150, 0x18);
+
+ /* stop bit */
+ WAIT(clock_hi, 100, 0x19);
+ WAIT(data_lo, 1, 0x19);
+
+ inhibit();
+ _delay_us(200); // wait to recover clock to hi
+ return data;
+ERROR:
+ if (ibm4704_error > 0x12) {
+ xprintf("x%02X ", ibm4704_error);
+ }
+ inhibit();
+ _delay_us(200); // wait to recover clock to hi
+ return -1;
+}
diff --git a/protocol/ibm4704.h b/protocol/ibm4704.h
new file mode 100644
index 0000000000..618cce6be0
--- /dev/null
+++ b/protocol/ibm4704.h
@@ -0,0 +1,110 @@
+/*
+Copyright 2014 Jun WAKO <wakojun@gmail.com>
+*/
+#ifndef IBM4704_H
+#define IBM4704_H
+
+#define IBM4704_ERR_NONE 0
+#define IBM4704_ERR_PARITY 0x70
+
+
+void ibm4704_init(void);
+uint8_t ibm4704_send(uint8_t data);
+uint8_t ibm4704_recv_response(void);
+uint8_t ibm4704_recv(void);
+
+
+/* Check pin configuration */
+#if !(defined(IBM4704_CLOCK_PORT) && \
+ defined(IBM4704_CLOCK_PIN) && \
+ defined(IBM4704_CLOCK_DDR) && \
+ defined(IBM4704_CLOCK_BIT))
+# error "ibm4704 clock pin configuration is required in config.h"
+#endif
+
+#if !(defined(IBM4704_DATA_PORT) && \
+ defined(IBM4704_DATA_PIN) && \
+ defined(IBM4704_DATA_DDR) && \
+ defined(IBM4704_DATA_BIT))
+# error "ibm4704 data pin configuration is required in config.h"
+#endif
+
+
+/*--------------------------------------------------------------------
+ * static functions
+ *------------------------------------------------------------------*/
+static inline void clock_lo(void)
+{
+ IBM4704_CLOCK_PORT &= ~(1<<IBM4704_CLOCK_BIT);
+ IBM4704_CLOCK_DDR |= (1<<IBM4704_CLOCK_BIT);
+}
+static inline void clock_hi(void)
+{
+ /* input with pull up */
+ IBM4704_CLOCK_DDR &= ~(1<<IBM4704_CLOCK_BIT);
+ IBM4704_CLOCK_PORT |= (1<<IBM4704_CLOCK_BIT);
+}
+static inline bool clock_in(void)
+{
+ IBM4704_CLOCK_DDR &= ~(1<<IBM4704_CLOCK_BIT);
+ IBM4704_CLOCK_PORT |= (1<<IBM4704_CLOCK_BIT);
+ _delay_us(1);
+ return IBM4704_CLOCK_PIN&(1<<IBM4704_CLOCK_BIT);
+}
+static inline void data_lo(void)
+{
+ IBM4704_DATA_PORT &= ~(1<<IBM4704_DATA_BIT);
+ IBM4704_DATA_DDR |= (1<<IBM4704_DATA_BIT);
+}
+static inline void data_hi(void)
+{
+ /* input with pull up */
+ IBM4704_DATA_DDR &= ~(1<<IBM4704_DATA_BIT);
+ IBM4704_DATA_PORT |= (1<<IBM4704_DATA_BIT);
+}
+static inline bool data_in(void)
+{
+ IBM4704_DATA_DDR &= ~(1<<IBM4704_DATA_BIT);
+ IBM4704_DATA_PORT |= (1<<IBM4704_DATA_BIT);
+ _delay_us(1);
+ return IBM4704_DATA_PIN&(1<<IBM4704_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
+ * keyboard checks Data line on start bit(Data:hi) and it stops sending if Data line is low.
+ */
+static inline void inhibit(void)
+{
+ clock_hi();
+ data_lo();
+}
+
+#endif