summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmk <wakojun@gmail.com>2014-01-06 17:57:30 -0800
committertmk <wakojun@gmail.com>2014-01-06 17:57:30 -0800
commit6e9260cc176a77702b22381d01c59f0deafcb996 (patch)
treef5b577d0bf5baaef9c524e9611807451d4f79e40
parenta35cf0e458090388202c2a0783c5d34f9b69acf7 (diff)
parentf7bb7c4fa99e6bfae311bd6674b6a2bd8537ea73 (diff)
Merge pull request #92 from bgould/upstream
Added NeXT keyboard converter
-rw-r--r--converter/next_usb/Makefile63
-rw-r--r--converter/next_usb/README45
-rw-r--r--converter/next_usb/config.h150
-rw-r--r--converter/next_usb/keymap.c177
-rw-r--r--converter/next_usb/led.c55
-rw-r--r--converter/next_usb/matrix.c269
-rw-r--r--converter/next_usb/next_timings.jpgbin0 -> 407936 bytes
-rw-r--r--protocol/next_kbd.c204
-rw-r--r--protocol/next_kbd.h63
9 files changed, 1026 insertions, 0 deletions
diff --git a/converter/next_usb/Makefile b/converter/next_usb/Makefile
new file mode 100644
index 0000000000..51d9de6b11
--- /dev/null
+++ b/converter/next_usb/Makefile
@@ -0,0 +1,63 @@
+# Target file name (without extension).
+TARGET = next_usb
+
+# Directory common source filess exist
+TOP_DIR = ../..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# keyboard dependent files
+SRC = keymap.c \
+ matrix.c \
+ led.c
+
+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
+
+SRC += next_kbd.c
+
+
+# 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
diff --git a/converter/next_usb/README b/converter/next_usb/README
new file mode 100644
index 0000000000..07ac89de30
--- /dev/null
+++ b/converter/next_usb/README
@@ -0,0 +1,45 @@
+NeXT non-ADB Keyboard Converter
+-------------------------------
+
+Cable connector inside keyboard case:
++-----+
+|Black|\
+|Green|-\
+|Yello|--\-------- to computer via Mini-Din 5a Connector
+|Orang|--/--------
+|Red |-/
+|Brown|/
++-----+
+
+Black - Ground to outer metal part of Mini Din 5a connector (not used)
+Green - Ground
+Yellow - Power button signal
+Orange - Keyboard Out
+Red - Keyboard In
+Brown - Vcc
+
+ATmega32u4 connections (pinout provided for Arduino Pro Micro):
+
+Keyboard out (orange) : PD0 (pin 3)
+Keyboard in (red) : PD1 (pin 2)
+Power Button (yellow) : PD4 (pin 4)
+Ground (black) : GND
+Vcc (brown) : VCC
+
+See attached next_timings.jpg file for a detailed illustration of NeXT keyboard protocol timings.
+
+Power button signal line is normally high when the keyboard is powered/initialized. It is pulled to ground when pressed. The converter automatically translates this to a "normal" keypress with code 0x5A. This connection is technically optional, the only side effect of not making this connection is the power key will do nothing.
+
+Converter is based heavily on Ladyada's original "USB NeXT Keyboard with Arduino Micro" tutorial (http://learn.adafruit.com/usb-next-keyboard-with-arduino-micro/overview). If you build this converter, show Adafruit some love and do it using an Arduino Micro (http://www.adafruit.com/products/1315) or their ATmega 32u4 Breakout Board (http://www.adafruit.com/products/296). Arduino Micro should work fine using the Arduino Pro Micro configuration above, same pins numbers and everything.
+
+TODO:
+-----
+
+I believe it might be possible to run the keyboard off of 3V; during testing I observed that the keyboard could sometimes function even without Vcc connected as long as the ground connection was good and the Keyboard In line was connected. If that works it should be easy to do a Bluetooth conversion and run the keyboard right off of a LiPo battery without a boost circuit
+
+Utilize second LED as status indicator for good initialization; also try to make hot plugging much more robust.
+
+Figure a better use for the Power button. Too easy to hit it by mistake to use for Suspend or Power Off - maybe move cap to different part of the board and consider that
+
+Figure out a better use for the lock LEDs. Right now they just light up when you press shift. Lame. Maybe implement proper Caps/Num/Scroll Locks
+
diff --git a/converter/next_usb/config.h b/converter/next_usb/config.h
new file mode 100644
index 0000000000..b3d188b0c1
--- /dev/null
+++ b/converter/next_usb/config.h
@@ -0,0 +1,150 @@
+/*
+NeXT non-ADB Keyboard USB Converter
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+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.
+
+*/
+
+#define VENDOR_ID 0xBCBC
+#define PRODUCT_ID 0xBCBC
+#define DEVICE_VER 0x0500
+#define MANUFACTURER t.m.k.
+#define PRODUCT NeXT Keyboard to USB converter
+#define DESCRIPTION USB converter for NeXT non-ADB Keyboard
+
+/* matrix size */
+#define MATRIX_ROWS 12 // keycode bit: 3-0
+#define MATRIX_COLS 8 // keycode bit: 6-4
+
+//#define DEBUG_ON_INIT 1
+
+//#define TEENSY_CONFIG 1
+#define PRO_MICRO_CONFIG 1
+
+// comment out if you don't want the keyboard's LEDs to flash upon initialization
+#define NEXT_KBD_INIT_FLASH_LEDS
+
+//============= Start of Arduino Pro Micro Configuration ==============
+#ifdef PRO_MICRO_CONFIG
+
+// this is the debugging LED that flashes when a key is being pressed
+// comment out in order to disable debugging LED
+#define NEXT_KBD_LED1_PORT PORTD
+#define NEXT_KBD_LED1_PIN PIND
+#define NEXT_KBD_LED1_DDR DDRD
+#define NEXT_KBD_LED1_BIT 5
+
+#define NEXT_KBD_LED1_ON NEXT_KBD_LED1_PORT &= ~(1<<NEXT_KBD_LED1_BIT);
+#define NEXT_KBD_LED1_OFF NEXT_KBD_LED1_PORT |= (1<<NEXT_KBD_LED1_BIT);
+
+// reserved for future use
+#define NEXT_KBD_LED2_PORT PORTB
+#define NEXT_KBD_LED2_PIN PINB
+#define NEXT_KBD_LED2_DDR DDRB
+#define NEXT_KBD_LED2_BIT 6
+
+#define NEXT_KBD_LED2_ON NEXT_KBD_LED2_PORT &= ~(1<<NEXT_KBD_LED2_BIT);
+#define NEXT_KBD_LED2_OFF NEXT_KBD_LED2_PORT |= (1<<NEXT_KBD_LED2_BIT);
+
+// corresponds to the Keyboard In wire on the NeXT connector
+// (red wire in NeXT connector) - pin 2 on the Pro Micro
+#define NEXT_KBD_OUT_PORT PORTD
+#define NEXT_KBD_OUT_PIN PIND
+#define NEXT_KBD_OUT_DDR DDRD
+#define NEXT_KBD_OUT_BIT 1
+
+// corresponds to the Keyboard Out wire on the NeXT connector
+// (orange wire in NeXT connector) - pin 3 on the Pro Micro
+#define NEXT_KBD_IN_PORT PORTD
+#define NEXT_KBD_IN_PIN PIND
+#define NEXT_KBD_IN_DDR DDRD
+#define NEXT_KBD_IN_BIT 0
+
+// this pin is an input for the power key on the NeXT keyboard
+// as the keyboard is powered on this should be normally high;
+// if it is pulled low it means the power button is being preseed
+// (yellow wire in NeXT connector) - pin 4 on the Pro Micro
+#define NEXT_KBD_PWR_PORT PORTD
+#define NEXT_KBD_PWR_PIN PIND
+#define NEXT_KBD_PWR_DDR DDRD
+#define NEXT_KBD_PWR_BIT 4
+
+#endif
+//============== End of Arduino Pro Micro Configuration ===============
+
+
+//================ Start of Teensy 2.0 Configuration =================
+#ifdef TEENSY_CONFIG
+
+// this is the debugging LED that flashes when a key is being pressed
+// comment out in order to disable debugging LED
+#define NEXT_KBD_LED_PORT PORTD
+#define NEXT_KBD_LED_PIN PIND
+#define NEXT_KBD_LED_DDR DDRD
+#define NEXT_KBD_LED_BIT 6
+
+#define NEXT_KBD_LED_ON NEXT_KBD_LED_PORT |= (1<<NEXT_KBD_LED_BIT);
+#define NEXT_KBD_LED_OFF NEXT_KBD_LED_PORT &= ~(1<<NEXT_KBD_LED_BIT);
+
+// corresponds to the Keyboard In wire on the NeXT connector
+// (red wire in NeXT connector)
+#define NEXT_KBD_OUT_PORT PORTB
+#define NEXT_KBD_OUT_PIN PINB
+#define NEXT_KBD_OUT_DDR DDRB
+#define NEXT_KBD_OUT_BIT 1
+
+// corresponds to the Keyboard Out wire on the NeXT connector
+// (orange wire in NeXT connector)
+#define NEXT_KBD_IN_PORT PORTB
+#define NEXT_KBD_IN_PIN PINB
+#define NEXT_KBD_IN_DDR DDRB
+#define NEXT_KBD_IN_BIT 0
+
+#endif
+//================= End of Teensy 2.0 Configuration ==================
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))|| \
+ (keyboard_report->mods == (MOD_BIT(KC_RALT) | MOD_BIT(KC_RCTL))) \
+)
diff --git a/converter/next_usb/keymap.c b/converter/next_usb/keymap.c
new file mode 100644
index 0000000000..d844f8a4e2
--- /dev/null
+++ b/converter/next_usb/keymap.c
@@ -0,0 +1,177 @@
+/*
+NeXT non-ADB Keyboard USB Converter
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+---------
+* TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+* Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/) \
+ released under BSD license \
+ https://github.com/adafruit/USB-NeXT-Keyboard
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+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 <stdint.h>
+#include <stdbool.h>
+#include <avr/pgmspace.h>
+#include "keycode.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "keymap.h"
+#include "keycode.h"
+
+// 32*8(256) byte array which converts PS/2 code into USB code
+static const uint16_t PROGMEM fn_actions[] = {
+ ACTION_LAYER_MOMENTARY(1), // FN0 - left command key
+ ACTION_LAYER_MOMENTARY(1), // FN1 - right command key
+ ACTION_KEY(KC_BSLS), // FN2 - number pad slash & backslash
+ ACTION_MODS_KEY(MOD_LSFT, KC_BSLS), // FN3 - number pad equals & pipe
+ ACTION_MODS_KEY(MOD_LCTL, KC_Z), // FN4 - cmd+undo on layer 1
+ ACTION_MODS_KEY(MOD_LCTL, KC_X), // FN5 - cmd+cut on layer 1
+ ACTION_MODS_KEY(MOD_LCTL, KC_C), // FN6 - cmd+copy on layer 1
+ ACTION_MODS_KEY(MOD_LCTL, KC_V), // FN7 - cmd+paste on layer 1
+};
+
+/* This is the physical layout that I am starting with:
+ * Note: there is some strangeness on the number pad;
+ * the equal sign shifts to pipe and forward slash shifts to backslash
+ * ,-----------------------------------------------------------. ,-----------. ,---------------.
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| BS | |VUp|Pwr|BrU| |` | =| /| *|
+ * |-----------------------------------------------------------| |-----------| |---------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | |VDn| |BrD| | 7| 8| 9| -|
+ * |------------------------------------------------------ | `---' `---' |-----------|---|
+ * |Ctrl | 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|
+ * |Alt |Cmd | Space |Cmd |Alt | |Lef|Dow|Rig| | 0| .| |
+ * `-----------------------------------------------------------' `-----------' `---------------'
+ *
+ * Keymap array:
+ * 8 bytes
+ * +---------+
+ * 0| |
+ * :| | 0x00-0x87
+ * ;| |
+ * 11| |
+ * +---------+
+ */
+#define KEYMAP( \
+ K49,K4A,K4B,K4C,K4D,K50,K4F,K4E,K1E,K1F,K20,K1D,K1C,K1B, K1A,K58,K19, K26,K27,K28,K25, \
+ K41,K42,K43,K44,K45,K48,K47,K46,K06,K07,K08,K05,K04,K03, K02, K01, K21,K22,K23,K24, \
+ K57,K39,K3A,K3B,K3C,K3D,K40,K3F,K3E,K2D,K2C,K2B, K2A, K12,K18,K13,K15, \
+ K56, K31,K32,K33,K34,K35,K37,K36,K2E,K2F,K30, K55, K16, K11,K17,K14, \
+ K52,K54, K38, K53,K51, K09,K0F,K10, K0B, K0C,K0D \
+) { \
+ { KC_NO, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
+ { KC_##K08, KC_##K09, KC_##K10, KC_##K0B, KC_##K0C, KC_##K0D, KC_NO, KC_##K0F }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
+ { KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
+ { KC_##K28, KC_NO, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
+ { KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47 }, \
+ { KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_##K4F }, \
+ { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \
+ { KC_##K58, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, }, \
+}
+
+
+static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+ /* Layer 0: default
+ * ,-----------------------------------------------------------. ,-----------. ,---------------.
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| BS | |Ins|Ref|Hom| |` | =| /| *|
+ * |-----------------------------------------------------------| |-----------| |---------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | |Del| |End| | 7| 8| 9| -|
+ * |-----------------------------------------------------' | `---' `---' |-----------|---|
+ * |Ctrl | 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|
+ * |Fn0 |Alt | Space |LGui |Fn1 | |Lef|Dow|Rig| | 0| .| |
+ * `-----------------------------------------------------------' `-----------' `---------------'
+ */
+ KEYMAP(
+ ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, WREF,HOME, GRV, FN3, FN2, PAST,
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,NO, DEL, END, P7, P8, P9, PMNS,
+ LCTL,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,
+ FN0, LALT, SPC, LGUI,FN1, LEFT,DOWN,RGHT, P0, PDOT,PENT
+
+ ),
+
+ /* Layer 1: extra keys
+ * ,-----------------------------------------------------------. ,-----------. ,---------------.
+ * |Grv| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| BS | |VUp|VMu|PgU| |` | =| /| *|
+ * |-----------------------------------------------------------| |-----------| |---------------|
+ * |Tab |Pau| W| E| R| T| Y| U| I| O|PSc| \| ]| | |VDn| |PgD| | 7| 8| 9| -|
+ * |-----------------------------------------------------' | `---' `---' |-----------|---|
+ * |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| Return| | 4| 5| 6| +|
+ * |-----------------------------------------------------------| ,---. |---------------|
+ * |Shift |UND|CUT|COP|PST| B| N| M| ,| .| /|Shift | |Up | | 1| 2| 3| |
+ * |-----------------------------------------------------------| ,-----------. |-----------|Ent|
+ * |Fn0 |Alt | Space |RGui |Fn1 | |Lef|Dow|Rig| | 0| .| |
+ * `-----------------------------------------------------------' `-----------' `---------------'
+ */
+ KEYMAP(
+
+ GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, VOLU,MUTE,PGUP, TRNS,TRNS,TRNS,TRNS,
+ TRNS,PAUS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,FN3, BSLS,TRNS, VOLD, PGDN, BTN1,MS_U,BTN2,WH_U,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, MS_L,MS_D,MS_R,WH_D,
+ TRNS, FN4, FN5, FN6, FN7, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS,TRNS,TRNS,
+ TRNS,RALT, TRNS, RGUI,TRNS, TRNS,TRNS,TRNS, TRNS, TRNS,TRNS
+
+ )
+};
+
+/* 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/next_usb/led.c b/converter/next_usb/led.c
new file mode 100644
index 0000000000..24db15e16a
--- /dev/null
+++ b/converter/next_usb/led.c
@@ -0,0 +1,55 @@
+/*
+NeXT non-ADB Keyboard USB Converter
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+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 "stdint.h"
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+
+}
diff --git a/converter/next_usb/matrix.c b/converter/next_usb/matrix.c
new file mode 100644
index 0000000000..fd6eb9d64f
--- /dev/null
+++ b/converter/next_usb/matrix.c
@@ -0,0 +1,269 @@
+/*
+NeXT non-ADB Keyboard USB Converter
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+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 <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#include "print.h"
+#include "util.h"
+#include "serial.h"
+#include "matrix.h"
+#include "debug.h"
+#include "matrix.h"
+#include "next_kbd.h"
+
+static void matrix_make(uint8_t code);
+static void matrix_break(uint8_t code);
+
+static uint8_t matrix[MATRIX_ROWS];
+#define ROW(code) ((code>>3)&0xF)
+#define COL(code) (code&0x07)
+
+static bool is_modified = false;
+
+/* number of matrix rows */
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+/* number of matrix columns */
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+#ifndef NEXT_KBD_LED1_ON
+#define NEXT_KBD_LED1_ON
+#endif
+
+#ifndef NEXT_KBD_LED1_OFF
+#define NEXT_KBD_LED1_OFF
+#endif
+
+#define NEXT_KBD_PWR_READ (NEXT_KBD_PWR_PIN&(1<<NEXT_KBD_PWR_BIT))
+
+static bool power_state = false;
+
+/* intialize matrix for scanning. should be called once. */
+void matrix_init(void)
+{
+#ifdef DEBUG_ON_INIT
+ debug_enable = true;
+#endif
+
+ // I've found that the matrix likes a little while for things to
+ // settle down before it gets started. Not sure why :)
+ _delay_ms(250);
+
+ dprintf("[ Intializing NeXT keyboard ]\n");
+ NEXT_KBD_LED1_DDR |= (1<<NEXT_KBD_LED1_BIT); // LED pin to output
+ NEXT_KBD_LED1_ON;
+
+ NEXT_KBD_PWR_DDR &= ~(1<<NEXT_KBD_PWR_BIT); // Power Button pin to input
+ NEXT_KBD_PWR_PIN |= (1<<NEXT_KBD_PWR_BIT); // KBD_PWR pull up
+
+ power_state = NEXT_KBD_PWR_READ ? false : true;
+ dprintf("Initial power button state: %b\n", power_state);
+
+ next_kbd_init();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
+
+#ifdef NEXT_KBD_INIT_FLASH_LEDS
+ dprintf("flashing LEDs:");
+ // flash the LEDs after initialization
+ bool leds_on = true;
+ for (uint8_t i = 0; i <= 6; i++)
+ {
+ leds_on = leds_on ? false : true;
+ dprintf(" %b", leds_on);
+ next_kbd_set_leds(leds_on, leds_on);
+ _delay_ms(250);
+ }
+ dprintf("\n");
+#endif
+
+ dprintf("[ NeXT keyboard initialized ]\n");
+
+ return;
+}
+
+#define NEXT_KBD_KEYCODE(response) (uint8_t)((response&0xFF)>>1)
+#define NEXT_KBD_PRESSED_KEYCODE(response) (uint8_t)(((response)&0xF00)==0x400)
+#define NEXT_KBD_PRESSED(response, mask) (uint8_t)(((response)&mask)>0)
+#define NEXT_KBD_PRESSED_CONTROL(response) NEXT_KBD_PRESSED(response,0x01000)
+#define NEXT_KBD_PRESSED_SHIFT_LEFT(response) NEXT_KBD_PRESSED(response,0x02000)
+#define NEXT_KBD_PRESSED_SHIFT_RGHT(response) NEXT_KBD_PRESSED(response,0x04000)
+#define NEXT_KBD_PRESSED_CMD_LEFT(response) NEXT_KBD_PRESSED(response,0x08000)
+#define NEXT_KBD_PRESSED_CMD_RGHT(response) NEXT_KBD_PRESSED(response,0x10000)
+#define NEXT_KBD_PRESSED_ALT_LEFT(response) NEXT_KBD_PRESSED(response,0x20000)
+#define NEXT_KBD_PRESSED_ALT_RGHT(response) NEXT_KBD_PRESSED(response,0x40000)
+#define NEXT_KBD_MAKE_OR_BREAK(key, code) \
+ do { \
+ if (NEXT_KBD_PRESSED_##key(resp) > 0) \
+ matrix_make(code); \
+ else \
+ matrix_break(code); \
+ } while (0);
+
+#define NEXT_KBD_PWR_KEYCODE 0x58
+
+/* scan all key states on matrix */
+uint8_t matrix_scan(void)
+{
+ _delay_ms(20);
+
+ //next_kbd_set_leds(false, false);
+ NEXT_KBD_LED1_OFF;
+
+ is_modified = false;
+
+ if (!NEXT_KBD_PWR_READ) {
+ matrix_make(NEXT_KBD_PWR_KEYCODE);
+ power_state = 1;
+ if (is_modified)
+ {
+ dprintf("Power state 1\n");
+
+ }
+ } else {
+ matrix_break(NEXT_KBD_PWR_KEYCODE);
+ power_state = 0;
+ if (is_modified)
+ {
+ dprintf("Power state 0\n");
+
+ }
+ }
+
+ uint32_t resp = (next_kbd_recv());
+
+ if (resp == NEXT_KBD_KMBUS_IDLE)
+ {
+ return 0;
+ }
+
+ NEXT_KBD_LED1_ON;
+
+ next_kbd_set_leds(
+ NEXT_KBD_PRESSED_SHIFT_LEFT(resp) ? true : false,
+ NEXT_KBD_PRESSED_SHIFT_RGHT(resp) ? true : false
+ );
+
+ dprintf("[ r=%04lX keycode=%02X pressed=%X CTRL=%X SHIFT_LEFT=%X SHIFT_RGHT=%X CMD_LEFT=%X CMD_RGHT=%X ALT_LEFT=%X ALT_RGHT=%X ]\n", \
+ resp, \
+ NEXT_KBD_KEYCODE(resp), \
+ NEXT_KBD_PRESSED_KEYCODE(resp), \
+ NEXT_KBD_PRESSED_CONTROL(resp), \
+ NEXT_KBD_PRESSED_SHIFT_LEFT(resp), \
+ NEXT_KBD_PRESSED_SHIFT_RGHT(resp), \
+ NEXT_KBD_PRESSED_CMD_LEFT(resp), \
+ NEXT_KBD_PRESSED_CMD_RGHT(resp), \
+ NEXT_KBD_PRESSED_ALT_LEFT(resp), \
+ NEXT_KBD_PRESSED_ALT_RGHT(resp) \
+ );
+
+ // Modifier keys don't return keycode; have to check the upper bits
+ NEXT_KBD_MAKE_OR_BREAK(ALT_RGHT, 0x51);
+ NEXT_KBD_MAKE_OR_BREAK(ALT_LEFT, 0x52);
+ NEXT_KBD_MAKE_OR_BREAK(CMD_RGHT, 0x53);
+ NEXT_KBD_MAKE_OR_BREAK(CMD_LEFT, 0x54);
+ NEXT_KBD_MAKE_OR_BREAK(SHIFT_RGHT, 0x55);
+ NEXT_KBD_MAKE_OR_BREAK(SHIFT_LEFT, 0x56);
+ NEXT_KBD_MAKE_OR_BREAK(CONTROL, 0x57);
+ NEXT_KBD_MAKE_OR_BREAK(KEYCODE, NEXT_KBD_KEYCODE(resp));
+
+ return 1;
+}
+
+/* whether modified from previous scan. used after matrix_scan. */
+bool matrix_is_modified()
+{
+ return is_modified;
+}
+
+/* whether a switch is on */
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & (1<<col));
+}
+
+/* matrix state on row */
+inline
+uint8_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+/* print matrix for debug */
+void matrix_print(void)
+{
+}
+
+inline
+static void matrix_make(uint8_t code)
+{
+ if (!matrix_is_on(ROW(code), COL(code))) {
+ matrix[ROW(code)] |= 1<<COL(code);
+ is_modified = true;
+ }
+}
+
+inline
+static void matrix_break(uint8_t code)
+{
+ if (matrix_is_on(ROW(code), COL(code))) {
+ matrix[ROW(code)] &= ~(1<<COL(code));
+ is_modified = true;
+ }
+}
diff --git a/converter/next_usb/next_timings.jpg b/converter/next_usb/next_timings.jpg
new file mode 100644
index 0000000000..c9e429fe11
--- /dev/null
+++ b/converter/next_usb/next_timings.jpg
Binary files differ
diff --git a/protocol/next_kbd.c b/protocol/next_kbd.c
new file mode 100644
index 0000000000..a5a07a7a85
--- /dev/null
+++ b/protocol/next_kbd.c
@@ -0,0 +1,204 @@
+/*
+
+NeXT non-ADB Keyboard Protocol
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+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 <stdint.h>
+#include <stdbool.h>
+#include <util/atomic.h>
+#include <util/delay.h>
+#include "next_kbd.h"
+#include "debug.h"
+
+static inline void out_lo(void);
+static inline void out_hi(void);
+static inline void query(void);
+static inline void reset(void);
+static inline uint32_t response(void);
+
+#define out_hi_delay(intervals) do { out_hi(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
+#define out_lo_delay(intervals) do { out_lo(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
+#define query_delay(intervals) do { query(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
+#define reset_delay(intervals) do { reset(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0);
+
+void next_kbd_init(void)
+{
+ out_hi();
+ NEXT_KBD_IN_DDR &= ~(1<<NEXT_KBD_IN_BIT); // KBD_IN to input
+ NEXT_KBD_IN_PORT |= (1<<NEXT_KBD_IN_BIT); // KBD_IN pull up
+
+ query_delay(5);
+ reset_delay(8);
+
+ query_delay(5);
+ reset_delay(8);
+}
+
+void next_kbd_set_leds(bool left, bool right)
+{
+ out_lo_delay(9);
+
+ out_hi_delay(3);
+ out_lo_delay(1);
+
+ if (left) {
+ out_hi_delay(1);
+ } else {
+ out_lo_delay(1);
+ }
+
+ if (right) {
+ out_hi_delay(1);
+ } else {
+ out_lo_delay(1);
+ }
+
+ out_lo_delay(7);
+ out_hi();
+}
+
+#define NEXT_KBD_READ (NEXT_KBD_IN_PIN&(1<<NEXT_KBD_IN_BIT))
+uint32_t next_kbd_recv(void)
+{
+
+ // First check to make sure that the keyboard is actually connected;
+ // if not, just return
+ // TODO: reflect the status of the keyboard in a return code
+ if (!NEXT_KBD_READ) {
+ sei();
+ return 0;
+ }
+
+ query();
+ uint32_t resp = response();
+
+ return resp;
+}
+
+static inline uint32_t response(void)
+{
+ cli();
+
+ // try a 5ms read; this should be called after the query method has
+ // been run so if a key is pressed we should get a response within
+ // 5ms; if not then send a reset and exit
+ uint8_t i = 0;
+ uint32_t data = 0;
+ uint16_t reset_timeout = 50000;
+ while (NEXT_KBD_READ && reset_timeout) {
+ asm(""); _delay_us(1); reset_timeout--;
+ }
+ if (!reset_timeout) {
+ reset();
+ sei();
+ return 0;
+ }
+ _delay_us(NEXT_KBD_TIMING / 2);
+ for (; i < 22; i++)
+ {
+ if (NEXT_KBD_READ)
+ {
+ data |= ((uint32_t) 1 << i);
+ /* Note:
+ * My testing with the ATmega32u4 showed that there might
+ * something wrong with the timing here; by the end of the
+ * second data byte some of the modifiers can get bumped out
+ * to the next bit over if we just cycle through the data
+ * based on the expected interval. There is a bit (i = 10)
+ * in the middle of the data that is always on followed by
+ * one that is always off - so we'll use that to reset our
+ * timing in case we've gotten ahead of the keyboard;
+ */
+ if (i == 10)
+ {
+ i++;
+ while (NEXT_KBD_READ) ;
+ _delay_us(NEXT_KBD_TIMING / 2);
+ }
+ } else {
+ /* redundant - but I don't want to remove if it might screw
+ * up the timing
+ */
+ data |= ((uint32_t) 0 << i);
+ }
+ _delay_us(NEXT_KBD_TIMING);
+ }
+
+ sei();
+
+ return data;
+}
+
+static inline void out_lo(void)
+{
+ NEXT_KBD_OUT_PORT &= ~(1<<NEXT_KBD_OUT_BIT);
+ NEXT_KBD_OUT_DDR |= (1<<NEXT_KBD_OUT_BIT);
+}
+
+static inline void out_hi(void)
+{
+ /* input with pull up */
+ NEXT_KBD_OUT_DDR &= ~(1<<NEXT_KBD_OUT_BIT);
+ NEXT_KBD_OUT_PORT |= (1<<NEXT_KBD_OUT_BIT);
+}
+
+static inline void query(void)
+{
+ out_lo_delay(5);
+ out_hi_delay(1);
+ out_lo_delay(3);
+ out_hi();
+}
+
+static inline void reset(void)
+{
+ out_lo_delay(1);
+ out_hi_delay(4);
+ out_lo_delay(1);
+ out_hi_delay(6);
+ out_lo_delay(10);
+ out_hi();
+}
diff --git a/protocol/next_kbd.h b/protocol/next_kbd.h
new file mode 100644
index 0000000000..6d455d4fab
--- /dev/null
+++ b/protocol/next_kbd.h
@@ -0,0 +1,63 @@
+/*
+NeXT non-ADB Keyboard Protocol
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+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>
+
+#ifndef NEXT_KBD_H
+#define NEXT_KBD_H
+
+#define NEXT_KBD_KMBUS_IDLE 0x300600
+#define NEXT_KBD_TIMING 50
+
+extern uint8_t next_kbd_error;
+
+/* host role */
+void next_kbd_init(void);
+void next_kbd_set_leds(bool left, bool right);
+uint32_t next_kbd_recv(void);
+
+#endif