1
0

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Kai Ryu 2014-05-07 11:16:59 +09:00
commit f2fd5127e1
83 changed files with 4145 additions and 287 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "protocol/usb_hid/USB_Host_Shield_2.0"]
path = protocol/usb_hid/USB_Host_Shield_2.0
url = git@github.com:tmk/USB_Host_Shield_2.0.git
[submodule "protocol/lufa/LUFA-git"]
path = protocol/lufa/LUFA-git
url = https://github.com/abcminiuser/lufa.git

View File

@ -33,13 +33,15 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
### converter
* [ps2_usb](converter/ps2_usb/) - [PS/2 keyboard to USB][GH_ps2]
* [adb_usb](converter/adb_usb/) - [ADB keyboard to USB][GH_adb]
* [m0110_usb](converter/m0110_usb) - [Machintosh 128K/512K/Plus keyboard to USB][GH_m0110]
* [m0110_usb](converter/m0110_usb) - [Macintosh 128K/512K/Plus keyboard to USB][GH_m0110]
* [terminal_usb](converter/terminal_usb/) - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
* [news_usb](converter/news_usb/) - [Sony NEWS keyboard to USB][GH_news]
* [x68k_usb](converter/x68k_usb/) - [Sharp X68000 keyboard to USB][GH_x68k]
* [sun_usb](converter/sun_usb/) - [Sun] to USB(type4, 5 and 3?)
* [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**
@ -50,6 +52,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
* [IIgs_Standard](keyboard/IIgs/) - Apple [IIGS] keyboard mod(by JeffreySung)
* [macway](keyboard/macway/) - [Compact keyboard mod][GH_macway] [retired]
* [KMAC](keyboard/kmac/) - Korean custom keyboard
* [Lightsaber](keyboard/lightsaber/) - Korean custom keyboard
[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930
[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047
@ -61,6 +64,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
@ -90,7 +94,7 @@ See [doc/keymap.md](doc/keymap.md).
Magic Comannds
Magic Commands
--------------
To see help press `Magic` + `H`.
@ -121,7 +125,7 @@ Following commands can be also executed with `Magic` + key. In console mode `Mag
**TBD**
### Boot Magic Configuration - Virtual DIP Switch
Boot Magic are executed during boot up time. Press Magic key below then pulgin keyboard cable.
Boot Magic are executed during boot up time. Press Magic key below then plug in keyboard cable.
Note that you must use keys of **Layer 0** as Magic keys. These settings are stored in EEPROM so that retain your configure over power cycles.
To avoid configuring accidentally additive salt key `KC_SPACE` also needs to be pressed along with the following configuration keys. The salt key is configurable in `config.h`. See [common/bootmagic.h](common/bootmagic.h).
@ -141,7 +145,7 @@ To avoid configuring accidentally additive salt key `KC_SPACE` also needs to be
#### Keymap
- Swap Control and CapsLock(`Left Control`)
- Change CapsLock to Control(`Casp Lock`)
- Change CapsLock to Control(`Caps Lock`)
- Swap LeftAlt and Gui(`Left Alt`)
- Swap RightAlt and Gui(`Right Alt`)
- Disable Gui(`Left Gui`)
@ -210,7 +214,7 @@ Architecture
Debuging
Debugging
--------
Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack.
@ -227,7 +231,7 @@ Files and Directories
* converter/ - protocol converter projects
* doc/ - documents
* common.mk - Makefile for common
* protoco.mk - Makefile for protocol
* protocol.mk - Makefile for protocol
* rules.mk - Makefile for build rules
### Common
@ -263,7 +267,7 @@ Files and Directories
Conding Style
Coding Style
-------------
- Doesn't use Tab to indent, use 4-spaces instead.

View File

@ -294,7 +294,7 @@ void process_action(keyrecord_t *record)
#ifdef BACKLIGHT_ENABLE
case ACT_BACKLIGHT:
if (!event.pressed) {
switch (action.backlight.id) {
switch (action.backlight.opt) {
case BACKLIGHT_INCREASE:
backlight_increase();
break;
@ -307,6 +307,9 @@ void process_action(keyrecord_t *record)
case BACKLIGHT_STEP:
backlight_step();
break;
case BACKLIGHT_LEVEL:
backlight_level(action.backlight.level);
break;
}
}
break;

View File

@ -87,7 +87,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* 1100|1111| id(8) Macro record?
*
* ACT_BACKLIGHT(1101):
* 1101|xxxx| id(8) Backlight commands
* 1101|opt |level(8) Backlight commands
*
* ACT_COMMAND(1110):
* 1110|opt | id(8) Built-in Command exec
@ -163,7 +163,9 @@ typedef union {
uint8_t kind :4;
} usage;
struct action_backlight {
uint8_t id :8;
uint8_t level :8;
uint8_t opt :4;
uint8_t kind :4;
} backlight;
struct action_command {
uint8_t id :8;
@ -282,21 +284,23 @@ enum layer_pram_tap_op {
/*
* Extensions
*/
enum backlight_id {
enum backlight_opt {
BACKLIGHT_INCREASE = 0,
BACKLIGHT_DECREASE = 1,
BACKLIGHT_TOGGLE = 2,
BACKLIGHT_STEP = 3,
BACKLIGHT_LEVEL = 4,
};
/* Macro */
#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id))
#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt)<<8 | (id))
/* Backlight */
#define ACTION_BACKLIGHT_INCREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE)
#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE)
#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE)
#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP)
#define ACTION_BACKLIGHT_INCREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE << 8)
#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
#define ACTION_BACKLIGHT_LEVEL(level) ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | level)
/* Command */
#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
/* Function */

View File

@ -16,6 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <util/delay.h>
#include "action.h"
#include "action_util.h"
#include "action_macro.h"
#ifdef DEBUG_ACTION
@ -39,12 +40,20 @@ void action_macro_play(const macro_t *macro_p)
case KEY_DOWN:
MACRO_READ();
dprintf("KEY_DOWN(%02X)\n", macro);
register_code(macro);
if (IS_MOD(macro)) {
add_weak_mods(MOD_BIT(macro));
} else {
register_code(macro);
}
break;
case KEY_UP:
MACRO_READ();
dprintf("KEY_UP(%02X)\n", macro);
unregister_code(macro);
if (IS_MOD(macro)) {
del_weak_mods(MOD_BIT(macro));
} else {
unregister_code(macro);
}
break;
case WAIT:
MACRO_READ();

View File

@ -104,3 +104,11 @@ void backlight_step(void)
dprintf("backlight step: %u\n", backlight_config.level);
backlight_set(backlight_config.level);
}
void backlight_level(uint8_t level)
{
backlight_config.level ^= level;
backlight_config.enable = !!backlight_config.level;
eeconfig_write_backlight(backlight_config.raw);
backlight_set(backlight_config.level);
}

View File

@ -24,18 +24,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
typedef union {
uint8_t raw;
struct {
bool enable:1;
uint8_t level:7;
bool enable :1;
uint8_t level :7;
};
} backlight_config_t;
void backlight_init(void);
void backlight_increase(void);
void backlight_decrease(void);
void backlight_toggle(void);
void backlight_step(void);
void backlight_set(uint8_t level);
void backlight_level(uint8_t level);
#endif

View File

@ -301,13 +301,13 @@ static bool command_common(uint8_t code)
case KC_S:
print("\n\n----- Status -----\n");
print_val_hex8(host_keyboard_leds());
print_val_hex8(keyboard_protocol);
print_val_hex8(keyboard_idle);
#ifdef PROTOCOL_PJRC
print_val_hex8(UDCON);
print_val_hex8(UDIEN);
print_val_hex8(UDINT);
print_val_hex8(usb_keyboard_leds);
print_val_hex8(usb_keyboard_protocol);
print_val_hex8(usb_keyboard_idle_config);
print_val_hex8(usb_keyboard_idle_count);
#endif

View File

@ -24,7 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef NKRO_ENABLE
bool keyboard_nkro = false;
bool keyboard_nkro = true;
#endif
static host_driver_t *driver;

View File

@ -32,6 +32,9 @@ extern "C" {
extern bool keyboard_nkro;
#endif
uint8_t keyboard_idle;
uint8_t keyboard_protocol;
/* host driver */
void host_set_driver(host_driver_t *driver);

View File

@ -94,6 +94,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
extern "C" {
#endif
/*
* keyboard report is 8-byte array retains state of 8 modifiers and 6 keys.
*
* byte |0 |1 |2 |3 |4 |5 |6 |7
* -----+--------+--------+--------+--------+--------+--------+--------+--------
* desc |mods |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5]
*
* It is exended to 16 bytes to retain 120keys+8mods when NKRO mode.
*
* byte |0 |1 |2 |3 |4 |5 |6 |7 ... |15
* -----+--------+--------+--------+--------+--------+--------+--------+-------- +--------
* desc |mods |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6] ... |bit[14]
*
* mods retains state of 8 modifiers.
*
* bit |0 |1 |2 |3 |4 |5 |6 |7
* -----+--------+--------+--------+--------+--------+--------+--------+--------
* desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui
*
*/
typedef union {
uint8_t raw[REPORT_SIZE];
struct {

View File

@ -71,8 +71,8 @@ Notes
Many ADB keyboards has no discrimination between right modifier and left one,
you will always see left control even if you press right control key.
Apple Extended Keyboard and Apple Extended Keyboard II are the examples.
Though ADB protocol itsef has the ability of distinction between right and left.
And most ADB keyboard has no NKRO functionality, though ADB protocol itsef has that.
Though ADB protocol itself has the ability of distinction between right and left.
And most ADB keyboard has no NKRO functionality, though ADB protocol itself has that.
See protocol/adb.c for more info.
EOF

View File

@ -0,0 +1,82 @@
# Target file name (without extension).
TARGET = ascii_usb
# Directory common source filess exist
TOP_DIR = ../..
# Directory keyboard dependent files exist
TARGET_DIR = .
# keyboard dependent files
SRC = keymap.c \
matrix.c \
led.c \
protocol/serial_uart.c
CONFIG_H = config.h
# MCU name, you MUST set this to match the board you are using
# type "make clean" after changing this, so all files will be rebuilt
#MCU = at90usb162 # Teensy 1.0
MCU = atmega32u4 # Teensy 2.0
#MCU = at90usb646 # Teensy++ 1.0
#MCU = at90usb1286 # Teensy++ 2.0
# Processor frequency.
# Normally the first thing your program should do is set the clock prescaler,
# so your program will run at the correct speed. You should also set this
# variable to same clock speed. The _delay_ms() macro uses this, and many
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000
#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8
# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)
# Interrupt driven control endpoint task
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Build Options
# *Comment out* to disable the options.
#
#MOUSEKEY_ENABLE = yes # Mouse keys
#EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = yes # Console for debug
#NKRO_ENABLE = yes # USB Nkey Rollover
# Boot Section Size in bytes
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
OPT_DEFS += -DBOOTLOADER_SIZE=4096
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

View File

@ -0,0 +1,38 @@
ASCII to USB keyboard protocol converter
========================================
This converts serial console terminal into USB keyboard, tested with TRS-80 model 100 TELCOM application.
Target MCU is ATMega32u4 but other USB capable AVR will also work.
Hardware
--------
Connect RX, TX and GND to UART pin of AVR. Note that you may need line driver/level shifter like MAX232 to interface high voltage of RS-232C.
Build Firmware
--------------
Configure UART setting and Just use 'make'
$ cd ascii_usb
$ make
Then, load the binary to MCU with your favorite programmer.
Limitation
----------
- This cannot see key up event, you cannot hold a key.
- Alt, Gui(Win/Mac) modifier key are not available.
TRS-80 model 100
----------------
Use TELCOM program with setting: 19200bps/8bit/odd parity/1stop bit
To set this configuration push Stat(F3) and input '9801D,10'. Then push Term(F4) to connect.

View File

@ -0,0 +1,70 @@
/*
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
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x5C01
#define DEVICE_VER 0x0100
#define MANUFACTURER t.m.k.
#define PRODUCT ASCII keyboard converter
#define DESCRIPTION converts Serial Console Terminal into USB keyboard
/* matrix size */
#define MATRIX_ROWS 16
#define MATRIX_COLS 16
/* key combination for command */
#define IS_COMMAND() ( \
host_get_first_key() == KC_BRK \
)
/*
* Serial(USART) configuration
* asynchronous, positive logic, 19200baud, bit order: LSB first
* 1-start bit, 8-data bit, odd parity, 1-stop bit
*/
#ifdef __AVR_ATmega32U4__
#define SERIAL_UART_BAUD 19200
#define SERIAL_UART_DATA UDR1
#define SERIAL_UART_UBRR ((F_CPU/(16UL*SERIAL_UART_BAUD))-1)
#define SERIAL_UART_RXD_VECT USART1_RX_vect
#define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1))
#define SERIAL_UART_INIT() do { \
UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \
UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8); /* baud rate */ \
UCSR1B |= (1<<RXCIE1) | (1<<RXEN1); /* RX interrupt, RX: enable */ \
UCSR1B |= (0<<TXCIE1) | (1<<TXEN1); /* TX interrupt, TX: enable */ \
UCSR1C |= (1<<UPM11) | (1<<UPM10); /* parity: none(00), even(01), odd(11) */ \
sei(); \
} while(0)
#else
#error "USART configuration is needed."
#endif
/* disable action features */
#define NO_ACTION_LAYER
#define NO_ACTION_TAPPING
#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
#endif

View File

@ -0,0 +1,42 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "action_util.h"
#include "util.h"
#include "print.h"
#include "keymap.h"
// Keymap is not used. See matrix.c.
/* translates key to keycode */
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
{
return KC_NO;
}
/* translates Fn keycode to action */
action_t keymap_fn_to_action(uint8_t keycode)
{
return (action_t) { .code = ACTION_NO };
}

25
converter/ascii_usb/led.c Normal file
View File

@ -0,0 +1,25 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdint.h"
#include "serial.h"
#include "led.h"
void led_set(uint8_t usb_led)
{
}

View File

@ -0,0 +1,195 @@
/*
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 "print.h"
#include "util.h"
#include "matrix.h"
#include "debug.h"
#include "action_util.h"
#include "protocol/serial.h"
/*
* Not use Matrix.
*
* ROW: 16(4bits)
* COL: 16(4bits)
*
* 8bit wide
* +---------+
* 0|00 ... 0F|
* 1|08 ... 1F|
* :| ... |
* :| ... |
* E|E0 ... EF|
* F|F0 ... FF|
* +---------+
*/
inline
uint8_t matrix_rows(void)
{
return MATRIX_ROWS;
}
inline
uint8_t matrix_cols(void)
{
return MATRIX_COLS;
}
void matrix_init(void)
{
debug_matrix = true;
serial_init();
debug("init\n");
return;
}
static void type_key(uint16_t keycode)
{
if (keycode == 0) return;
uint8_t mods = keycode>>8;
uint8_t key = keycode&0xFF;
if (mods) {
add_mods(mods);
send_keyboard_report();
}
add_key(key);
send_keyboard_report();
del_key(key);
send_keyboard_report();
if (mods) {
del_mods(mods);
send_keyboard_report();
}
}
static uint16_t code2key(uint8_t code)
{
// ASCII to key combination in US laout
switch (code) {
case 0x01 ... 0x08: // Ctrl-[a-z]
return MOD_BIT(KC_LCTRL)<<8 | (KC_A + (code-0x01));
case 0x09: return KC_TAB; // TAB(Ctrl-i)
case 0x0A ... 0x0C: // Ctrl-[a-z]
return MOD_BIT(KC_LCTRL)<<8 | (KC_A + (code-0x01));
case 0x0D: return KC_ENTER; // Enter(Ctrl-m)
case 0x0E ... 0x1A: // Ctrl-[a-z]
return MOD_BIT(KC_LCTRL)<<8 | (KC_A + (code-0x01));
case 0x1B: return KC_ESC;
case 0x1C: return KC_RIGHT;
case 0x1D: return KC_LEFT;
case 0x1E: return KC_UP;
case 0x1F: return KC_DOWN;
case 0x20: return KC_SPACE;
case 0x21: return MOD_BIT(KC_LSHIFT)<<8 | KC_1; // !
case 0x22: return MOD_BIT(KC_LSHIFT)<<8 | KC_QUOTE; // "
case 0x23: return MOD_BIT(KC_LSHIFT)<<8 | KC_3; // #
case 0x24: return MOD_BIT(KC_LSHIFT)<<8 | KC_4; // $
case 0x25: return MOD_BIT(KC_LSHIFT)<<8 | KC_5; // %
case 0x26: return MOD_BIT(KC_LSHIFT)<<8 | KC_7; // &
case 0x27: return KC_QUOTE; // '
case 0x28: return MOD_BIT(KC_LSHIFT)<<8 | KC_9; // (
case 0x29: return MOD_BIT(KC_LSHIFT)<<8 | KC_0; // )
case 0x2A: return MOD_BIT(KC_LSHIFT)<<8 | KC_8; // *
case 0x2B: return MOD_BIT(KC_LSHIFT)<<8 | KC_EQUAL; // +
case 0x2C: return KC_COMMA; // ,
case 0x2D: return KC_MINUS; // -
case 0x2E: return KC_DOT; // .
case 0x2F: return KC_SLASH; // /
case 0x30: return KC_0;
case 0x31 ... 0x39: // 1-9
return KC_1 + (code-0x31);
case 0x3A: return MOD_BIT(KC_LSHIFT)<<8 | KC_SCLN; // :
case 0x3B: return KC_SCLN; // ;
case 0x3C: return MOD_BIT(KC_LSHIFT)<<8 | KC_COMMA; // <
case 0x3D: return KC_EQUAL; // =
case 0x3E: return MOD_BIT(KC_LSHIFT)<<8 | KC_DOT; // >
case 0x3F: return MOD_BIT(KC_LSHIFT)<<8 | KC_SLASH; // ?
case 0x40: return MOD_BIT(KC_LSHIFT)<<8 | KC_2; // @
case 0x41 ... 0x5A: // A-Z
return MOD_BIT(KC_LSHIFT)<<8 | (KC_A + (code-0x41));
case 0x5B: return KC_LBRACKET; // [
case 0x5C: return KC_BSLASH; //
case 0x5D: return KC_RBRACKET; // ]
case 0x5E: return MOD_BIT(KC_LSHIFT)<<8 | KC_6; // ^
case 0x5F: return MOD_BIT(KC_LSHIFT)<<8 | KC_MINUS; // _
case 0x61 ... 0x7A: // a-z
return KC_A + (code-0x61);
case 0x7B: return MOD_BIT(KC_LSHIFT)<<8 | KC_LBRACKET; // {
case 0x7C: return MOD_BIT(KC_LSHIFT)<<8 | KC_BSLASH; // |
case 0x7D: return MOD_BIT(KC_LSHIFT)<<8 | KC_RBRACKET; // }
case 0x7E: return MOD_BIT(KC_LSHIFT)<<8 | KC_GRAVE; // }
case 0x7F: return KC_DELETE; //
}
return 0;
}
uint8_t matrix_scan(void)
{
uint16_t code = serial_recv2();
if (code == -1) {
return 0;
}
print_hex8(code); print(" ");
// echo back
serial_send(code);
type_key(code2key(code));
return code;
}
inline
bool matrix_has_ghost(void)
{
return false;
}
inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
return false;
}
inline
matrix_row_t matrix_get_row(uint8_t row)
{
return 0;
}
void matrix_print(void)
{
print("\nr/c 0123456789ABCDEF\n");
for (uint8_t row = 0; row < matrix_rows(); row++) {
phex(row); print(": ");
pbin_reverse(matrix_get_row(row));
print("\n");
}
}

View File

@ -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

View File

@ -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.

View File

@ -0,0 +1,74 @@
/*
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)) \
)
/*
* 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

View File

@ -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 ??
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

View File

@ -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)]) };
}

View File

@ -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 }, \
*/

View File

@ -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;
}

View File

@ -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),
};

View File

@ -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)
{
}

View File

@ -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;
}

View File

@ -2,7 +2,7 @@ M0110/M0110A to USB keyboard converter
======================================
This firmware converts the protocol of Apple Macintosh keyboard **M0110**, **M0110A** and **M0120** into USB. Target of this project is USB AVR controller **ATmega32U4**. Using this converter you can revive these retro keyboards with modern computer.
Pics of **M0110 + M0120** and **M0110A**.
Pictures of **M0110 + M0120** and **M0110A**.
![M0110+M0120](http://i.imgur.com/dyvXb2Tm.jpg)
![M0110A](http://i.imgur.com/HuHOEoHm.jpg)
@ -31,7 +31,7 @@ Note that original cable used with Mac is **straight** while phone handset cable
<http://en.wikipedia.org/wiki/Modular_connector#4P4C>
Close-up pic of handset cable. You can see one end of plug has reverse color codes against the other. Click to enlarge.
Close-up picture of handset cable. You can see one end of plug has reverse color codes against the other. Click to enlarge.
[![4P4C cable](http://i.imgur.com/3S9P1mYm.jpg?1)](http://i.imgur.com/3S9P1mY.jpg?1)
[Teensy]: http://www.pjrc.com/teensy/
@ -43,12 +43,12 @@ Close-up pic of handset cable. You can see one end of plug has reverse color cod
![Jack fig](http://www.kbdbabel.org/conn/kbd_connector_macplus.png)
### Pull-up Registor
You may need pull-up registors on signal lines(`CLOCK`, `DATA`) in particular when you have long or coiled cable. **1k-10k Ohm** will be OK for this purpose. In that case the converter may not read signal from keyboard correctly without pull-up resistors.
### Pull-up Resistor
You may need pull-up resistors on signal lines(`CLOCK`, `DATA`) in particular when you have long or coiled cable. **1k-10k Ohm** will be OK for this purpose. In that case the converter may not read signal from keyboard correctly without pull-up resistors.
Building Frimware
Building Firmware
-----------------
To compile firmware you need AVR GCC. You can edit *Makefile* and *config.h* to change compile options and pin configuration.

View File

@ -1,5 +1,5 @@
# Target file name (without extension).
TARGET = ps2_usb_jis
TARGET = next_usb
# Directory common source filess exist
TOP_DIR = ../..
@ -7,6 +7,12 @@ 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
@ -24,44 +30,26 @@ MCU = atmega32u4 # Teensy 2.0
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
NKRO_ENABLE = yes # USB Nkey Rollover
CONSOLE_ENABLE = yes # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
#NKRO_ENABLE = yes # USB Nkey Rollover
#PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened)
#PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin
PS2_USE_BUSYWAIT = yes # uses primitive reference code
# keyboard dependent files
SRC = keymap_jis.c \
matrix.c \
led.c
ifdef PS2_USE_USART
SRC += protocol/ps2_usart.c
OPT_DEFS += -DPS2_USE_USART
endif
ifdef PS2_USE_INT
SRC += protocol/ps2.c
OPT_DEFS += -DPS2_USE_INT
endif
ifdef PS2_USE_BUSYWAIT
SRC += protocol/ps2.c
OPT_DEFS += -DPS2_USE_BUSYWAIT
endif
#CONFIG_H = config_pjrc_usart.h
CONFIG_H = config.h
#---------------- Programming Options --------------------------
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
SRC += next_kbd.c
# Search Path
@ -69,7 +57,7 @@ VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/pjrc.mk
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/protocol/pjrc.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

45
converter/next_usb/README Normal file
View File

@ -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

150
converter/next_usb/config.h Normal file
View File

@ -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))) \
)

177
converter/next_usb/keymap.c Normal file
View File

@ -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)]) };
}

55
converter/next_usb/led.c Normal file
View File

@ -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)
{
}

269
converter/next_usb/matrix.c Normal file
View File

@ -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;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

View File

@ -16,11 +16,11 @@ Connector
(receptacle)
Wiring: You can change this with ediging config.h.
Wiring: You can change this with editing config.h.
Pin mini DIN MCU
----------------------------------
1 ~RST PD1
1 ~RST(TXD) PD3
2 GND GND
3 ~RDY PD4
4 RXD PD2
@ -34,12 +34,9 @@ Wiring: You can change this with ediging config.h.
Protocol
--------
Singnal: Asynchronous, Positive logic, 19200baud, Least bit first
Signal: Asynchronous, Positive logic, 19200baud, Least bit first
Frame format: 1-Start bit(Lo), 8-Data bits, Odd-Parity, 1-Stop bit
This converter uses software method for testing purpose. AVR UART engine will work better.
Build Firmware

View File

@ -1,3 +1,6 @@
#
# Makefile for Teensy
#
# Target file name (without extension).
TARGET = ps2_usb_lufa
@ -59,7 +62,7 @@ ARCH = AVR8
F_USB = $(F_CPU)
# Interrupt driven control endpoint task(+60)
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Boot Section Size in *bytes*
@ -68,7 +71,7 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Atmel DFU loader 4096
# LUFA bootloader 4096
# USBaspLoader 2048
OPT_DEFS += -DBOOTLOADER_SIZE=4096
OPT_DEFS += -DBOOTLOADER_SIZE=512
# Build Options

View File

@ -0,0 +1,98 @@
#
# Makefile for TMK keyboard converter rev2
# https://github.com/tmk/keyboard_converter#pcb-rev1
#
# Target file name (without extension).
TARGET = ps2_usb_tmk_rev1
# 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
ifdef KEYMAP
SRC := keymap_$(KEYMAP).c $(SRC)
else
SRC := keymap_plain.c $(SRC)
endif
CONFIG_H = config_tmk_rev1.h
# MCU name
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)
# 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
# PS/2 Options
#
PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened)
#PS2_USE_BUSYWAIT = yes # uses primitive reference code
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

View File

@ -0,0 +1,98 @@
#
# Makefile for TMK keyboard converter rev2
# https://github.com/tmk/keyboard_converter#pcb-rev2
#
# Target file name (without extension).
TARGET = ps2_usb_tmk_rev2
# 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
ifdef KEYMAP
SRC := keymap_$(KEYMAP).c $(SRC)
else
SRC := keymap_plain.c $(SRC)
endif
CONFIG_H = config_tmk_rev2.h
# MCU name
MCU = atmega32u2
# 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)
# 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
# PS/2 Options
#
PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin
#PS2_USE_BUSYWAIT = yes # uses primitive reference code
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

View File

@ -1,50 +1,59 @@
PS/2 to USB keyboard converter
==============================
This firmware converts PS/2 keyboard protocol to USB and supports only Scan Code Set 2.
PS/2 signal handling implementations
------------------------------------
Following three methods are used to implement PS/2 signal handling.
### Simple and stupid busy-wait(ps2_busywait.c)
This is expected to implemented with portable C code for reference.
### Interrupt driven(ps2_interrupt.c)
Uses pin interrupt to detect falling edge of clock line.
### USART hardware module(ps2_usart.c)
Uses AVR USART engine to recevie PS/2 signal.
To select method edit Makefile.
This firmware converts PS/2 keyboard protocol to USB.(It supports Scan Code Set 2.)
Connect Wires
-------------
In case of Teensy2.0(ATMega32U4):
1. Connect Vcc and GND.
2. Connect Clock and Data line.
- Busywait: Clock is on PD5 and Data on PD2.
- Interrupt: Clock is on PD1 and Data on PD2.
- USART: Clock is on PD5 and Data on PD2.
1. Connect **Vcc** and **GND**.
2. Connect **Clock** and **Data** line.
- **Interrupt**: **Clock** is on `PD1` and **Data** on `PD0`.(Recommended. Soarer's converter compatible)
- **Busywait**: **Clock** is on `PD1` and **Data** on `PD0`.
- **USART**: **Clock** is on `PD5` and **Data** on `PD2`.
3. Optionally you need pull-up register. 1K-10K Ohm is OK.
To change pin configuration edit config.h.
Build Frimware
Build Firmware
--------------
Just run `make`:
For **PJRC Teensy** just run `make`:
$ make clean
$ make
To select keymap:
$ make clean
$ make KEYMAP=[plain|jis|spacefn|...]
After that you will find HEX file `ps2_usb_lufa.hex` in current directory.
- For **TMK converter Rev.1** use `make -f Makefile.tmk_rev1` instead of `make` and HEX file is `ps2_usb_tmk_rev1.hex`.
- For **TMK converter Rev.2** use `make -f Makefile.tmk_rev2` instead of `make` and HEX file is `ps2_usb_tmk_rev2.hex`.
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.
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 README.md of top directory) and existent keymap files.
PS/2 signal handling implementations
------------------------------------
Following three methods can be used to implement PS/2 signal handling.
### Simple and stupid busy-wait(ps2_busywait.c)
This is expected to implemented with portable C code for reference.
### Interrupt driven(ps2_interrupt.c)
Uses pin interrupt to detect falling edge of clock line.
### USART hardware module(ps2_usart.c)
Uses AVR USART engine to receive PS/2 signal.
To select method edit Makefile.
V-USB Support

View File

@ -0,0 +1,147 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include <avr/interrupt.h>
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6512
#define DEVICE_VER 0x0001
#define MANUFACTURER t.m.k.
#define PRODUCT PS/2 keyboard converter
#define DESCRIPTION convert PS/2 keyboard to USB
/* matrix size */
#define MATRIX_ROWS 32 // keycode bit: 3-0
#define MATRIX_COLS 8 // keycode bit: 6-4
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) || \
keyboard_report->mods == (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RSHIFT)) \
)
//#define NO_SUSPEND_POWER_DOWN
/*
* PS/2 Busywait
*/
#ifdef PS2_USE_BUSYWAIT
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 5
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 2
#endif
/*
* PS/2 USART
*/
#ifdef PS2_USE_USART
#if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
/* XCK for clock line and RXD for data line */
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 5
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 2
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */
/* set DDR of CLOCK as input to be slave */
#define PS2_USART_INIT() do { \
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
UCSR1C = ((1 << UMSEL10) | \
(3 << UPM10) | \
(0 << USBS1) | \
(3 << UCSZ10) | \
(0 << UCPOL1)); \
UCSR1A = 0; \
UBRR1H = 0; \
UBRR1L = 0; \
} while (0)
#define PS2_USART_RX_INT_ON() do { \
UCSR1B = ((1 << RXCIE1) | \
(1 << RXEN1)); \
} while (0)
#define PS2_USART_RX_POLL_ON() do { \
UCSR1B = (1 << RXEN1); \
} while (0)
#define PS2_USART_OFF() do { \
UCSR1C = 0; \
UCSR1B &= ~((1 << RXEN1) | \
(1 << TXEN1)); \
} while (0)
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1))
#define PS2_USART_RX_DATA UDR1
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1)))
#define PS2_USART_RX_VECT USART1_RX_vect
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
/* XCK for clock line and RXD for data line */
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 4
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0
/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */
/* set DDR of CLOCK as input to be slave */
#define PS2_USART_INIT() do { \
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
UCSR0C = ((1 << UMSEL00) | \
(3 << UPM00) | \
(0 << USBS0) | \
(3 << UCSZ00) | \
(0 << UCPOL0)); \
UCSR0A = 0; \
UBRR0H = 0; \
UBRR0L = 0; \
} while (0)
#define PS2_USART_RX_INT_ON() do { \
UCSR0B = ((1 << RXCIE0) | \
(1 << RXEN0)); \
} while (0)
#define PS2_USART_RX_POLL_ON() do { \
UCSR0B = (1 << RXEN0); \
} while (0)
#define PS2_USART_OFF() do { \
UCSR0C = 0; \
UCSR0B &= ~((1 << RXEN0) | \
(1 << TXEN0)); \
} while (0)
#define PS2_USART_RX_READY (UCSR0A & (1<<RXC0))
#define PS2_USART_RX_DATA UDR0
#define PS2_USART_ERROR (UCSR0A & ((1<<FE0) | (1<<DOR0) | (1<<UPE0)))
#define PS2_USART_RX_VECT USART_RX_vect
#endif
#endif
#endif

View File

@ -0,0 +1,86 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include <avr/interrupt.h>
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6512
#define DEVICE_VER 0x0001
#define MANUFACTURER t.m.k.
#define PRODUCT PS/2 keyboard converter
#define DESCRIPTION convert PS/2 keyboard to USB
/* matrix size */
#define MATRIX_ROWS 32 // keycode bit: 3-0
#define MATRIX_COLS 8 // keycode bit: 6-4
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) || \
keyboard_report->mods == (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RSHIFT)) \
)
//#define NO_SUSPEND_POWER_DOWN
/*
* PS/2 Busywait
*/
#ifdef PS2_USE_BUSYWAIT
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 1
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0
#endif
/*
* PS/2 Pin interrupt
*/
#ifdef PS2_USE_INT
/* uses INT1 for clock line(ATMega32U4) */
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 1
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0
#define PS2_INT_INIT() do { \
EICRA |= ((1<<ISC11) | \
(0<<ISC10)); \
} while (0)
#define PS2_INT_ON() do { \
EIMSK |= (1<<INT1); \
} while (0)
#define PS2_INT_OFF() do { \
EIMSK &= ~(1<<INT1); \
} while (0)
#define PS2_INT_VECT INT1_vect
#endif
#endif

View File

@ -20,9 +20,10 @@ 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 = atmega32u4 # Teensy 2.0
#MCU = at90usb646 # Teensy++ 1.0
#MCU = at90usb1286 # Teensy++ 2.0
MCU = atmega32u2
# Processor frequency.

View File

@ -34,11 +34,11 @@ Connector
Protocol
--------
Singnal: Asynchronous, Negative logic, 1200baud, No Flow control
Signal: Asynchronous, Negative logic, 1200baud, No Flow control
Frame format: 1-Start bit, 8-Data bits, No-Parity, 1-Stop bit
AVR USART engine expects positive logic while Sun keyboard signal is negative.
To use AVR UART engine you need exteral inverter in front of RX and TX pin.
To use AVR UART engine you need external inverter in front of RX and TX pin.
Otherwise you can software serial routine to communicate the keyboard.
This converter uses software method, you doesn't need any inverter part.

View File

@ -77,12 +77,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
K63, K64,K65,K66,K67,K68,K69,K6A,K6B,K6C,K6D, K0D,K14,K6E, \
K77,K13, K78, K79, K7A,K43,K62,K18,K1B,K1C \
) KEYMAP( \
HELP, K05,K06,K08,K0A, K0C,K0E,K10,K11, K12,K07,K09,K0B, PSCR,SLCK,PAUS, MUTE,VOLD,VOLU,PWR, \
HELP, K05,K06,K08,K0A, K0C,K0E,K10,K11, K12,K07,K09,K0B, PSCR,SLCK,PAUS, MUTE,VOLD,VOLU,K30, \
K01, AGAIN, K1D,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27,K28,K29,K58,K2A, K2C, K34, K60, K62, PSLS,PAST,PMNS, \
MENU, UNDO, K35, K36,K37,K38,K39,K3A,K3B,K3C,K3D,K3E,K3F,K40,K41, K2B, K42, K4A, K7B, P7, P8, P9, PPLS, \
SELECT, COPY, K4C, K4D,K4E,K4F,K50,K51,K52,K53,K54,K55,K56,K57, K59, P4, P5, P6, \
EXECUTE,PASTE, K63, K64,K65,K66,K67,K68,K69,K6A,K6B,K6C,K6D, K6E, K14, P1, P2, P3, PENT, \
FIND, CUT, K77,K13, K78, HENK, K79, MHEN, KANA, K7A,K43,K0D, K18, K1B, K1C, P0, PDOT \
SELECT, K33, K4C, K4D,K4E,K4F,K50,K51,K52,K53,K54,K55,K56,K57, K59, P4, P5, P6, \
EXECUTE,K49, K63, K64,K65,K66,K67,K68,K69,K6A,K6B,K6C,K6D, K6E, K14, P1, P2, P3, PENT, \
FIND, K61, K77,K13, K78, HENK, K79, MHEN, KANA, K7A,K43,K0D, K18, K1B, K1C, P0, PDOT \
)

View File

@ -63,7 +63,8 @@ uint8_t matrix_cols(void)
void matrix_init(void)
{
print_enable = true;
DDRD |= (1<<6);
PORTD |= (1<<6);
debug_enable = true;
serial_init();

View File

@ -6,7 +6,7 @@ Hardware requirement
Arduino Leonardo
http://arduino.cc/en/Main/ArduinoBoardLeonardo
Circuit@Home USB Host Sheild 2.0
Circuit@Home USB Host Shield 2.0
http://www.circuitsathome.com/products-page/arduino-shields/usb-host-shield-2-0-for-arduino

View File

@ -12,7 +12,7 @@ X68000 keyboard has ALPS linear switches.
Hardware
--------
Target MCU is ATMega32u4 but other USB capable AVR will also work.
You can use PJRC Teensy as dev board.
You can use PJRC Teensy as development board.
http://www.pjrc.com/teensy/
Wiring:
@ -83,7 +83,7 @@ bit 6-0 following scan code
Data from computer
------------------
- LED contorol ON/OFF(0/1)
- LED control ON/OFF(0/1)
bit 7 1(fixed)
bit 6 全角
bit 5 ひらがな

View File

@ -14,7 +14,7 @@ dfj's NKRO(2010/06)
http://geekhack.org/showthread.php?p=204389#post204389
Terminogy
Terminology
---------
NKRO
ghost
@ -26,7 +26,7 @@ membrane
OS Support Status
-----------------
USB NKRO is possible *without* a custom driver.
At least following OSes supports.
At least following OS's supports.
Windows7 64bit
WindowsXP
Windows2000 SP4
@ -37,7 +37,7 @@ At least following OSes supports.
Custom Driver for USB NKRO
--------------------------
NOT NEEDED
at least when using fllowing report formats on Windows, Linux or MacOSX.
at least when using following report formats on Windows, Linux or MacOSX.
USB NKRO methods
@ -47,8 +47,8 @@ USB NKRO methods
If the keyboard has 2 virtual keyboard with Standard report(6KRO), it gets 12KRO.
Using this method means the keyboard is a composite device.
2. Exteded report
It needs large report size for this method to achive NKRO.
2. Extended report
It needs large report size for this method to achieve NKRO.
If a keyboard has 101keys, it needs 103byte report. It seems to be inefficient.
3. Bitmap report
@ -122,8 +122,8 @@ Considerations
Compatibility
boot protocol
minor/old system
Some BIOS doesn't send SET_PROTCOL request, a keyboard can't switch to boot protocol mode.
This may cuase a problem on a keyboard which uses other report than Standard.
Some BIOS doesn't send SET_PROTOCOL request, a keyboard can't switch to boot protocol mode.
This may cause a problem on a keyboard which uses other report than Standard.
Reactivity
USB polling time
OS/Driver processing time

View File

@ -40,7 +40,7 @@ Move to project directory in the firmware source.
Build firmware using GNU `make` command. You'll see `<project>_<variant>.hex` file in that directory unless something unexpected occurs in build process.
mkae -f Makefile.<variant> clean
make -f Makefile.<variant> clean
make -f Makefile.<variant>
@ -71,14 +71,14 @@ Or to program with `dfu-programmer` run:
#### FLIP GUI tutorial
1. On menu bar click Device -> Select, then. `ATmega32u4`.
2. On menu bar click Settings -> Communication -> USB, then click 'Open' button on 'USB Port Connection' dialog.
At this point you'll see greyouted widgets on the app get colored and ready.
At this point you'll see grey-outed widgets on the app get colored and ready.
3. On menu bar click File -> Load HEX File, then select your firmware hex file on File Selector dialog.
4. On 'Operations Flow' panel click 'Run' button to load the firmware binary to the chip. Note that you should keep 'Erase', 'Blank Check', 'Program' and 'Verify' check boxes selected.
5. Re-plug USB cord or click 'Start Application' button to restart your controller.
Done.
See also these instaructions if you need.
See also these instructions if you need.
- <http://code.google.com/p/micropendous/wiki/LoadingFirmwareWithFLIP>
- <http://www.atmel.com/Images/doc7769.pdf>
@ -95,7 +95,7 @@ Or use this command if you have command line version of Teensy Loader installed.
### 4. Program with Other programmer
You may want to use other programmer like `avrdude` with AVRISPmkII, Aruduino or USBasp. In that case you can still use make target `program` for build with configuring `PROGRAM_CMD` in Makefile.
You may want to use other programmer like `avrdude` with AVRISPmkII, Arduino or USBasp. In that case you can still use make target `program` for build with configuring `PROGRAM_CMD` in Makefile.
$ make -f Makefile.<variant> program
@ -135,7 +135,7 @@ Optional. Note that ***comment out*** to disable them.
#BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
### 3. Programmer
Optional. Set proper command for your controller, bootloader and programmer. This command can be used with `make program`. Not needed if you use `FLIP`, `dfu-programmer` or `Teesy Loader`.
Optional. Set proper command for your controller, bootloader and programmer. This command can be used with `make program`. Not needed if you use `FLIP`, `dfu-programmer` or `Teensy Loader`.
# avrdude with AVRISPmkII
PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex
@ -158,7 +158,7 @@ Config.h Options
/* Mechanical locking CapsLock support. Use KC_LCAP instead of KC_CAPS in keymap */
#define CAPSLOCK_LOCKING_ENABLE
/* Locking CapsLock resynchronize hack */
/* Locking CapsLock re-synchronize hack */
#define CAPSLOCK_LOCKING_RESYNC_ENABLE
### 3. Disable Debug and Print

View File

@ -68,7 +68,7 @@ On the other hand, you shall change `layer_state` to overlay base layer with som
Note that ***higher layer has higher priority on stack of layers***, namely firmware falls down from top layer to bottom to look up keycode. Once it spots keycode other than **`KC_TRNS`**(transparent) on a layer it stops searching and lower layers aren't referred.
You can place `KC_TRNS` on overlay layer changes just part of layout to fall back on lower or base layer.
Key with `KC_TRANS` doen't has its own keycode and refers to lower valid layers for keycode, instead.
Key with `KC_TRANS` doesn't has its own keycode and refers to lower valid layers for keycode, instead.
See example below.
@ -155,12 +155,12 @@ You can find other keymap definitions in file `keymap.c` located on project dire
## 1. Keycode
See [`common/keycode.h`](../common/keycode.h) or keycode table below for the detail. Keycode is internal **8bit code** to inidicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action registers key to host on press and unregister on release, while some of other keycodes has some special actions like `Fn` keys, Media contorl keys, System control keys and Mousekeys.
See [`common/keycode.h`](../common/keycode.h) or keycode table below for the detail. Keycode is internal **8bit code** to indicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action registers key to host on press and unregister on release, while some of other keycodes has some special actions like `Fn` keys, Media control keys, System control keys and Mousekeys.
***In `KEYMAP()` macro you should omit prefix part `KC_` of keycode to keep keymap compact.*** For example, just use `A` instead you place `KC_A` in `KEYMAP()`. Some keycodes has 4-letter **short name** in addition to descriptive name, you'll prefer short one in `KEYMAP()`.
### 1.0 Other key
- `KC_NO` for no aciton
- `KC_NO` for no action
- `KC_TRNS` for layer transparency (See above)
### 1.1 Normal key
@ -192,7 +192,7 @@ There are 8 modifiers which has discrimination between left and right.
- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation
### 1.5 Fn key
`KC_FNnn` are keycodes for `Fn` key which not given any actions at the beginning unlike most of keycodes has its own inborn action. To use these keycodes in `KEYMAP()` you need to assign action you want at first. Action of `Fn` key is defined in `fn_actions[]` and its index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` keyocde indicates the action defined in first element of the array. ***32 `Fn` keys can be defined at most.***
`KC_FNnn` are keycodes for `Fn` key which not given any actions at the beginning unlike most of keycodes has its own inborn action. To use these keycodes in `KEYMAP()` you need to assign action you want at first. Action of `Fn` key is defined in `fn_actions[]` and its index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` keycode indicates the action defined in first element of the array. ***32 `Fn` keys can be defined at most.***
### 1.6 Keycode Table
See keycode table in [`doc/keycode.txt`](./keycode.txt) for description of keycodes.
@ -205,7 +205,7 @@ There are 8 modifiers which has discrimination between left and right.
## 2. Action
See [`common/action_code.h`](../common/action_code.h). Action is a **16bit code** and defines function to perform on events of a key like press, release, holding and tapping.
Most of keys just register 8bit scancode to host, but to support other complex features needs 16bit extended action codes internally. However, using 16bit action codes in keymap results in double size in memory compared to using jsut keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP()` instead of action codes.
Most of keys just register 8bit scancode to host, but to support other complex features needs 16bit extended action codes internally. However, using 16bit action codes in keymap results in double size in memory compared to using just keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP()` instead of action codes.
***You can just use keycodes of `Normal key`, `Modifier`, `Mousekey` and `System & Media key` in keymap*** to indicate corresponding actions instead of using action codes. While ***to use other special actions you should use keycode of `Fn` key defined in `fn_actions[]`.***
@ -230,7 +230,7 @@ You can define these actions on *'A'* key and *'left shift'* modifier with:
#### 2.1.2 Modified key
This action is comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes.
Say you want to assign a key to `Shift + 1` to get charactor *'!'* or `Alt + Tab` to switch application windows.
Say you want to assign a key to `Shift + 1` to get character *'!'* or `Alt + Tab` to switch application windows.
ACTION_MODS_KEY(MOD_LSFT, KC_1)
ACTION_MODS_KEY(MOD_LALT, KC_TAB)
@ -269,10 +269,10 @@ Default Layer is a layer which always is valid and referred to when actions is n
This sets Default Layer to given parameter `layer` and activate it.
ACTION_DEFAULT_LAYER(layer)
ACTION_DEFAULT_LAYER_SET(layer)
#### 2.2.2 Momentary Switch
#### 2.2.2 Momentary
Turns on `layer` momentarily while holding, in other words it activates when key is pressed and deactivate when released.
ACTION_LAYER_MOMENTARY(layer)
@ -342,7 +342,7 @@ Turns on layer only and clear all layer on release..
ACTION_LAYER_BIT_XOR(part, bits, on)
ACTION_LAYER_BIT_SET(part, bits, on)
These actions works with prameters as following code.
These actions works with parameters as following code.
uint8_t shift = part*4;
uint32_t mask = (bits&0x10) ? ~(0xf<<shift) : 0;
@ -368,7 +368,7 @@ Default Layer also has bitwise operations, they are executed when key is release
MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )
#### 2.3.1 Macro Commands
- **I()** change interavl of stroke.
- **I()** change interval of stroke.
- **D()** press key
- **U()** release key
- **T()** type key(press and release)
@ -377,7 +377,7 @@ Default Layer also has bitwise operations, they are executed when key is release
#### 2.3.2 Examples
***TODO: sample impl***
***TODO: sample implementation***
See `keyboard/hhkb/keymap.c` for sample.
@ -403,7 +403,7 @@ To define tappable `Function` action in keymap use this.
void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)
This C function is called every time key is operated, argument `id` selects action to be performed and `opt` can be used for option. Functon `id` can be 0-255 and `opt` can be 0-15.
This C function is called every time key is operated, argument `id` selects action to be performed and `opt` can be used for option. Function `id` can be 0-255 and `opt` can be 0-15.
`keyrecord_t` is comprised of key event and tap count. `keyevent_t` indicates which and when key is pressed or released. From `tap_count` you can know tap state, 0 means no tap. These information will be used in user function to decide how action of key is performed.
@ -423,7 +423,7 @@ This C function is called every time key is operated, argument `id` selects acti
uint8_t row;
} key_t;
***TODO: sample impl***
***TODO: sample implementation***
See `keyboard/hhkb/keymap.c` for sample.
@ -444,6 +444,10 @@ Step through backlight levels.
ACTION_BACKLIGHT_STEP()
Turn a specific backlight level on or off.
ACTION_BACKLIGHT_LEVEL(1)
#### 2.5.2 Turn on / off backlight
Turn the backlight on and off without changing level.
@ -462,8 +466,8 @@ This action makes 'Layer 1' active(valid) on key press event and inactive on rel
ACTION_LAYER_MOMENTARY(1)
Note that after switching on press the actions on destinaton layer(Layer 1) are perfomed.
***Thus you shall need to place an action to go back on destination layer***, or you will be stuck in destination layer without way to get back. Usually you need to palce same action or 'KC_TRNS` on destination layer to get back.
Note that after switching on press the actions on destination layer(Layer 1) are performed.
***Thus you shall need to place an action to go back on destination layer***, or you will be stuck in destination layer without way to get back. Usually you need to place same action or 'KC_TRNS` on destination layer to get back.
### 3.2 Toggle switching
@ -480,7 +484,7 @@ These actions switch a layer only while holding a key but register the key on ta
ACTION_LAYER_TAP_KEY(2, KC_SCLN)
With this you can place a layer switching action on normal key like ';' without losing its original key register function. This action allows you to have layer switchig action without necessity of a dedicated key. It means you can have it even on home row of keyboard.
With this you can place a layer switching action on normal key like ';' without losing its original key register function. This action allows you to have layer switching action without necessity of a dedicated key. It means you can have it even on home row of keyboard.
@ -511,17 +515,17 @@ Layer switching with tap key:
### 4.2 Tap Toggle
This is a feature to assign both toggle layer and momentary switch layer action to just same one physical key. It works as mementary layer switch when holding a key but toggle switch with several taps.
This is a feature to assign both toggle layer and momentary switch layer action to just same one physical key. It works as momentary layer switch when holding a key but toggle switch with several taps.
ACTION_LAYER_TAP_TOGGLE(1)
### 4.3 Oneshot Modifier
This runs onetime effect swhich modify only on just one following key. It works as normal modifier key when holding down while oneshot modifier when tapping.
This runs onetime effects which modify only on just one following key. It works as normal modifier key when holding down while oneshot modifier when tapping.
ACTION_MODS_ONESHOT(MOD_LSFT)
Say you want to type 'The', you have to push and hold Shift key before type 't' then release it before type 'h' and 'e', otherwise you'll get 'THe' or 'the' unintentionally. With Oneshot Modifier you can tap Shift then type 't', 'h' and 'e' normally, you don't need to holding Shift key properly here. This mean you can realease Shift before 't' is pressed down.
Say you want to type 'The', you have to push and hold Shift key before type 't' then release it before type 'h' and 'e', otherwise you'll get 'THe' or 'the' unintentionally. With Oneshot Modifier you can tap Shift then type 't', 'h' and 'e' normally, you don't need to holding Shift key properly here. This mean you can release Shift before 't' is pressed down.
Oneshot effect is cancel unless following key is pressed down within `ONESHOT_TIMEOUT` of `config.h`. No timeout when it is `0` or not defined.

View File

@ -48,7 +48,7 @@ Other Keyboard Firmware Projects
- <http://geekhack.org/index.php?topic=19458.0>
## kbdbabel.org[converter][vintage][protocol][8051]
Great resourse of vintage keyboard protocol information and code
Great resource of vintage keyboard protocol information and code
- <http://www.kbdbabel.org/>

View File

@ -1,4 +1,4 @@
Replacable USB Controller for Apple IIgs/Standard(M0116)
Replaceable USB Controller for Apple IIgs/Standard(M0116)
JeffreySung(nattyman@gmail.com)
===============================
@ -32,7 +32,7 @@ PJRC Teensy
1. Bypass #31 pin(from board) to E4(Teensy)
2. Bypass #30 pin(from board) to F2(Teensy)
3. Bypass #6 pin(from board) to A0(Teensy)
4. Refer doc directory
4. Refer to documentation directory
To Do
=====

View File

@ -80,7 +80,7 @@ See [keymap_plain.c](keymap_plain.c) for detail.
### 3. Hasu
This is my favourite keymap with HHKB Fn, Vi cursor and Mousekey layer. See [keymap_hasu.c](keymap_hasu.c) for detail.
This is my favorite keymap with HHKB Fn, Vi cursor and Mousekey layer. See [keymap_hasu.c](keymap_hasu.c) for detail.
### 4. SpaceFN

View File

@ -102,7 +102,7 @@ ARCH = AVR8
F_USB = $(F_CPU)
# Interrupt driven control endpoint task
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Boot Section Size in *bytes*

View File

@ -24,7 +24,7 @@ See README of [tmk_keyboard] for more.
* No risks: Everything is all reversible
* No need for PCB trace patching, case cutting or any other destructive mod
* Can keep original controller intact
* Can change all HHKB behaviour as you like
* Can change all HHKB behavior as you like
###Cons
* Void your warranty
@ -54,11 +54,11 @@ Several version of keymap are available in advance but you are recommended to de
### Program
First, push reset button on board to start bootloader.
This command programs the controller with [dfu-programmer] if the tool is intalled and configured properly.
This command programs the controller with [dfu-programmer] if the tool is installed and configured properly.
$ make dfu
Or you can also use [FLIP] command to program. Also the tool should be intalled and configured properly. FLIP GUI app is also available.
Or you can also use [FLIP] command to program. Also the tool should be installed and configured properly. FLIP GUI application is also available.
$ make flip
@ -70,7 +70,7 @@ To define your own keymap create file named `keymap_<name>.c` and see keymap doc
##Hardware
You have some options for hardware. Development boards with USB AVR family(ATMega32U4, AT90USB1286) like Teensy will work while MegaAVR with [V-USB] library is also cheapear option for DIY.
You have some options for hardware. Development boards with USB AVR family(ATMega32U4, AT90USB1286) like Teensy will work while MegaAVR with [V-USB] library is also cheaper option for DIY.
###1. TMK Alt Controller Board
TMK designed [Keyboard Controller Board for HHKB Pro2(KiCad project)](https://github.com/tmk/HHKB_controller).

View File

@ -25,7 +25,7 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
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, FN3, QUOT,FN4, \
FN5, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \
FN11,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \
LGUI,LALT, FN6, RALT,RGUI),
/* Layer 1: HHKB mode (HHKB Fn)
@ -131,12 +131,9 @@ const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
/* id for user defined functions */
enum function_id {
LSHIFT_LPAREN,
RSHIFT_RPAREN,
};
enum macro_id {
LSHIFT_PAREN,
RSHIFT_PAREN,
HELLO,
VOLUP,
};
@ -163,10 +160,7 @@ const uint16_t fn_actions[] PROGMEM = {
// [8] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // LControl with tap Backspace
// [9] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC), // LControl with tap Esc
[11] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // Function: LShift with tap '('
[12] = ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // Function: RShift with tap ')'
// [13] = ACTION_MACRO_TAP(LSHIFT_PAREN), // Macro: LShift with tap '('
// [14] = ACTION_MACRO_TAP(RSHIFT_PAREN), // Macro: RShift with tap ')'
[11] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // Function: LShift with tap '('
// [15] = ACTION_MACRO(HELLO), // Macro: say hello
// [9] = ACTION_MACRO(VOLUP), // Macro: media key
};
@ -177,32 +171,13 @@ const uint16_t fn_actions[] PROGMEM = {
*/
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
keyevent_t event = record->event;
tap_t tap = record->tap;
switch (id) {
case LSHIFT_PAREN:
if (tap.count > 0 && !tap.interrupted) {
return (event.pressed ?
MACRO( D(LSHIFT), D(9), U(9), U(LSHIFT), END ) : MACRO_NONE);
} else {
return (event.pressed ?
MACRO( D(LSHIFT), END ) : MACRO( U(LSHIFT), END ) );
}
case RSHIFT_PAREN:
if (tap.count > 0 && !tap.interrupted) {
return (event.pressed ?
MACRO( D(RSHIFT), D(0), U(0), U(RSHIFT), END ) : MACRO_NONE);
} else {
return (event.pressed ?
MACRO( D(RSHIFT), END ) : MACRO( U(RSHIFT), END ) );
}
case HELLO:
return (event.pressed ?
return (record->event.pressed ?
MACRO( I(0), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
MACRO_NONE );
case VOLUP:
return (event.pressed ?
return (record->event.pressed ?
MACRO( D(VOLU), U(VOLU), END ) :
MACRO_NONE );
}
@ -216,48 +191,36 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
*/
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
keyevent_t event = record->event;
tap_t tap = record->tap;
if (record->event.pressed) dprint("P"); else dprint("R");
dprintf("%d", record->tap.count);
if (record->tap.interrupted) dprint("i");
dprint("\n");
switch (id) {
case LSHIFT_LPAREN:
// LShft + tap '('
// NOTE: cant use register_code to avoid conflicting with magic key bind
if (event.pressed) {
if (tap.count == 0 || tap.interrupted) {
//add_mods(MOD_BIT(KC_LSHIFT));
layer_on(1);
// Shift parentheses example: LShft + tap '('
// http://stevelosh.com/blog/2012/10/a-modern-space-cadet/#shift-parentheses
// http://geekhack.org/index.php?topic=41989.msg1304899#msg1304899
if (record->event.pressed) {
if (record->tap.count > 0 && !record->tap.interrupted) {
if (record->tap.interrupted) {
dprint("tap interrupted\n");
register_mods(MOD_BIT(KC_LSHIFT));
}
} else {
add_mods(MOD_BIT(KC_LSHIFT));
add_key(KC_9);
send_keyboard_report();
del_mods(MOD_BIT(KC_LSHIFT));
del_key(KC_9);
send_keyboard_report();
register_mods(MOD_BIT(KC_LSHIFT));
}
} else {
if (tap.count == 0 || tap.interrupted) {
//del_mods(MOD_BIT(KC_LSHIFT));
layer_off(1);
}
}
break;
case RSHIFT_RPAREN:
// RShift + tap ')'
if (event.pressed) {
if (tap.count == 0 || tap.interrupted) {
add_mods(MOD_BIT(KC_RSHIFT));
if (record->tap.count > 0 && !(record->tap.interrupted)) {
add_weak_mods(MOD_BIT(KC_LSHIFT));
send_keyboard_report();
register_code(KC_9);
unregister_code(KC_9);
del_weak_mods(MOD_BIT(KC_LSHIFT));
send_keyboard_report();
record->tap.count = 0; // ad hoc: cancel tap
} else {
add_mods(MOD_BIT(KC_RSHIFT));
add_key(KC_0);
send_keyboard_report();
del_mods(MOD_BIT(KC_RSHIFT));
del_key(KC_0);
send_keyboard_report();
}
} else {
if (tap.count == 0 || tap.interrupted) {
del_mods(MOD_BIT(KC_RSHIFT));
unregister_mods(MOD_BIT(KC_LSHIFT));
}
}
break;

View File

@ -18,7 +18,7 @@ Move to this directory then just run `make` like:
Use `Makefile.pjrc` if you want to use PJRC stack or use `Makefile.lufa` for LUFA stack.
Booloader
Bootloader
---------
The PCB is hardwired to run the bootloader if the key at the `Caps Lock` position is held down when connecting the keyboard.

View File

@ -0,0 +1,126 @@
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device.
# Please customize your programmer settings(PROGRAM_CMD)
#
# make teensy = Download the hex file to the device, using teensy_loader_cli.
# (must have teensy_loader_cli installed).
#
# make dfu = Download the hex file to the device, using dfu-programmer (must
# have dfu-programmer installed).
#
# make flip = Download the hex file to the device, using Atmel FLIP (must
# have Atmel FLIP installed).
#
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
# (must have dfu-programmer installed).
#
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
# (must have Atmel FLIP installed).
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# Target file name (without extension).
TARGET = lightsaber_lufa
# Directory common source filess exist
TOP_DIR = ../..
# Directory keyboard dependent files exist
TARGET_DIR = .
# List C source files here. (C dependencies are automatically generated.)
SRC = keymap.c \
matrix.c \
led.c \
backlight.c
CONFIG_H = config.h
# MCU name
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 = 8000000
#
# 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)
# Build Options
# comment out to disable the options.
#
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
#MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = yes # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
# Boot Section Size in bytes
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
OPT_DEFS += -DBOOTLOADER_SIZE=4096
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk
winkey: OPT_DEFS += -DLAYOUT_WINKEY
winkey: all

View File

@ -0,0 +1,94 @@
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device.
# Please customize your programmer settings(PROGRAM_CMD)
#
# make teensy = Download the hex file to the device, using teensy_loader_cli.
# (must have teensy_loader_cli installed).
#
# make dfu = Download the hex file to the device, using dfu-programmer (must
# have dfu-programmer installed).
#
# make flip = Download the hex file to the device, using Atmel FLIP (must
# have Atmel FLIP installed).
#
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
# (must have dfu-programmer installed).
#
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
# (must have Atmel FLIP installed).
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# Target file name (without extension).
TARGET = lightsaber_pjrc
# Directory common source filess exist
TOP_DIR = ../..
# Directory keyboard dependent files exist
TARGET_DIR = .
# keyboard dependent files
SRC = keymap.c \
matrix.c \
led.c \
backlight.c
CONFIG_H = config.h
# MCU name
MCU = atmega32u4
# Processor frequency.
# Normally the first thing your program should do is set the clock prescaler,
# so your program will run at the correct speed. You should also set this
# variable to same clock speed. The _delay_ms() macro uses this, and many
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 8000000
# Build Options
# comment out to disable the options.
#
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
#MOUSEKEY_ENABLE = yes # Mouse keys(+5000)
EXTRAKEY_ENABLE = yes # Audio control and System control(+600)
CONSOLE_ENABLE = yes # Console for debug
COMMAND_ENABLE = yes # Commands for debug and configuration
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
#NKRO_ENABLE = yes # USB Nkey Rollover(+500)
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/pjrc.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk
winkey: OPT_DEFS += -DLAYOUT_WINKEY
winkey: all

View File

@ -0,0 +1,26 @@
Lightsaber keyboard firmware
======================
Korean custom keyboard designed by Duck.
*Note that this is not the official firmware*
Supported models
----------------
All pcb options are supported.
Build
-----
Move to this directory then just run `make` like:
$ make -f Makefile.[pjrc|lufa]
Use `Makefile.pjrc` if you want to use PJRC stack or use `Makefile.lufa` for LUFA stack.
Bootloader
---------
The PCB is hardwired to run the bootloader if the key at the `one above backspace` position is held down when connecting the keyboard.
It is still possible to use Boot Magic and Command to access the bootloader though.

View File

@ -0,0 +1,86 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>
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 <avr/io.h>
#include "backlight.h"
/* Backlight pin configuration
*
* Alphas PB1 (high)
* Numeric PB2 (high)
* Mod+Num PB3 (high)
* Backside PD6 (high)
* TopRight PD7 (low)
* F-Row PE6 (high)
*/
void backlight_set(uint8_t level)
{
// Set as output.
DDRB |= (1<<1) | (1<<2) | (1<<3);
DDRD |= (1<<6) | (1<<7);
DDRE |= (1<<6);
if (level & BACKLIGHT_ALPHA)
{
PORTB |= (1<<1);
}
else
{
PORTB &= ~(1<<1);
}
if (level & BACKLIGHT_NUMERIC)
{
PORTB |= (1<<2);
}
else
{
PORTB &= ~(1<<2);
}
if (level & BACKLIGHT_MODNUM)
{
PORTB |= (1<<3);
}
else
{
PORTB &= ~(1<<3);
}
if (level & BACKLIGHT_BACKSIDE)
{
PORTD |= (1<<6);
}
else
{
PORTD &= ~(1<<6);
}
if (level & BACKLIGHT_TOPRIGHT)
{
PORTD &= ~(1<<7);
}
else
{
PORTD |= (1<<7);
}
if (level & BACKLIGHT_FROW)
{
PORTE |= (1<<6);
}
else
{
PORTE &= ~(1<<6);
}
}

View File

@ -0,0 +1,9 @@
enum backlight_level {
BACKLIGHT_ALPHA = 0b0000001,
BACKLIGHT_NUMERIC = 0b0000010,
BACKLIGHT_MODNUM = 0b0000100,
BACKLIGHT_BACKSIDE = 0b0001000,
BACKLIGHT_TOPRIGHT = 0b0010000,
BACKLIGHT_FROW = 0b0100000,
};

View File

@ -0,0 +1,46 @@
/*
Copyright 2013 Mathias Andersson <wraul@dbox.se>
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
/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6050
#define DEVICE_VER 0x0104
#define MANUFACTURER Duck
#define PRODUCT Lightsaber
/* message strings */
#define DESCRIPTION t.m.k. keyboard firmware for Lightsaber
/* matrix size */
#define MATRIX_ROWS 6
#define MATRIX_COLS 18
/* number of backlight levels */
#define BACKLIGHT_LEVELS 1
/* Set 0 if need no debouncing */
#define DEBOUNCE 5
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
)
#endif

View File

@ -0,0 +1,77 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Keymap for Lightsaber controller
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "report.h"
#include "host.h"
#include "debug.h"
#include "keymap.h"
// Convert physical keyboard layout to matrix array.
// This is a macro to define keymap easily in keyboard layout form.
#define KEYMAP( \
K5A, K5B, K5C, K5D, K5E, K5F, K5G, K5H, K5I, K5J, K5K, K5L, K5M, K5N, K5O, K5P, K5Q, K5R, \
K4A, K4B, K4C, K4D, K4E, K4F, K4G, K4H, K4I, K4J, K4K, K4L, K4M, K4N, K4O, K4P, K4Q, K4R, \
K3A, K3B, K3C, K3D, K3E, K3F, K3G, K3H, K3I, K3J, K3K, K3L, K3M, K3N, K3O, K3P, K3Q, K3R, \
K2A, K2B, K2C, K2D, K2E, K2F, K2G, K2H, K2I, K2J, K2K, K2L, K2M, K2N, K2O, K2P, K2Q, K2R, \
K1A, K1C, K1D, K1E, K1F, K1G, K1H, K1I, K1J, K1K, K1L, K1M, K1N, K1O, K1P, K1Q, K1R, \
K0A, K0B, K0C, K0G, K0K, K0L, K0M, K0N, K0O, K0P, K0Q, K0R \
) { \
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 */ \
/* 5 */ { KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_##K5F, KC_##K5G, KC_##K5H, KC_##K5I, KC_##K5J, KC_##K5K, KC_##K5L, KC_##K5M, KC_##K5N, KC_##K5O, KC_##K5P, KC_##K5Q, KC_##K5R}, \
/* 4 */ { KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_##K4F, KC_##K4G, KC_##K4H, KC_##K4I, KC_##K4J, KC_##K4K, KC_##K4L, KC_##K4M, KC_##K4N, KC_##K4O, KC_##K4P, KC_##K4Q, KC_##K4R}, \
/* 3 */ { KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F, KC_##K3G, KC_##K3H, KC_##K3I, KC_##K3J, KC_##K3K, KC_##K3L, KC_##K3M, KC_##K3N, KC_##K3O, KC_##K3P, KC_##K3Q, KC_##K3R}, \
/* 2 */ { KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F, KC_##K2G, KC_##K2H, KC_##K2I, KC_##K2J, KC_##K2K, KC_##K2L, KC_##K2M, KC_##K2N, KC_##K2O, KC_##K2P, KC_##K2Q, KC_##K2R}, \
/* 1 */ { KC_##K1A, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F, KC_##K1G, KC_##K1H, KC_##K1I, KC_##K1J, KC_##K1K, KC_##K1L, KC_NO, KC_##K1M, KC_##K1N, KC_##K1O, KC_##K1P, KC_##K1Q, KC_##K1R}, \
/* 0 */ { KC_##K0A, KC_##K0B, KC_##K0C, KC_NO, KC_NO, KC_##K0G, KC_NO, KC_NO, KC_##K0K, KC_NO, KC_##K0L, KC_NO, KC_##K0M, KC_##K0N, KC_##K0O, KC_##K0P, KC_##K0Q, KC_##K0R} \
}
#include "keymap_winkey.h"
#define KEYMAPS_SIZE (sizeof(keymaps) / sizeof(keymaps[0]))
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0]))
/* translates key to keycode */
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
{
if (layer < KEYMAPS_SIZE) {
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
} else {
// fall back to layer 0
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]);
}
}
/* translates Fn keycode to action */
action_t keymap_fn_to_action(uint8_t keycode)
{
action_t action;
if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
} else {
action.code = ACTION_NO;
}
return action;
}

View File

@ -0,0 +1,29 @@
#include "backlight.h"
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KEYMAP(\
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, INS, PSCR, SLCK, BRK, \
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, NUMLOCK,KP_SLASH,KP_ASTERISK,KP_MINUS, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, KP_7, KP_8, KP_9, KP_PLUS, \
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,FN0, ENT, KP_4, KP_5, KP_6, NO, \
LSFT, Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, RSFT, KP_1, KP_2, KP_3, KP_ENTER, \
LCTL,LGUI,LALT, SPC, NO, RALT,RGUI,RCTL, KP_0, NO, KP_DOT, NO), \
KEYMAP(\
CALC,MYCM,WSCH,WHOM,MAIL,MUTE,VOLD,VOLU,MSEL,MSTP,MPLY,MPRV,MNXT,TRNS, TRNS, WAKE, PWR, SLEP, \
FN1, FN2, FN3, FN4, FN5, FN6, FN7, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,PGDN,TRNS,LEFT,DOWN,UP ,RGHT,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \
TRNS, TRNS,TRNS,TRNS,TRNS,PGUP,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS, \
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS, TRNS, TRNS, TRNS, TRNS)
};
static const uint16_t PROGMEM fn_actions[] = {
[0] = ACTION_LAYER_MOMENTARY(1),
[1] = ACTION_BACKLIGHT_TOGGLE(),
[2] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_ALPHA),
[3] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_MODNUM),
[4] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_NUMERIC),
[5] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_FROW),
[6] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_BACKSIDE),
[7] = ACTION_BACKLIGHT_LEVEL(BACKLIGHT_TOPRIGHT)
};

54
keyboard/lightsaber/led.c Normal file
View File

@ -0,0 +1,54 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>
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 <avr/io.h>
#include "stdint.h"
#include "led.h"
/* LED pin configuration
*
* Caps PB0 (low)
* NumLock PB4 (low)
*
*/
void led_set(uint8_t usb_led)
{
// Set as output.
DDRB |= (1<<0) | (1<<4);
if (usb_led & (1<<USB_LED_CAPS_LOCK))
{
// Output low.
PORTB &= ~(1<<0);
}
else
{
// Output high.
PORTB |= (1<<0);
}
if (usb_led & (1<<USB_LED_NUM_LOCK))
{
// Output low.
PORTB &= ~(1<<4);
}
else
{
// Output high.
PORTB |= (1<<4);
}
}

View File

@ -0,0 +1,292 @@
/*
Copyright 2014 Ralf Schmitt <ralf@bunkertor.net>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"
#ifndef DEBOUNCE
# define DEBOUNCE 0
#endif
static uint8_t debouncing = DEBOUNCE;
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
static uint8_t read_rows(void);
static uint8_t read_fwkey(void);
static void init_rows(void);
static void unselect_cols(void);
static void select_col(uint8_t col);
inline
uint8_t matrix_rows(void)
{
return MATRIX_ROWS;
}
inline
uint8_t matrix_cols(void)
{
return MATRIX_COLS;
}
void matrix_init(void)
{
unselect_cols();
init_rows();
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
matrix_debouncing[i] = 0;
}
}
uint8_t matrix_scan(void)
{
for (uint8_t col = 0; col < MATRIX_COLS; col++) { // 0-17
select_col(col);
_delay_us(3); // TODO: Determine the correct value needed here.
uint8_t rows = read_rows();
// Use the otherwise unused col: 12 row: 3 for firmware.
if(col == 12) {
rows |= read_fwkey();
}
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { // 0-5
bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
bool curr_bit = rows & (1<<row);
if (prev_bit != curr_bit) {
matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
if (debouncing) {
dprint("bounce!: "); dprintf("%02X", debouncing); dprintln();
}
debouncing = DEBOUNCE;
}
}
unselect_cols();
}
if (debouncing) {
if (--debouncing) {
_delay_ms(1);
} else {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
}
}
}
return 1;
}
bool matrix_is_modified(void)
{
if (debouncing) return false;
return true;
}
inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
return (matrix[row] & ((matrix_row_t)1<<col));
}
inline
matrix_row_t matrix_get_row(uint8_t row)
{
return matrix[row];
}
void matrix_print(void)
{
print("\nr/c 0123456789ABCDEF\n");
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
}
}
uint8_t matrix_key_count(void)
{
uint8_t count = 0;
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
count += bitpop32(matrix[i]);
}
return count;
}
/* Row pin configuration
* row: 0 1 2 3 4 5
* pin: PD0 PD1 PD2 PD3 PD5 PB7
*
* Firmware uses its own pin PE2
*/
static void init_rows(void)
{
// Input (DDR:0, PORT:0)
DDRD &= ~0b00101111;
PORTD &= ~0b00101111;
DDRB &= ~(1<<7);
PORTB &= ~(1<<7);
// Input with pull-up (DDR:0, PORT:1)
DDRE &= ~(1<<2);
PORTE |= (1<<2);
}
static uint8_t read_rows(void)
{
return (PIND&(1<<0) ? (1<<0) : 0) |
(PIND&(1<<1) ? (1<<1) : 0) |
(PIND&(1<<2) ? (1<<2) : 0) |
(PIND&(1<<3) ? (1<<3) : 0) |
(PIND&(1<<5) ? (1<<4) : 0) |
(PINB&(1<<7) ? (1<<5) : 0);
}
static uint8_t read_fwkey(void)
{
return PINE&(1<<2) ? 0 : (1<<3);
}
/* Columns 0 - 15
* These columns uses two 74HC237D 3 to 8 bit demultiplexers.
* col / pin: PC6 PB6 PF0 PF1 PC7
* 0: 1 0 0 0 0
* 1: 1 0 1 0 0
* 2: 1 0 0 1 0
* 3: 1 0 1 1 0
* 4: 1 0 0 0 1
* 5: 1 0 1 0 1
* 6: 1 0 0 1 1
* 7: 1 0 1 1 1
* 8: 0 1 0 0 0
* 9: 0 1 1 0 0
* 10: 0 1 0 1 0
* 11: 0 1 1 1 0
* 12: 0 1 0 0 1
* 13: 0 1 1 0 1
* 14: 0 1 0 1 1
* 15: 0 1 1 1 1
*
* col: 16
* pin: PB5
*
* col: 17
* pin: PD4
*/
static void unselect_cols(void)
{
DDRB |= (1<<5) | (1<<6);
PORTB &= ~((1<<5) | (1<<6));
DDRC |= (1<<6) | (1<<7);
PORTC &= ~((1<<6) | (1<<7));
DDRD |= (1<<4);
PORTD &= ~(1<<4);
DDRF |= (1<<0) | (1<<1);
PORTF &= ~((1<<0) | (1<<1));
}
static void select_col(uint8_t col)
{
// Output high (DDR:1, PORT:1) to select
switch (col) {
case 0:
PORTC |= (1<<6);
break;
case 1:
PORTC |= (1<<6);
PORTF |= (1<<0);
break;
case 2:
PORTC |= (1<<6);
PORTF |= (1<<1);
break;
case 3:
PORTC |= (1<<6);
PORTF |= (1<<0) | (1<<1);
break;
case 4:
PORTC |= (1<<6);
PORTC |= (1<<7);
break;
case 5:
PORTC |= (1<<6);
PORTF |= (1<<0);
PORTC |= (1<<7);
break;
case 6:
PORTC |= (1<<6);
PORTF |= (1<<1);
PORTC |= (1<<7);
break;
case 7:
PORTC |= (1<<6);
PORTF |= (1<<0) | (1<<1);
PORTC |= (1<<7);
break;
case 8:
PORTB |= (1<<6);
break;
case 9:
PORTB |= (1<<6);
PORTF |= (1<<0);
break;
case 10:
PORTB |= (1<<6);
PORTF |= (1<<1);
break;
case 11:
PORTB |= (1<<6);
PORTF |= (1<<0) | (1<<1);
break;
case 12:
PORTB |= (1<<6);
PORTC |= (1<<7);
break;
case 13:
PORTB |= (1<<6);
PORTF |= (1<<0);
PORTC |= (1<<7);
break;
case 14:
PORTB |= (1<<6);
PORTF |= (1<<1);
PORTC |= (1<<7);
break;
case 15:
PORTB |= (1<<6);
PORTF |= (1<<0) | (1<<1);
PORTC |= (1<<7);
break;
case 16:
PORTB |= (1<<5);
break;
case 17:
PORTD |= (1<<4);
break;
}
}

View File

@ -33,7 +33,7 @@ between 0 and 255:
### 2. Sleep LED
It is possible to have the LEDs fade in and out when the computer is suspended.
To enable this feature, uncoment the `SLEEP_LED_ENABLE` line in the makefile you are using:
To enable this feature, uncomment the `SLEEP_LED_ENABLE` line in the makefile you are using:
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend

169
protocol/ibm4704.c Normal file
View File

@ -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;
}

110
protocol/ibm4704.h Normal file
View File

@ -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

View File

@ -1,7 +1,12 @@
LUFA_DIR = protocol/lufa
# Path to the LUFA library
LUFA_PATH ?= protocol/lufa/LUFA-120730
ifeq (, $(wildcard $(TOP_DIR)/$(LUFA_DIR)/LUFA-git/LUFA/Version.h))
LUFA_PATH ?= $(LUFA_DIR)/LUFA-120730
else
LUFA_PATH ?= $(LUFA_DIR)/LUFA-git
endif
# Create the LUFA source path variables by including the LUFA makefile
ifneq (, $(wildcard $(TOP_DIR)/$(LUFA_PATH)/LUFA/Build/lufa_sources.mk))
@ -30,9 +35,12 @@ VPATH += $(TOP_DIR)/$(LUFA_PATH)
#endif
# LUFA library compile-time options and predefined tokens
LUFA_OPTS = -D USB_DEVICE_ONLY
LUFA_OPTS += -D USE_FLASH_DESCRIPTORS
LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
LUFA_OPTS = -DUSB_DEVICE_ONLY
LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS
LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
#LUFA_OPTS += -DINTERRUPT_CONTROL_ENDPOINT
LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8
LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1
OPT_DEFS += -DF_USB=$(F_USB)UL
OPT_DEFS += -DARCH=ARCH_$(ARCH)

@ -0,0 +1 @@
Subproject commit b6c18b2a7c544653efbe12a1d4e8ba65e7d83c35

View File

@ -230,12 +230,12 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
.USBSpecification = VERSION_BCD(01.10),
.USBSpecification = VERSION_BCD(1,1,0),
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = 8,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
/* specified in config.h */
.VendorID = VENDOR_ID,
@ -246,7 +246,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
.ProductStrIndex = 0x02,
.SerialNumStrIndex = NO_DESCRIPTOR,
.NumberOfConfigurations = 1
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
/*******************************************************************************
@ -292,7 +292,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
.HIDSpec = VERSION_BCD(01.11),
.HIDSpec = VERSION_BCD(1,1,1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,
@ -306,7 +306,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = KEYBOARD_EPSIZE,
.PollingIntervalMS = 0x01
.PollingIntervalMS = 0x0A
},
/*
@ -333,7 +333,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
.HIDSpec = VERSION_BCD(01.11),
.HIDSpec = VERSION_BCD(1,1,1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,
@ -347,7 +347,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MOUSE_EPSIZE,
.PollingIntervalMS = 0x01
.PollingIntervalMS = 0x0A
},
#endif
@ -375,7 +375,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
.HIDSpec = VERSION_BCD(01.11),
.HIDSpec = VERSION_BCD(1,1,1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,
@ -389,7 +389,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = EXTRAKEY_EPSIZE,
.PollingIntervalMS = 0x01
.PollingIntervalMS = 0x0A
},
#endif
@ -417,7 +417,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
.HIDSpec = VERSION_BCD(01.11),
.HIDSpec = VERSION_BCD(1,1,1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,
@ -469,7 +469,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
.HIDSpec = VERSION_BCD(01.11),
.HIDSpec = VERSION_BCD(1,1,1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,

View File

@ -137,13 +137,17 @@ typedef struct
#ifdef CONSOLE_ENABLE
# define CONSOLE_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 1)
//# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
#else
# define CONSOLE_OUT_EPNUM EXTRAKEY_IN_EPNUM
#endif
#ifdef NKRO_ENABLE
# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
# if defined(__AVR_ATmega32U2__) && NKRO_IN_EPNUM > 4
# error "Endpoints are not available enough to support all functions. Remove some in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO)"
# endif
#endif
@ -159,4 +163,14 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
/* new API */
#if LUFA_VERSION_INTEGER < 0x140302
#undef VERSION_BCD
#define VERSION_BCD(Major, Minor, Revision) \
CPU_TO_LE16( ((Major & 0xFF) << 8) | \
((Minor & 0x0F) << 4) | \
(Revision & 0x0F) )
#endif
#endif

View File

@ -52,8 +52,8 @@
#include "descriptor.h"
#include "lufa.h"
static uint8_t idle_duration = 0;
static uint8_t protocol_report = 1;
uint8_t keyboard_idle = 0;
uint8_t keyboard_protocol = 1;
static uint8_t keyboard_led_stats = 0;
static report_keyboard_t keyboard_report_sent;
@ -184,15 +184,6 @@ void EVENT_USB_Device_StartOfFrame(void)
/** Event handler for the USB_ConfigurationChanged event.
* This is fired when the host sets the current configuration of the USB device after enumeration.
*/
#if LUFA_VERSION_INTEGER < 0x120730
/* old API 120219 */
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint(epnum, eptype, epdir, epsize, epbank)
#else
/* new API >= 120730 */
#define ENDPOINT_BANK_SINGLE 1
#define ENDPOINT_BANK_DOUBLE 2
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint((epdir) | (epnum) , eptype, epsize, epbank)
#endif
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
@ -217,9 +208,11 @@ void EVENT_USB_Device_ConfigurationChanged(void)
/* Setup Console HID Report Endpoints */
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
#if 0
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
#endif
#ifdef NKRO_ENABLE
/* Setup NKRO HID Report Endpoints */
@ -279,6 +272,7 @@ void EVENT_USB_Device_ControlRequest(void)
// Interface
switch (USB_ControlRequest.wIndex) {
case KEYBOARD_INTERFACE:
case NKRO_INTERFACE:
Endpoint_ClearSETUP();
while (!(Endpoint_IsOUTReceived())) {
@ -299,21 +293,29 @@ void EVENT_USB_Device_ControlRequest(void)
case HID_REQ_GetProtocol:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
Endpoint_Write_8(protocol_report);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
Endpoint_Write_8(keyboard_protocol);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
}
break;
case HID_REQ_SetProtocol:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
protocol_report = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
#ifdef NKRO_ENABLE
keyboard_nkro = !!keyboard_protocol;
#endif
clear_keyboard();
}
}
break;
@ -323,7 +325,7 @@ void EVENT_USB_Device_ControlRequest(void)
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
idle_duration = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
}
break;
@ -332,7 +334,7 @@ void EVENT_USB_Device_ControlRequest(void)
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
Endpoint_Write_8(idle_duration);
Endpoint_Write_8(keyboard_idle);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
@ -351,7 +353,7 @@ static uint8_t keyboard_leds(void)
static void send_keyboard(report_keyboard_t *report)
{
uint8_t timeout = 0;
uint8_t timeout = 255;
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
@ -359,26 +361,27 @@ static void send_keyboard(report_keyboard_t *report)
/* Select the Keyboard Report Endpoint */
#ifdef NKRO_ENABLE
if (keyboard_nkro) {
/* Report protocol - NKRO */
Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
}
else
#endif
{
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
}
/* Check if Keyboard Endpoint Ready for Read/Write */
while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
/* Check if write ready for a polling interval around 1ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
if (!Endpoint_IsReadWriteAllowed()) return;
/* Write Keyboard Report Data */
#ifdef NKRO_ENABLE
if (keyboard_nkro) {
/* Write Keyboard Report Data */
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
}
else
#endif
{
/* boot mode */
/* Boot protocol */
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
/* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
/* Write Keyboard Report Data */
Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
}
@ -391,7 +394,7 @@ static void send_keyboard(report_keyboard_t *report)
static void send_mouse(report_mouse_t *report)
{
#ifdef MOUSE_ENABLE
uint8_t timeout = 0;
uint8_t timeout = 255;
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
@ -399,8 +402,9 @@ static void send_mouse(report_mouse_t *report)
/* Select the Mouse Report Endpoint */
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
/* Check if Mouse Endpoint Ready for Read/Write */
while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
/* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
/* Write Mouse Report Data */
Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
@ -412,7 +416,7 @@ static void send_mouse(report_mouse_t *report)
static void send_system(uint16_t data)
{
uint8_t timeout = 0;
uint8_t timeout = 255;
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
@ -422,14 +426,18 @@ static void send_system(uint16_t data)
.usage = data
};
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
/* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
Endpoint_ClearIN();
}
static void send_consumer(uint16_t data)
{
uint8_t timeout = 0;
uint8_t timeout = 255;
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
@ -439,7 +447,11 @@ static void send_consumer(uint16_t data)
.usage = data
};
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
/* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
Endpoint_ClearIN();
}

View File

@ -66,4 +66,15 @@ typedef struct {
uint16_t usage;
} __attribute__ ((packed)) report_extra_t;
#if LUFA_VERSION_INTEGER < 0x120730
/* old API 120219 */
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint(epnum, eptype, epdir, epsize, epbank)
#else
/* new API >= 120730 */
#define ENDPOINT_BANK_SINGLE 1
#define ENDPOINT_BANK_DOUBLE 2
#define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint((epdir) | (epnum) , eptype, epsize, epbank)
#endif
#endif

204
protocol/next_kbd.c Normal file
View File

@ -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();
}

63
protocol/next_kbd.h Normal file
View File

@ -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

View File

@ -38,6 +38,7 @@
#include "sleep_led.h"
#endif
#include "suspend.h"
#include "action.h"
#include "action_util.h"
@ -628,6 +629,7 @@ uint8_t usb_configured(void)
void usb_remote_wakeup(void)
{
UDCON |= (1<<RMWKUP);
while (UDCON & (1<<RMWKUP));
}
@ -692,20 +694,20 @@ ISR(USB_GEN_vect)
}
/* TODO: should keep IDLE rate on each keyboard interface */
#ifdef NKRO_ENABLE
if (!keyboard_nkro && usb_keyboard_idle_config && (++div4 & 3) == 0) {
if (!keyboard_nkro && keyboard_idle && (++div4 & 3) == 0) {
#else
if (usb_keyboard_idle_config && (++div4 & 3) == 0) {
if (keyboard_idle && (++div4 & 3) == 0) {
#endif
UENUM = KBD_ENDPOINT;
if (UEINTX & (1<<RWAL)) {
usb_keyboard_idle_count++;
if (usb_keyboard_idle_count == usb_keyboard_idle_config) {
if (usb_keyboard_idle_count == keyboard_idle) {
usb_keyboard_idle_count = 0;
/* TODO: fix keyboard_report inconsistency */
/* To avoid Mac SET_IDLE behaviour.
UEDATX = keyboard_report_prev->mods;
UEDATX = 0;
uint8_t keys = usb_keyboard_protocol ? KBD_REPORT_KEYS : 6;
uint8_t keys = keyboard_protocol ? KBD_REPORT_KEYS : 6;
for (uint8_t i=0; i<keys; i++) {
UEDATX = keyboard_report_prev->keys[i];
}
@ -901,13 +903,13 @@ ISR(USB_COM_vect)
}
if (bRequest == HID_GET_IDLE) {
usb_wait_in_ready();
UEDATX = usb_keyboard_idle_config;
UEDATX = keyboard_idle;
usb_send_in();
return;
}
if (bRequest == HID_GET_PROTOCOL) {
usb_wait_in_ready();
UEDATX = usb_keyboard_protocol;
UEDATX = keyboard_protocol;
usb_send_in();
return;
}
@ -921,14 +923,18 @@ ISR(USB_COM_vect)
return;
}
if (bRequest == HID_SET_IDLE) {
usb_keyboard_idle_config = (wValue >> 8);
keyboard_idle = (wValue >> 8);
usb_keyboard_idle_count = 0;
//usb_wait_in_ready();
usb_send_in();
return;
}
if (bRequest == HID_SET_PROTOCOL) {
usb_keyboard_protocol = wValue;
keyboard_protocol = wValue;
#ifdef NKRO_ENABLE
keyboard_nkro = !!keyboard_protocol;
#endif
clear_keyboard();
//usb_wait_in_ready();
usb_send_in();
return;

View File

@ -34,12 +34,12 @@
// protocol setting from the host. We use exactly the same report
// either way, so this variable only stores the setting since we
// are required to be able to report which setting is in use.
uint8_t usb_keyboard_protocol=1;
uint8_t keyboard_protocol=1;
// the idle configuration, how often we send the report to the
// host (ms * 4) even when it hasn't changed
// Windows and Linux set 0 while OS X sets 6(24ms) by SET_IDLE request.
uint8_t usb_keyboard_idle_config=125;
uint8_t keyobard_idle=125;
// count until idle timeout
uint8_t usb_keyboard_idle_count=0;
@ -61,10 +61,7 @@ int8_t usb_keyboard_send_report(report_keyboard_t *report)
else
#endif
{
if (usb_keyboard_protocol)
result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE);
else
result = send_report(report, KBD_ENDPOINT, 0, 6);
result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE);
}
if (result) return result;

View File

@ -30,8 +30,6 @@
#include "host.h"
extern uint8_t usb_keyboard_protocol;
extern uint8_t usb_keyboard_idle_config;
extern uint8_t usb_keyboard_idle_count;
extern volatile uint8_t usb_keyboard_leds;