Merge remote-tracking branch 'tmk/master'

This commit is contained in:
Mark Sikora 2020-01-12 14:23:17 -05:00
commit 2ac00aa8a1
96 changed files with 15031 additions and 7760 deletions

6
.gitmodules vendored
View file

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

View file

@ -1,27 +0,0 @@
ADB keyboard handle id
======================
0x01 Apple Standard keyboard M0116 ANSI
0x01 Apple Desktop Bus keyboard 658-4081 ANSI
0x02 Apple Extended Keyboard M0115 ANSI
0x02 Apple Extended Keyboard II M3501 ANSI
0x03 Logical id for Extended Protocol
0x10 Apple Adjustable keyboard M1242 ANSI
Adjustable Keyboard media key
=============================
Media key part has different address than the main keyboard(0x02).
Device Address: 0x07(Appliances/Misc devices)
Handler ID: 0x02
Scan Codes
----------
Media key ADB Code Code in Matix
-----------------------------------------
Volume Up: 0x03 0x48
Volume Down: 0x02 0x49
Mute: 0x01 0x4a
Mic: 0x00 0x42
As for these keys raw ADB codes are translate into logical codes in matrix.

View file

@ -9,7 +9,6 @@ TARGET_DIR ?= .
# project specific files
SRC ?= matrix.c \
led.c \
adb.c
CONFIG_H = config.h
@ -64,26 +63,27 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Atmel DFU loader 4096 for TMK Converter rev.1/rev.2
# LUFA bootloader 4096
# USBaspLoader 2048
OPT_DEFS += -DBOOTLOADER_SIZE=4096
BOOTLOADER_SIZE ?= 4096
OPT_DEFS += -DBOOTLOADER_SIZE=$(BOOTLOADER_SIZE)
# 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
ADB_MOUSE_ENABLE = yes
#UNIMAP_ENABLE = yes
#ACTIONMAP_ENABLE = yes # Use 16bit actionmap instead of 8bit keymap
#KEYMAP_SECTION_ENABLE = yes # fixed address keymap for keymap editor
BOOTMAGIC_ENABLE ?= no # 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 ?= no # USB Nkey Rollover
ADB_MOUSE_ENABLE ?= yes # ADB Mouse support
UNIMAP_ENABLE ?= yes # Use unimap
ACTIONMAP_ENABLE ?= no # Use 16bit actionmap instead of 8bit keymap
KEYMAP_SECTION_ENABLE ?= yes # fixed address keymap for keymap editor
# ADB Mice need acceleration for todays much bigger screens.
OPT_DEFS += -DADB_MOUSE_MAXACC=8
ADB_MOUSE_MAXACC ?= 8
OPT_DEFS += -DADB_MOUSE_MAXACC=$(ADB_MOUSE_MAXACC)
# Optimize size but this may cause error "relocation truncated to fit"
@ -93,10 +93,10 @@ OPT_DEFS += -DADB_MOUSE_MAXACC=8
#
# Keymap file
#
ifdef UNIMAP_ENABLE
ifeq (yes,$(strip $(UNIMAP_ENABLE)))
KEYMAP_FILE = unimap
else
ifdef ACTIONMAP_ENABLE
ifeq (yes,$(strip $(ACTIONMAP_ENABLE)))
KEYMAP_FILE = actionmap
else
KEYMAP_FILE = keymap

View file

@ -1,5 +0,0 @@
TARGET = adb_usb_rev1_unimap
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
MCU = atmega32u4
include Makefile

View file

@ -1,5 +0,0 @@
TARGET = adb_usb_rev2_unimap
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
MCU = atmega32u2
include Makefile

View file

@ -1,10 +1,10 @@
ADB to USB keyboard converter
=============================
This firmware converts Apple ADB keyboard protocol to USB, you can use it to plug old ADB keyboard into modern computer. It works on TMK ADB-USB Converter, PJRC Teensy2.0 and other USB AVR MCU(ATMega32U4, AT90USB64/128 or etc) and needs more than 10KB flash at least.
This firmware converts Apple ADB keyboard/mouse protocol to USB, you can use it to plug old ADB keyboard/mouse into modern computer. It works on prebuilt TMK ADB-USB Converter or generic dev board with USB AVR MCU(ATMega32U4/2) like Teensy2.0.
Discuss here: http://geekhack.org/showwiki.php?title=Island:14290
Discuss about this here: http://geekhack.org/showwiki.php?title=Island:14290
You can buy a TMK converter here: https://geekhack.org/index.php?topic=72052.0
Prebuilt TMK ADB-USB converter is available here: https://geekhack.org/index.php?topic=72052.0
@ -16,18 +16,20 @@ https://github.com/tmk/tmk_keyboard/tree/master/converter/adb_usb
Also check these when you are in trouble.
https://github.com/tmk/tmk_keyboard/wiki
https://github.com/tmk/tmk_keyboard/labels/NOTE
https://github.com/tmk/tmk_keyboard/issues
Wiring
------
Connect ADB pins to controller just by 3 lines(Vcc, GND, Data). By default Data line uses port PD0.
If you build this yourself you have to solder some wires.
Connect ADB pins to controller just by 3 lines(Vcc, GND, Data) at least. By default Data line uses port PD0.
This is not needed but you can connect PSW to PD1 optionally.
ADB female socket from the front:
,--_--.
/ o4 3o \ 1: DATA
| o2 1o | 2: Power SW
| o2 1o | 2: PSW(Power SW)
- === - 3: VCC
`-___-' 4: GND
@ -36,13 +38,13 @@ https://github.com/tmk/tmk_keyboard/wiki/FAQ#pull-up-resistor
Pull-up resister:
Keyboard Conveter
Keyboard AVR MCU
,------.
5V------+------|VCC |
| | |
[R] | |
| | |
Signal--+------|PD0 |
DATA----+------|PD0 |
| |
GND------------|GND |
`------'
@ -58,59 +60,60 @@ Build firmware and Program microcontroller
------------------------------------------
See [doc/build.md](../../tmk_core/doc/build.md).
To build firmware and program TMK Converter run these commands:
To build firmware and program TMK ADB-USB Converter run these commands:
$ make -f Makefile clean
$ make -f Makefile [KEYMAP=(plain|ansi|iso|hasu)]
$ make -f Makefile [KEYMAP=(plain|ansi|iso|hasu)] dfu
$ make -f Makefile [KEYMAP=yourname]
$ make -f Makefile [KEYMAP=yourname] dfu
You can select keymap with optional `KEYMAP=` (plain is default). Push button on the converter before running `dfu` target.
You can select keymap name with optional `KEYMAP=` ('plain' is default name). Push button on the converter before running `dfu` target.
Use **Makefile.rev1** for old TMK Converter rev.1 and **Makefile.teensy** for Teensy2.0 instead of **Makefile**. For TMK Converter rev.2 just use **Makefile**.
To program Teensy you can use `teensy` target:
$ make -f Makefile.teensy [KEYMAP=(plain|ansi|iso|hasu)] teensy
Use **Makefile.rev1** for old TMK Converter rev.1 and Teensy2.0 instead of **Makefile**.
Keymap
------
You can change a keymap by editing code of keymap_[plain|ansi|iso|hasu|yours].c.
You can change keymap by editing code of unimap_plain.c directly, or copy it to your own keymap file like unimap_yourname.c and edit the file.
How to define the keymap is probably obvious. You can find key symbols in common/keycode.h. And see [doc/keymap.md](../../tmk_core/doc/keymap.md) for more detail.
Magic command
-------------
To get help press `h` holding Magic key. Magic key is `Power key`.
To get help message in hid_listen press `h` holding Magic key. Magic key is `Power key`.
https://github.com/tmk/tmk_keyboard/wiki#debug
Locking CapsLock
----------------
Many of old ADB keyboards have mechanical push-lock switch for Capslock key and this converter supports the locking Capslock key by default. See README in top directory for more detail about this feature.
Many of old ADB keyboards have mechanical push-lock switch for Capslock key and this converter supports the locking Capslock key by default. Use keycode `LCAP` instead of `CAPS` in your keymap in short. See README in top directory for more detail.
https://github.com/tmk/tmk_keyboard/blob/master/README.md#mechanical-locking-support
Also you may want to remove locking pin from the push-lock switch to use capslock as a normal momentary switch.
If you want to remap Capslock key you will have to remove locking pin or just replace with normal momentary switch. Some keyboards like Apple Adujstable keyboard use firmware-base locking with momentary switch for Capslock and remapping it won't be useful in most cases.
Mouse support
-------------
ADB mouse support was added by @mek-apelsin on Apr,2015. It supports only one button as of now.
https://github.com/tmk/tmk_keyboard/pull/207
Notes
-----
Notes for keyboard
------------------
Not-extended ADB keyboards have 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 can discriminate both side
modifiers except for GUI key(Windows/Command).
And most ADB keyboard has no diodes in its matrix so they are not NKRO,
though ADB protocol itself supports it. See protocol/adb.c for more info.
And most of ADB keyboards have no diodes in its matrix so they are not NKRO unfortunately,
though ADB protocol itself supports it. See tmk_core/protocol/adb.c for more info.
If keyboard has ISO layout you may have swapped keys problem, see this for the detail.
https://github.com/tmk/tmk_keyboard/issues/35
Notes for mouse
---------------
ADB mouse support was added by @mek-apelsin on Apr,2015.
https://github.com/tmk/tmk_keyboard/pull/207
All one-button mouses should be supported.
As of 2019 June, the converter can handle multi-button mice and trackball up to eight buttons if the pointing device supports Apple Extended Mouse protocol. But some devices use their own specific protocol unfortunately and they will work as one-button mouse unless device specific code is added.
Kensington Turbo Mouse 5(#64210) is supported now.
https://github.com/tmk/tmk_keyboard/issues/274#issuecomment-504726633
EOF

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

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

View file

@ -21,7 +21,6 @@ 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 "debug.h"
@ -31,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "host.h"
#include "led.h"
#include "timer.h"
#include "wait.h"
@ -38,31 +38,49 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
static bool has_media_keys = false;
static bool is_iso_layout = false;
#if ADB_MOUSE_ENABLE
#define dmprintf(fmt, ...) do { if (debug_mouse) xprintf(fmt, ##__VA_ARGS__); } while (0)
static uint16_t mouse_cpi = 100;
static void mouse_init(uint8_t addr);
#endif
// matrix state buffer(1:on, 0:off)
static matrix_row_t matrix[MATRIX_ROWS];
static void register_key(uint8_t key);
static void device_scan(void)
{
xprintf("\nScan:\n");
for (uint8_t addr = 0; addr < 16; addr++) {
uint16_t reg3 = adb_host_talk(addr, ADB_REG_3);
if (reg3) {
xprintf(" addr:%d, reg3:%04X\n", addr, reg3);
}
}
}
void matrix_init(void)
{
debug_enable = true;
//debug_matrix = true;
//debug_keyboard = true;
//debug_mouse = true;
// LED on
DDRD |= (1<<6); PORTD |= (1<<6);
adb_host_init();
// wait for keyboard to boot up and receive command
_delay_ms(2000);
// device scan
xprintf("Before init:\n");
for (uint8_t addr = 1; addr < 16; addr++) {
uint16_t reg3 = adb_host_talk(addr, ADB_REG_3);
if (reg3) {
xprintf("Scan: addr:%d, reg3:%04X\n", addr, reg3);
}
_delay_ms(20);
}
// wait for line and device to be stable
wait_ms(100);
device_scan();
//
// Keyboard
//
xprintf("\nKeyboard:\n");
// Determine ISO keyboard by handler id
// http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L815
uint8_t handler_id = (uint8_t) adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_3);
@ -76,47 +94,169 @@ void matrix_init(void)
is_iso_layout = false;
break;
}
xprintf("hadler_id: %02X, is_iso_layout: %s\n", handler_id, (is_iso_layout ? "yes" : "no"));
xprintf("hadler: %02X, ISO: %s\n", handler_id, (is_iso_layout ? "yes" : "no"));
// Adjustable keyboard media keys: address=0x07 and handlerID=0x02
has_media_keys = (0x02 == (adb_host_talk(ADB_ADDR_APPLIANCE, ADB_REG_3) & 0xff));
if (has_media_keys) {
xprintf("Found: media keys\n");
xprintf("Media keys\n");
}
// Enable keyboard left/right modifier distinction
// Listen Register3
// upper byte: reserved bits 0000, keyboard address 0010
// lower byte: device handler 00000011
adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_3, ADB_ADDR_KEYBOARD, ADB_HANDLER_EXTENDED_PROTOCOL);
adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_3, ADB_ADDR_KEYBOARD, ADB_HANDLER_EXTENDED_KEYBOARD);
// device scan
xprintf("After init:\n");
for (uint8_t addr = 1; addr < 16; addr++) {
uint16_t reg3 = adb_host_talk(addr, ADB_REG_3);
if (reg3) {
xprintf("Scan: addr:%d, reg3:%04X\n", addr, reg3);
}
_delay_ms(20);
}
//
// Mouse
//
// https://developer.apple.com/library/archive/technotes/hw/hw_01.html#Extended
#ifdef ADB_MOUSE_ENABLE
xprintf("\nMouse:\n");
// Check device on addr3
mouse_init(ADB_ADDR_MOUSE);
#endif
device_scan();
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
led_set(host_keyboard_leds());
debug_enable = true;
//debug_matrix = true;
//debug_keyboard = true;
//debug_mouse = true;
print("debug enabled.\n");
// LED off
DDRD |= (1<<6); PORTD &= ~(1<<6);
return;
}
#ifdef ADB_MOUSE_ENABLE
static void mouse_init(uint8_t orig_addr)
{
uint16_t reg3;
uint8_t mouse_handler;
uint8_t addr;
again:
mouse_handler = (reg3 = adb_host_talk(orig_addr, ADB_REG_3)) & 0xFF;
if (!reg3) return;
dmprintf("addr%d reg3: %02X\n", orig_addr, reg3);
// Move device to tmp address
adb_host_flush(orig_addr);
adb_host_listen(orig_addr, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_TMP, 0xFE);
adb_host_flush(ADB_ADDR_TMP);
mouse_handler = (reg3 = adb_host_talk(ADB_ADDR_TMP, ADB_REG_3)) & 0xFF;
if (!reg3) {
dmprintf("move fail\n");
goto again;
}
addr = ADB_ADDR_TMP;
dmprintf("addr%d reg3: %02X\n", addr, reg3);
detect_again:
if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE || mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) {
adb_host_flush(addr);
adb_host_listen(addr, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_EXTENDED_MOUSE);
mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF;
if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) {
adb_host_flush(addr);
adb_host_listen(addr, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_CLASSIC2_MOUSE);
mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF;
}
if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) {
xprintf("Classic 100cpi\n");
mouse_cpi = 100;
}
if (mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) {
xprintf("Classic 200cpi\n");
mouse_cpi = 200;
}
}
// Extended Mouse Protocol
if (mouse_handler == ADB_HANDLER_EXTENDED_MOUSE) {
// Device info format(reg1 8-byte data)
// 0-3: device id
// 4-5: resolution in units/inch (0xC8=200upi)
// 6 : device class (0: Tablet, 1: Mouse, 2: Trackball)
// 7 : num of buttons
uint8_t len;
uint8_t buf[8];
len = adb_host_talk_buf(addr, ADB_REG_1, buf, sizeof(buf));
if (len > 5) {
mouse_cpi = (buf[4]<<8) | buf[5];
} else {
mouse_cpi = 100;
}
if (len) {
xprintf("Ext: [", len);
for (int8_t i = 0; i < len; i++) xprintf("%02X ", buf[i]);
xprintf("] cpi=%d\n", mouse_cpi);
}
// Kensington Turbo Mouse 5: default device
if (buf[0] == 0x4B && buf[1] == 0x4D && buf[2] == 0x4C && buf[3] == 0x31) {
xprintf("TM5: default\n");
// Move it to addr0 to remove this device and get new device with handle id 50 on addr 3
// and the new device on address 3 should be handled with command sequence later.
//
// Turbo Mouse 5 has one default device on addr3 as normal mouse at first, and another device
// with hander id 50 appears after the default device is moved from addr3.
// The mouse has the two devices at same time transiently in the result. The default device is
// removed automatically after the another device receives command sequence.
// NOTE: The mouse hangs if you try moving the two deivces to same address.
adb_host_flush(addr);
adb_host_listen(addr, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_0, 0xFE);
} else {
xprintf("Unknown\n");
}
}
if (mouse_handler == ADB_HANDLER_TURBO_MOUSE) {
xprintf("TM5: ext\n");
// Kensington Turbo Mouse 5 command sequence to enable four buttons
// https://elixir.bootlin.com/linux/v4.4/source/drivers/macintosh/adbhid.c#L1176
// https://github.com/NetBSD/src/blob/64b8a48e1288eb3902ed73113d157af50b2ec596/sys/arch/macppc/dev/ams.c#L261
static uint8_t cmd1[] = { 0xE7, 0x8C, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x94 };
static uint8_t cmd2[] = { 0xA5, 0x14, 0x00, 0x00, 0x69, 0xFF, 0xFF, 0x27 };
adb_host_flush(addr);
adb_host_listen_buf(addr, ADB_REG_2, cmd1, sizeof(cmd1));
adb_host_flush(addr);
adb_host_listen_buf(addr, ADB_REG_2, cmd2, sizeof(cmd2));
}
// Move all mouses to a address after init to be polled
adb_host_flush(addr);
adb_host_listen(addr, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_MOUSE_POLL, 0xFE);
adb_host_flush(ADB_ADDR_MOUSE_POLL);
mouse_handler = (reg3 = adb_host_talk(addr, ADB_REG_3)) & 0xFF;
if (reg3) {
dmprintf("detect again\n");
goto detect_again;
}
goto again;
// dmprintf("handler: %d\n", mouse_handler);
// dmprintf("cpi: %d\n", mouse_cpi);
}
#ifdef MAX
#undef MAX
@ -127,7 +267,8 @@ static report_mouse_t mouse_report = {};
void adb_mouse_task(void)
{
uint16_t codes;
uint8_t len;
uint8_t buf[5];
int16_t x, y;
static int8_t mouseacc;
@ -138,47 +279,92 @@ void adb_mouse_task(void)
if (timer_elapsed(tick_ms) < 12) return;
tick_ms = timer_read();
codes = adb_host_mouse_recv();
static uint16_t detect_ms;
if (timer_elapsed(detect_ms) > 1000) {
detect_ms = timer_read();
// check new device on addr3
mouse_init(ADB_ADDR_MOUSE);
}
// Extended Mouse Protocol data can be 2-5 bytes
// https://developer.apple.com/library/archive/technotes/hw/hw_01.html#Extended
//
// Byte 0: b00 y06 y05 y04 y03 y02 y01 y00
// Byte 1: b01 x06 x05 x04 x03 x02 x01 x00
// Byte 2: b02 y09 y08 y07 b03 x09 x08 x07
// Byte 3: b04 y12 y11 y10 b05 x12 x11 x10
// Byte 4: b06 y15 y14 y13 b07 x15 x14 x13
//
// b--: Button state.(0: on, 1: off)
// x--: X axis movement.
// y--: Y axis movement.
len = adb_host_talk_buf(ADB_ADDR_MOUSE_POLL, ADB_REG_0, buf, sizeof(buf));
// If nothing received reset mouse acceleration, and quit.
if (!codes) {
if (len < 2) {
mouseacc = 1;
return;
};
// Bit sixteen is button.
if (~codes & (1 << 15))
mouse_report.buttons |= MOUSE_BTN1;
if (codes & (1 << 15))
mouse_report.buttons &= ~MOUSE_BTN1;
// lower seven bits are movement, as signed int_7.
// low byte is X-axis, high byte is Y.
y = (codes>>8 & 0x3F);
x = (codes>>0 & 0x3F);
// bit seven and fifteen is negative
// usb does not use int_8, but int_7 (measuring distance) with sign-bit.
if (codes & (1 << 6))
x = (x-0x40);
if (codes & (1 << 14))
y = (y-0x40);
// Store off-buttons and 0-movements in unused bytes
bool xneg = false;
bool yneg = false;
if (len == 2) {
if (buf[0] & 0x40) yneg = true;
if (buf[1] & 0x40) xneg = true;
} else {
if (buf[len - 1] & 0x40) yneg = true;
if (buf[len - 1] & 0x04) xneg = true;
}
for (int8_t i = len; i < sizeof(buf); i++) {
buf[i] = 0x88;
if (yneg) buf[i] |= 0x70;
if (xneg) buf[i] |= 0x07;
}
// 8 buttons at max
// TODO: Fix HID report descriptor for mouse to support button6-8
uint8_t buttons = 0;
if (!(buf[4] & 0x08)) buttons |= MOUSE_BTN8;
if (!(buf[4] & 0x80)) buttons |= MOUSE_BTN7;
if (!(buf[3] & 0x08)) buttons |= MOUSE_BTN6;
if (!(buf[3] & 0x80)) buttons |= MOUSE_BTN5;
if (!(buf[2] & 0x08)) buttons |= MOUSE_BTN4;
if (!(buf[2] & 0x80)) buttons |= MOUSE_BTN3;
if (!(buf[1] & 0x80)) buttons |= MOUSE_BTN2;
if (!(buf[0] & 0x80)) buttons |= MOUSE_BTN1;
mouse_report.buttons = buttons;
int16_t xx, yy;
yy = (buf[0] & 0x7F) | (buf[2] & 0x70) << 3 | (buf[3] & 0x70) << 6 | (buf[4] & 0x70) << 9;
xx = (buf[1] & 0x7F) | (buf[2] & 0x07) << 7 | (buf[3] & 0x07) << 10 | (buf[4] & 0x07) << 13;
// Accelerate mouse. (They weren't meant to be used on screens larger than 320x200).
x *= mouseacc;
y *= mouseacc;
x = xx * mouseacc;
y = yy * mouseacc;
// TODO: Fix HID report descriptor for mouse to support finer resolution
// Cap our two bytes per axis to one byte.
// Easier with a MIN-function, but since -MAX(-a,-b) = MIN(a,b)...
// I.E. MIN(MAX(x,-127),127) = -MAX(-MAX(x, -127), -127) = MIN(-MIN(-x,127),127)
// I.E. MIN(MAX(x,-127),127) = -MAX(-MAX(x, -127), -127) = MIN(-MIN(-x,127),127)
mouse_report.x = -MAX(-MAX(x, -127), -127);
mouse_report.y = -MAX(-MAX(y, -127), -127);
if (debug_mouse) {
print("adb_host_mouse_recv: "); print_bin16(codes); print("\n");
print("adb_mouse raw: [");
phex(mouseacc); print(" ");
phex(mouse_report.buttons); print("|");
print_decs(mouse_report.x); print(" ");
print_decs(mouse_report.y); print("]\n");
xprintf("Mouse: [");
for (int8_t i = 0; i < len; i++) xprintf("%02X ", buf[i]);
xprintf("] ");
xprintf("[B:%02X, X:%d(%d), Y:%d(%d), A:%d]\n", mouse_report.buttons, mouse_report.x, xx, mouse_report.y, yy, mouseacc);
}
// Send result by usb.
host_mouse_send(&mouse_report);
// TODO: acceleration curve is needed for precise operation?
// increase acceleration of mouse
mouseacc += ( mouseacc < ADB_MOUSE_MAXACC ? 1 : 0 );
mouseacc += ( mouseacc < (mouse_cpi < 200 ? ADB_MOUSE_MAXACC : ADB_MOUSE_MAXACC/2) ? 1 : 0 );
return;
}
#endif
@ -265,12 +451,14 @@ uint8_t matrix_scan(void)
register_key(0x7F);
} else if (codes == 0xFFFF) { // power key release
register_key(0xFF);
} else if (key0 == 0xFF) { // error
xprintf("adb_host_kbd_recv: ERROR(%d)\n", codes);
// something wrong or plug-in
matrix_init();
return key1;
} else {
// Macally keyboard sends keys inversely against ADB protocol
// https://deskthority.net/workshop-f7/macally-mk96-t20116.html
if (key0 == 0xFF) {
key0 = key1;
key1 = 0xFF;
}
/* Swap codes for ISO keyboard
* https://github.com/tmk/tmk_keyboard/issues/35
*
@ -337,3 +525,8 @@ static void register_key(uint8_t key)
matrix[row] |= (1<<col);
}
}
void led_set(uint8_t usb_led)
{
adb_host_kbd_led(ADB_ADDR_KEYBOARD, ~usb_led);
}

View file

@ -243,50 +243,3 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
}
#endif
/*
ADB ANSI/ISO Keymapping Note
============================
ANSI
,----------- ----------.
| *a| 1| 2 =|Backspa|
|----------- ----------|
|Tab | Q| | ]| *c|
|----------- ----------|
|CapsLo| A| '|Return |
|----------- ----------|
|Shift | Shift |
`----------- ----------'
ISO
,----------- ----------.
| *a| 1| 2 =|Backspa|
|----------- ----------|
|Tab | Q| | ]|Retur|
|----------- -----` |
|CapsLo| A| '| *c| |
|----------- ----------|
|Shif| *b| Shift |
`----------- ----------'
ADB Keyboard scan code:
ADB scan code USB usage
------------- ---------
Key ANSI ISO ANSI ISO
---------------------------------------------
*a 0x32 0x0A 0x35 0x35
*b ---- 0x32 ---- 0x64
*c 0x2A 0x2A 0x31 0x31(or 0x32)
TMK ADB-USB mapping:
ADB USB(ANSI) USB(ISO)
---------------------------------
0x32 0x35 0x64
0x0A ---- 0x35
0x2A 0x31 0x31(or 0x32)
Note that mappings of ADB code 0x32 are diffrent between ANSI and ISO keyboard.
https://github.com/tmk/tmk_keyboard/issues/35
*/

View file

@ -1,5 +1,5 @@
/*
Copyright 2016 Jun Wako <wakojun@gmail.com>
Copyright 2016-19 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
@ -22,26 +22,43 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "unimap.h"
/* Apple Extended Keyboard Common layout: ANSI+ISO
* ,---. .---------------. ,---------------. ,---------------. ,-----------. ,---------------.
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |VDn|VUp|Mut|F24|
* `---' `---------------' `---------------' `---------------' `-----------' `---------------'
* ,-----------------------------------------------------------. ,-----------. ,---------------.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *|
* |-----------------------------------------------------------| |-----------| |---------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -|
* |-----------------------------------------------------------| `-----------' |---------------|
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +|
* |-----------------------------------------------------------| ,---. |---------------|
/* ADB Keyboard unified layout
* ,---. .---------------. ,---------------. ,---------------. ,-----------. ,---.
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|
* `---' `---------------' `---------------' `---------------' `-----------' `---'
* ,-----------------------------------------------------------. ,-----------. ,---------------. ,---.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| |VUp|
* |-----------------------------------------------------------| |-----------| |---------------| |---|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -| |VDn|
* |-----------------------------------------------------------| `-----------' |---------------| |---|
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +| |Mut|
* |-----------------------------------------------------------| ,---. |---------------| `---'
* |Shif|\ | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| |
* |-----------------------------------------------------------| ,-----------. |-----------|Ent|
* |Ctrl |Alt |Gui | Space |Gui |Alt |Ctrl | |Lef|Dow|Rig| | 0| .| |
* `-----------------------------------------------------------' `-----------' `---------------'
* Command = Gui
* Option = Alt
* Power key = F24
* Mic = F13(Adjustable keyboard)
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| ,---.
* |Ctrl |Opt |Gui | Space |Gui* |Opt |Ctrl | |Lef|Dow|Rig| | 0| .| | |Ply|
* `-----------------------------------------------------------' `-----------' `---------------' `---'
* NOTE: Not-extended ADB keyboards have no discrimination between left and right modifiers.
* Use left ones for mapping. Right modifier always sends same code as left one.
* Apple Extended Keyboard can discriminate the modifiers except for Command(GUI) key.
*/
#define UNIMAP_ADB( \
K29, K3A,K3B,K3C,K3D,K3E,K3F,K40,K41,K42,K43,K44,K45, K46,K47,K48, K73, \
K35,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27,K2D,K2E, K2A, K49,K4A,K4B, K53,K54,K55,K56, K02, \
K2B,K14,K1A,K08,K15,K17,K1C,K18,K0C,K12,K13,K2F,K30, K31, K4C,K4D,K4E, K5F,K60,K61,K57, K01, \
K39,K04,K16,K07,K09,K0A,K0B,K0D,K0E,K0F,K33,K34, K32,K28, K5C,K5D,K5E,K66, K03, \
K79,K64,K1D,K1B,K06,K19,K05,K11,K10,K36,K37,K38, K7D, K52, K59,K5A,K5B,K58, \
K78,K7A,K7B, K2C, K7E,K7C, K50,K51,K4F, K62,K63, K68 \
) UNIMAP( \
K68, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, K73, \
K29, K3A, K3B, K3C, K3D, K3E, K3F, K40, K41, K42, K43, K44, K45, K46, K47, K48, K01, K02, K03, \
K35, K1E, K1F, K20, K21, K22, K23, K24, K25, K26, K27, K2D, K2E, JYEN,K2A, K49, K4A, K4B, K53, K54, K55, K56, \
K2B, K14, K1A, K08, K15, K17, K1C, K18, K0C, K12, K13, K2F, K30, K31, K4C, K4D, K4E, K5F, K60, K61, K57, \
K39, K04, K16, K07, K09, K0A, K0B, K0D, K0E, K0F, K33, K34, K32, K28, K5C, K5D, K5E, K66, \
K79, K64, K1D, K1B, K06, K19, K05, K11, K10, K36, K37, K38, RO, K7D, K52, K59, K5A, K5B, K58, \
K78, K7B, K7A, MHEN, K2C, HENK,KANA,K7E, RGUI,APP, K7C, K50, K51, K4F, K62, K63, PEQL \
)
// http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c
// http://opensource.apple.com//source/IOHIDFamily/IOHIDFamily-701.20.10/IOHIDFamily/Cosmo_USB2ADB.c
// http://m0115.web.fc2.com/m0115.jpg

View file

@ -1,5 +1,5 @@
/*
Copyright 2016 Jun Wako <wakojun@gmail.com>
Copyright 2016-19 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
@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define AC_FN0 ACTION_LAYER_TAP_KEY(1, KC_GRV)
#define AC_FN1 ACTION_LAYER_TAP_KEY(1, KC_BSLS)
#define AC_FN1 ACTION_LAYER_TAP_KEY(2, KC_BSLS)
#define AC_PKEY ACTION_MODS_TAP_KEY(MOD_NONE, KC_POWER)
#ifdef KEYMAP_SECTION_ENABLE
@ -26,22 +26,81 @@ const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] __attribute__ ((section ("
#else
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
#endif
UNIMAP(
MPLY,NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, PKEY,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS, VOLD,VOLU,MUTE,
FN0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, NO, BSPC, INS, HOME,PGUP, NLCK,PEQL,PSLS,PAST,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, FN1, DEL, END, PGDN, P7, P8, P9, PMNS,
LCAP,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, P4, P5, P6, PPLS,
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, NO, RSFT, UP, P1, P2, P3, PENT,
LCTL,LGUI,LALT,NO, SPC, NO, NO, RALT,RGUI,NO, RCTL, LEFT,DOWN,RGHT, P0, PDOT,NO
/* ADB Keyboard unified layout
* ,---. .---------------. ,---------------. ,---------------. ,-----------. ,---.
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|
* `---' `---------------' `---------------' `---------------' `-----------' `---'
* ,-----------------------------------------------------------. ,-----------. ,---------------. ,---.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| |VUp|
* |-----------------------------------------------------------| |-----------| |---------------| |---|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -| |VDn|
* |-----------------------------------------------------------| `-----------' |---------------| |---|
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|# |Retn| | 4| 5| 6| +| |Mut|
* |-----------------------------------------------------------| ,---. |---------------| `---'
* |Shif|\ | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| |
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| ,---.
* |Ctrl |Opt |Gui | Space |Gui* |Opt |Ctrl | |Lef|Dow|Rig| | 0| .| | |Ply|
* `-----------------------------------------------------------' `-----------' `---------------' `---'
* NOTE: Not-extended ADB keyboards have no discrimination between left and right modifiers.
* Use left ones for mapping. Right modifier always sends same code as left one.
* Apple Extended Keyboard can discriminate the modifiers except for Command(GUI) key.
*/
[0] = UNIMAP_ADB(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS, PKEY,
FN0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PEQL,PSLS,PAST, VOLU,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, FN1, DEL, END, PGDN, P7, P8, P9, PMNS, VOLD,
LCAP,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, P4, P5, P6, PPLS, MUTE,
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, PENT,
LCTL,LALT,LGUI, SPC, RALT,RCTL, LEFT,DOWN,RGHT, P0, PDOT, MPLY
),
UNIMAP(
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,F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS,DEL, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, INS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,LEFT,RGHT, TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,DOWN, TRNS,TRNS, PGUP, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, HOME,PGDN,END, TRNS, TRNS,TRNS
/*
* ,---. .---------------. ,---------------. ,---------------. ,-----------. ,---.
* | `| | | | | | | | | | | | | | | | | | | | | |
* `---' `---------------' `---------------' `---------------' `-----------' `---'
* ,-----------------------------------------------------------. ,-----------. ,---------------. ,---.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | | | | | | | | | | |
* |-----------------------------------------------------------| |-----------| |---------------| |---|
* | | | | | | | | |PrS|ScL|Pau|Up |INS| | | | | | | | | | | | |
* |-----------------------------------------------------------| `-----------' |---------------| |---|
* |CapsLo|VoD|VoU|Mut| | | | |Hom|PgU|Lef|Rig|# |Retn| | | | | | | |
* |-----------------------------------------------------------| ,---. |---------------| `---'
* | | | | | | | | | |End|PgD|Dow|Shift | |PgU| | | | | |
* |-----------------------------------------------------------| ,-----------. |-----------| | ,---.
* | | | | | | | | |Hom|PgD|End| | | | | | |
* `-----------------------------------------------------------' `-----------' `---------------' `---'
*/
[1] = UNIMAP_ADB(
GRV, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, INS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, TRNS,
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,LEFT,RGHT, TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,DOWN, TRNS, PGUP, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS, HOME,PGDN,END, TRNS, TRNS, TRNS
),
/*
* ,---. .---------------. ,---------------. ,---------------. ,-----------. ,---.
* | `| | | | | | | | | | | | | | | | | | | | | |
* `---' `---------------' `---------------' `---------------' `-----------' `---'
* ,-----------------------------------------------------------. ,-----------. ,---------------. ,---.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | | | | | | | | | | |
* |-----------------------------------------------------------| |-----------| |---------------| |---|
* | | | | | | | | |PrS|ScL|Pau|Up |INS| | | | | | | | | | | | |
* |-----------------------------------------------------------| `-----------' |---------------| |---|
* |CapsLo|VoD|VoU|Mut| | | | |Hom|PgU|Lef|Rig|# |Retn| | | | | | | |
* |-----------------------------------------------------------| ,---. |---------------| `---'
* | | | | | | | | | |End|PgD|Dow|Shift | |PgU| | | | | |
* |-----------------------------------------------------------| ,-----------. |-----------| | ,---.
* | | | | | | | | |Hom|PgD|End| | | | | | |
* `-----------------------------------------------------------' `-----------' `---------------' `---'
*/
[2] = UNIMAP_ADB(
GRV, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, INS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, TRNS,
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,LEFT,RGHT, TRNS,TRNS, TRNS,TRNS,TRNS,TRNS, TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,DOWN, TRNS, PGUP, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS, HOME,PGDN,END, TRNS, TRNS, TRNS
),
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,115 @@
# Target file name (without extension).
TARGET ?= ibmpc_usb
# Directory common source filess exist
TMK_DIR ?= ../../tmk_core
# Directory keyboard dependent files exist
TARGET_DIR ?= .
# project specific files
SRC ?= protocol/ibmpc.c \
ibmpc_usb.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 ?= 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
# Not work with suart debug
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# This improves response of keyboard when wakeup
OPT_DEFS += -DSUSPEND_MODE_STANDBY
# Boot Section Size in *bytes*
# Teensy halfKay 512
# Teensy++ halfKay 1024
# Atmel DFU loader 4096
# LUFA bootloader 4096
# USBaspLoader 2048
# Bootloader size can be calculated from fuse bits
#BOOTLOADER_SIZE ?= 4096
#OPT_DEFS += -DBOOTLOADER_SIZE=$(BOOTLOADER_SIZE)
# Build Options
# comment out to disable the options.
#
BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE ?= no # 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
KEYMAP_SECTION_ENABLE = yes
UNIMAP_ENABLE = yes
# Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax
#
# Keymap file
#
ifdef UNIMAP_ENABLE
KEYMAP_FILE = unimap
else
ifdef ACTIONMAP_ENABLE
KEYMAP_FILE = actionmap
else
KEYMAP_FILE = keymap
endif
endif
ifdef KEYMAP
SRC := $(KEYMAP_FILE)_$(KEYMAP).c $(SRC)
else
SRC := $(KEYMAP_FILE)_plain.c $(SRC)
endif
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TMK_DIR)
include $(TMK_DIR)/protocol.mk
include $(TMK_DIR)/protocol/lufa.mk
include $(TMK_DIR)/common.mk
include $(TMK_DIR)/rules.mk

View file

@ -0,0 +1,4 @@
TARGET = ibmpc_usb_at90usb1286
MCU = at90usb1286
include Makefile

View file

@ -0,0 +1,4 @@
TARGET = ibmpc_usb_atmega32u2
MCU = atmega32u2
include Makefile

View file

@ -1,3 +1,4 @@
TARGET = adb_usb_teensy
TARGET = ibmpc_usb_atmega32u4
MCU = atmega32u4
include Makefile

View file

@ -0,0 +1,168 @@
IBM PC Keyboard Converter
=========================
The converter translates IBM PC keyboard protocols to use classic keyboards with modern computer with USB ports.
It supports both IBM XT and AT protocols, and all of scan code set 1, 2 and 3 with one firmware.
This is not finish project and still work in progress as of 2019-12-02. Test in the field and feedback from users are needed to improve
This project is intended to integrated existent TMK XT, PS/2 and Terminal converters.
- IBM XT converter: https://geekhack.org/index.php?topic=94649.0
- PS/2 converter: https://geekhack.org/index.php?topic=14618.0
- IBM Terminal converter: http://geekhack.org/index.php?topic=27272.0
Keyboard supported
------------------
- PC XT keyboard of IBM 5150 5160
- 83-key: 1501100 1501105
- PC AT keyboard of IBM 5170
- 84-key: 6450200 6450225
- PC Terminal keyboard of IBM 5271(3270 PC)
- 122-key: 6110344 6110345 1397000
- 102-key: 1390680 1395764 1392595
- PS/2 keyboards(AT+CodeSet2)
- Clones of above models
Hardware
--------
Firmware supports ATMega32u4 and ATMega32u2 by default, Teensy2 or ProMicro can be used.
Wire controller pins below to keyboard signals, besides VCC and GND. This is compatible for Soarer's converter.
- Data PD0
- Clock PD1
- Reset PB6 or PB7 (For some of XT keyboards. Not needed for AT, PS/2 and Terminal)
Pull up resistors of 1-4.7K Ohm on both Data and Clock line are recommended, without them it won't work in some cases.
### Reset
Old Type-1 IBM XT keyboard and some of XT clones need this to reset its controller on startup. Many of IBM XT keyboards available are Type-2 and don't need the reset pin.
See this for Type-1 vs Type-2:
https://vintagecomputer.ca/ibm-pc-model-f-keyboard-type-1-vs-type-2/
As for clones Zenith Z-150 XT and Leading Edge DC-2014 are known to need this.
### Connector pinouts
#### XT
- http://www.kbdbabel.org/conn/kbd_connector_ibmpc.png
- https://allpinouts.org/pinouts/connectors/input_device/keyboard-xt-5-pin/
#### AT
- http://www.kbdbabel.org/conn/kbd_connector_ps2.png
- https://old.pinouts.ru/InputCables/KeyboardPC5_pinout.shtml
#### PS/2
- https://pinouts.ru/InputCables/KeyboardPC6_pinout.shtml
#### Terminal
- http://www.kbdbabel.org/conn/kbd_connector_ibmterm.png
- http://www.kbdbabel.org/conn/kbd_connector_ibm3179_318x_319x.png
Source Code
-----------
https://github.com/tmk/tmk_keyboard/tree/master/converter/ibmpc_usb
Build Firmware
--------------
$ cd converter/ibmpc_usb
$ make clean
$ make
Keyboard discrimination
-----------------------
This section explains how the converter determines proper protocol and scan code set for keyboard. The converter need to do that before starting to receive and translate scan codes from keyboard.
### Keyboard ID
After startup the converter sends 0xF2 command to get keyboard ID and sees how the keyboard responds to the command.
Response from keyboard:
- XT keyboard doesn't support any command and returns no response.
- AT keyboard should respond with 0xFA to the command but returns no keyboard ID.
- PS/2 keyboard should respond with 0xFA to the command, followd by keyboard ID, such as 0xAB86.
- Terminal keyboard should respond with 0xFA to the command, followed by keyboard ID, such as 0xBFBF.
Now we can dscriminate the keyboard and determine suitable protocol and scan code set as described below.
### Protocol
- Signals from XT keyboard are recognized by XT protocol.
- Signals from AT, PS/2 and Terminal keyboard are recognized by AT protocol.
### Scan code Set
- Scan codes from XT keyboard are handled as CodeSet1.
- Scan codes from AT and PS/2 keyboard are handled as CodeSet2.
- Scan codes from Terminal keyhboard are handled as CodeSet3.
Debug
-----
Use hid_listen to see debug outputs from the converter.
https://www.pjrc.com/teensy/hid_listen.html
Resources
---------
IBM PC Keyboard Protocol Resources:
[a] [Microsoft USB HID to PS/2 Translation Table - Scan Code Set 1 and 2](
http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf)
[b] [Microsoft Keyboard Scan Code Specification - Special rules of Scan Code Set 1 and 2](
http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc)
[1] [PS/2 Reference Manuals - Collection of IBM Personal System/2 documents](
http://www.mcamafia.de/pdf/pdfref.htm)
[2] [Keyboard and Auxiliary Device Controller - Signal Timing and Format](
http://www.mcamafia.de/pdf/ibm_hitrc07.pdf)
[3] [Keyboards(101- and 102-key) - Keyboard Layout, Scan Code Set, POR, and Commands](
http://www.mcamafia.de/pdf/ibm_hitrc11.pdf)
[4] [IBM PC XT Keyboard Protocol](
https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol)
[5] [IBM Keyboard Scan Code by John Elliott - 83-key, 84-key, 102-key and 122-key](
https://www.seasip.info/VintagePC/index.html)
[6] [IBM 1391406 Keyboard - Scan Code Set 2 of 102-key PS/2 keyboard](
https://www.seasip.info/VintagePC/ibm_1391406.html)
[7] [The IBM 6110344 Keyboard - Scan Code Set 3 of 122-key terminal keyboard](
https://www.seasip.info/VintagePC/ibm_6110344.html)
[y] [TrackPoint Engineering Specifications for version 3E](
https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html)
[z] [Soarer's XT/AT/PS2/Terminal to USB converter](
https://geekhack.org/index.php?topic=17458.0)
TODO
----
### Reset method for rescue
For converter without accesible reset button when magickey combo doesn't work.
Check pin status at powerup:
- if Data and/or Clock are pull down to GND
### Force protocol and scan code set
Keyboard discrimination may fail and you have to configure them by hand.
### Add AT90usb1286 support for Teensy2++

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
/*
Copyright 2019 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 0x1bee
#define DEVICE_VER 0x0001
#define MANUFACTURER t.m.k.
#define PRODUCT IBM PC keyboard converter
#define DESCRIPTION convert IBM PC keyboard to USB
/* matrix size */
#define MATRIX_ROWS 16 // keycode bit: 6-3
#define MATRIX_COLS 8 // keycode bit: 2-0
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) || \
keyboard_report->mods == (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) \
)
/*
* Pin and interrupt configuration
*/
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB1286__)
/* uses INT1 for clock line */
#define IBMPC_CLOCK_PORT PORTD
#define IBMPC_CLOCK_PIN PIND
#define IBMPC_CLOCK_DDR DDRD
#define IBMPC_CLOCK_BIT 1
#define IBMPC_DATA_PORT PORTD
#define IBMPC_DATA_PIN PIND
#define IBMPC_DATA_DDR DDRD
#define IBMPC_DATA_BIT 0
#define IBMPC_RST_PORT PORTB
#define IBMPC_RST_PIN PINB
#define IBMPC_RST_DDR DDRB
#define IBMPC_RST_BIT1 6
#define IBMPC_RST_BIT2 7
/* reset for XT keyboard: low pulse for 500ms and after that HiZ for safety */
#define IBMPC_RESET() do { \
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT1); \
IBMPC_RST_DDR |= (1<<IBMPC_RST_BIT1); \
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT2); \
IBMPC_RST_DDR |= (1<<IBMPC_RST_BIT2); \
_delay_ms(500); \
IBMPC_RST_DDR &= ~(1<<IBMPC_RST_BIT1); \
IBMPC_RST_DDR &= ~(1<<IBMPC_RST_BIT2); \
} while (0)
#define IBMPC_INT_INIT() do { \
EICRA |= ((1<<ISC11) | \
(0<<ISC10)); \
} while (0)
#define IBMPC_INT_ON() do { \
EIMSK |= (1<<INT1); \
} while (0)
#define IBMPC_INT_OFF() do { \
EIMSK &= ~(1<<INT1); \
} while (0)
#define IBMPC_INT_VECT INT1_vect
#else
#error "No pin configuration in config.h"
#endif
#endif

View file

@ -0,0 +1,853 @@
/*
Copyright 2019 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 "print.h"
#include "util.h"
#include "debug.h"
#include "ibmpc.h"
#include "host.h"
#include "led.h"
#include "matrix.h"
#include "timer.h"
#include "action.h"
#include "ibmpc_usb.h"
static void matrix_make(uint8_t code);
static void matrix_break(uint8_t code);
static int8_t process_cs1(void);
static int8_t process_cs2(void);
static int8_t process_cs3(void);
static uint8_t matrix[MATRIX_ROWS];
#define ROW(code) ((code>>3)&0x0F)
#define COL(code) (code&0x07)
static int16_t read_wait(uint16_t wait_ms)
{
uint16_t start = timer_read();
int16_t code;
while ((code = ibmpc_host_recv()) == -1 && timer_elapsed(start) < wait_ms);
return code;
}
static uint16_t read_keyboard_id(void)
{
uint16_t id = 0;
int16_t code = 0;
// Disable
code = ibmpc_host_send(0xF5);
// Read ID
code = ibmpc_host_send(0xF2);
if (code == -1) return 0xFFFF; // XT or No keyboard
if (code != 0xFA) return 0xFFFE; // Broken PS/2?
code = read_wait(1000);
if (code == -1) return 0x0000; // AT
id = (code & 0xFF)<<8;
code = read_wait(1000);
id |= code & 0xFF;
// Enable
code = ibmpc_host_send(0xF4);
return id;
}
void matrix_init(void)
{
debug_enable = true;
ibmpc_host_init();
// hard reset for XT keyboard
IBMPC_RESET();
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
return;
}
/*
* keyboard recognition
*
* 1. Send F2 to get keyboard ID
* a. no ACK(FA): XT keyobard
* b. ACK but no ID: 84-key AT keyboard CodeSet2
* c. ID is AB 83: PS/2 keyboard CodeSet2
* d. ID is BF BF: Terminal keyboard CodeSet3
* e. error on recv: maybe broken PS/2
*/
uint16_t keyboard_id = 0x0000;
keyboard_kind_t keyboard_kind = NONE;
uint8_t matrix_scan(void)
{
// scan code reading states
static enum {
INIT,
WAIT_STARTUP,
READ_ID,
LED_SET,
LOOP,
END
} state = INIT;
static uint16_t last_time;
if (ibmpc_error) {
xprintf("err: %02X\n", ibmpc_error);
// when recv error, neither send error nor buffer full
if (!(ibmpc_error & (IBMPC_ERR_SEND | IBMPC_ERR_FULL))) {
// keyboard init again
if (state == LOOP) {
xprintf("init\n");
state = INIT;
}
}
// clear or process error
ibmpc_error = IBMPC_ERR_NONE;
}
switch (state) {
case INIT:
ibmpc_protocol = IBMPC_PROTOCOL_AT;
keyboard_kind = NONE;
keyboard_id = 0x0000;
last_time = timer_read();
state = WAIT_STARTUP;
matrix_clear();
clear_keyboard();
break;
case WAIT_STARTUP:
// read and ignore BAT code and other codes when power-up
ibmpc_host_recv();
if (timer_elapsed(last_time) > 1000) {
state = READ_ID;
}
break;
case READ_ID:
keyboard_id = read_keyboard_id();
if (ibmpc_error) {
xprintf("err: %02X\n", ibmpc_error);
ibmpc_error = IBMPC_ERR_NONE;
}
xprintf("ID: %04X\n", keyboard_id);
if (0xAB00 == (keyboard_id & 0xFF00)) {
// CodeSet2 PS/2
keyboard_kind = PC_AT;
} else if (0xBF00 == (keyboard_id & 0xFF00)) {
// CodeSet3 Terminal
keyboard_kind = PC_TERMINAL;
} else if (0x0000 == keyboard_id) {
// CodeSet2 AT
keyboard_kind = PC_AT;
} else if (0xFFFF == keyboard_id) {
// CodeSet1 XT
keyboard_kind = PC_XT;
} else if (0xFFFE == keyboard_id) {
// CodeSet2 PS/2 fails to response?
keyboard_kind = PC_AT;
} else if (0x00FF == keyboard_id) {
// Mouse is not supported
xprintf("Mouse: not supported\n");
keyboard_kind = NONE;
} else {
keyboard_kind = PC_AT;
}
// protocol
if (keyboard_kind == PC_XT) {
xprintf("kbd: XT\n");
ibmpc_protocol = IBMPC_PROTOCOL_XT;
} else if (keyboard_kind == PC_AT) {
xprintf("kbd: AT\n");
ibmpc_protocol = IBMPC_PROTOCOL_AT;
} else if (keyboard_kind == PC_TERMINAL) {
xprintf("kbd: Terminal\n");
ibmpc_protocol = IBMPC_PROTOCOL_AT;
// Set all keys - make/break [3]p.23
ibmpc_host_send(0xF8);
} else {
xprintf("kbd: Unknown\n");
ibmpc_protocol = IBMPC_PROTOCOL_AT;
}
state = LED_SET;
break;
case LED_SET:
led_set(host_keyboard_leds());
state = LOOP;
case LOOP:
switch (keyboard_kind) {
case PC_XT:
process_cs1();
break;
case PC_AT:
process_cs2();
break;
case PC_TERMINAL:
process_cs3();
break;
default:
break;
}
break;
default:
break;
}
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];
}
uint8_t matrix_key_count(void)
{
uint8_t count = 0;
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
count += bitpop(matrix[i]);
}
return count;
}
inline
static void matrix_make(uint8_t code)
{
if (!matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] |= 1<<COL(code);
}
}
inline
static void matrix_break(uint8_t code)
{
if (matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] &= ~(1<<COL(code));
}
}
void matrix_clear(void)
{
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
}
void led_set(uint8_t usb_led)
{
if (keyboard_kind != PC_AT) return;
uint8_t ibmpc_led = 0;
if (usb_led & (1<<USB_LED_SCROLL_LOCK))
ibmpc_led |= (1<<IBMPC_LED_SCROLL_LOCK);
if (usb_led & (1<<USB_LED_NUM_LOCK))
ibmpc_led |= (1<<IBMPC_LED_NUM_LOCK);
if (usb_led & (1<<USB_LED_CAPS_LOCK))
ibmpc_led |= (1<<IBMPC_LED_CAPS_LOCK);
ibmpc_host_set_led(ibmpc_led);
}
/*******************************************************************************
* XT: Scan Code Set 1
*
* See [3], [a]
*
* E0-escaped scan codes are translated into unused range of the matrix.(54-7F)
*
* 01-53: Normal codes used in original XT keyboard
* 54-7F: Not used in original XT keyboard
*
* 0 1 2 3 4 5 6 7 8 9 A B C D E F
* 50 - - - - * * x x x x * * * * * *
* 60 * * * * x x x x x x x x x x x *
* 70 x * * x * * x * * x * x * x x *
*
* -: codes existed in original XT keyboard
* *: E0-escaped codes translated
* x: Non-espcaped codes(Some are not used in real keyboards probably)
*
* Codes assigned in range 54-7F:
*
* 50 - 60 Up* 70 KANAx
* 51 - 61 Left* 71 Insert*
* 52 - 62 Down* 72 Delete*
* 53 - 63 Right* 73 ROx
* 54 PrintScr* 64 F13x 74 Home*
* 55 Pause* 65 F14x 75 End*
* 56 Euro2x 66 F15x 76 F24x
* 57 F11x 67 F16x 77 PageUp*
* 58 F12x 68 F17x 78 PageDown*
* 59 Keypad=x 69 F18x 79 HENKANx
* 5A LGUI* 6A F19x 7A RCTL*
* 5B RGUI* 6B F20x 7B MUHENKANx
* 5C APP* 6C F21x 7C RALT*
* 5D Mute* 6D F22x 7D JPYx
* 5E Volume Down* 6E F23x 7E Keypad,x
* 5F Volume Up* 6F Keypad Enter* 7F Keypad/ *
*/
static uint8_t cs1_e0code(uint8_t code) {
switch(code) {
// Original IBM XT keyboard doesn't use E0-codes probably
// Some XT compatilble keyobards need these keys?
case 0x37: return 0x54; // Print Screen
case 0x46: return 0x55; // Ctrl + Pause
case 0x5B: return 0x5A; // Left GUI
case 0x5C: return 0x5B; // Right GUI
case 0x5D: return 0x5C; // Application
case 0x20: return 0x5D; // Mute
case 0x2E: return 0x5E; // Volume Down
case 0x30: return 0x5F; // Volume Up
case 0x48: return 0x60; // Up
case 0x4B: return 0x61; // Left
case 0x50: return 0x62; // Down
case 0x4D: return 0x63; // Right
case 0x1C: return 0x6F; // Keypad Enter
case 0x52: return 0x71; // Insert
case 0x53: return 0x72; // Delete
case 0x47: return 0x74; // Home
case 0x4F: return 0x75; // End
case 0x49: return 0x77; // Page Up
case 0x51: return 0x78; // Page Down
case 0x1D: return 0x7A; // Right Ctrl
case 0x38: return 0x7C; // Right Alt
case 0x35: return 0x7F; // Keypad /
// Shared matrix cell with other keys
case 0x5E: return 0x70; // Power (KANA)
case 0x5F: return 0x79; // Sleep (HENKAN)
case 0x63: return 0x7B; // Wake (MUHENKAN)
default:
xprintf("!CS1_?!\n");
return code;
}
return 0x00;
}
static int8_t process_cs1(void)
{
static enum {
INIT,
E0,
// Pause: E1 1D 45, E1 9D C5
E1,
E1_1D,
E1_9D,
} state = INIT;
uint16_t code = ibmpc_host_recv();
if (code == -1) {
return 0;
}
switch (state) {
case INIT:
switch (code) {
case 0xE0:
state = E0;
break;
case 0xE1:
state = E1;
break;
default:
if (code < 0x80)
matrix_make(code);
else
matrix_break(code & 0x7F);
break;
}
break;
case E0:
switch (code) {
case 0x2A:
case 0xAA:
case 0x36:
case 0xB6:
//ignore fake shift
state = INIT;
break;
default:
if (code < 0x80)
matrix_make(cs1_e0code(code));
else
matrix_break(cs1_e0code(code & 0x7F));
state = INIT;
break;
}
break;
case E1:
switch (code) {
case 0x1D:
state = E1_1D;
break;
case 0x9D:
state = E1_9D;
break;
default:
state = INIT;
break;
}
break;
case E1_1D:
switch (code) {
case 0x45:
matrix_make(0x55);
break;
default:
state = INIT;
break;
}
break;
case E1_9D:
switch (code) {
case 0x45:
matrix_break(0x55);
break;
default:
state = INIT;
break;
}
break;
default:
state = INIT;
}
return 0;
}
/*******************************************************************************
* AT, PS/2: Scan Code Set 2
*
* Exceptional Handling
* --------------------
* Some keys should be handled exceptionally. See [b].
*
* Scan codes are varied or prefix/postfix'd depending on modifier key state.
*
* 1) Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left
* a) when Num Lock is off
* modifiers | make | break
* ----------+---------------------------+----------------------
* Ohter | <make> | <break>
* LShift | E0 F0 12 <make> | <break> E0 12
* RShift | E0 F0 59 <make> | <break> E0 59
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
*
* b) when Num Lock is on
* modifiers | make | break
* ----------+---------------------------+----------------------
* Other | E0 12 <make> | <break> E0 F0 12
* Shift'd | <make> | <break>
*
* Handling: These prefix/postfix codes are ignored.
*
*
* 2) Keypad /
* modifiers | make | break
* ----------+---------------------------+----------------------
* Ohter | <make> | <break>
* LShift | E0 F0 12 <make> | <break> E0 12
* RShift | E0 F0 59 <make> | <break> E0 59
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
*
* Handling: These prefix/postfix codes are ignored.
*
*
* 3) PrintScreen
* modifiers | make | break
* ----------+--------------+-----------------------------------
* Other | E0 12 E0 7C | E0 F0 7C E0 F0 12
* Shift'd | E0 7C | E0 F0 7C
* Control'd | E0 7C | E0 F0 7C
* Alt'd | 84 | F0 84
*
* Handling: These prefix/postfix codes are ignored, and both scan codes
* 'E0 7C' and 84 are seen as PrintScreen.
*
* 4) Pause
* modifiers | make(no break code)
* ----------+--------------------------------------------------
* Other | E1 14 77 E1 F0 14 F0 77
* Control'd | E0 7E E0 F0 7E
*
* Handling: Both code sequences are treated as a whole.
* And we need a ad hoc 'pseudo break code' hack to get the key off
* because it has no break code.
*
* Notes:
* 'Hanguel/English'(F1) and 'Hanja'(F2) have no break code. See [a].
* These two Korean keys need exceptional handling and are not supported for now.
*
*/
static uint8_t cs2_e0code(uint8_t code) {
switch(code) {
// E0 prefixed codes translation See [a].
case 0x11: return 0x0F; // right alt
case 0x14: return 0x17; // right control
case 0x1F: return 0x19; // left GUI
case 0x27: return 0x1F; // right GUI
case 0x2F: return 0x5C; // apps
case 0x4A: return 0x60; // keypad /
case 0x5A: return 0x62; // keypad enter
case 0x69: return 0x27; // end
case 0x6B: return 0x53; // cursor left
case 0x6C: return 0x2F; // home
case 0x70: return 0x39; // insert
case 0x71: return 0x37; // delete
case 0x72: return 0x3F; // cursor down
case 0x74: return 0x47; // cursor right
case 0x75: return 0x4F; // cursor up
case 0x7A: return 0x56; // page down
case 0x7D: return 0x5E; // page up
case 0x7C: return 0x6F; // Print Screen
case 0x7E: return 0x00; // Control'd Pause
case 0x21: return 0x65; // volume down
case 0x32: return 0x6E; // volume up
case 0x23: return 0x7F; // mute
case 0x10: return 0x08; // (WWW search) -> F13
case 0x18: return 0x10; // (WWW favourites) -> F14
case 0x20: return 0x18; // (WWW refresh) -> F15
case 0x28: return 0x20; // (WWW stop) -> F16
case 0x30: return 0x28; // (WWW forward) -> F17
case 0x38: return 0x30; // (WWW back) -> F18
case 0x3A: return 0x38; // (WWW home) -> F19
case 0x40: return 0x40; // (my computer) -> F20
case 0x48: return 0x48; // (email) -> F21
case 0x2B: return 0x50; // (calculator) -> F22
case 0x34: return 0x08; // (play/pause) -> F13
case 0x3B: return 0x10; // (stop) -> F14
case 0x15: return 0x18; // (previous track) -> F15
case 0x4D: return 0x20; // (next track) -> F16
case 0x50: return 0x28; // (media select) -> F17
case 0x5E: return 0x50; // (ACPI wake) -> F22
case 0x3F: return 0x57; // (ACPI sleep) -> F23
case 0x37: return 0x5F; // (ACPI power) -> F24
// https://github.com/tmk/tmk_keyboard/pull/636
case 0x03: return 0x18; // Help DEC LK411 -> F15
case 0x04: return 0x08; // F13 DEC LK411
case 0x0B: return 0x20; // Do DEC LK411 -> F16
case 0x0C: return 0x10; // F14 DEC LK411
case 0x0D: return 0x19; // LCompose DEC LK411 -> LGUI
case 0x79: return 0x6D; // KP- DEC LK411 -> PCMM
case 0x83: return 0x28; // F17 DEC LK411
default: return (code & 0x7F);
}
}
static int8_t process_cs2(void)
{
// scan code reading states
static enum {
INIT,
F0,
E0,
E0_F0,
// Pause
E1,
E1_14,
E1_F0,
E1_F0_14,
E1_F0_14_F0,
} state = INIT;
uint16_t code = ibmpc_host_recv();
if (code == -1) {
return 0;
}
switch (state) {
case INIT:
switch (code) {
case 0xE0:
state = E0;
break;
case 0xF0:
state = F0;
break;
case 0xE1:
state = E1;
break;
case 0x83: // F7
matrix_make(0x02);
state = INIT;
break;
case 0x84: // Alt'd PrintScreen
matrix_make(0x6F);
state = INIT;
break;
case 0x00: // Overrun [3]p.26
matrix_clear();
xprintf("!CS2_OVERRUN!\n");
state = INIT;
break;
case 0xAA: // Self-test passed
case 0xFC: // Self-test failed
// reset or plugin-in new keyboard
state = INIT;
return -1;
break;
default: // normal key make
if (code < 0x80) {
matrix_make(code);
} else {
matrix_clear();
xprintf("!CS2_INIT!\n");
}
state = INIT;
}
break;
case E0: // E0-Prefixed
switch (code) {
case 0x12: // to be ignored
case 0x59: // to be ignored
state = INIT;
break;
case 0xF0:
state = E0_F0;
break;
default:
if (code < 0x80) {
matrix_make(cs2_e0code(code));
} else {
matrix_clear();
xprintf("!CS2_E0!\n");
}
state = INIT;
}
break;
case F0: // Break code
switch (code) {
case 0x83: // F7
matrix_break(0x02);
state = INIT;
break;
case 0x84: // Alt'd PrintScreen
matrix_break(0x6F);
state = INIT;
break;
default:
if (code < 0x80) {
matrix_break(code);
} else {
matrix_clear();
xprintf("!CS2_F0!\n");
}
state = INIT;
}
break;
case E0_F0: // Break code of E0-prefixed
switch (code) {
case 0x12: // to be ignored
case 0x59: // to be ignored
state = INIT;
break;
default:
if (code < 0x80) {
matrix_break(cs2_e0code(code));
} else {
matrix_clear();
xprintf("!CS2_E0_F0!\n");
}
state = INIT;
}
break;
// Pause make: E1 14 77
case E1:
switch (code) {
case 0x14:
state = E1_14;
break;
case 0xF0:
state = E1_F0;
break;
default:
state = INIT;
}
break;
case E1_14:
switch (code) {
case 0x77:
matrix_make(0x00);
state = INIT;
break;
default:
state = INIT;
}
break;
// Pause break: E1 F0 14 F0 77
case E1_F0:
switch (code) {
case 0x14:
state = E1_F0_14;
break;
default:
state = INIT;
}
break;
case E1_F0_14:
switch (code) {
case 0xF0:
state = E1_F0_14_F0;
break;
default:
state = INIT;
}
break;
case E1_F0_14_F0:
switch (code) {
case 0x77:
matrix_break(0x00);
state = INIT;
break;
default:
state = INIT;
}
break;
default:
state = INIT;
}
return 0;
}
/*
* Terminal: Scan Code Set 3
*
* See [3], [7]
*
* Scan code 0x83 and 0x84 are handled exceptioanally to fit into 1-byte range index.
*/
static int8_t process_cs3(void)
{
static enum {
READY,
F0,
} state = READY;
uint16_t code = ibmpc_host_recv();
if (code == -1) {
return 0;
}
switch (state) {
case READY:
switch (code) {
case 0x00:
case 0xff:
xprintf("!CS3_%02X!\n", code);
break;
case 0xF0:
state = F0;
break;
case 0x83: // F7
matrix_make(0x02);
break;
case 0x84: // keypad -
matrix_make(0x7F);
break;
default: // normal key make
if (code < 0x80) {
matrix_make(code);
} else {
xprintf("!CS3_%02X!\n", code);
}
state = READY;
}
break;
case F0: // Break code
switch (code) {
case 0x00:
case 0xff:
xprintf("!CS3_F0_%02X!\n", code);
state = READY;
break;
case 0x83: // F7
matrix_break(0x02);
state = READY;
break;
case 0x84: // keypad -
matrix_break(0x7F);
state = READY;
break;
default:
if (code < 0x80) {
matrix_break(code);
} else {
xprintf("!CS3_F0_%02X!\n", code);
}
state = READY;
}
break;
}
return 0;
}
/*
* IBM PC Keyboard Protocol Resources:
*
* [a] Microsoft USB HID to PS/2 Translation Table - Scan Code Set 1 and 2
* http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
*
* [b] Microsoft Keyboard Scan Code Specification - Special rules of Scan Code Set 1 and 2
* http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
*
* [1] PS/2 Reference Manuals - Collection of IBM Personal System/2 documents.
* http://www.mcamafia.de/pdf/pdfref.htm
*
* [2] Keyboard and Auxiliary Device Controller - Signal Timing and Format
* http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
*
* [3] Keyboards(101- and 102-key) - Keyboard Layout, Scan Code Set, POR, and Commands.
* http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
*
* [4] IBM PC XT Keyboard Protocol
* https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
*
* [5] IBM Keyboard Scan Code by John Elliott - 83-key, 84-key, 102-key and 122-key
* https://www.seasip.info/VintagePC/index.html
*
* [6] IBM 1391406 Keyboard - Scan Code Set 2 of 102-key PS/2 keyboard
* https://www.seasip.info/VintagePC/ibm_1391406.html
*
* [7] The IBM 6110344 Keyboard - Scan Code Set 3 of 122-key terminal keyboard
* https://www.seasip.info/VintagePC/ibm_6110344.html
*
* [y] TrackPoint Engineering Specifications for version 3E
* https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
*
* [z] [Soarer's XT/AT/PS2/Terminal to USB converter]
* https://geekhack.org/index.php?topic=17458.0
*
*/

View file

@ -0,0 +1,9 @@
#ifndef IBMPC_USB_H
#define IBMPC_USB_H
typedef enum { NONE, PC_XT, PC_AT, PC_TERMINAL } keyboard_kind_t;
extern uint16_t keyboard_id;
extern keyboard_kind_t keyboard_kind;
#endif

View file

@ -0,0 +1,45 @@
/*
Copyright 2016 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 "unimap_trans.h"
#define AC_FN0 ACTION_LAYER_MOMENTARY(1)
#ifdef KEYMAP_SECTION_ENABLE
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
#else
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
#endif
UNIMAP(
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS, VOLD,VOLU,MUTE,
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS,
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, P4, P5, P6, PCMM,
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RO, RSFT, UP, P1, P2, P3, PENT,
LCTL,LGUI,LALT,MHEN, SPC, HENK,KANA,RALT,RGUI,FN0, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PEQL
),
UNIMAP(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
GRV, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, INS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,LEFT,RGHT, TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,DOWN, TRNS,TRNS, PGUP, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, HOME,PGDN,END, TRNS,TRNS,TRNS
),
};

View file

@ -0,0 +1,237 @@
/*
Copyright 2019 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 UNIMAP_TRANS_H
#define UNIMAP_TRANS_H
#include <stdint.h>
#include <avr/pgmspace.h>
#include "unimap.h"
#include "action.h"
#include "ibmpc_usb.h"
/* Mapping to Universal keyboard layout
*
* Universal keyboard layout
* ,-----------------------------------------------.
* |F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|
* ,---. |-----------------------------------------------| ,-----------. ,-----------.
* |Esc| |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10|F11|F12| |PrS|ScL|Pau| |VDn|VUp|Mut|
* `---' `-----------------------------------------------' `-----------' `-----------'
* ,-----------------------------------------------------------. ,-----------. ,---------------.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|JPY|Bsp| |Ins|Hom|PgU| |NmL| /| *| -|
* |-----------------------------------------------------------| |-----------| |---------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ | |Del|End|PgD| | 7| 8| 9| +|
* |-----------------------------------------------------------| `-----------' |---------------|
* |CapsL | A| S| D| F| G| H| J| K| L| ;| '| ^a|Retn| | 4| 5| 6|KP,|
* |-----------------------------------------------------------| ,---. |---------------|
* |Shft| <| Z| X| C| V| B| N| M| ,| .| /| RO|Shift | |Up | | 1| 2| 3|KP=|
* |-----------------------------------------------------------| ,-----------. |---------------|
* |Ctl|Gui|Alt|MHEN| Space |HENK|KANA|Alt|Gui|App|Ctl| |Lef|Dow|Rig| | #| 0| .|Ent|
* `-----------------------------------------------------------' `-----------' `---------------'
*/
/*
* Scan Code Set 1:
* ,-------. ,--------------------------------------------------------------------------.
* | F1| F2| |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| BS |NumLck |ScrLck |
* |-------| |--------------------------------------------------------------------------|
* | F3| F4| | Tab | Q| W| E| R| T| Y| U| I| O| P| [| ] | | 7| 8| 9| -|
* |-------| |------------------------------------------------------|Ent|---------------|
* | F5| F6| | Ctrl | A| S| D| F| G| H| J| K| L| ;| '| `| | 4| 5| 6| |
* |-------| |----------------------------------------------------------------------| |
* | F7| F8| |Shif| \| Z| X| C| V| B| N| M| ,| .| /|Shift| *| 1| 2| 3| +|
* |-------| |----------------------------------------------------------------------| |
* | F9|F10| | Alt | Space |CapsLck| 0 | . | |
* `-------' `--------------------------------------------------------------------------'
*
* ,-------. ,--------------------------------------------------------------------------.
* | 3B| 3C| | 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E | 45 | 46 |
* |-------| |--------------------------------------------------------------------------|
* | 3D| 3E| | 0F | 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B | | 47| 48| 49| 4A|
* |-------| |------------------------------------------------------| 1C|---------------|
* | 3F| 40| | 1D | 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| | 4B| 4C| 4D| |
* |-------| |----------------------------------------------------------------------| |
* | 41| 42| | 2A | 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35| 36 | 37| 4F| 50| 51| 4E|
* |-------| |----------------------------------------------------------------------| |
* | 43| 44| | 38 | 39 | 3A | 52 | 53 | |
* `-------' `--------------------------------------------------------------------------'
* [3], [a]
*/
const uint8_t PROGMEM unimap_cs1[MATRIX_ROWS][MATRIX_COLS] = {
{ UNIMAP_NO, UNIMAP_ESC, UNIMAP_1, UNIMAP_2, UNIMAP_3, UNIMAP_4, UNIMAP_5, UNIMAP_6 }, /* 00-07 */
{ UNIMAP_7, UNIMAP_8, UNIMAP_9, UNIMAP_0, UNIMAP_MINUS, UNIMAP_EQUAL, UNIMAP_BSPACE,UNIMAP_TAB }, /* 08-0F */
{ UNIMAP_Q, UNIMAP_W, UNIMAP_E, UNIMAP_R, UNIMAP_T, UNIMAP_Y, UNIMAP_U, UNIMAP_I }, /* 10-17 */
{ UNIMAP_O, UNIMAP_P, UNIMAP_LBRC, UNIMAP_RBRC, UNIMAP_ENTER, UNIMAP_LCTL, UNIMAP_A, UNIMAP_S, }, /* 18-1F */
{ UNIMAP_D, UNIMAP_F, UNIMAP_G, UNIMAP_H, UNIMAP_J, UNIMAP_K, UNIMAP_L, UNIMAP_SCLN }, /* 20-27 */
{ UNIMAP_QUOTE, UNIMAP_GRAVE, UNIMAP_LSHIFT,UNIMAP_BSLASH,UNIMAP_Z, UNIMAP_X, UNIMAP_C, UNIMAP_V, }, /* 28-2F */
{ UNIMAP_B, UNIMAP_N, UNIMAP_M, UNIMAP_COMMA, UNIMAP_DOT, UNIMAP_SLASH, UNIMAP_RSHIFT,UNIMAP_PAST }, /* 30-37 */
{ UNIMAP_LALT, UNIMAP_SPACE, UNIMAP_CAPS, UNIMAP_F1, UNIMAP_F2, UNIMAP_F3, UNIMAP_F4, UNIMAP_F5 }, /* 38-3F */
{ UNIMAP_F6, UNIMAP_F7, UNIMAP_F8, UNIMAP_F9, UNIMAP_F10, UNIMAP_NLCK, UNIMAP_SLCK, UNIMAP_P7 }, /* 40-47 */
{ UNIMAP_P8, UNIMAP_P9, UNIMAP_PMNS, UNIMAP_P4, UNIMAP_P5, UNIMAP_P6, UNIMAP_PPLS, UNIMAP_P1 }, /* 48-4F */
{ UNIMAP_P2, UNIMAP_P3, UNIMAP_P0, UNIMAP_PDOT, UNIMAP_PSCR, UNIMAP_PAUSE, UNIMAP_NUHS, UNIMAP_F11 }, /* 50-57 */
{ UNIMAP_F12, UNIMAP_PEQL, UNIMAP_LGUI, UNIMAP_RGUI, UNIMAP_APP, UNIMAP_MUTE, UNIMAP_VOLD, UNIMAP_VOLU }, /* 58-5F */
{ UNIMAP_UP, UNIMAP_LEFT, UNIMAP_DOWN, UNIMAP_RIGHT, UNIMAP_F13, UNIMAP_F14, UNIMAP_F15, UNIMAP_F16 }, /* 60-67 */
{ UNIMAP_F17, UNIMAP_F18, UNIMAP_F19, UNIMAP_F20, UNIMAP_F21, UNIMAP_F22, UNIMAP_F23, UNIMAP_PENT }, /* 68-6F */
{ UNIMAP_KANA, UNIMAP_INSERT,UNIMAP_DELETE,UNIMAP_RO, UNIMAP_HOME, UNIMAP_END, UNIMAP_F24, UNIMAP_PGUP }, /* 70-77 */
{ UNIMAP_PGDN, UNIMAP_HENK, UNIMAP_RCTL, UNIMAP_MHEN, UNIMAP_RALT, UNIMAP_JYEN, UNIMAP_PCMM, UNIMAP_PSLS }, /* 78-7F */
};
/*
* Scan Code Set 2:
* ,-----------------------------------------------.
* |F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|
* ,---. |-----------------------------------------------| ,-----------. ,-----------.
* |Esc| |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10|F11|F12| |PrS|ScL|Pau| |VDn|VUp|Mut|
* `---' `-----------------------------------------------' `-----------' `-----------'
* ,-----------------------------------------------------------. ,-----------. ,---------------.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|JPY|Bsp| |Ins|Hom|PgU| |NmL| /| *| -|
* |-----------------------------------------------------------| |-----------| |---------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ | |Del|End|PgD| | 7| 8| 9| +|
* |-----------------------------------------------------------| `-----------' |---------------|
* |CapsL | A| S| D| F| G| H| J| K| L| ;| '| ^a|Entr| | 4| 5| 6|KP,|
* |-----------------------------------------------------------| ,---. |---------------|
* |Shft| <| Z| X| C| V| B| N| M| ,| .| /| RO|Shift | |Up | | 1| 2| 3|Ent|
* |-----------------------------------------------------------| ,-----------. |---------------|
* |Ctl|Gui|Alt|MHEN| Space |HENK|KANA|Alt|Gui|App|Ctl| |Lef|Dow|Rig| | #| 0| .|KP=|
* `-----------------------------------------------------------' `-----------' `---------------'
*
* ,-----------------------------------------------.
* | 08| 10| 18| 20| 28| 30| 38| 40| 48| 50| 57| 5F|
* ,---. |-----------------------------------------------| ,-----------. ,-----------.
* | 76| | 05| 06| 04| 0C| 03| 0B| 83| 0A| 01| 09| 78| 07| |+7C| 7E|+77| |*21|*32|*23|
* `---' `-----------------------------------------------' `-----------' `-----------'
* ,-----------------------------------------------------------. ,-----------. ,---------------.
* | 0E| 16| 1E| 26| 25| 2E| 36| 3D| 3E| 46| 45| 4E| 55| 6A| 66| |*70|*6C|*7D| | 77|*4A| 7C| 7B|
* |-----------------------------------------------------------| |-----------| |---------------|
* | 0D | 15| 1D| 24| 2D| 2C| 35| 3C| 43| 44| 4D| 54| 5B| 5D | |*71|*69|*7A| | 6C| 75| 7D| 79|
* |-----------------------------------------------------------| `-----------' |---------------|
* | 58 | 1C| 1B| 23| 2B| 34| 33| 3B| 42| 4B| 4C| 52| ^a| 5A | | 6B| 73| 74| 6D|
* |-----------------------------------------------------------| ,---. |---------------|
* | 12 | 61| 1A| 22| 21| 2A| 32| 31| 3A| 41| 49| 4A| 51| 59 | |*75| | 69| 72| 7A|*5A|
* |-----------------------------------------------------------| ,-----------. |---------------|
* | 14|*1F| 11| 67 | 29 | 64 | 13 |*11|*27|*2F|*14| |*6B|*72|*74| | 68| 70| 71| 63|
* `-----------------------------------------------------------' `-----------' `---------------'
* *: E0-prefixed codes
* +: Special codes sequence
* ^a: ISO hash key uses identical scancode 5D to US backslash.
* 51, 63, 68, 6A, 6D: Hidden keys in IBM model M [6]
*/
const uint8_t PROGMEM unimap_cs2[MATRIX_ROWS][MATRIX_COLS] = {
{ UNIMAP_PAUS, UNIMAP_F9, UNIMAP_F7, UNIMAP_F5, UNIMAP_F3, UNIMAP_F1, UNIMAP_F2, UNIMAP_F12 }, /* 00-07 */
{ UNIMAP_F13, UNIMAP_F10, UNIMAP_F8, UNIMAP_F6, UNIMAP_F4, UNIMAP_TAB, UNIMAP_GRV, UNIMAP_RALT }, /* 08-0F */
{ UNIMAP_F14, UNIMAP_LALT, UNIMAP_LSHIFT,UNIMAP_KANA, UNIMAP_LCTL, UNIMAP_Q, UNIMAP_1, UNIMAP_RCTL }, /* 10-17 */
{ UNIMAP_F15, UNIMAP_LGUI, UNIMAP_Z, UNIMAP_S, UNIMAP_A, UNIMAP_W, UNIMAP_2, UNIMAP_RGUI }, /* 18-1F */
{ UNIMAP_F16, UNIMAP_C, UNIMAP_X, UNIMAP_D, UNIMAP_E, UNIMAP_4, UNIMAP_3, UNIMAP_END }, /* 20-27 */
{ UNIMAP_F17, UNIMAP_SPACE, UNIMAP_V, UNIMAP_F, UNIMAP_T, UNIMAP_R, UNIMAP_5, UNIMAP_HOME }, /* 28-2F */
{ UNIMAP_F18, UNIMAP_N, UNIMAP_B, UNIMAP_H, UNIMAP_G, UNIMAP_Y, UNIMAP_6, UNIMAP_DEL }, /* 30-37 */
{ UNIMAP_F19, UNIMAP_INS, UNIMAP_M, UNIMAP_J, UNIMAP_U, UNIMAP_7, UNIMAP_8, UNIMAP_DOWN }, /* 38-3F */
{ UNIMAP_F20, UNIMAP_COMMA, UNIMAP_K, UNIMAP_I, UNIMAP_O, UNIMAP_0, UNIMAP_9, UNIMAP_RIGHT }, /* 40-47 */
{ UNIMAP_F21, UNIMAP_DOT, UNIMAP_SLASH, UNIMAP_L, UNIMAP_SCOLON,UNIMAP_P, UNIMAP_MINUS, UNIMAP_UP }, /* 48-4F */
{ UNIMAP_F22, UNIMAP_RO, UNIMAP_QUOTE, UNIMAP_LEFT, UNIMAP_LBRC, UNIMAP_EQUAL, UNIMAP_PGDN, UNIMAP_F23 }, /* 50-57 */
{ UNIMAP_CAPS, UNIMAP_RSHIFT,UNIMAP_ENTER, UNIMAP_RBRC, UNIMAP_APP, UNIMAP_BSLASH,UNIMAP_PGUP, UNIMAP_F24 }, /* 58-5F */
{ UNIMAP_PSLS, UNIMAP_NUBS, UNIMAP_PENT, UNIMAP_PEQL, UNIMAP_HENK, UNIMAP_VOLD, UNIMAP_BSPACE,UNIMAP_MHEN }, /* 60-67 */
{ UNIMAP_NUHS, UNIMAP_P1, UNIMAP_JYEN, UNIMAP_P4, UNIMAP_P7, UNIMAP_PCMM, UNIMAP_VOLU, UNIMAP_PSCR }, /* 68-6F */
{ UNIMAP_P0, UNIMAP_PDOT, UNIMAP_P2, UNIMAP_P5, UNIMAP_P6, UNIMAP_P8, UNIMAP_ESC, UNIMAP_NLCK }, /* 70-77 */
{ UNIMAP_F11, UNIMAP_PPLS, UNIMAP_P3, UNIMAP_PMNS, UNIMAP_PAST, UNIMAP_P9, UNIMAP_SLCK, UNIMAP_MUTE }, /* 78-7F */
};
/*
* Scan Code Set 3:
* ,-----------------------------------------------.
* |F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|
* |-----------------------------------------------|
* |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10|F11|F12|
* `-----------------------------------------------'
* ,-------. ,-----------------------------------------------------------. ,-----------. ,---------------.
* |PrS|Esc| | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Yen| BS| |Ins|Hom|PgU| |NmL| /| *| -|
* |-------| |-----------------------------------------------------------| |-----------| |---------------|
* |ScL|Hen| |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| +|
* |-------| |-----------------------------------------------------------| `-----------' |-----------|---|
* |Pau|Muh| |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #| Ret| |Up | | 4| 5| 6| ,|
* |-------| |-----------------------------------------------------------| ,-----------. |---------------|
* |VoD|VoU| |Shif| \| Z| X| C| V| B| N| M| ,| ,| /| RO| Shift| |Lef|App|Rig| | 1| 2| 3|Ent|
* |-------| |-----------------------------------------------------------| `-----------' |-----------|---|
* |Gui|Gui| |Ctrl| |Alt | Space |Alt | |Ctrl| |Dow| |Kan| 0| .| =|
* `-------' `----' `---------------------------------------' `----' `---' `---------------'
*
* ,-----------------------------------------------.
* | 08| 10| 18| 20| 28| 30| 38| 40| 48| 50| 57| 5F|
* |-----------------------------------------------|
* | 07| 0F| 17| 1F| 27| 2F| 37| 3F| 47| 4F| 56| 5E|
* `-----------------------------------------------'
* ,-------. ,-----------------------------------------------------------. ,-----------. ,---------------.
* | 05| 06| | 0E| 16| 1E| 26| 25| 2E| 36| 3D| 3E| 46| 45| 4E| 55| 5D| 66| | 67| 6E| 6F| | 76| 77| 7E|*84|
* |-------| |-----------------------------------------------------------| |-----------| |---------------|
* | 04| 0C| | 0D | 15| 1D| 24| 2D| 2C| 35| 3C| 43| 44| 4D| 54| 5B| 5C | | 64| 65| 6D| | 6C| 75| 7D| 7C|
* |-------| |-----------------------------------------------------------| `-----------' |---------------|
* | 03| 0B| | 58 | 1C| 1B| 23| 2B| 34| 33| 3B| 42| 4B| 4C| 52| 53| 5A | | 63| | 6B| 73| 74| 7B|
* |-------| |-----------------------------------------------------------| ,-----------. |---------------|
* |*83| 0A| | 12 | 13| 1A| 22| 21| 2A| 32| 31| 3A| 41| 49| 4A| 51| 59 | | 61| 62| 6A| | 69| 72| 7A| 79|
* |-------| |-----------------------------------------------------------| `-----------' |---------------|
* | 01| 09| | 11 | |19 | 29 |39 | | 58 | | 60| | 68| 70| 71| 78|
* `-------' `-----' `---------------------------------------' `-----' `---' `---------------'
* *: 83=02, 84=7F
* 51, 5C, 5D, 68, 78: Hidden keys in IBM 122-key terminal keyboard [7]
*/
const uint8_t PROGMEM unimap_cs3[MATRIX_ROWS][MATRIX_COLS] = {
{ UNIMAP_NO, UNIMAP_LGUI, UNIMAP_VOLD, UNIMAP_PAUSE, UNIMAP_SLCK, UNIMAP_PSCR, UNIMAP_ESC, UNIMAP_F1 }, /* 00-07 */
{ UNIMAP_F13, UNIMAP_RGUI, UNIMAP_VOLU, UNIMAP_MHEN, UNIMAP_HENK, UNIMAP_TAB, UNIMAP_GRV, UNIMAP_F2 }, /* 08-0F */
{ UNIMAP_F14, UNIMAP_LCTL, UNIMAP_LSHIFT,UNIMAP_NUBS, UNIMAP_CAPS, UNIMAP_Q, UNIMAP_1, UNIMAP_F3 }, /* 10-17 */
{ UNIMAP_F15, UNIMAP_LALT, UNIMAP_Z, UNIMAP_S, UNIMAP_A, UNIMAP_W, UNIMAP_2, UNIMAP_F4 }, /* 18-1F */
{ UNIMAP_F16, UNIMAP_C, UNIMAP_X, UNIMAP_D, UNIMAP_E, UNIMAP_4, UNIMAP_3, UNIMAP_F5 }, /* 20-27 */
{ UNIMAP_F17, UNIMAP_SPACE, UNIMAP_V, UNIMAP_F, UNIMAP_T, UNIMAP_R, UNIMAP_5, UNIMAP_F6 }, /* 28-2F */
{ UNIMAP_F18, UNIMAP_N, UNIMAP_B, UNIMAP_H, UNIMAP_G, UNIMAP_Y, UNIMAP_6, UNIMAP_F7 }, /* 30-37 */
{ UNIMAP_F19, UNIMAP_RALT, UNIMAP_M, UNIMAP_J, UNIMAP_U, UNIMAP_7, UNIMAP_8, UNIMAP_F8 }, /* 38-3F */
{ UNIMAP_F20, UNIMAP_COMMA, UNIMAP_K, UNIMAP_I, UNIMAP_O, UNIMAP_0, UNIMAP_9, UNIMAP_F9 }, /* 40-47 */
{ UNIMAP_F21, UNIMAP_DOT, UNIMAP_SLASH, UNIMAP_L, UNIMAP_SCOLON,UNIMAP_P, UNIMAP_MINUS, UNIMAP_F10 }, /* 48-4F */
{ UNIMAP_F22, UNIMAP_RO, UNIMAP_QUOTE, UNIMAP_NUHS, UNIMAP_LBRC, UNIMAP_EQUAL, UNIMAP_F11, UNIMAP_F23 }, /* 50-57 */
{ UNIMAP_RCTL, UNIMAP_RSHIFT,UNIMAP_ENTER, UNIMAP_RBRC, UNIMAP_BSLASH,UNIMAP_JYEN, UNIMAP_F12, UNIMAP_F24 }, /* 58-5F */
{ UNIMAP_DOWN, UNIMAP_LEFT, UNIMAP_APP, UNIMAP_UP, UNIMAP_DEL, UNIMAP_END, UNIMAP_BSPACE,UNIMAP_INS }, /* 60-67 */
{ UNIMAP_KANA, UNIMAP_P1, UNIMAP_RIGHT, UNIMAP_P4, UNIMAP_P7, UNIMAP_PGDN, UNIMAP_HOME, UNIMAP_PGUP }, /* 68-6F */
{ UNIMAP_P0, UNIMAP_PDOT, UNIMAP_P2, UNIMAP_P5, UNIMAP_P6, UNIMAP_P8, UNIMAP_NLCK, UNIMAP_PSLS }, /* 70-77 */
{ UNIMAP_PEQL, UNIMAP_PENT, UNIMAP_P3, UNIMAP_PCMM, UNIMAP_PPLS, UNIMAP_P9, UNIMAP_PAST, UNIMAP_PMNS }, /* 78-7F */
};
extern const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS];
action_t action_for_key(uint8_t layer, keypos_t key)
{
uint8_t unimap_pos;
switch (keyboard_kind) {
case PC_XT:
unimap_pos = pgm_read_byte(&unimap_cs1[key.row][key.col]);
break;
case PC_AT:
unimap_pos = pgm_read_byte(&unimap_cs2[key.row][key.col]);
break;
case PC_TERMINAL:
unimap_pos = pgm_read_byte(&unimap_cs3[key.row][key.col]);
break;
default:
return (action_t)ACTION_NO;
}
if (unimap_pos == UNIMAP_NO) return (action_t)ACTION_NO;
return (action_t)pgm_read_word(&actionmaps[(layer)][(unimap_pos & 0x70) >> 4][(unimap_pos & 0x0f)]);
}
#endif

101
converter/pc88_usb/Makefile Normal file
View file

@ -0,0 +1,101 @@
# Target file name (without extension).
TARGET ?= pc88_usb
# Directory common source filess exist
TMK_DIR ?= ../../tmk_core
# Directory keyboard dependent files exist
TARGET_DIR ?= .
# keyboard dependent files
# Add one of lines below to select serial protocol implementation
# protocol/serial_uart.c
# protocol/serial_soft.c
SRC ?= matrix.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 ?= atmega32u2 # TMK Converter
# 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
COMMAND_ENABLE ?= yes # Commands for debug and configuration
#NKRO_ENABLE ?= yes # USB Nkey Rollover
##UNIMAP_ENABLE ?= yes
# Boot Section Size in bytes
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
OPT_DEFS += -DBOOTLOADER_SIZE=4096
#
# Keymap file
#
ifeq (yes,$(strip $(UNIMAP_ENABLE)))
KEYMAP_FILE = unimap
else
ifeq (yes,$(strip $(ACTIONMAP_ENABLE)))
KEYMAP_FILE = actionmap
else
KEYMAP_FILE = keymap
endif
endif
ifdef KEYMAP
SRC := $(KEYMAP_FILE)_$(KEYMAP).c $(SRC)
else
SRC := $(KEYMAP_FILE).c $(SRC)
endif
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TMK_DIR)
include $(TMK_DIR)/protocol/lufa.mk
include $(TMK_DIR)/protocol.mk
include $(TMK_DIR)/common.mk
include $(TMK_DIR)/rules.mk

View file

@ -0,0 +1,4 @@
TARGET ?= pc88_usb_32u4
MCU ?= atmega32u4
include Makefile

View file

@ -0,0 +1,101 @@
# Target file name (without extension).
TARGET ?= pc88_usb_unimap
# Directory common source filess exist
TMK_DIR ?= ../../tmk_core
# Directory keyboard dependent files exist
TARGET_DIR ?= .
# keyboard dependent files
# Add one of lines below to select serial protocol implementation
# protocol/serial_uart.c
# protocol/serial_soft.c
SRC ?= matrix.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 ?= atmega32u2 # TMK Converter
# 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
COMMAND_ENABLE ?= yes # Commands for debug and configuration
#NKRO_ENABLE ?= yes # USB Nkey Rollover
UNIMAP_ENABLE ?= yes
# Boot Section Size in bytes
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
OPT_DEFS += -DBOOTLOADER_SIZE=4096
#
# Keymap file
#
ifeq (yes,$(strip $(UNIMAP_ENABLE)))
KEYMAP_FILE = unimap
else
ifeq (yes,$(strip $(ACTIONMAP_ENABLE)))
KEYMAP_FILE = actionmap
else
KEYMAP_FILE = keymap
endif
endif
ifdef KEYMAP
SRC := $(KEYMAP_FILE)_$(KEYMAP).c $(SRC)
else
SRC := $(KEYMAP_FILE).c $(SRC)
endif
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TMK_DIR)
include $(TMK_DIR)/protocol/lufa.mk
include $(TMK_DIR)/protocol.mk
include $(TMK_DIR)/common.mk
include $(TMK_DIR)/rules.mk

View file

@ -0,0 +1,4 @@
TARGET ?= pc88_usb_32u4_unimap
MCU ?= atmega32u4
include Makefile.unimap

73
converter/pc88_usb/README Normal file
View file

@ -0,0 +1,73 @@
PC88(Late type) to USB keyboard protocol converter
=======================================
Target MCU is ATMega32u2 but other USB capable AVR will also work.
README FIRST
---------
This converter is for TYPE-B keyboard. For keyboards other than TYPE-B,
change the mode switch on the back of the keyboard.
Stand the left foot on the back of the keyboard and there are two slits.
There is a mode change switch in the back of it.
When this switch is up, TYPE-B mode is set.
When connecting a keyboard to this adapter, be sure to set to TYPE-B mode.
Connector
---------
On host/converter:
5Pin mini DIN
___ ___
/ |_| \
/ 5 4 \
| 3 | 2 |
\_ 1 _/
\_____/
(receptacle)
Wiring: You can change this with editing config.h.
Pin mini DIN MCU
----------------------------------
1 5V VCC
2 GND GND
3 DATA RD2
4 NC
5 NC
Protocol
--------
Signal: Asynchronous, Positive logic, 20800bps, Least bit first
Frame format: 1-Start bit(Lo), 8-Data bits, non-Parity, 1-Stop bit
Build Firmware
--------------
Just use 'make' to bild firmware for TMK PC88 converter.
$ make -f Makefile.unimap clean
$ make -f Makefile.unimap
To flash firmware
$ make -f Makefile.unimap dfu
then push button on converter to flash firmware.
If you are using ATMega32u4 based board instead of premade TMK PC88 converter(ATMega32u2) use following commands.
$ make -f Makefile.unimap.32u4 clean
$ make -f Makefile.unimap.32u4
$ make -f Makefile.unimap.32u4 dfu

121
converter/pc88_usb/config.h Normal file
View file

@ -0,0 +1,121 @@
/*
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
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x8801
#define DEVICE_VER 0x0101
#define MANUFACTURER t.m.k.
#define PRODUCT PC88 keyboard converter
#define DESCRIPTION converts PC88 keyboard protocol into USB
/* matrix size */
#define MATRIX_ROWS 16
#define MATRIX_COLS 8
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->keys[0] == KC_STOP || \
keyboard_report->mods == (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) \
)
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
/*
* PC88 Serial(USART) configuration
* asynchronous, positive logic, 20800baud, bit order: LSB first
* 1-start bit, 8-data bit, non parity, 1-stop bit
*/
/*
* Software Serial
* Add protocol/serial_soft.c to SRC in Makefile
*/
#define SERIAL_SOFT_BAUD 20800
#define SERIAL_SOFT_PARITY_NONE
#define SERIAL_SOFT_BIT_ORDER_LSB
#define SERIAL_SOFT_LOGIC_POSITIVE
/* RXD Port */
#define SERIAL_SOFT_RXD_DDR DDRD
#define SERIAL_SOFT_RXD_PORT PORTD
#define SERIAL_SOFT_RXD_PIN PIND
#define SERIAL_SOFT_RXD_BIT 2
#define SERIAL_SOFT_RXD_READ() (SERIAL_SOFT_RXD_PIN&(1<<SERIAL_SOFT_RXD_BIT))
/* RXD Interupt */
#define SERIAL_SOFT_RXD_VECT INT2_vect
#define SERIAL_SOFT_RXD_INIT() do { \
/* pin configuration: input with pull-up */ \
SERIAL_SOFT_RXD_DDR &= ~(1<<SERIAL_SOFT_RXD_BIT); \
SERIAL_SOFT_RXD_PORT |= (1<<SERIAL_SOFT_RXD_BIT); \
/* enable interrupt: INT2(falling edge) */ \
EICRA |= ((1<<ISC21)|(0<<ISC20)); \
EIMSK |= (1<<INT2); \
sei(); \
} while (0)
#define SERIAL_SOFT_RXD_INT_ENTER()
#define SERIAL_SOFT_RXD_INT_EXIT() do { \
/* clear interrupt flag */ \
EIFR = (1<<INTF2); \
} while (0)
/* TXD Port */
#define SERIAL_SOFT_TXD_DDR DDRD
#define SERIAL_SOFT_TXD_PORT PORTD
#define SERIAL_SOFT_TXD_PIN PIND
#define SERIAL_SOFT_TXD_BIT 3
#define SERIAL_SOFT_TXD_HI() do { SERIAL_SOFT_TXD_PORT |= (1<<SERIAL_SOFT_TXD_BIT); } while (0)
#define SERIAL_SOFT_TXD_LO() do { SERIAL_SOFT_TXD_PORT &= ~(1<<SERIAL_SOFT_TXD_BIT); } while (0)
#define SERIAL_SOFT_TXD_INIT() do { \
/* pin configuration: output */ \
SERIAL_SOFT_TXD_DDR |= (1<<SERIAL_SOFT_TXD_BIT); \
/* idle */ \
SERIAL_SOFT_TXD_ON(); \
} while (0)
/*
* Hardware Serial(UART)
* Add protocol/serial_uart.c to SRC in Makefile
*/
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__)
#define SERIAL_UART_BAUD 20800
#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 |= (0<<UPM11) | (0<<UPM10); /* parity: none(00), even(01), odd(11) */ \
DDRD &= ~(1<<2); PORTD |= (1<<2); /* Pull-up RXD pin */ \
sei(); \
} while(0)
#else
#error "USART configuration is needed."
#endif
#endif

130
converter/pc88_usb/keymap.c Normal file
View file

@ -0,0 +1,130 @@
/*
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 "keycode.h"
#include "action.h"
#include "util.h"
#include "serial.h"
#include "keymap.h"
// Following macros help you to define a keymap with the form of actual keyboard layout.
/* Keyboard Scan codes
* ,---. ,---. ,------------------------. ,------------------------. ,-------.
* | 60| | 61| | 62 | 63 | 64 | 65 | 66 | | 67 | 68 | 69 | 6A | 6B | | 36| 37|
* `---' `---' `------------------------' `------------------------' `-------'
* ,---------------------------------------------------------------. ,-------. ,---------------.
* | 00 | 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E | | 38| 39| | 3E| 3F| 4D| 41|
* |---------------------------------------------------------------| `-------' |---------------|
* | 0F | 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| | | 42| 43| 44| 45|
* |--------------------------------------------------------` 1C | ,-------. |---------------|
* | 74| 71| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| 28| | | 3A | | 46| 47| 48| 49|
* |---------------------------------------------------------------| |-------| |---------------|
* | 70 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 78 | | 3B| 3C| | 4A| 4B| 4C| 4D|
* `---------------------------------------------------------------' |-------| |---------------|
* | 72| 73| 51 | 34 | 35 | 7A| 7B| | 3D | | 4E| 4F| 50| 79|
* `-------------------------------------------' `-------' `---------------'
*/
#define KEYMAP( \
K60, K61, K62, K63, K64, K65, K66, K67, K68, K69, K6A, K6B, K36, K37, \
K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, K38, K39, K3E, K3F, K40, K41, \
K0F, K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K42, K43, K44, K45, \
K74, K71, K1D, K1E, K1F, K20, K21, K22, K23, K24, K25, K26, K27,K28, K3A, K46, K47, K48, K49, \
K70, K29, K2A, K2B, K2C, K2D, K2E, K2F, K30, K31, K32, K33, K78, K3B, K3C, K4A, K4B, K4C, K4D, \
K72, K73, K51, K34, K35, K7A, K7B, K3D, K4E, K4F, K50, K79 \
) { \
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
{ KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##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_##K29, 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_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_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67 }, \
{ KC_##K68, KC_##K69, KC_##K6A, KC_##K6B, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_NO, KC_NO, KC_NO }, \
{ KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_NO, KC_NO, KC_NO, KC_NO } \
}
const action_t fn_actions[] PROGMEM = {
[0] = ACTION_FUNCTION(0), // toggle all LEDs
};
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
static bool led = false;
switch (id) {
case 0:
if (record->event.pressed) {
if ((led = !led))
serial_send(0x80); // all on
else
serial_send(0xff); // all off
}
break;
}
}
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keyboard Scan codes
* ,---. ,---. ,------------------------. ,------------------------. ,-------.
* | 60| | 61| | 62 | 63 | 64 | 65 | 66 | | 67 | 68 | 69 | 6A | 6B | | 36| 37|
* `---' `---' `------------------------' `------------------------' `-------'
* ,---------------------------------------------------------------. ,-------. ,---------------.
* | 00 | 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E | | 38| 39| | 3E| 3F| 4D| 41|
* |---------------------------------------------------------------| `-------' |---------------|
* | 0F | 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| | | 42| 43| 44| 45|
* |--------------------------------------------------------` 1C | ,-------. |---------------|
* | 74| 71| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| 28| | | 3A | | 46| 47| 48| 49|
* |---------------------------------------------------------------| |-------| |---------------|
* | 70 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 78 | | 3B| 3C| | 4A| 4B| 4C| 4D|
* `---------------------------------------------------------------' |-------| |---------------|
* | 72| 73| 51 | 34 | 35 | 7A| 7B| | 3D | | 4E| 4F| 50| 79|
* `-------------------------------------------' `-------' `---------------'
*/
/* ANSI */
KEYMAP(
PAUS,PSCR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, PGDN,PGUP,
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS, EQL, BSLS,BSPC, INS, DEL, HOME, END,PMNS,PSLS,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, ENT, P7, P8, P9, PAST,
LCTL,LCAP,A, S, D, F, G, H, J, K, L, SCLN,QUOT,F18, UP, P4, P5, P6, PPLS,
LSFT, Z, X, C, V, B, N, M, COMM,DOT, SLSH,GRV, RSFT, LEFT,RGHT, P1, P2, P3, PEQL,
F19, LGUI,LALT, SPC, RALT, APP, RGUI, DOWN, P0, PCMM,PDOT,PENT
),
/* JIS */
KEYMAP(
PAUS, PSCR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, PGDN,PGUP,
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS, EQL, JYEN,BSPC, INS, DEL, HOME, END,PMNS,PSLS,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, ENT, P7, P8, P9, PAST,
LCTL,LCAP,A, S, D, F, G, H, J, K, L, SCLN,QUOT,NUHS, UP, P4, P5, P6, PPLS,
LSFT, Z, X, C, V, B, N, M, COMM,DOT, SLSH,RO, RSFT, LEFT,RGHT, P1, P2, P3, PEQL,
KANA,LALT,MHEN, SPC, HENK, RGUI,ZKHK, DOWN, P0, PCMM,PDOT,PENT
),
};

View file

@ -0,0 +1,95 @@
/*
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/io.h>
#include <util/delay.h>
#include "print.h"
#include "util.h"
#include "matrix.h"
#include "led.h"
#include "debug.h"
#include "protocol/serial.h"
/*
* Matrix Array usage:
*
* ROW: 16(4bits)
* COL: 8(3bits)
*
* 8bit wide
* +---------+
* 0|00 ... 07|
* 1|08 ... 0F|
* :| ... |
* :| ... |
* E|70 ... 77|
* F|78 ... 7F|
* +---------+
*/
static uint8_t matrix[MATRIX_ROWS];
#define ROW(code) ((code>>3)&0xF)
#define COL(code) (code&0x07)
void matrix_init(void)
{
debug_keyboard = true;
serial_init();
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
print("matrix_init done.\n");
return;
}
uint8_t matrix_scan(void)
{
uint16_t code;
code = serial_recv2();
if (code == -1) {
return 0;
}
print_hex8(code); print(" ");
if (code&0x80) {
// break code
if (matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] &= ~(1<<COL(code));
}
} else {
// make code
if (!matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] |= (1<<COL(code));
}
}
return code;
}
inline
uint8_t matrix_get_row(uint8_t row)
{
return matrix[row];
}
void led_set(uint8_t usb_led)
{
}

View file

@ -0,0 +1,45 @@
/*
Copyright 2017 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 "unimap_trans.h"
#define AC_FN0 ACTION_LAYER_MOMENTARY(1)
#ifdef KEYMAP_SECTION_ENABLE
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
#else
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
#endif
UNIMAP(
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS, VOLD,VOLU,MUTE,
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS,
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, P4, P5, P6, COMM,
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RO, RSFT, UP, P1, P2, P3, PENT,
LCTL,LGUI,LALT,MHEN, SPC, HENK,KANA,RALT,RGUI,FN0, RCTL, LEFT,DOWN,RGHT, P0, DOT, PEQL
),
UNIMAP(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
GRV, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, INS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,LEFT,RGHT, TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,DOWN, TRNS,TRNS, PGUP, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, HOME,PGDN,END, TRNS, TRNS,TRNS
),
};

View file

@ -0,0 +1,64 @@
/*
Copyright 2018 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 _TRANS_H
#define _TRANS_H
#include <stdint.h>
#include <avr/pgmspace.h>
#include "unimap.h"
/* Mapping PC88 scan codes to UNIMAP layout codes
*
* PC88 scan codes
* ,---. ,---. ,------------------------. ,------------------------. ,-------.
* | 60| | 61| | 62 | 63 | 64 | 65 | 66 | | 67 | 68 | 69 | 6A | 6B | | 36| 37|
* `---' `---' `------------------------' `------------------------' `-------'
* ,---------------------------------------------------------------. ,-------. ,---------------.
* | 00 | 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E | | 38| 39| | 3E| 3F| 4D| 41|
* |---------------------------------------------------------------| `-------' |---------------|
* | 0F | 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| | | 42| 43| 44| 45|
* |--------------------------------------------------------` 1C | ,-------. |---------------|
* | 74| 71| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| 28| | | 3A | | 46| 47| 48| 49|
* |---------------------------------------------------------------| |-------| |---------------|
* | 70 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 78 | | 3B| 3C| | 4A| 4B| 4C| 4D|
* `---------------------------------------------------------------' |-------| |---------------|
* | 72| 73| 51 | 34 | 35 | 7A| 7B| | 3D | | 4E| 4F| 50| 79|
* `-------------------------------------------' `-------' `---------------'
*
*
*/
const uint8_t PROGMEM unimap_trans[MATRIX_ROWS][MATRIX_COLS] = {
{ UNIMAP_ESC, UNIMAP_1, UNIMAP_2, UNIMAP_3, UNIMAP_4, UNIMAP_5, UNIMAP_6, UNIMAP_7 }, /* 00-07 */
{ UNIMAP_8, UNIMAP_9, UNIMAP_0, UNIMAP_MINS, UNIMAP_EQL, UNIMAP_JYEN, UNIMAP_BSPC, UNIMAP_TAB }, /* 08-0F */
{ UNIMAP_Q, UNIMAP_W, UNIMAP_E, UNIMAP_R, UNIMAP_T, UNIMAP_Y, UNIMAP_U, UNIMAP_I }, /* 10-17 */
{ UNIMAP_O, UNIMAP_P, UNIMAP_LBRC, UNIMAP_RBRC, UNIMAP_ENT, UNIMAP_A, UNIMAP_S, UNIMAP_D }, /* 18-1F */
{ UNIMAP_F, UNIMAP_G, UNIMAP_H, UNIMAP_J, UNIMAP_K, UNIMAP_L, UNIMAP_SCLN, UNIMAP_QUOT }, /* 20-27 */
{ UNIMAP_BSLS, UNIMAP_Z, UNIMAP_X, UNIMAP_C, UNIMAP_V, UNIMAP_B, UNIMAP_N, UNIMAP_M }, /* 28-2F */
{ UNIMAP_COMM, UNIMAP_DOT, UNIMAP_SLSH, UNIMAP_RO, UNIMAP_SPC, UNIMAP_HENK, UNIMAP_PGDN, UNIMAP_PGUP }, /* 30-37 */
{ UNIMAP_INS, UNIMAP_DEL, UNIMAP_UP, UNIMAP_LEFT, UNIMAP_RGHT, UNIMAP_DOWN, UNIMAP_HOME, UNIMAP_END }, /* 38-3F */
{ UNIMAP_PMNS, UNIMAP_PSLS, UNIMAP_P7, UNIMAP_P8, UNIMAP_P9, UNIMAP_PAST, UNIMAP_P4, UNIMAP_P5 }, /* 40-47 */
{ UNIMAP_P6, UNIMAP_PPLS, UNIMAP_P1, UNIMAP_P2, UNIMAP_P3, UNIMAP_PEQL, UNIMAP_P0, UNIMAP_PCMM }, /* 48-4F */
{ UNIMAP_PDOT, UNIMAP_MHEN, UNIMAP_F11, UNIMAP_F12, UNIMAP_F13, UNIMAP_F14, UNIMAP_F15, UNIMAP_NO }, /* 50-57 */
{ UNIMAP_F21, UNIMAP_F22, UNIMAP_F23, UNIMAP_F24, UNIMAP_NO, UNIMAP_NO, UNIMAP_APP, UNIMAP_NO }, /* 58-5F */
{ UNIMAP_PAUS, UNIMAP_PSCR, UNIMAP_F1, UNIMAP_F2, UNIMAP_F3, UNIMAP_F4, UNIMAP_F5, UNIMAP_F6 }, /* 60-67 */
{ UNIMAP_F7, UNIMAP_F8, UNIMAP_F9, UNIMAP_F10, UNIMAP_NO, UNIMAP_NO, UNIMAP_NO, UNIMAP_NO }, /* 68-6F */
{ UNIMAP_LSFT, UNIMAP_CAPS, UNIMAP_KANA, UNIMAP_LALT, UNIMAP_LCTL, UNIMAP_NO, UNIMAP_NO, UNIMAP_NO }, /* 70-77 */
{ UNIMAP_RSFT, UNIMAP_PENT, UNIMAP_RGUI, UNIMAP_GRV, UNIMAP_NO, UNIMAP_NO, UNIMAP_NO, UNIMAP_NO } /* 78-7F */
};
#endif

View file

@ -50,7 +50,7 @@ ARCH ?= AVR8
F_USB ?= $(F_CPU)
# Interrupt driven control endpoint task
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Build Options

View file

@ -64,23 +64,23 @@ If you are using ATMega32u4 based board instead of premade TMK PC98 converter(AT
PC98 Scan Codes
---------------
,---. ,---. ,------------------------. ,------------------------. ,------------------------.
|Pau| |PrS| | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10| | F11| F12| F13| F14| F15|
|Stp| |Cpy| | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10| | F11| F12| F13| F14| F15|
`---' `---' `------------------------' `------------------------' `------------------------'
,-------------------------------------------------------------. ,-------. ,---------------.
| Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|JPY|Bspc| |Ins|Del| |Hom|End| -| /|
| Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|JPY|Bspc| |Ins|Del| |Hom|Hlp| -| /|
|-------------------------------------------------------------| |-------| |---------------|
| Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | |PgD|PgU| | 7| 8| 9| *|
| Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | |RUp|RDn| | 7| 8| 9| *|
|-------------------------------------------------------`Enter| |-------| |---------------|
|Ctl|Cap| A| S| D| F| G| H| J| K| L| ;| '| \| | | Up | | 4| 5| 6| +|
|-------------------------------------------------------------| |-------| |---------------|
| Shift | Z| X| C| V| B| N| M| ,| .| /| RO| Shift | |Lef|Rig| | 1| 2| 3| =|
`-------------------------------------------------------------' |-------| |---------------|
^3|Kana|Gui|Alt|MHEN| Space |HENK|Alt|Gui|App|^2 | Down | | 0| ,| .| ^1|
|Kana|Win|GRP|NFER| Space |XFER| ^2|Win| ^3| | Down | | 0| ,| .| ^1|
`-------------------------------------------------------' `-------' `---------------'
^1: Enter on keypad is identical to Enter on alphanumeric portion.
^2: Right Alt is ALT on DIGITAL WAVE Dboard while Menu on PC-9821 keyboard.
App is HOME key on PC98XL keyboard.
^3: Caps and Kana are locking keys, either mechanically or by firmware emulation.
^1: Enter on keypad is identical to Enter on alphanumeric portion
^2: ALT on DIGITAL WAVE Dboard while Menu on PC-9821 keyboard
^3: HOME on PC98XL keyboard
^4: CAPS and Kana are locking keys, either mechanically or by firmware emulation
,---. ,---. ,------------------------. ,------------------------. ,------------------------.

View file

@ -32,7 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->keys[0] == KC_STOP || \
matrix_is_on(12, 0) || /* STOP */ \
keyboard_report->mods == (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) \
)

View file

@ -71,12 +71,12 @@ static void pc98_inhibit_repeat(void)
RETRY:
pc98_send(0x9C);
code = pc98_wait_response();
if (code != -1) xprintf("send 9C: %02X\n", code);
if (code != -1) dprintf("send 9C: %02X\n", code);
if (code != 0xFA) return;
pc98_send(0x70);
code = pc98_wait_response();
if (code != -1) xprintf("send 70: %02X\n", code);
if (code != -1) dprintf("send 70: %02X\n", code);
if (code != 0xFA) goto RETRY;
}
@ -87,18 +87,17 @@ static void pc98_led_set(void)
RETRY:
pc98_send(0x9D);
code = pc98_wait_response();
if (code != -1) xprintf("send 9D: %02X\n", code);
if (code != -1) dprintf("send 9D: %02X\n", code);
if (code != 0xFA) return;
pc98_send(pc98_led);
code = pc98_wait_response();
if (code != -1) xprintf("send %02X: %02X\n", pc98_led, code);
if (code != -1) dprintf("send %02X: %02X\n", pc98_led, code);
if (code != 0xFA) goto RETRY;
}
void matrix_init(void)
{
debug_keyboard = true;
PC98_RST_DDR |= (1<<PC98_RST_BIT);
PC98_RDY_DDR |= (1<<PC98_RDY_BIT);
PC98_RTY_DDR |= (1<<PC98_RTY_BIT);
@ -125,7 +124,6 @@ void matrix_init(void)
// ready to receive from keyboard
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT); // RDY: low
print("matrix_init done.\n");
return;
}
@ -145,7 +143,7 @@ uint8_t matrix_scan(void)
return 0;
}
print_hex8(code); print(" ");
dprintf("%02X ", code);
if (code&0x80) {
// break code
@ -180,6 +178,6 @@ void led_set(uint8_t usb_led)
pc98_led = 0x70;
if (usb_led & (1<<USB_LED_NUM_LOCK)) pc98_led |= (1<<0);
if (usb_led & (1<<USB_LED_CAPS_LOCK)) pc98_led |= (1<<2);
xprintf("usb_led: %02X\n", usb_led);
xprintf("pc98_led: %02X\n", pc98_led);
dprintf("usb_led: %02X\n", usb_led);
dprintf("pc98_led: %02X\n", pc98_led);
}

View file

@ -26,7 +26,7 @@ const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
#endif
/*
,---. ,---. ,------------------------. ,------------------------. ,------------------------.
|Pau| |PrS| | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10| | F11| F12| F13| F14| F15|
| | |PrS| | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10| | F11| F12| F13| F14| F15|
`---' `---' `------------------------' `------------------------' `------------------------'
,-------------------------------------------------------------. ,-------. ,---------------.
| Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|JPY|Bspc| |Ins|Del| |Hom|End| -| /|
@ -42,7 +42,7 @@ const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
Caps and Kana are locking keys.
*/
UNIMAP_PC98(
PAUS,PSCR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
NO, PSCR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, DEL, HOME,END, PMNS,PSLS,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, PGDN,PGUP, P7, P8, P9, PAST,
LCTL,LCAP,A, S, D, F, G, H, J, K, L, SCLN,QUOT,BSLS,ENT, UP, P4, P5, P6, PPLS,

View file

@ -0,0 +1,20 @@
TARGET ?= ps2_usb_32u4
MCU = atmega32u4
CONFIG_H = config.h
BOOTLOADER_SIZE = 4096
BOOTMAGIC_ENABLE ?= no
MOUSEKEY_ENABLE ?= yes
EXTRAKEY_ENABLE ?= yes
CONSOLE_ENABLE ?= yes
COMMAND_ENABLE ?= yes
NKRO_ENABLE ?= yes
PS2_USE_USART = no
PS2_USE_INT = yes
PS2_USE_BUSYWAIT = no
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
include Makefile

View file

@ -1,6 +1,6 @@
TARGET ?= ps2_usb_rev1
TARGET ?= ps2_usb_rev1_unimap
MCU = atmega32u4
CONFIG_H = config_rev1.h
CONFIG_H = config.h
BOOTLOADER_SIZE = 4096
BOOTMAGIC_ENABLE ?= no
@ -14,4 +14,7 @@ PS2_USE_USART = yes
PS2_USE_INT = no
PS2_USE_BUSYWAIT = no
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
include Makefile

View file

@ -1,6 +1,6 @@
TARGET ?= ps2_usb_rev2
TARGET ?= ps2_usb_rev2_unimap
MCU = atmega32u2
CONFIG_H = config_rev2.h
CONFIG_H = config.h
BOOTLOADER_SIZE = 4096
BOOTMAGIC_ENABLE ?= no
@ -14,4 +14,7 @@ PS2_USE_USART = no
PS2_USE_INT = yes
PS2_USE_BUSYWAIT = no
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
include Makefile

View file

@ -1,5 +0,0 @@
TARGET = ps2_usb_rev1_unimap
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
include Makefile.rev1

View file

@ -1,6 +0,0 @@
TARGET = ps2_usb_rev2_unimap
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
#LUFA_DEBUG_SUART = yes
include Makefile.rev2

View file

@ -2,17 +2,14 @@ PS/2 to USB keyboard converter
==============================
This firmware converts PS/2 keyboard protocol to USB.(It supports Scan Code Set 2.)
You can discuss about this converter here.
Connect Wires
-------------
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. You need pull-up resistors. 1K-10K Ohm would be fine.
https://geekhack.org/index.php?topic=14618.0
To change pin configuration edit **config.h** and **Makefile**.
Preassembled TMK PS/2-USB converter is available here.
https://geekhack.org/index.php?topic=72052.0
Build Firmware
@ -27,32 +24,47 @@ To program firmware push the button on converter and run:
$ make -f Makefile.rev2 KEYMAP=plain dfu
- For **TMK converter Rev.1** use `make -f Makefile.rev1` instead.
- To select keymap use `jis`, `spacefn` or your own in place of `plain`.
For **TMK converter Rev.1** use `Makefile.rev1` instead.
If your use DIY converter with ATMega32u4 board you can use `Makefile.32u4`, but note that progarmming with 'dfu' may not work for your converter.
Build your own converter
------------------------
Use ATMega32u4 as controller and Makefile.32u4 to build firmware.
1. Wire **Vcc** and **GND** properly.
2. Connect **Clock** to `PD1` and **Data** to `PD0` line. (Compatible to Soarer's converter pin configuration)
3. You need pull-up resistors on both signal lines. 1K-10K Ohm would be fine.
You can configure controller and pin configurations in Makefile and config.h.
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 README.md of top directory) and existent keymap files.
To define your own keymap copy `unimap_plain.c` to `unimap_<name>.c` and edit it. Or just edit `unimap_plain.c` directly.
See wiki pages and documents.
https://github.com/tmk/tmk_keyboard/wiki
PS/2 signal handling implementations
------------------------------------
Following three methods can be used to implement PS/2 signal handling.
Following three methods are available 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.
- **Interrupt** Uses pin interrupt to detect falling edge of clock line. **Recommended.** (ps2_interrupt.c)
- **Busywait** Implementation with portable C code for reference. (ps2_busywait.c)
- **USART** Uses AVR USART hardware engine to receive PS/2 signal. You must use this fothis for V-USB. (ps2_usart.c)
To select method edit Makefile.
TMK converter rev1 uses **USART** and rev2 uses **Interrupt** for reference.
You can change method by editing `Makefile` but not needed in most case.
V-USB Support
-------------
With V-USB you can use this converter on ATmega(168/328) but it doesn't support NKRO at this time.
With V-USB you can use this converter on ATmega(168/328). Use Makefile.vusb to build firmeware. Not supported actively anymore.
Circuit:

View file

@ -1,147 +0,0 @@
/*
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_LALT) | MOD_BIT(KC_RALT)) \
)
//#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

@ -1,95 +0,0 @@
/*
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_LALT) | MOD_BIT(KC_RALT)) \
)
//#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
#ifdef LUFA_DEBUG_SUART
# define SUART_OUT_DDR DDRD
# define SUART_OUT_PORT PORTD
# define SUART_OUT_BIT 4
# define SUART_IN_DDR DDRD
# define SUART_IN_PIN PIND
# define SUART_IN_BIT 4
#endif
#endif

View file

@ -15,6 +15,7 @@ Data: PD0
Clock: PD1
And VCC and GND, of course. See RESOURCE for keyboard connector pin assign.
Use 1K ohm pull-up resisters on the signal lines.
BUILD
@ -27,10 +28,21 @@ $ make
RESOURCE
--------
Soarer's Converter: http://geekhack.org/index.php?topic=17458.0
102keys(1392595): http://geekhack.org/index.php?topic=10737.0
122keys(1390876): http://www.seasip.info/VintagePC/ibm_1390876.html
KbdBabel: http://www.kbdbabel.org/
RJ45 Connector: http://www.kbdbabel.org/conn/kbd_connector_ibmterm.png
DIN Connector: http://www.kbdbabel.org/conn/kbd_connector_ibm3179_318x_319x.png
Terminal keyboards
------------------
122-key
1390876 http://www.seasip.info/VintagePC/ibm_1390876.html
6110344 http://www.seasip.info/VintagePC/ibm_6110344.html
102-key
1392595 https://deskthority.net/viewtopic.php?t=8371 https://geekhack.org/index.php?topic=10737.0
1386303 https://geekhack.org/index.php?topic=66959.0
1391406 http://www.seasip.info/VintagePC/ibm_1391406.html
EOF

View file

@ -26,19 +26,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/*
* IBM Terminal keyboard 6110345(122keys)/1392595(102keys)
* http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M
/*
* IBM Terminal keyboard 122-key
* http://www.seasip.info/VintagePC/ibm_1391406.html
*
* Keymap array:
* 8 bytes
* +---------+
* 0| |
* :| | 0x00-0x87
* ;| |
* 17| |
* +---------+
*/
#define KEYMAP( \
K08,K10,K18,K20,K28,K30,K38,K40,K48,K50,K57,K5F, \
@ -69,21 +59,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
{ KC_NO, KC_NO, KC_NO, KC_##K83, KC_##K84, KC_NO, KC_NO, KC_NO, }, \
}
/*
* IBM Terminal keyboard 1399625, 101-key
* IBM Terminal keyboard 102-key
* http://www.seasip.info/VintagePC/ibm_1391406.html
*/
#define KEYMAP_101( \
K08, K07,K0F,K17,K1F,K27,K2F,K37,K3F,K47,K4F,K56,K5E, K57,K5F,K62, \
\
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, K67,K6E,K6F, K76,K77,K7E,K84, \
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5C, K64,K65,K6D, K6C,K75,K7D, \
K14,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K7C, \
K12, K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, K63, K69,K72,K7A, \
K11, K19, K29, K39, K58, K61,K60,K6A, K70, K71,K79 \
#define KEYMAP_102( \
K08, K07,K0F,K17,K1F,K27,K2F,K37,K3F,K47,K4F,K56,K5E, K57,K5F,K62, \
\
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K5D,K66, K67,K6E,K6F, K76,K77,K7E,K84, \
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, K5C, K64,K65,K6D, K6C,K75,K7D,K7C, \
K14,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K53,K5A, K6B,K73,K74,K7B, \
K12,K13,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K51,K59, K63, K69,K72,K7A,K79, \
K11, K19, K29, K39, K58, K61,K60,K6A, K68,K70,K71,K78 \
) { \
{ KC_NO, KC_NO , KC_NO, KC_NO , KC_NO , KC_NO , KC_NO , KC_##K07 }, \
{ KC_##K08, KC_NO , KC_NO , KC_NO , KC_NO , KC_##K0D, KC_##K0E, KC_##K0F }, \
{ KC_NO , KC_##K11, KC_##K12, KC_NO , KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
{ KC_NO , KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
{ KC_NO , KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F }, \
{ KC_NO , KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
{ KC_NO , KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F }, \
@ -91,12 +83,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
{ KC_NO , KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \
{ KC_NO , KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47 }, \
{ KC_NO , KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_##K4F }, \
{ KC_NO , KC_NO , KC_##K52, KC_NO , KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \
{ KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_##K5C, KC_NO , KC_##K5E, KC_##K5F }, \
{ KC_NO , KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \
{ KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_##K5F }, \
{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67 }, \
{ KC_NO , KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C, KC_##K6D, KC_##K6E, KC_##K6F }, \
{ KC_##K68, KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C, KC_##K6D, KC_##K6E, KC_##K6F }, \
{ KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 }, \
{ KC_NO , KC_##K79, KC_##K7A, KC_NO , KC_##K7C, KC_##K7D, KC_##K7E, KC_NO }, \
{ KC_##K78, KC_##K79, KC_##K7A, KC_##K7B, KC_##K7C, KC_##K7D, KC_##K7E, KC_NO }, \
{ KC_NO, KC_NO, KC_NO, KC_NO , KC_##K84, KC_NO, KC_NO, KC_NO, }, \
}
@ -127,27 +119,25 @@ const uint8_t PROGMEM fn_keycode[] = {
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* 0: default
*
/*
* ,-----------------------------------------------.
* |F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|
* `-----------------------------------------------'
* `-----------------------------------------------'
* ,-----------------------------------------------.
* |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10|F11|F12|
* `-----------------------------------------------'
* `-----------------------------------------------'
* ,-------. ,-----------------------------------------------------------. ,-----------. ,---------------.
* |PrS|Esc| | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \|BS | |Ins|Hom|PgU| |NmL| /| *| -|
* |PrS|Esc| | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| BS| |Ins|Hom|PgU| |NmL| /| *| -|
* |-------| |-----------------------------------------------------------| |-----------| |---------------|
* |ScL|In4| |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| |
* |-------| |-----------------------------------------------------------| `-----------' |-----------| +|
* |Pau|In5| |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #|Retu| |Up | | 4| 5| 6| |
* |ScL|In4| |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| +|
* |-------| |-----------------------------------------------------------| `-----------' |-----------|---|
* |Pau|In5| |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #| Ret| |Up | | 4| 5| 6| ,|
* |-------| |-----------------------------------------------------------| ,-----------. |---------------|
* |App|In6| |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|Shift | |Lef|In2|Rig| | 1| 2| 3| |
* |-------| |-----------------------------------------------------------| `-----------' |-----------|Ent|
* |Gui|Gui| |Ctrl| |Alt | Space |Alt | |Ctrl| |Dow| | 0| .| |
* |App|In6| |Shif| \| Z| X| C| V| B| N| M| ,| ,| /| RO| Shift| |Lef|In2|Rig| | 1| 2| 3|Ent|
* |-------| |-----------------------------------------------------------| `-----------' |-----------|---|
* |Gui|Gui| |Ctrl| |Alt | Space |Alt | |Ctrl| |Dow| | 00| 0| .| =|
* `-------' `----' `---------------------------------------' `----' `---' `---------------'
*/
/*
KEYMAP(
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
@ -156,48 +146,35 @@ const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
SLCK,INT4, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS,
PAUS,INT5, CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, UP, P4, P5, P6, PCMM,
APP, INT6, LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RO, RSFT, LEFT,INT2,RGHT, P1, P2, P3, PENT,
RGUI,LGUI, LCTL, LALT, SPC, RALT, RCTL, DOWN, NO, P0, PDOT,NO
),
*/
// pseudo ANSI
KEYMAP(
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
PSCR,ESC, GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, NO, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
SLCK,INT4, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, NO, DEL, END, PGDN, P7, P8, P9, PPLS,
PAUS,INT5, CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, BSLS,ENT, UP, P4, P5, P6, PCMM,
APP, INT6, LSFT,LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, NO, RSFT, LEFT,INT2,RGHT, P1, P2, P3, PENT,
RGUI,LGUI, LCTL, LALT, SPC, RALT, RCTL, DOWN, NO, P0, PDOT,NO
RGUI,LGUI, LCTL, LALT, SPC, RALT, RCTL, DOWN, P00, P0, PDOT,PEQL
),
/* 101-key keymaps
*/
/* 0: default
#if 0
/*
* ,---. ,---------------. ,---------------. ,---------------. ,-----------.
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau|
* `---' `---------------' `---------------' `---------------' `-----------'
* ,-----------------------------------------------------------. ,-----------. ,---------------.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| /| *| -|
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| BS| |Ins|Hom|PgU| |NmL| /| *| -|
* |-----------------------------------------------------------| |-----------| |---------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| |
* |-----------------------------------------------------------| `-----------' |-----------| +|
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| |
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| +|
* |-----------------------------------------------------------| `-----------' |-----------|---|
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #| Ret| | 4| 5| 6| ,|
* |-----------------------------------------------------------| ,---. |---------------|
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| |
* |-----------------------------------------------------------| ,-----------. |-----------|Ent|
* |Ctrl| |Alt | Space |Alt | |Ctrl| |Lef|Dow|Rig| | 0| .| |
* |Shift | Z| X| C| V| B| N| M| ,| ,| /| RO| Shift| |Up | | 1| 2| 3|Ent|
* |-----------------------------------------------------------| ,-----------. |-----------|---|
* |Ctrl| |Alt | Space |Alt | |Ctrl| |Lef|Dow|Rig| | 00| 0| .| =|
* `----' `---------------------------------------' `----' `-----------' `---------------'
*/
/*
KEYMAP_101(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK, BRK,
KEYMAP_102(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS,
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,MINS, EQL,BSPC, INS,HOME,PGUP, NLCK,PSLS,PAST,PMNS,
TAB, Q, W, E, R, T, Y, U, I, O, P,LBRC,RBRC,BSLS, DEL, END,PGDN, P7, P8, P9,
CAPS, A, S, D, F, G, H, J, K, L,SCLN,QUOT, ENT, P4, P5, P6,PPLS,
LSFT, Z, X, C, V, B, N, M,COMM, DOT,SLSH, RSFT, UP, P1, P2, P3,
LCTL, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS,
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, P4, P5, P6, PCMM,
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RO, RSFT, UP, P1, P2, P3, PENT,
LCTL, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, P00, P0, PDOT,PEQL
),
*/
#endif
};

View file

@ -1,6 +1,20 @@
TARGET = usb_usb_debug
UNIMAP_ENABLE = yes
#UNIMAP_ENABLE = yes
#KEYMAP_SECTION_ENABLE = yes
#LUFA_DEBUG = yes
OPT_DEFS += -DDEBUG_USB_HOST
# LUFA debug print
# This may prevent USB enumeration and keyboard init
LUFA_DEBUG = yes
# Select one of outputs for debug print
LUFA_DEBUG_UART = yes
#LUFA_DEBUG_SUART = yes
# USB_Host_Shield_2.0 debug print
# This may prevent USB enumeration and keyboard init
#OPT_DEFS += -DDEBUG_USB_HOST
CONSOLE_ENABLE = yes
MOUSEKEY_ENABLE = no
EXTRAKEY_ENABLE = no
include Makefile

View file

@ -2,4 +2,6 @@ TARGET = usb_usb_unimap
UNIMAP_ENABLE = yes
KEYMAP_SECTION_ENABLE = yes
#LUFA_DEBUG = yes
#CONSOLE_ENABLE = no
NO_DEBUG = yes
include Makefile

View file

@ -1,104 +0,0 @@
USB to USB keyboard protocol converter
======================================
See for detail and discussion.
https://geekhack.org/index.php?topic=69169.0
Hardware requirement
--------------------
There are two options.
### TMK USB-USB Converter
You can buy a fully assembled converter from me here.
https://geekhack.org/index.php?topic=69169.0
### Arduino Leonardo + Circuit@Home USB Host Shield 2.0
Buying Arduino Leonardo and USB Host Shield 2.0(from Circuit@home) will be better, you won't need even soldering iron.
http://arduino.cc/en/Main/ArduinoBoardLeonardo
https://www.circuitsathome.com/products-page/arduino-shields/usb-host-shield-2-0-for-arduino-assembled/
Other compatible boards like Arduino's Shield will also work well but I think Sparkfun's needs to be modified.
http://arduino.cc/en/Main/ArduinoUSBHostShield
https://www.sparkfun.com/products/9947
Also Pro Micro 3.3V(not Mini) or Teensy with mini host shield will work with some fixes on signal/power routing.
https://www.circuitsathome.com/products-page/arduino-shields/usb-host-shield-for-arduino-pro-mini
https://www.sparkfun.com/products/12587
https://www.pjrc.com/teensy/td_libs_USBHostShield.html
Build firmware
--------------
Build.
$ git clone https://github.com/tmk/tmk_keyboard.git
$ cd tmk_keyboard
$ git submodule init
$ git submodule update
$ cd converter/usb_usb
$ make
And Program converter. Push button on TMK converter and just run this.
$ make dfu
In case of Leonardo push reset button then run command. Serial port name(COM17) depends your system. On Linux I got /dev/ttyACM0.
$ DEV=COM17 make program
or
$ avrdude -patmega32u4 -cavr109 -b57600 -Uflash:w:usb_usb.hex -PCOM17
Limitation
----------
Only supports 'HID Boot protocol'.
Note that the converter can host only USB "boot protocol" keyboard(6KRO), not NKRO, it is possible to support NKRO keyboard but you will need to write HID report parser for that. Every NKRO keyboard can have different HID report and it is difficult to support all kind of NKRO keyboards in the market.
Keymap editor
-------------
You can editor keymap and download firmware with web brwoser.
- http://www.tmk-kbd.com/tmk_keyboard/editor/unimap/?usb_usb
Update
------
2014/12/11 Added Hub support(confirmed with HHKB pro2)
2016/09/10 Unimap editor support
2016/10/18 Fix LED state at startup
2017/05/xx Fix startup code for FC660C(3eae475)
2018/02/xx Add Korean and Brazilian specific keys(ab6ddac,b2fa0ffa)
2018/07/xx Fix startup issue(c2ce617)
2018/10/xx Use fixed LUFA stack and update USB_Host_Shield_2.0
Resource
--------
USB Host Sheild 2.0
https://www.circuitsathome.com/products-page/arduino-shields/usb-host-shield-2-0-for-arduino
https://www.circuitsathome.com/products-page/arduino-shields/usb-host-shield-for-arduino-pro-mini
USB Host Sheild 2.0 source
https://github.com/felis/USB_Host_Shield_2.0
Arduino USB Host Shield(with bootst converter)
http://arduino.cc/en/Main/ArduinoUSBHostShield
Arduino source
https://github.com/arduino/Arduino/hardware/arduino/{cores,variants}
Initial release of TMK USB-USB converter
https://geekhack.org/index.php?topic=33057.msg653549#msg653549
http://deskthority.net/workshop-f7/is-remapping-a-usb-keyboard-using-teensy-possible-t2841-30.html#p74854
Arduino-based hardware keyboard remapper - Colemak forum
http://forum.colemak.com/viewtopic.php?id=1561
Teensy + Host Shield
http://www.pjrc.com/teensy/td_libs_USBHostShield.html

View file

@ -0,0 +1,96 @@
USB to USB keyboard protocol converter
======================================
See for detail and discussion here.
- https://geekhack.org/index.php?topic=69169.0
Hardware requirement
--------------------
There are two options.
### TMK USB-USB Converter
You can buy a fully preassembled converter from me here.
- https://geekhack.org/index.php?topic=72052.0
### Arduino Leonardo + USB Host Shield
Buying Arduino Leonardo and USB Host Shield.
- https://store.arduino.cc/usa/leonardo
- https://store.arduino.cc/usa/arduino-usb-host-shield
- https://www.sparkfun.com/products/9947
Build firmware
--------------
Build.
$ git clone https://github.com/tmk/tmk_keyboard.git
$ cd tmk_keyboard
$ git submodule init
$ git submodule update
$ cd converter/usb_usb
$ make
And Program converter. Push button on TMK converter and just run this.
$ make dfu
In case of Leonardo push reset button then run command. Serial port name(COM17) depends your system. On Linux I got /dev/ttyACM0.
$ DEV=COM17 make program
or
$ avrdude -patmega32u4 -cavr109 -b57600 -Uflash:w:usb_usb.hex -PCOM17
Limitation
----------
Only supports 'HID Boot protocol'.
Note that the converter can host only USB "boot protocol" keyboard(6KRO), not NKRO, it is possible to support NKRO keyboard but you will need to write HID report parser for that. Every NKRO keyboard can have different HID report and it is difficult to support all kind of NKRO keyboards in the market.
Keymap editor
-------------
You can editor keymap and download firmware with web brwoser.
- http://www.tmk-kbd.com/tmk_keyboard/editor/unimap/?usb_usb
Update
------
- 2014/12/11 Added Hub support(confirmed with HHKB pro2)
- 2016/09/10 Unimap editor support
- 2016/10/18 Fix LED state at startup
- 2017/05/xx Fix startup code for FC660C(3eae475)
- 2018/02/xx Add Korean and Brazilian specific keys(ab6ddac,b2fa0ffa)
- 2018/07/xx Fix startup issue(c2ce617)
- 2018/10/xx Use fixed LUFA stack and update USB_Host_Shield_2.0
- 2019/09/18 Add BTLD(bootlader jump) key to unimap
Resource
--------
### USB Host Sheild 2.0
- https://www.circuitsathome.com/products-page/arduino-shields/usb-host-shield-2-0-for-arduino
### USB Host Sheild 2.0 source
- https://github.com/felis/USB_Host_Shield_2.0
### Arduino USB Host Shield(with bootst converter)
- http://arduino.cc/en/Main/ArduinoUSBHostShield
### Arduino source
- https://github.com/arduino/Arduino/hardware/arduino/{cores,variants}
### Arduino-based hardware keyboard remapper - Colemak forum
- http://forum.colemak.com/viewtopic.php?id=1561
### Teensy + Host Shield
- http://www.pjrc.com/teensy/td_libs_USBHostShield.html

File diff suppressed because it is too large Load diff

View file

@ -36,4 +36,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* key combination for command */
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
// Disable power saving in USB suspend loop but remote wakeup is still valid.
// This allows keep USB::Task() going during suspend without power down time delay.
//#define NO_SUSPEND_POWER_DOWN
// Disable USB startup wait, which can delays starting UHS2 Task() for 350-600ms.
//#define NO_USB_STARTUP_WAIT_LOOP
// Disable USB suspend loop, which blocks UHS2 Task() while power saving.
// Note that this also disables power saving and remote wakeup from keyboard completely.
//#define NO_USB_SUSPEND_LOOP
#endif

View file

@ -35,7 +35,7 @@ const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
),
UNIMAP(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
GRV, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,
GRV, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,BTLD, TRNS,TRNS,TRNS,
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, INS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,LEFT,RGHT, TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,

View file

@ -35,6 +35,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "host.h"
#include "keyboard.h"
#include "hook.h"
#include "suspend.h"
#include "lufa.h"
/* KEY CODE to Matrix
*
@ -71,8 +75,6 @@ static bool matrix_is_mod =false;
* This supports two cascaded hubs and four keyboards
*/
USB usb_host;
USBHub hub1(&usb_host);
USBHub hub2(&usb_host);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> kbd1(&usb_host);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> kbd2(&usb_host);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> kbd3(&usb_host);
@ -81,6 +83,8 @@ KBDReportParser kbd_parser1;
KBDReportParser kbd_parser2;
KBDReportParser kbd_parser3;
KBDReportParser kbd_parser4;
USBHub hub1(&usb_host);
USBHub hub2(&usb_host);
uint8_t matrix_rows(void) { return MATRIX_ROWS; }
@ -136,12 +140,6 @@ uint8_t matrix_scan(void) {
or_report(kbd_parser4.report);
matrix_is_mod = true;
dprintf("state: %02X %02X", keyboard_report.mods, keyboard_report.reserved);
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
dprintf(" %02X", keyboard_report.keys[i]);
}
dprint("\r\n");
} else {
matrix_is_mod = false;
}
@ -151,17 +149,17 @@ uint8_t matrix_scan(void) {
usb_host.Task();
timer = timer_elapsed(timer);
if (timer > 100) {
dprintf("host.Task: %d\n", timer);
xprintf("host.Task: %d\n", timer);
}
static uint8_t usb_state = 0;
if (usb_state != usb_host.getUsbTaskState()) {
usb_state = usb_host.getUsbTaskState();
dprintf("usb_state: %02X\n", usb_state);
xprintf("usb_state: %02X\n", usb_state);
// restore LED state when keyboard comes up
if (usb_state == USB_STATE_RUNNING) {
dprintf("speed: %s\n", usb_host.getVbusState()==FSHOST ? "full" : "low");
xprintf("speed: %s\n", usb_host.getVbusState()==FSHOST ? "full" : "low");
keyboard_set_leds(host_keyboard_leds());
}
}
@ -218,12 +216,6 @@ uint8_t matrix_key_count(void) {
}
void matrix_print(void) {
print("\nr/c 0123456789ABCDEF\n");
for (uint8_t row = 0; row < matrix_rows(); row++) {
xprintf("%02d: ", row);
print_bin_reverse16(matrix_get_row(row));
print("\n");
}
}
void led_set(uint8_t usb_led)
@ -233,3 +225,28 @@ void led_set(uint8_t usb_led)
if (kbd3.isReady()) kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
if (kbd4.isReady()) kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
}
// We need to keep doing UHS2 USB::Task() to initialize keyboard
// even before USB is not configured.
void hook_usb_startup_wait_loop(void)
{
matrix_scan();
}
// We need to keep doing UHS2 USB::Task() to initialize keyboard
// even during USB bus is suspended and remote wakeup is not enabled yet on LUFA side.
// This situation can happen just after pluging converter into USB port.
void hook_usb_suspend_loop(void)
{
#ifndef LUFA_DEBUG_UART
// This corrupts debug print when suspend
suspend_power_down();
#endif
if (USB_Device_RemoteWakeupEnabled) {
if (suspend_wakeup_condition()) {
USB_Device_SendRemoteWakeup();
}
} else {
matrix_scan();
}
}

View file

@ -1,4 +0,0 @@
TARGET = alps64_editor
KEYMAP_SECTION_ENABLE = yes # fixed address keymap for keymap editor
KEYMAP = editor
include Makefile

File diff suppressed because it is too large Load diff

View file

@ -25,13 +25,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "print.h"
#include "debug.h"
#include "util.h"
#include "timer.h"
#include "matrix.h"
#ifndef DEBOUNCE
# define DEBOUNCE 5
#endif
static uint8_t debouncing = DEBOUNCE;
static bool debouncing = false;
static uint16_t debouncing_time = 0;
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
@ -70,26 +72,24 @@ uint8_t matrix_scan(void)
{
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
select_row(i);
_delay_us(30); // without this wait read unstable value.
_delay_us(30); // delay for settling
matrix_row_t cols = read_cols();
if (matrix_debouncing[i] != cols) {
matrix_debouncing[i] = cols;
if (debouncing) {
debug("bounce!: "); debug_hex(debouncing); debug("\n");
dprintf("bounce: %d %d@%02X\n", timer_elapsed(debouncing_time), i, matrix_debouncing[i]^cols);
}
debouncing = DEBOUNCE;
matrix_debouncing[i] = cols;
debouncing = true;
debouncing_time = timer_read();
}
unselect_rows();
}
if (debouncing) {
if (--debouncing) {
_delay_ms(1);
} else {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
}
if (debouncing && timer_elapsed(debouncing_time) >= DEBOUNCE) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
}
debouncing = false;
}
return 1;

View file

@ -17,9 +17,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "unimap_trans.h"
#define AC_L1 ACTION_LAYER_TAP_KEY(1, KC_RGUI)
#ifdef KEYMAP_SECTION_ENABLE
const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
#else
@ -41,14 +38,7 @@ const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
[0] = UNIMAP_ALPS64( \
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, NUHS,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, ENT, \
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT,ESC, \
LCTL,LGUI,LALT, SPC, APP, RALT,L1, RCTL),
[1] = UNIMAP_ALPS64( \
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, BSPC, \
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT, PENT, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN, TRNS,TRNS, \
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
LCTL,LALT,LGUI, SPC, RGUI,RALT,APP, RCTL),
};

File diff suppressed because it is too large Load diff

View file

@ -51,7 +51,7 @@ void matrix_init(void)
// LEDs on NumLock, CapsLock and ScrollLock(PB4, PB5, PB6)
DDRB |= (1<<4) | (1<<5) | (1<<6);
PORTB |= (1<<4) | (1<<5) | (1<<6);
PORTB &= ~((1<<4) | (1<<5) | (1<<6));
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;

View file

@ -25,13 +25,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "print.h"
#include "debug.h"
#include "util.h"
#include "timer.h"
#include "matrix.h"
#ifndef DEBOUNCE
# define DEBOUNCE 5
#endif
static uint8_t debouncing = DEBOUNCE;
static bool debouncing = false;
static uint16_t debouncing_time = 0;
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
@ -60,26 +63,24 @@ uint8_t matrix_scan(void)
{
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
select_row(i);
_delay_us(30); // without this wait read unstable value.
_delay_us(1); // delay for settling
matrix_row_t cols = read_cols();
if (matrix_debouncing[i] != cols) {
matrix_debouncing[i] = cols;
if (debouncing) {
debug("bounce!: "); debug_hex(debouncing); debug("\n");
dprintf("bounce: %d %d@%02X\n", timer_elapsed(debouncing_time), i, matrix_debouncing[i]^cols);
}
debouncing = DEBOUNCE;
matrix_debouncing[i] = cols;
debouncing = true;
debouncing_time = timer_read();
}
unselect_rows();
}
if (debouncing) {
if (--debouncing) {
_delay_ms(1);
} else {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
}
if (debouncing && timer_elapsed(debouncing_time) >= DEBOUNCE) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
}
debouncing = false;
}
return 1;

View file

@ -50,10 +50,22 @@ endif
ifeq (yes,$(strip $(CONSOLE_ENABLE)))
OPT_DEFS += -DCONSOLE_ENABLE
else
OPT_DEFS += -DNO_PRINT
# Remove print functions when console is disabled and
# no other print method like UART is available
ifneq (yes, $(strip $(DEBUG_PRINT_AVAILABLE)))
OPT_DEFS += -DNO_PRINT
OPT_DEFS += -DNO_DEBUG
endif
endif
ifeq (yes,$(strip $(NO_DEBUG)))
OPT_DEFS += -DNO_DEBUG
endif
ifeq (yes,$(strip $(NO_PRINT)))
OPT_DEFS += -DNO_PRINT
endif
ifeq (yes,$(strip $(COMMAND_ENABLE)))
SRC += $(COMMON_DIR)/command.c
OPT_DEFS += -DCOMMAND_ENABLE
@ -89,14 +101,16 @@ ifeq (yes,$(strip $(KEYMAP_SECTION_ENABLE)))
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
else ifeq ($(strip $(MCU)),atmega32u4)
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
else ifeq ($(strip $(MCU)),at90usb1286)
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr51.x
else
EXTRALDFLAGS = $(error no ldscript for keymap section)
endif
endif
# Version string
VERSION := $(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
OPT_DEFS += -DVERSION=$(VERSION)
TMK_VERSION := $(shell (git describe --always --dirty=+ || echo 'unknown') 2> /dev/null)
OPT_DEFS += -DTMK_VERSION=$(TMK_VERSION)
# Search Path

View file

@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action.h"
#include "hook.h"
#include "wait.h"
#include "bootloader.h"
#ifdef DEBUG_ACTION
#include "debug.h"
@ -58,6 +59,8 @@ void action_exec(keyevent_t event)
void process_action(keyrecord_t *record)
{
if (hook_process_action(record)) return;
keyevent_t event = record->event;
#ifndef NO_ACTION_TAPPING
uint8_t tap_count = record->tap.count;
@ -339,6 +342,15 @@ void process_action(keyrecord_t *record)
break;
#endif
case ACT_COMMAND:
switch (action.command.id) {
case COMMAND_BOOTLOADER:
if (event.pressed) {
clear_keyboard();
wait_ms(50);
bootloader_jump();
}
break;
}
break;
#ifndef NO_ACTION_FUNCTION
case ACT_FUNCTION:

View file

@ -48,7 +48,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* 0100|10| usage(10) (reserved)
* 0100|11| usage(10) (reserved)
*
* ACT_MOUSEKEY(0110): TODO: Not needed?
* ACT_MOUSEKEY(0101): TODO: Not needed?
* 0101|xxxx| keycode Mouse key
*
* 011x|xxxx xxxx xxxx (reseved)
@ -290,6 +290,12 @@ enum layer_pram_tap_op {
/*
* Extensions
*/
/* 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 */
enum backlight_opt {
BACKLIGHT_INCREASE = 0,
BACKLIGHT_DECREASE = 1,
@ -297,18 +303,18 @@ enum backlight_opt {
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 << 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))
enum command_ids {
COMMAND_BOOTLOADER, // jump to bootloader
};
#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (id))
/* Function */
enum function_opts {
FUNC_TAP = 0x8, /* indciates function is tappable */

View file

@ -283,43 +283,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define AC_WWW_STOP ACTION_USAGE_CONSUMER(APPCONTROL_STOP)
#define AC_WWW_REFRESH ACTION_USAGE_CONSUMER(APPCONTROL_REFRESH)
#define AC_WWW_FAVORITES ACTION_USAGE_CONSUMER(APPCONTROL_BOOKMARKS)
/* Jump to bootloader */
#define AC_BOOTLOADER ACTION_KEY(KC_BOOTLOADER)
/* Fn key */
/*
#define AC_FN0 ACTION_KEY(KC_FN0)
#define AC_FN1 ACTION_KEY(KC_FN1)
#define AC_FN2 ACTION_KEY(KC_FN2)
#define AC_FN3 ACTION_KEY(KC_FN3)
#define AC_FN4 ACTION_KEY(KC_FN4)
#define AC_FN5 ACTION_KEY(KC_FN5)
#define AC_FN6 ACTION_KEY(KC_FN6)
#define AC_FN7 ACTION_KEY(KC_FN7)
#define AC_FN8 ACTION_KEY(KC_FN8)
#define AC_FN9 ACTION_KEY(KC_FN9)
#define AC_FN10 ACTION_KEY(KC_FN10)
#define AC_FN11 ACTION_KEY(KC_FN11)
#define AC_FN12 ACTION_KEY(KC_FN12)
#define AC_FN13 ACTION_KEY(KC_FN13)
#define AC_FN14 ACTION_KEY(KC_FN14)
#define AC_FN15 ACTION_KEY(KC_FN15)
#define AC_FN16 ACTION_KEY(KC_FN16)
#define AC_FN17 ACTION_KEY(KC_FN17)
#define AC_FN18 ACTION_KEY(KC_FN18)
#define AC_FN19 ACTION_KEY(KC_FN19)
#define AC_FN20 ACTION_KEY(KC_FN20)
#define AC_FN21 ACTION_KEY(KC_FN21)
#define AC_FN22 ACTION_KEY(KC_FN22)
#define AC_FN23 ACTION_KEY(KC_FN23)
#define AC_FN24 ACTION_KEY(KC_FN24)
#define AC_FN25 ACTION_KEY(KC_FN25)
#define AC_FN26 ACTION_KEY(KC_FN26)
#define AC_FN27 ACTION_KEY(KC_FN27)
#define AC_FN28 ACTION_KEY(KC_FN28)
#define AC_FN29 ACTION_KEY(KC_FN29)
#define AC_FN30 ACTION_KEY(KC_FN30)
#define AC_FN31 ACTION_KEY(KC_FN31)
*/
/* Mousekey */
#define AC_MS_UP ACTION_MOUSEKEY(KC_MS_UP)
#define AC_MS_DOWN ACTION_MOUSEKEY(KC_MS_DOWN)
@ -338,6 +302,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define AC_MS_ACCEL1 ACTION_MOUSEKEY(KC_MS_ACCEL1)
#define AC_MS_ACCEL2 ACTION_MOUSEKEY(KC_MS_ACCEL2)
/* Command */
#define AC_BOOTLOADER ACTION_COMMAND(COMMAND_BOOTLOADER, 0)
/*
* Short names
*/
@ -396,6 +364,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define AC_P8 ACTION_KEY(KC_KP_8)
#define AC_P9 ACTION_KEY(KC_KP_9)
#define AC_P0 ACTION_KEY(KC_KP_0)
#define AC_P00 ACTION_KEY(KC_KP_00)
#define AC_P000 ACTION_KEY(KC_KP_000)
#define AC_PDOT ACTION_KEY(KC_KP_DOT)
#define AC_PCMM ACTION_KEY(KC_KP_COMMA)
#define AC_PSLS ACTION_KEY(KC_KP_SLASH)
@ -447,9 +417,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define AC_WSTP ACTION_USAGE_CONSUMER(APPCONTROL_STOP)
#define AC_WREF ACTION_USAGE_CONSUMER(APPCONTROL_REFRESH)
#define AC_WFAV ACTION_USAGE_CONSUMER(APPCONTROL_BOOKMARKS)
/* Jump to bootloader */
#define AC_BTLD ACTION_KEY(KC_BOOTLOADER)
/* Transparent */
#define AC_TRNS ACTION_KEY(KC_TRANSPARENT)
/* Command */
#define AC_BTLD AC_BOOTLOADER
#endif

View file

@ -3,6 +3,7 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/boot.h>
#include <util/delay.h>
#include "bootloader.h"
@ -16,8 +17,8 @@
* AVR Boot section size are defined by setting BOOTSZ fuse in fact. Consult with your MCU datasheet.
* Note that 'Word'(2 bytes) size and address are used in datasheet while TMK uses 'Byte'.
*
*
* Size of Bootloaders in bytes:
* Atmel DFU loader(ATmega32U2) 4096
* Atmel DFU loader(ATmega32U4) 4096
* Atmel DFU loader(AT90USB128) 8192
* LUFA bootloader(ATmega32U4) 4096
@ -27,45 +28,60 @@
* Teensy++ halfKay(AT90USB128) 1024
*
*
* AVR Boot section is located at the end of Flash memory like the followings.
* AVR Boot section is located at the end of Flash memory.
*
*
* byte Atmel/LUFA(ATMega32u4) byte Atmel(AT90SUB128)
* 0x0000 +---------------+ 0x00000 +---------------+
* | | | |
* | | | |
* | Application | | Application |
* | | | |
* = = = =
* | | 32KB-4KB | | 128KB-8KB
* 0x6000 +---------------+ 0x1FC00 +---------------+
* | Bootloader | 4KB | Bootloader | 8KB
* 0x7FFF +---------------+ 0x1FFFF +---------------+
*
*
* byte Teensy(ATMega32u4) byte Teensy++(AT90SUB128)
* 0x0000 +---------------+ 0x00000 +---------------+
* | | | |
* | | | |
* | Application | | Application |
* | | | |
* = = = =
* | | 32KB-512B | | 128KB-1KB
* 0x7E00 +---------------+ 0x1FC00 +---------------+
* | Bootloader | 512B | Bootloader | 1KB
* 0x7FFF +---------------+ 0x1FFFF +---------------+
* byte ATMega32u4 with 4096-byte Boot section
* 0x0000 +---------------+
* | |
* | |
* | Application | 28KB
* | |
* = =
* | |
* 0x7000 +---------------+ <---- BOOTLOADER_START
* | Bootloader | 4KB BOOTLOADER_SIZE
* 0x7FFF +---------------+ <---- FLASHEND
*/
#ifndef BOOTLOADER_SIZE
#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
#define BOOTLOADER_SIZE 4096
/* bootloader start address in byte */
#define BOOTLOADER_START (FLASHEND - bootloader_size() + 1)
/* boot section size in byte */
static inline uint16_t bootloader_size(void)
{
#if defined(BOOTLOADER_SIZE)
return BOOTLOADER_SIZE;
#else
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || \
defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega16U2__) || \
defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
uint8_t hfuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
switch ((hfuse >> 1) & 3) {
case 0: return 4096;
case 1: return 2048;
case 2: return 1024;
case 3: return 512;
}
return 4096;
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || \
defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
uint8_t hfuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
switch ((hfuse >> 1) & 3) {
case 0: return 8192;
case 1: return 4096;
case 2: return 2048;
case 3: return 1024;
}
return 8192;
#else
#error Set Boot section size to BOOTLOADER_SIZE in config.h
#endif
#endif
#define FLASH_SIZE (FLASHEND + 1L)
#define BOOTLOADER_START (FLASH_SIZE - BOOTLOADER_SIZE)
}
/*
* Entering the Bootloader via Software
/*
* Entering the Bootloader via Software
* http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
*/
#define BOOTLOADER_RESET_KEY 0xB007B007
@ -76,7 +92,6 @@ void bootloader_jump(void) {
#ifdef PROTOCOL_LUFA
USB_Disable();
cli();
_delay_ms(2000);
#endif
#ifdef PROTOCOL_PJRC
@ -87,6 +102,14 @@ void bootloader_jump(void) {
_delay_ms(5);
#endif
#ifndef NO_BOOTLOADER_CATERINA_BOOTKEY
// Set bootkey for Arduino Leonardo and Pro Micro bootloader
// Watchdog reset with bootkey causes the bootloader to enter program mode instead of starting application.
// https://github.com/arduino/ArduinoCore-avr/blob/master/bootloaders/caterina/Caterina.c#L68-L69
// https://github.com/sparkfun/SF32u4_boards/blob/master/sparkfun/avr/bootloaders/caterina/Caterina.c#L88-L89
*(volatile uint16_t *)0x0800 = 0x7777;
#endif
// watchdog reset
reset_key = BOOTLOADER_RESET_KEY;
wdt_enable(WDTO_250MS);
@ -101,85 +124,20 @@ void bootloader_jump_after_watchdog_reset(void)
if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
reset_key = 0;
// My custom USBasploader requires this to come up.
// some of bootloaders may need to preseve?
MCUSR = 0;
// Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
MCUSR &= ~(1<<WDRF);
// disable watchdog timer
wdt_disable();
#ifndef NO_BOOTLOADER_CATERINA_BOOTKEY
// Clear bootkey of Caterina bootloader for other bootloaders
// Leonardo and Pro Micro with Arduino default fuse setting don't reach here
// because bootloader section are executed before application everytime.
*(volatile uint16_t *)0x0800 = 0;
#endif
// This is compled into 'icall', address should be in word unit, not byte.
((void (*)(void))(BOOTLOADER_START/2))();
((void (*)(void))( (uint16_t)(BOOTLOADER_START / 2) ))();
}
}
#if 0
/* Jumping To The Bootloader
* http://www.pjrc.com/teensy/jump_to_bootloader.html
*
* This method doen't work when using LUFA. idk why.
* - needs to initialize more regisers or interrupt setting?
*/
void bootloader_jump(void) {
#ifdef PROTOCOL_LUFA
USB_Disable();
cli();
_delay_ms(2000);
#endif
#ifdef PROTOCOL_PJRC
cli();
UDCON = 1;
USBCON = (1<<FRZCLK);
UCSR1B = 0;
_delay_ms(5);
#endif
/*
* Initialize
*/
#if defined(__AVR_AT90USB162__)
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
DDRB = 0; DDRC = 0; DDRD = 0;
PORTB = 0; PORTC = 0; PORTD = 0;
#elif defined(__AVR_ATmega32U4__)
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#elif defined(__AVR_AT90USB646__)
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#elif defined(__AVR_AT90USB1286__)
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#endif
/*
* USBaspLoader
*/
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
// This makes custom USBasploader come up.
MCUSR = 0;
// initialize ports
PORTB = 0; PORTC= 0; PORTD = 0;
DDRB = 0; DDRC= 0; DDRD = 0;
// disable interrupts
EIMSK = 0; EECR = 0; SPCR = 0;
ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
ADCSRA = 0; TWCR = 0; UCSR0B = 0;
#endif
// This is compled into 'icall', address should be in word unit, not byte.
((void (*)(void))(BOOTLOADER_START/2))();
}
#endif

View file

@ -1,4 +1,3 @@
// TODO: Teensy support(ATMega32u4/AT90USB128)
// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
/* UART Example for Teensy USB Development Board
* http://www.pjrc.com/teensy/
@ -32,9 +31,42 @@
#include "uart.h"
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
# define UDRn UDR0
# define UBRRn UBRR0
# define UCSRnA UCSR0A
# define UCSRnB UCSR0B
# define UCSRnC UCSR0C
# define U2Xn U2X0
# define RXENn RXEN0
# define TXENn TXEN0
# define RXCIEn RXCIE0
# define UCSZn1 UCSZ01
# define UCSZn0 UCSZ00
# define UDRIEn UDRIE0
# define UDRE_vect USART_UDRE_vect
# define RX_vect USART_RX_vect
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
# define UDRn UDR1
# define UBRRn UBRR1
# define UCSRnA UCSR1A
# define UCSRnB UCSR1B
# define UCSRnC UCSR1C
# define U2Xn U2X1
# define RXENn RXEN1
# define TXENn TXEN1
# define RXCIEn RXCIE1
# define UCSZn1 UCSZ11
# define UCSZn0 UCSZ10
# define UDRIEn UDRIE1
# define UDRE_vect USART1_UDRE_vect
# define RX_vect USART1_RX_vect
#endif
// These buffers may be any size from 2 to 256 bytes.
#define RX_BUFFER_SIZE 64
#define TX_BUFFER_SIZE 40
#define TX_BUFFER_SIZE 256
static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
static volatile uint8_t tx_buffer_head;
@ -47,10 +79,10 @@ static volatile uint8_t rx_buffer_tail;
void uart_init(uint32_t baud)
{
cli();
UBRR0 = (F_CPU / 4 / baud - 1) / 2;
UCSR0A = (1<<U2X0);
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
UBRRn = (F_CPU / 4 / baud - 1) / 2;
UCSRnA = (1<<U2Xn);
UCSRnB = (1<<RXENn) | (1<<TXENn) | (1<<RXCIEn);
UCSRnC = (1<<UCSZn1) | (1<<UCSZn0);
tx_buffer_head = tx_buffer_tail = 0;
rx_buffer_head = rx_buffer_tail = 0;
sei();
@ -63,11 +95,13 @@ void uart_putchar(uint8_t c)
i = tx_buffer_head + 1;
if (i >= TX_BUFFER_SIZE) i = 0;
// return immediately to avoid deadlock when interrupt is disabled(called from ISR)
if (tx_buffer_tail == i && (SREG & (1<<SREG_I)) == 0) return;
while (tx_buffer_tail == i) ; // wait until space in buffer
//cli();
tx_buffer[i] = c;
tx_buffer_head = i;
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0);
UCSRnB = (1<<RXENn) | (1<<TXENn) | (1<<RXCIEn) | (1<<UDRIEn);
//sei();
}
@ -98,27 +132,27 @@ uint8_t uart_available(void)
}
// Transmit Interrupt
ISR(USART_UDRE_vect)
ISR(UDRE_vect)
{
uint8_t i;
if (tx_buffer_head == tx_buffer_tail) {
// buffer is empty, disable transmit interrupt
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
UCSRnB = (1<<RXENn) | (1<<TXENn) | (1<<RXCIEn);
} else {
i = tx_buffer_tail + 1;
if (i >= TX_BUFFER_SIZE) i = 0;
UDR0 = tx_buffer[i];
UDRn = tx_buffer[i];
tx_buffer_tail = i;
}
}
// Receive Interrupt
ISR(USART_RX_vect)
ISR(RX_vect)
{
uint8_t c, i;
c = UDR0;
c = UDRn;
i = rx_buffer_head + 1;
if (i >= RX_BUFFER_SIZE) i = 0;
if (i != rx_buffer_tail) {

View file

@ -284,7 +284,7 @@ static bool command_common(uint8_t code)
print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
"VER: " STR(DEVICE_VER) "\n");
print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n");
print("BUILD: " STR(TMK_VERSION) " (" __TIME__ " " __DATE__ ")\n");
/* build options */
print("OPTIONS:"
#ifdef PROTOCOL_PJRC

View file

@ -47,3 +47,8 @@ void hook_keyboard_leds_change(uint8_t led_status) {
__attribute__((weak))
void hook_bootmagic(void) {}
__attribute__((weak))
bool hook_process_action(keyrecord_t *record) {
return false;
}

View file

@ -20,6 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keyboard.h"
#include "led.h"
#include "action.h"
#ifdef __cplusplus
extern "C" {
#endif
/* -------------------------------------
* Protocol hooks
@ -47,6 +52,10 @@ void hook_usb_suspend_loop(void);
* the "normal" indicator LED status by default. */
void hook_usb_wakeup(void);
/* Called repeatedly until getting to CONFIGURED state */
/* Default behaviour: do nothing. */
void hook_usb_startup_wait_loop(void);
/* -------------------------------------
* Keyboard hooks
@ -76,5 +85,12 @@ void hook_keyboard_leds_change(uint8_t led_status);
/* Default behaviour: do nothing. */
void hook_bootmagic(void);
/* Called on before processing key event */
/* returns true if the event is consumed and default action is not needed. */
bool hook_process_action(keyrecord_t *record);
#ifdef __cplusplus
}
#endif
#endif /* _HOOKS_H_ */

View file

@ -116,6 +116,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_P8 KC_KP_8
#define KC_P9 KC_KP_9
#define KC_P0 KC_KP_0
#define KC_P00 KC_KP_00
#define KC_P000 KC_KP_000
#define KC_PDOT KC_KP_DOT
#define KC_PCMM KC_KP_COMMA
#define KC_PSLS KC_KP_SLASH

View file

@ -155,9 +155,7 @@ static action_t keycode_to_action(uint8_t keycode)
return (action_t)ACTION_TRANSPARENT;
break;
case KC_BOOTLOADER:
clear_keyboard();
wait_ms(50);
bootloader_jump(); // not return
return (action_t)ACTION_COMMAND(COMMAND_BOOTLOADER, 0);
break;
default:
return (action_t)ACTION_NO;

View file

@ -33,6 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MOUSE_BTN3 (1<<2)
#define MOUSE_BTN4 (1<<3)
#define MOUSE_BTN5 (1<<4)
#define MOUSE_BTN6 (1<<5)
#define MOUSE_BTN7 (1<<6)
#define MOUSE_BTN8 (1<<7)
/* Consumer Page(0x0C)
* following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx

View file

@ -5,9 +5,17 @@
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
void suspend_idle(uint8_t timeout);
void suspend_power_down(void);
bool suspend_wakeup_condition(void);
void suspend_wakeup_init(void);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -6,17 +6,19 @@ The following hooks are available available:
Hook function | Timing
--------------------------------|-----------------------------------------------
`hook_early_init(void)` | Early in the boot process, before the matrix is initialized and before a connection is made with the host. Thus, this hook has access to very few parameters, but it is a good place to define any custom parameters needed by other early processes.
`hook_late_init(void)` | Near the end of the boot process, after Boot Magic has run and LEDs have been initialized.
`hook_bootmagic(void)` | During the Boot Magic window, after EEPROM and Bootloader checks are made, but before any other built-in Boot Magic checks are made.
`hook_usb_wakeup(void)` | When the device wakes up from USB suspend state.
`hook_usb_suspend_entry(void)` | When the device enters USB suspend state.
`hook_usb_suspend_loop(void)` | Continuously, while the device is in USB suspend state. *Default action:* power down and periodically check the matrix, causing wakeup if needed.
`hook_keyboard_loop(void)` | Continuously, during the main loop, after the matrix is checked.
`hook_matrix_change(keyevent_t event)` | When a matrix state change is detected, before any other actions are processed.
`hook_layer_change(uint32_t layer_state)` | When any layer is changed.
`hook_default_layer_change(uint32_t default_layer_state)` | When any default layer is changed.
`hook_keyboard_leds_change(uint8_t led_status)` | Whenever a change in the LED status is performed. *Default action:* call `keyboard_set_leds(led_status)`
`void hook_early_init(void)` | Early in the boot process, before the matrix is initialized and before a connection is made with the host. Thus, this hook has access to very few parameters, but it is a good place to define any custom parameters needed by other early processes.
`void hook_late_init(void)` | Near the end of the boot process, after Boot Magic has run and LEDs have been initialized.
`void hook_bootmagic(void)` | During the Boot Magic window, after EEPROM and Bootloader checks are made, but before any other built-in Boot Magic checks are made.
`void hook_usb_startup_wait_loop(void)` | Continuously, until the device gets ready and into USB configured state.
`void hook_usb_wakeup(void)` | When the device wakes up from USB suspend state.
`void hook_usb_suspend_entry(void)` | When the device enters USB suspend state.
`void hook_usb_suspend_loop(void)` | Continuously, while the device is in USB suspend state. *Default action:* power down and periodically check the matrix, causing wakeup if needed.
`void hook_keyboard_loop(void)` | Continuously, during the main loop, after the matrix is checked.
`void hook_matrix_change(keyevent_t event)` | When a matrix state change is detected, before any other actions are processed.
`void hook_layer_change(uint32_t layer_state)` | When any layer is changed.
`void hook_default_layer_change(uint32_t default_layer_state)` | When any default layer is changed.
`void hook_keyboard_leds_change(uint8_t led_status)` | Whenever a change in the LED status is performed. *Default action:* call `keyboard_set_leds(led_status)`
`bool hook_process_action(keyrecord_t *record)` | Before key event is processed by tmk_core. Return true if the event is consumed and default action is not needed.

View file

@ -0,0 +1,322 @@
/* Default linker script, for normal executables */
/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:51)
__TEXT_REGION_LENGTH__ = DEFINED(__TEXT_REGION_LENGTH__) ? __TEXT_REGION_LENGTH__ : 128K;
__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : 0xff00;
__EEPROM_REGION_LENGTH__ = DEFINED(__EEPROM_REGION_LENGTH__) ? __EEPROM_REGION_LENGTH__ : 64K;
__FUSE_REGION_LENGTH__ = DEFINED(__FUSE_REGION_LENGTH__) ? __FUSE_REGION_LENGTH__ : 1K;
__LOCK_REGION_LENGTH__ = DEFINED(__LOCK_REGION_LENGTH__) ? __LOCK_REGION_LENGTH__ : 1K;
__SIGNATURE_REGION_LENGTH__ = DEFINED(__SIGNATURE_REGION_LENGTH__) ? __SIGNATURE_REGION_LENGTH__ : 1K;
__USER_SIGNATURE_REGION_LENGTH__ = DEFINED(__USER_SIGNATURE_REGION_LENGTH__) ? __USER_SIGNATURE_REGION_LENGTH__ : 1K;
MEMORY
{
/* With keymap section
*
* TODO: should be as below
* Flash Map of AT90USB(128KB)
* +------------+ 0x0000
* | .vectors |
* | .progmem |
* | .init0-9 | > text region
* | .text |
* | .fini9-0 |
* | |
* |------------| _etext
* | .data |
* | .bss | > data region
* | .noinit |
* | |
* |------------| 0x1D800
* | .keymap | > keymap region(2KB)
* |------------| 0x1E000
* | bootloader | 8KB
* +------------+ 0x1FFFF
*
* FIXME: Use this To fit to ATMega32U4 unimap address
* Flash Map of AT90USB(128KB)
* +------------+ 0x0000
* | .vectors |
* | .progmem |
* | .init0-9 | > text region
* | .text |
* | .fini9-0 |
* | |
* |------------| _etext
* | .data |
* | .bss | > data region
* | .noinit |
* | |
* |------------| 0x6800
* | .keymap | > keymap region(2KB)
* |------------| 0x7000
* ~ ~
* ~ ~
* |------------| 0x1E000
* | bootloader | 8KB
* +------------+ 0x1FFFF
*/
text (rx) : ORIGIN = 0, LENGTH = __TEXT_REGION_LENGTH__
keymap (rw!x) : ORIGIN = 0x6800, LENGTH = 2K
data (rw!x) : ORIGIN = 0x800100, LENGTH = __DATA_REGION_LENGTH__
eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = __EEPROM_REGION_LENGTH__
fuse (rw!x) : ORIGIN = 0x820000, LENGTH = __FUSE_REGION_LENGTH__
lock (rw!x) : ORIGIN = 0x830000, LENGTH = __LOCK_REGION_LENGTH__
signature (rw!x) : ORIGIN = 0x840000, LENGTH = __SIGNATURE_REGION_LENGTH__
user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = __USER_SIGNATURE_REGION_LENGTH__
}
SECTIONS
{
/* Read-only sections, merged into text segment: */
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text :
{
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t*)
}
.rela.text :
{
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t*)
}
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata :
{
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r*)
}
.rela.rodata :
{
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r*)
}
.rel.data :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d*)
}
.rela.data :
{
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d*)
}
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
/* Internal text space or external memory. */
.text :
{
*(.vectors)
KEEP(*(.vectors))
/* For data that needs to reside in the lower 64k of progmem. */
*(.progmem.gcc*)
/* PR 13812: Placing the trampolines here gives a better chance
that they will be in range of the code that uses them. */
. = ALIGN(2);
__trampolines_start = . ;
/* The jump trampolines for the 16-bit limited relocs will reside here. */
*(.trampolines)
*(.trampolines*)
__trampolines_end = . ;
/* avr-libc expects these data to reside in lower 64K. */
*libprintf_flt.a:*(.progmem.data)
*libc.a:*(.progmem.data)
*(.progmem*)
. = ALIGN(2);
/* For future tablejump instruction arrays for 3 byte pc devices.
We don't relax jump/call instructions within these sections. */
*(.jumptables)
*(.jumptables*)
/* For code that needs to reside in the lower 128k progmem. */
*(.lowtext)
*(.lowtext*)
__ctors_start = . ;
*(.ctors)
__ctors_end = . ;
__dtors_start = . ;
*(.dtors)
__dtors_end = . ;
KEEP(SORT(*)(.ctors))
KEEP(SORT(*)(.dtors))
/* From this point on, we don't bother about wether the insns are
below or above the 16 bits boundary. */
*(.init0) /* Start here after reset. */
KEEP (*(.init0))
*(.init1)
KEEP (*(.init1))
*(.init2) /* Clear __zero_reg__, set up stack pointer. */
KEEP (*(.init2))
*(.init3)
KEEP (*(.init3))
*(.init4) /* Initialize data and BSS. */
KEEP (*(.init4))
*(.init5)
KEEP (*(.init5))
*(.init6) /* C++ constructors. */
KEEP (*(.init6))
*(.init7)
KEEP (*(.init7))
*(.init8)
KEEP (*(.init8))
*(.init9) /* Call main(). */
KEEP (*(.init9))
*(.text)
. = ALIGN(2);
*(.text.*)
. = ALIGN(2);
*(.fini9) /* _exit() starts here. */
KEEP (*(.fini9))
*(.fini8)
KEEP (*(.fini8))
*(.fini7)
KEEP (*(.fini7))
*(.fini6) /* C++ destructors. */
KEEP (*(.fini6))
*(.fini5)
KEEP (*(.fini5))
*(.fini4)
KEEP (*(.fini4))
*(.fini3)
KEEP (*(.fini3))
*(.fini2)
KEEP (*(.fini2))
*(.fini1)
KEEP (*(.fini1))
*(.fini0) /* Infinite loop after program termination. */
KEEP (*(.fini0))
_etext = . ;
} > text
.data :
{
PROVIDE (__data_start = .) ;
*(.data)
*(.data*)
*(.gnu.linkonce.d*)
*(.rodata) /* We need to include .rodata here if gcc is used */
*(.rodata*) /* with -fdata-sections. */
*(.gnu.linkonce.r*)
. = ALIGN(2);
_edata = . ;
PROVIDE (__data_end = .) ;
} > data AT> text
.bss ADDR(.data) + SIZEOF (.data) : AT (ADDR (.bss))
{
PROVIDE (__bss_start = .) ;
*(.bss)
*(.bss*)
*(COMMON)
PROVIDE (__bss_end = .) ;
} > data
__data_load_start = LOADADDR(.data);
__data_load_end = __data_load_start + SIZEOF(.data);
/* Global data not cleared after reset. */
.noinit ADDR(.bss) + SIZEOF (.bss) : AT (ADDR (.noinit))
{
PROVIDE (__noinit_start = .) ;
*(.noinit*)
PROVIDE (__noinit_end = .) ;
_end = . ;
PROVIDE (__heap_start = .) ;
} > data
/* keymap region is located at end of flash
* .fn_actions Fn actions definitions
* .keymaps Mapping layers
*/
.keymap :
{
PROVIDE(__keymap_start = .) ;
*(.keymap.fn_actions) /* 32*actions = 64bytes */
. = ALIGN(0x40);
*(.keymap.keymaps) /* rest of .keymap section */
*(.keymap*)
/* . = ALIGN(0x800); */ /* keymap section takes 2KB- */
} > keymap = 0x00 /* zero fill */
.eeprom :
{
/* See .data above... */
KEEP(*(.eeprom*))
__eeprom_end = . ;
} > eeprom
.fuse :
{
KEEP(*(.fuse))
KEEP(*(.lfuse))
KEEP(*(.hfuse))
KEEP(*(.efuse))
} > fuse
.lock :
{
KEEP(*(.lock*))
} > lock
.signature :
{
KEEP(*(.signature*))
} > signature
.user_signatures :
{
KEEP(*(.user_signatures*))
} > user_signatures
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
}

View file

@ -1,5 +1,5 @@
/*
Copyright 2011 Jun WAKO <wakojun@gmail.com>
Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
Copyright 2013 Shay Green <gblargg@gmail.com>
This software is licensed with a Modified BSD License.
@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <avr/io.h>
#include <avr/interrupt.h>
#include "adb.h"
#include "print.h"
// GCC doesn't inline functions normally
@ -92,81 +93,164 @@ uint16_t adb_host_kbd_recv(uint8_t addr)
}
#ifdef ADB_MOUSE_ENABLE
__attribute__ ((weak))
void adb_mouse_init(void) {
return;
return;
}
uint16_t adb_host_mouse_recv(void)
{
return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0);
__attribute__ ((weak))
void adb_mouse_task(void) {
return;
}
#endif
uint16_t adb_host_talk(uint8_t addr, uint8_t reg)
// This sends Talk command to read data from register and returns length of the data.
uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
{
uint16_t data = 0;
for (int8_t i =0; i < len; i++) buf[i] = 0;
cli();
attention();
send_byte((addr<<4) | (ADB_CMD_TALK<<2) | reg);
send_byte((addr<<4) | ADB_CMD_TALK | reg);
place_bit0(); // Stopbit(0)
// TODO: Service Request(Srq):
// Device holds low part of comannd stopbit for 140-260us
//
// Command:
// ......._ ______________________ ___ ............_ -------
// | | | | | | |
// Command | | | | | Data bytes | |
// ........|___| | 140-260 |__| |_............|___|
// |stop0 | Tlt Stop-to-Start |start1| |stop0 |
//
// Command without data:
// ......._ __________________________
// | |
// Command | |
// ........|___| | 140-260 |
// |stop0 | Tlt Stop-to-Start |
//
// Service Request:
// ......._ ______ ___ ............_ -------
// | 140-260 | | | | | |
// Command | Service Request | | | | Data bytes | |
// ........|___________________| |__| |_............|___|
// |stop0 | |start1| |stop0 |
// ......._ __________
// | 140-260 |
// Command | Service Request |
// ........|___________________|
// |stop0 |
// This can be happened?
// ......._ ______________________ ___ ............_ -----
// | | | | | | 140-260 |
// Command | | | | | Data bytes | Service Request |
// ........|___| | 140-260 |__| |_............|_________________|
// |stop0 | Tlt Stop-to-Start |start1| |stop0 |
//
// "Service requests are issued by the devices during a very specific time at the
// end of the reception of the command packet.
// If a device in need of service issues a service request, it must do so within
// the 65 µs of the Stop Bits low time and maintain the line low for a total of 300 µs."
//
// "A device sends a Service Request signal by holding the bus low during the low
// portion of the stop bit of any command or data transaction. The device must lengthen
// the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15."
// http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf
if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
xprintf("R");
sei();
return -30; // something wrong
return 0;
}
if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
sei();
return 0; // No data to send
return 0; // No data from device(not error);
}
uint8_t n = 17; // start bit + 16 data bits
// start bit(1)
if (!wait_data_hi(40)) {
xprintf("S");
sei();
return 0;
}
if (!wait_data_lo(100)) {
xprintf("s");
sei();
return 0;
}
uint8_t n = 0; // bit count
do {
//
// |<- bit_cell_max(130) ->|
// | |<- lo ->|
// | | |<-hi->|
// _______
// | | |
// | 130-lo | lo-hi |
// |________| |
//
uint8_t lo = (uint8_t) wait_data_hi(130);
if (!lo)
goto error;
goto error; // no more bit or after stop bit
uint8_t hi = (uint8_t) wait_data_lo(lo);
if (!hi)
goto error;
goto error; // stop bit extedned by Srq?
hi = lo - hi;
lo = 130 - lo;
if (n/8 >= len) continue; // can't store in buf
data <<= 1;
if (lo < hi) {
data |= 1;
}
else if (n == 17) {
sei();
return -20;
buf[n/8] <<= 1;
if ((130 - lo) < (lo - hi)) {
buf[n/8] |= 1;
}
}
while ( --n );
// Stop bit can't be checked normally since it could have service request lenghtening
// and its high state never goes low.
if (!wait_data_hi(351) || wait_data_lo(91)) {
sei();
return -21;
}
sei();
return data;
while ( ++n );
error:
sei();
return -n;
return n/8;
}
uint16_t adb_host_talk(uint8_t addr, uint8_t reg)
{
uint8_t len;
uint8_t buf[8];
len = adb_host_talk_buf(addr, reg, buf, 8);
if (len != 2) return 0;
return (buf[0]<<8 | buf[1]);
}
void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
{
cli();
attention();
send_byte((addr<<4) | ADB_CMD_LISTEN | reg);
place_bit0(); // Stopbit(0)
// TODO: Service Request
_delay_us(200); // Tlt/Stop to Start
place_bit1(); // Startbit(1)
for (int8_t i = 0; i < len; i++) {
send_byte(buf[i]);
//xprintf("%02X ", buf[i]);
}
place_bit0(); // Stopbit(0);
sei();
}
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l)
{
uint8_t buf[2] = { data_h, data_l };
adb_host_listen_buf(addr, reg, buf, 2);
}
void adb_host_flush(uint8_t addr)
{
cli();
attention();
send_byte((addr<<4) | (ADB_CMD_LISTEN<<2) | reg);
send_byte((addr<<4) | ADB_CMD_FLUSH);
place_bit0(); // Stopbit(0)
_delay_us(200); // Tlt/Stop to Start
place_bit1(); // Startbit(1)
send_byte(data_h);
send_byte(data_l);
place_bit0(); // Stopbit(0);
sei();
}

View file

@ -1,5 +1,5 @@
/*
Copyright 2011 Jun WAKO <wakojun@gmail.com>
Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
@ -54,16 +54,28 @@ POSSIBILITY OF SUCH DAMAGE.
/* ADB commands */
// Default Address
#define ADB_ADDR_0 0
#define ADB_ADDR_DONGLE 1
#define ADB_ADDR_KEYBOARD 2
#define ADB_ADDR_MOUSE 3
#define ADB_ADDR_TABLET 4
#define ADB_ADDR_APPLIANCE 7
#define ADB_ADDR_8 8
#define ADB_ADDR_9 9
#define ADB_ADDR_10 10
#define ADB_ADDR_11 11
#define ADB_ADDR_12 12
#define ADB_ADDR_13 13
#define ADB_ADDR_14 14
#define ADB_ADDR_15 15
// for temporary purpose, do not use for polling
#define ADB_ADDR_TMP 15
#define ADB_ADDR_MOUSE_POLL 10
// Command Type
#define ADB_CMD_RESET 0
#define ADB_CMD_FLUSH 1
#define ADB_CMD_LISTEN 2
#define ADB_CMD_TALK 3
#define ADB_CMD_LISTEN 8
#define ADB_CMD_TALK 12
// Register
#define ADB_REG_0 0
#define ADB_REG_1 1
@ -76,16 +88,22 @@ POSSIBILITY OF SUCH DAMAGE.
#define ADB_HANDLER_M0115 0x02
#define ADB_HANDLER_M3501 0x02
#define ADB_HANDLER_M1242_ANSI 0x10
#define ADB_HANDLER_EXTENDED_PROTOCOL 0x03
#define ADB_HANDLER_EXTENDED_KEYBOARD 0x03
#define ADB_HANDLER_CLASSIC1_MOUSE 0x01
#define ADB_HANDLER_CLASSIC2_MOUSE 0x02
#define ADB_HANDLER_EXTENDED_MOUSE 0x04
#define ADB_HANDLER_TURBO_MOUSE 0x32
// ADB host
void adb_host_init(void);
bool adb_host_psw(void);
uint16_t adb_host_kbd_recv(uint8_t addr);
uint16_t adb_host_mouse_recv(void);
uint16_t adb_host_talk(uint8_t addr, uint8_t reg);
uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l);
void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);
void adb_host_flush(uint8_t addr);
void adb_host_kbd_led(uint8_t addr, uint8_t led);
void adb_mouse_task(void);
void adb_mouse_init(void);

View file

@ -39,7 +39,7 @@ 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.
Start bit: can be long as 300-350us during start up and upto 2500us while key scanning
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.
@ -58,7 +58,7 @@ uint8_t ibm4704_send(uint8_t data)
clock_lo();
/* wait for Start bit(Clock:lo/Data:hi) */
WAIT(data_hi, 300, 0x30);
WAIT(data_hi, 5000, 0x30);
/* Data bit */
for (uint8_t i = 0; i < 8; i++) {
@ -89,7 +89,7 @@ uint8_t ibm4704_send(uint8_t data)
return 0;
ERROR:
idle();
if (ibm4704_error > 0x30) {
if (ibm4704_error >= 0x30) {
xprintf("S:%02X ", ibm4704_error);
}
IBM4704_INT_ON();

264
tmk_core/protocol/ibmpc.c Normal file
View file

@ -0,0 +1,264 @@
/*
Copyright 2010,2011,2012,2013,2019 Jun WAKO <wakojun@gmail.com>
This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
GPL-compatible, and OK to use in both free and proprietary applications.
Additions and corrections to this file are welcome.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*
* IBM PC keyboard protocol
*/
#include <stdbool.h>
#include <avr/interrupt.h>
#include "ringbuf.h"
#include "ibmpc.h"
#include "debug.h"
#include "timer.h"
#include "wait.h"
#define WAIT(stat, us, err) do { \
if (!wait_##stat(us)) { \
ibmpc_error = err; \
goto ERROR; \
} \
} while (0)
#define BUF_SIZE 16
static uint8_t buf[BUF_SIZE];
static ringbuf_t rb = {
.buffer = buf,
.head = 0,
.tail = 0,
.size_mask = BUF_SIZE - 1
};
volatile uint8_t ibmpc_protocol = IBMPC_PROTOCOL_AT;
volatile uint8_t ibmpc_error = IBMPC_ERR_NONE;
void ibmpc_host_init(void)
{
clock_init();
data_init();
idle();
IBMPC_INT_INIT();
IBMPC_INT_ON();
// POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
//wait_ms(2500);
}
int16_t ibmpc_host_send(uint8_t data)
{
bool parity = true;
ibmpc_error = IBMPC_ERR_NONE;
if (ibmpc_protocol == IBMPC_PROTOCOL_XT) return -1;
dprintf("w%02X ", data);
IBMPC_INT_OFF();
/* terminate a transmission if we have */
inhibit();
wait_us(100); // 100us [4]p.13, [5]p.50
/* 'Request to Send' and Start bit */
data_lo();
clock_hi();
WAIT(clock_lo, 10000, 1); // 10ms [5]p.50
/* Data bit[2-9] */
for (uint8_t i = 0; i < 8; i++) {
wait_us(15);
if (data&(1<<i)) {
parity = !parity;
data_hi();
} else {
data_lo();
}
WAIT(clock_hi, 50, 2);
WAIT(clock_lo, 50, 3);
}
/* Parity bit */
wait_us(15);
if (parity) { data_hi(); } else { data_lo(); }
WAIT(clock_hi, 50, 4);
WAIT(clock_lo, 50, 5);
/* Stop bit */
wait_us(15);
data_hi();
/* Ack */
WAIT(data_lo, 50, 6);
WAIT(clock_lo, 50, 7);
/* wait for idle state */
WAIT(clock_hi, 50, 8);
WAIT(data_hi, 50, 9);
idle();
IBMPC_INT_ON();
return ibmpc_host_recv_response();
ERROR:
ibmpc_error |= IBMPC_ERR_SEND;
idle();
IBMPC_INT_ON();
return -1;
}
int16_t ibmpc_host_recv_response(void)
{
// Command may take 25ms/20ms at most([5]p.46, [3]p.21)
uint8_t retry = 25;
while (retry-- && ringbuf_is_empty(&rb)) {
wait_ms(1);
}
int16_t data = ringbuf_get(&rb);
if (data != -1) dprintf("r%02X ", data);
return data;
}
/* get data received by interrupt */
int16_t ibmpc_host_recv(void)
{
int16_t data = ringbuf_get(&rb);
if (data != -1) dprintf("r%02X ", data);
return data;
}
ISR(IBMPC_INT_VECT)
{
static uint16_t last_time = 0;
static enum {
START,
BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
PARITY,
STOP,
} state = START;
static uint8_t data = 0;
static uint8_t parity = 1;
// return unless falling edge
if (clock_in()) {
return;
}
// Reset state when taking more than 1ms
if (last_time && timer_elapsed(last_time) > 10) {
ibmpc_error = IBMPC_ERR_TIMEOUT | IBMPC_ERR_RECV | state;
state = START;
data = 0;
parity = 1;
}
last_time = timer_read();
switch (state) {
case START:
if (ibmpc_protocol == IBMPC_PROTOCOL_XT) {
// ignore start(0) bit
if (!data_in()) return;
} else {
if (data_in())
goto ERROR;
}
case BIT0:
case BIT1:
case BIT2:
case BIT3:
case BIT4:
case BIT5:
case BIT6:
case BIT7:
data >>= 1;
if (data_in()) {
data |= 0x80;
parity++;
}
if (state == BIT7 && ibmpc_protocol == IBMPC_PROTOCOL_XT) {
if (!ringbuf_put(&rb, data)) {
ibmpc_error = IBMPC_ERR_FULL;
goto ERROR;
}
ibmpc_error = IBMPC_ERR_NONE;
goto DONE;
}
break;
case PARITY:
if (data_in()) {
if (!(parity & 0x01))
goto ERROR;
} else {
if (parity & 0x01)
goto ERROR;
}
break;
case STOP:
if (!data_in())
goto ERROR;
if (!ringbuf_put(&rb, data)) {
ibmpc_error = IBMPC_ERR_FULL;
goto ERROR;
}
ibmpc_error = IBMPC_ERR_NONE;
goto DONE;
break;
default:
goto ERROR;
}
goto NEXT;
ERROR:
ibmpc_error |= state;
ibmpc_error |= IBMPC_ERR_RECV;
ringbuf_reset(&rb);
DONE:
last_time = 0;
state = START;
data = 0;
parity = 1;
return;
NEXT:
state++;
return;
}
/* send LED state to keyboard */
void ibmpc_host_set_led(uint8_t led)
{
ibmpc_host_send(0xED);
ibmpc_host_send(led);
}

199
tmk_core/protocol/ibmpc.h Normal file
View file

@ -0,0 +1,199 @@
/*
Copyright 2010,2011,2012,2013,2019 Jun WAKO <wakojun@gmail.com>
This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
GPL-compatible, and OK to use in both free and proprietary applications.
Additions and corrections to this file are welcome.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IBMPC_H
#define IBMPC_H
#include <stdbool.h>
#include "wait.h"
#include "print.h"
/*
* IBM PC keyboard protocol
*
* PS/2 Resources
* --------------
* [1] The PS/2 Mouse/Keyboard Protocol
* http://www.computer-engineering.org/ps2protocol/
* Concise and thorough primer of PS/2 protocol.
*
* [2] Keyboard and Auxiliary Device Controller
* http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
* Signal Timing and Format
*
* [3] Keyboards(101- and 102-key)
* http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
* Keyboard Layout, Scan Code Set, POR, and Commands.
*
* [4] PS/2 Reference Manuals
* http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
* Collection of IBM Personal System/2 documents.
*
* [5] TrackPoint Engineering Specifications for version 3E
* https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
*/
#define IBMPC_ACK 0xFA
#define IBMPC_RESEND 0xFE
#define IBMPC_SET_LED 0xED
#define IBMPC_PROTOCOL_AT 0
#define IBMPC_PROTOCOL_XT 1
// TODO: error numbers
#define IBMPC_ERR_NONE 0
#define IBMPC_ERR_RECV 0x00
#define IBMPC_ERR_SEND 0x10
#define IBMPC_ERR_TIMEOUT 0x20
#define IBMPC_ERR_FULL 0x40
#define IBMPC_LED_SCROLL_LOCK 0
#define IBMPC_LED_NUM_LOCK 1
#define IBMPC_LED_CAPS_LOCK 2
extern volatile uint8_t ibmpc_protocol;
extern volatile uint8_t ibmpc_error;
void ibmpc_host_init(void);
int16_t ibmpc_host_send(uint8_t data);
int16_t ibmpc_host_recv_response(void);
int16_t ibmpc_host_recv(void);
void ibmpc_host_set_led(uint8_t usb_led);
/*--------------------------------------------------------------------
* static functions
*------------------------------------------------------------------*/
#if defined(__AVR__)
/*
* Clock
*/
static inline void clock_init(void)
{
IBMPC_CLOCK_PORT &= ~(1<<IBMPC_CLOCK_BIT);
IBMPC_CLOCK_DDR |= (1<<IBMPC_CLOCK_BIT);
}
static inline void clock_lo(void)
{
IBMPC_CLOCK_PORT &= ~(1<<IBMPC_CLOCK_BIT);
IBMPC_CLOCK_DDR |= (1<<IBMPC_CLOCK_BIT);
}
static inline void clock_hi(void)
{
/* input with pull up */
IBMPC_CLOCK_DDR &= ~(1<<IBMPC_CLOCK_BIT);
IBMPC_CLOCK_PORT |= (1<<IBMPC_CLOCK_BIT);
}
static inline bool clock_in(void)
{
IBMPC_CLOCK_DDR &= ~(1<<IBMPC_CLOCK_BIT);
IBMPC_CLOCK_PORT |= (1<<IBMPC_CLOCK_BIT);
wait_us(1);
return IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT);
}
/*
* Data
*/
static inline void data_init(void)
{
IBMPC_DATA_DDR &= ~(1<<IBMPC_DATA_BIT);
IBMPC_DATA_PORT |= (1<<IBMPC_DATA_BIT);
}
static inline void data_lo(void)
{
IBMPC_DATA_PORT &= ~(1<<IBMPC_DATA_BIT);
IBMPC_DATA_DDR |= (1<<IBMPC_DATA_BIT);
}
static inline void data_hi(void)
{
/* input with pull up */
IBMPC_DATA_DDR &= ~(1<<IBMPC_DATA_BIT);
IBMPC_DATA_PORT |= (1<<IBMPC_DATA_BIT);
}
static inline bool data_in(void)
{
IBMPC_DATA_DDR &= ~(1<<IBMPC_DATA_BIT);
IBMPC_DATA_PORT |= (1<<IBMPC_DATA_BIT);
wait_us(1);
return IBMPC_DATA_PIN&(1<<IBMPC_DATA_BIT);
}
#endif
static inline uint16_t wait_clock_lo(uint16_t us)
{
while (clock_in() && us) { asm(""); wait_us(1); us--; }
return us;
}
static inline uint16_t wait_clock_hi(uint16_t us)
{
while (!clock_in() && us) { asm(""); wait_us(1); us--; }
return us;
}
static inline uint16_t wait_data_lo(uint16_t us)
{
while (data_in() && us) { asm(""); wait_us(1); us--; }
return us;
}
static inline uint16_t wait_data_hi(uint16_t us)
{
while (!data_in() && us) { asm(""); wait_us(1); us--; }
return us;
}
/* idle state that device can send */
static inline void idle(void)
{
clock_hi();
data_hi();
}
/* inhibit device to send */
static inline void inhibit(void)
{
clock_lo();
data_hi();
}
#endif

View file

@ -49,7 +49,20 @@ OPT_DEFS += $(LUFA_OPTS)
# This indicates using LUFA stack
OPT_DEFS += -DPROTOCOL_LUFA
ifeq (yes,$(strip $(LUFA_DEBUG)))
LUFA_OPTS += -DLUFA_DEBUG
endif
ifeq (yes,$(strip $(LUFA_DEBUG_SUART)))
SRC += common/avr/suart.S
LUFA_OPTS += -DLUFA_DEBUG_SUART
# Keep print/debug lines when disabling HID console. See common.mk.
DEBUG_PRINT_AVAILABLE = yes
endif
ifeq (yes,$(strip $(LUFA_DEBUG_UART)))
SRC += common/avr/uart.c
LUFA_OPTS += -DLUFA_DEBUG_UART
# Keep print/debug lines when disabling HID console. See common.mk.
DEBUG_PRINT_AVAILABLE = yes
endif

View file

@ -56,6 +56,10 @@
#include "avr/suart.h"
#endif
#ifdef LUFA_DEBUG_UART
#include "uart.h"
#endif
#include "matrix.h"
#include "descriptor.h"
#include "lufa.h"
@ -218,7 +222,9 @@ static void console_task(void)
*/
void EVENT_USB_Device_Connect(void)
{
#ifdef LUFA_DEBUG
print("[C]");
#endif
/* For battery powered device */
if (!USB_IsInitialized) {
USB_Disable();
@ -229,7 +235,9 @@ void EVENT_USB_Device_Connect(void)
void EVENT_USB_Device_Disconnect(void)
{
#ifdef LUFA_DEBUG
print("[D]");
#endif
/* For battery powered device */
USB_IsInitialized = false;
/* TODO: This doesn't work. After several plug in/outs can not be enumerated.
@ -575,25 +583,22 @@ static void send_consumer(uint16_t data)
/*******************************************************************************
* sendchar
******************************************************************************/
#ifdef CONSOLE_ENABLE
int8_t sendchar(uint8_t c)
{
#ifdef LUFA_DEBUG_SUART
xmit(c);
#endif
bool r = console_putc(c);
return (r ? 0 : -1);
}
#else
int8_t sendchar(uint8_t c)
{
#ifdef LUFA_DEBUG_SUART
xmit(c);
#ifdef LUFA_DEBUG_UART
uart_putchar(c);
#endif
#ifdef CONSOLE_ENABLE
console_putc(c);
#endif
return 0;
}
#endif
/*******************************************************************************
@ -629,11 +634,15 @@ int main(void)
SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
#endif
#ifdef LUFA_DEBUG_UART
uart_init(115200);
#endif
// setup sendchar: DO NOT USE print functions before this line
print_set_sendchar(sendchar);
host_set_driver(&lufa_driver);
print("Keyboard init.\n");
print("\n\nTMK:" STR(TMK_VERSION) "/LUFA\n\n");
hook_early_init();
keyboard_setup();
setup_usb();
@ -645,6 +654,7 @@ int main(void)
keyboard_init();
#ifndef NO_USB_STARTUP_WAIT_LOOP
/* wait for USB startup */
while (USB_DeviceState != DEVICE_STATE_Configured) {
#if defined(INTERRUPT_CONTROL_ENDPOINT)
@ -652,19 +662,20 @@ int main(void)
#else
USB_USBTask();
#endif
matrix_scan();
hook_usb_startup_wait_loop();
}
print("\nUSB configured.\n");
#endif
hook_late_init();
print("\nKeyboard start.\n");
while (1) {
#ifndef NO_USB_SUSPEND_LOOP
while (USB_DeviceState == DEVICE_STATE_Suspended) {
#ifdef LUFA_DEBUG
print("[s]");
#endif
hook_usb_suspend_loop();
}
#endif
keyboard_task();
@ -690,12 +701,12 @@ static uint8_t _led_stats = 0;
__attribute__((weak))
void hook_usb_suspend_entry(void)
{
// Turn LED off to save power
// Set 0 with putting aside status before suspend and restore
// it after wakeup, then LED is updated at keyboard_task() in main loop
// Turn off LED to save power and keep its status to resotre it later.
// LED status will be updated by keyboard_task() in main loop hopefully.
_led_stats = keyboard_led_stats;
keyboard_led_stats = 0;
led_set(keyboard_led_stats);
// Calling long task here can prevent USB state transition
matrix_clear();
clear_keyboard();
@ -707,7 +718,10 @@ void hook_usb_suspend_entry(void)
__attribute__((weak))
void hook_usb_suspend_loop(void)
{
#ifndef LUFA_DEBUG_UART
// This corrupts debug print when suspend
suspend_power_down();
#endif
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
USB_Device_SendRemoteWakeup();
}
@ -721,10 +735,11 @@ void hook_usb_wakeup(void)
sleep_led_disable();
#endif
// Restore LED status
// BIOS/grub won't recognize/enumerate if led_set() takes long(around 40ms?)
// Converters fall into the case and miss wakeup event(timeout to reply?) in the end.
//led_set(host_keyboard_leds());
// Instead, restore stats and update at keyboard_task() in main loop
// Restore LED status and update at keyboard_task() in main loop
keyboard_led_stats = _led_stats;
// Calling long task here can prevent USB state transition
}
__attribute__((weak))
void hook_usb_startup_wait_loop(void) {}

View file

@ -4,7 +4,7 @@ USB_HID_DIR = protocol/usb_hid
#
# USB Host Shield
#
USB_HOST_SHIELD_DIR = $(USB_HID_DIR)/USB_Host_Shield_2.0-git
USB_HOST_SHIELD_DIR = $(USB_HID_DIR)/USB_Host_Shield_2.0-tmk
USB_HOST_SHIELD_SRC = \
$(USB_HOST_SHIELD_DIR)/Usb.cpp \
$(USB_HOST_SHIELD_DIR)/usbhid.cpp \

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

@ -0,0 +1 @@
Subproject commit 48b2a0950496c7b8ba1bb6ddb937b6f00a6de781

View file

@ -1,21 +1,24 @@
#include "parser.h"
#include "usb_hid.h"
#include "debug.h"
#include "print.h"
void KBDReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
{
dprintf("input %d:", hid->GetAddress());
xprintf("input %d:", hid->GetAddress());
for (uint8_t i = 0; i < len; i++) {
dprintf(" %02X", buf[i]);
xprintf(" %02X", buf[i]);
}
dprint("\r\n");
xprintf("\r\n");
// ignore Cherry 0101010101010101 bug report
// Rollover error
// Cherry: 0101010101010101
// https://geekhack.org/index.php?topic=69169.msg2638223#msg2638223
if (buf[1] == 0x01) {
dprint("Cherry bug: ignored\r\n");
// Apple: 0000010101010101
// https://geekhack.org/index.php?topic=69169.msg2760969#msg2760969
if (buf[2] == 0x01) {
xprintf("Rollover error: ignored\r\n");
return;
}