Merge remote-tracking branch 'tmk/master'
This commit is contained in:
commit
c9659f3048
48 changed files with 14033 additions and 14737 deletions
220
README.md
220
README.md
|
|
@ -1,80 +1,16 @@
|
|||
TMK Keyboard Firmware Collection
|
||||
================================
|
||||
This repository includes keyboard and converter firmware projects built with [`tmk_core`][tmk_core] keyboard library.
|
||||
This repository includes keyboard and converter firmware projects built with [`tmk_core`](https://github.com/tmk/tmk_core) keyboard library.
|
||||
|
||||
The latest source code is available here: <http://github.com/tmk/tmk_keyboard>
|
||||
|
||||
|
||||
Updates
|
||||
-------
|
||||
#### 2017/01/11
|
||||
Changed action code for `ACTION_LAYER_MODS` and this may cause incompatibility with existent shared URL and downloaded firmwware of keymap editor. If you are using the action you just have to redefine it on keymap editor. Existent keymap code should not suffer.
|
||||
|
||||
#### 2016/06/26
|
||||
Keymap framework was updated. `fn_actions[]` should be defined as `action_t` instead of `uint16_t`. And default code for keymap handling is now included in core you just need define `uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS]` and `action_t fn_actions[]`.
|
||||
Documentation
|
||||
-------------
|
||||
Refer to wiki pages for further info.
|
||||
|
||||
|
||||
#### 2016/06/22
|
||||
Some projects were moved from `converter` and `keyboard` to `orphan` directory. Those might be removed in some future but you will be able to access them with `orphans` tag. See <https://github.com/tmk/tmk_keyboard/issues/173>
|
||||
|
||||
#### 2016/02/10
|
||||
core: flabbergast's Chibios protocol was merged from <https://github.com/flabbergast/tmk_keyboard/tree/chibios> (@72b1668). See [tmk_core/protocol/chibios/README.md](tmk_core/protocol/chibios/README.md). Chibios protocol supports Cortex-M such as STM32 and Kinetis.
|
||||
|
||||
#### 2015/04/22
|
||||
Core library was separated to other branch `core`. <https://github.com/tmk/tmk_keyboard/tree/core>
|
||||
|
||||
In `Makefile` you need to set `TMK_DIR` to indicate core library location now.
|
||||
|
||||
TMK_DIR = ../../tmk_core
|
||||
|
||||
|
||||
|
||||
Projects
|
||||
--------
|
||||
You can find some keyboard specific projects under `converter` and `keyboard` directory.
|
||||
|
||||
### converter
|
||||
* [ps2_usb](converter/ps2_usb/) - [PS/2 keyboard to USB][GH_ps2]
|
||||
* [adb_usb](converter/adb_usb/) - [ADB keyboard to USB][GH_adb]
|
||||
* [m0110_usb](converter/m0110_usb) - [Macintosh 128K/512K/Plus keyboard to USB][GH_m0110]
|
||||
* [terminal_usb](converter/terminal_usb/) - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
|
||||
* [news_usb](converter/news_usb/) - [Sony NEWS keyboard to USB][GH_news]
|
||||
* [x68k_usb](converter/x68k_usb/) - [Sharp X68000 keyboard to USB][GH_x68k]
|
||||
* [sun_usb](converter/sun_usb/) - [Sun] to USB(type4, 5 and 3?)
|
||||
* [pc98_usb](converter/pc98_usb/) - [PC98] to USB
|
||||
* [usb_usb](converter/usb_usb/) - [USB to USB][GH_usb]
|
||||
* [ibm4704_usb](converter/ibm4704_usb) - [IBM 4704 keyboard to USB][GH_ibm4704]
|
||||
* [next_usb](converter/next_usb) - NeXT(Non-ADB) to USB, contributed by [BCG](https://github.com/bgould) and based on [Adafruit's work](https://learn.adafruit.com/usb-next-keyboard-with-arduino-micro/overview)
|
||||
|
||||
### keyboard
|
||||
* [hhkb](keyboard/hhkb/) - [Happy Hacking Keyboard pro][GH_hhkb] **my main board**
|
||||
* [alps64](keyboard/alps64/) - [Alps64 PCB](https://geekhack.org/index.php?topic=69740.0)
|
||||
* [hbkb](keyboard/hbkb/) - [Happy Buckling spring keyboard][GH_hbkb](IBM Model M 60% mod)
|
||||
* [Infinity](keyboard/infinity/) - Massdrop [Infinity keyboard][Infinity]
|
||||
* [gh60](keyboard/gh60/) - [GH60] DIY 60% keyboard [prototype][GH60_proto] **my second board**
|
||||
* [onekey](keyboard/onekey/) - Simple one key keyboard example
|
||||
|
||||
|
||||
### Projects based tmk_keyboard or tmk_core
|
||||
https://github.com/tmk/tmk_keyboard/wiki/TMK-Based-Projects
|
||||
|
||||
|
||||
[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047
|
||||
[GH_ps2]: http://geekhack.org/showwiki.php?title=Island:14618
|
||||
[GH_adb]: http://geekhack.org/showwiki.php?title=Island:14290
|
||||
[GH_hhkb_bt]: http://geekhack.org/showwiki.php?title=Island:20851
|
||||
[GH_m0110]: http://geekhack.org/showwiki.php?title=Island:24965
|
||||
[GH_news]: http://geekhack.org/showwiki.php?title=Island:25759
|
||||
[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272
|
||||
[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060
|
||||
[GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483
|
||||
[GH_ibm4704]: http://geekhack.org/index.php?topic=54706.0
|
||||
[GH60]: http://geekhack.org/index.php?topic=34959
|
||||
[GH60_proto]: http://geekhack.org/index.php?topic=37570.0
|
||||
[PC98]: http://en.wikipedia.org/wiki/NEC_PC-9801
|
||||
[Sun]: http://en.wikipedia.org/wiki/Sun-3
|
||||
[Infinity]: https://www.massdrop.com/buy/infinity-keyboard-kit
|
||||
[tmk_core]: https://github.com/tmk/tmk_core
|
||||
https://github.com/tmk/tmk_keyboard/wiki
|
||||
|
||||
|
||||
|
||||
|
|
@ -83,149 +19,3 @@ License
|
|||
**GPLv2** or later. Some protocol files are under **Modified BSD License**.
|
||||
|
||||
Third party libraries like LUFA, PJRC and V-USB have their own license respectively.
|
||||
|
||||
|
||||
|
||||
Build Firmware and Program Controller
|
||||
-------------------------------------
|
||||
See [tmk_core/doc/build.md](tmk_core/doc/build.md).
|
||||
|
||||
|
||||
|
||||
Change your keymap
|
||||
------------------
|
||||
See [tmk_core/doc/keymap.md](tmk_core/doc/keymap.md).
|
||||
|
||||
|
||||
|
||||
Magic Commands
|
||||
--------------
|
||||
To see help press `Magic` + `H`.
|
||||
|
||||
`Magic` key combination is `LShift` + `RShift` in many projects, but `Power` key on ADB converter.
|
||||
`Magic` keybind can be vary on each project, check `config.h` in project directory.
|
||||
|
||||
Following commands can be also executed with `Magic` + key. In console mode `Magic` keybind is not needed.
|
||||
|
||||
----- Command Help -----
|
||||
c: enter console mode
|
||||
d: toggle debug enable
|
||||
x: toggle matrix debug
|
||||
k: toggle keyboard debug
|
||||
m: toggle mouse debug
|
||||
v: print device version & info
|
||||
t: print timer count
|
||||
s: print status
|
||||
e: print eeprom config
|
||||
n: toggle NKRO
|
||||
0/F10: switch to Layer0
|
||||
1/F1: switch to Layer1
|
||||
2/F2: switch to Layer2
|
||||
3/F3: switch to Layer3
|
||||
4/F4: switch to Layer4
|
||||
PScr: power down/remote wake-up
|
||||
Caps: Lock Keyboard(Child Proof)
|
||||
Paus: jump to bootloader
|
||||
|
||||
|
||||
|
||||
Boot Magic Configuration - Virtual DIP Switch
|
||||
---------------------------------------------
|
||||
Boot Magic are executed during boot up time. Press Magic key below then plug in keyboard cable.
|
||||
Note that you must use keys of **Layer 0** as Magic keys. These settings are stored in EEPROM so that retain your configure over power cycles.
|
||||
|
||||
To avoid configuring accidentally additive salt key `KC_SPACE` also needs to be pressed along with the following configuration keys. The salt key is configurable in `config.h`. See [tmk_core/common/bootmagic.h](tmk_core/common/bootmagic.h).
|
||||
|
||||
#### General
|
||||
- Skip reading EEPROM to start with default configuration(`ESC`)
|
||||
- Clear configuration stored in EEPROM to reset configuration(`Backspace`)
|
||||
|
||||
#### Bootloader
|
||||
- Kick up Bootloader(`B`)
|
||||
|
||||
#### Debug
|
||||
- Debug enable(`D`)
|
||||
- Debug matrix enable(`D`+`X`)
|
||||
- Debug keyboard enable(`D`+`K`)
|
||||
- Debug mouse enable(`D`+`M`)
|
||||
|
||||
#### Keymap
|
||||
- Swap Control and CapsLock(`Left Control`)
|
||||
- Change CapsLock to Control(`Caps Lock`)
|
||||
- Swap LeftAlt and Gui(`Left Alt`)
|
||||
- Swap RightAlt and Gui(`Right Alt`)
|
||||
- Disable Gui(`Left Gui`)
|
||||
- Swap Grave and Escape(`Grave`)
|
||||
- Swap BackSlash and BackSpace(`Back Slash`)
|
||||
- Enable NKRO on boot(`N`)
|
||||
|
||||
#### Default Layer
|
||||
- Set Default Layer to 0(`0`)
|
||||
- Set Default Layer to 1(`1`)
|
||||
- Set Default Layer to 2(`2`)
|
||||
- Set Default Layer to 3(`3`)
|
||||
- Set Default Layer to 4(`4`)
|
||||
- Set Default Layer to 5(`5`)
|
||||
- Set Default Layer to 6(`6`)
|
||||
- Set Default Layer to 7(`7`)
|
||||
|
||||
|
||||
|
||||
Mechanical Locking support
|
||||
--------------------------
|
||||
This feature makes it possible for you to use mechanical locking switch for `CapsLock`, `NumLock`
|
||||
or `ScrollLock`. To enable this feature define these macros in `config.h` and use `KC_LCAP`, `KC_LN
|
||||
UM` or `KC_LSCR` in keymap for locking key instead of normal `KC_CAPS`, `KC_NLCK` or `KC_SLCK`. Res
|
||||
ync option tries to keep switch state consistent with keyboard LED state.
|
||||
|
||||
#define LOCKING_SUPPORT_ENABLE
|
||||
#define LOCKING_RESYNC_ENABLE
|
||||
|
||||
|
||||
|
||||
Start Your Own Project
|
||||
-----------------------
|
||||
1. Add `tmk_core` into your repository using `git submodule` or `git subtree`.
|
||||
2. Copy files from `tmk_keybaord` or other project similar to yours
|
||||
3. Edit those files to support your keyboard.
|
||||
|
||||
See these as examples.
|
||||
- https://github.com/tmk/infinity_ergodox
|
||||
- https://github.com/tmk/whitefox
|
||||
|
||||
|
||||
|
||||
Debugging
|
||||
--------
|
||||
Use PJRC's `hid_listen` to see debug messages. You can use xprintf() to display debug info, see `tmk_core/common/xprintf.h`.
|
||||
|
||||
- https://www.pjrc.com/teensy/hid_listen.html
|
||||
|
||||
|
||||
|
||||
Files and Directories
|
||||
-------------------
|
||||
### Top
|
||||
* keyboard/ - keyboard projects
|
||||
* converter/ - protocol converter projects
|
||||
* tmk_core/ - core library
|
||||
* tmk_core/doc/ - documents
|
||||
|
||||
|
||||
|
||||
Contribution
|
||||
------------
|
||||
- Report bugs in github **[Issues](https://github.com/tmk/tmk_keyboard/issues)**.
|
||||
- Pull requets are also welcomed.
|
||||
|
||||
|
||||
|
||||
Coding Style
|
||||
-------------
|
||||
- Doesn't use Tab to indent, use 4-spaces instead.
|
||||
|
||||
|
||||
|
||||
Other Keyboard Firmware Projects
|
||||
------------------
|
||||
You can learn a lot about keyboard firmware from these. See [Other Projects](https://github.com/tmk/tmk_keyboard/wiki/Other-Protjects) other than TMK.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -41,7 +41,7 @@ static bool is_iso_layout = false;
|
|||
#if ADB_MOUSE_ENABLE
|
||||
#define dmprintf(fmt, ...) do { /* if (debug_mouse) */ xprintf("M:" fmt, ##__VA_ARGS__); } while (0)
|
||||
static uint16_t mouse_cpi = 100;
|
||||
static void mouse_init(uint8_t addr);
|
||||
static void mouse_init(void);
|
||||
#endif
|
||||
|
||||
// matrix state buffer(1:on, 0:off)
|
||||
|
|
@ -58,6 +58,65 @@ static void device_scan(void)
|
|||
xprintf(" addr:%d, reg3:%04X\n", addr, reg3);
|
||||
}
|
||||
}
|
||||
xprintf("\n");
|
||||
}
|
||||
|
||||
static void keyboard_init(void)
|
||||
{
|
||||
uint16_t reg3;
|
||||
uint8_t handler;
|
||||
|
||||
// Check if there is keyboard at default address
|
||||
reg3 = adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_3);
|
||||
if (!reg3) return;
|
||||
if (reg3) {
|
||||
xprintf("K:found: addr:" xstr(ADB_ADDR_KEYBOARD) " reg3:%04X\n", reg3);
|
||||
adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_KBD_TMP, 0xFE);
|
||||
}
|
||||
|
||||
// Check if there is device to setup at temporary address
|
||||
reg3 = adb_host_talk(ADB_ADDR_KBD_TMP, ADB_REG_3);
|
||||
if (!reg3) {
|
||||
xprintf("K:fail: move\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine ISO keyboard by handler id
|
||||
// http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L815
|
||||
handler = reg3 & 0xFF;
|
||||
switch (handler) {
|
||||
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
|
||||
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
|
||||
case 0xC4: case 0xC7:
|
||||
is_iso_layout = true;
|
||||
break;
|
||||
default:
|
||||
is_iso_layout = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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("K: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_KBD_TMP, ADB_REG_3, ADB_ADDR_KBD_TMP, ADB_HANDLER_EXTENDED_KEYBOARD);
|
||||
reg3 = adb_host_talk(ADB_ADDR_KBD_TMP, ADB_REG_3);
|
||||
|
||||
adb_host_kbd_led(ADB_ADDR_KBD_TMP, ~(host_keyboard_leds()));
|
||||
|
||||
// Move to keyboard polling address
|
||||
adb_host_listen(ADB_ADDR_KBD_TMP, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_KBD_POLL, 0xFE);
|
||||
if (adb_host_talk(ADB_ADDR_KBD_TMP, ADB_REG_3)) {
|
||||
xprintf("K:fail: move\n");
|
||||
}
|
||||
xprintf("K:setup: addr:" xstr(ADB_ADDR_KBD_POLL) " reg3:%04X, ISO:%s\n",
|
||||
reg3, (is_iso_layout ? "yes" : "no"));
|
||||
}
|
||||
|
||||
void matrix_init(void)
|
||||
|
|
@ -81,106 +140,69 @@ void matrix_init(void)
|
|||
// M0115J(AEK), M3501(AEKII), M0116(Standard), M1242(Adjustable),
|
||||
// G5431(Mouse), 64210(Kensington Trubo Mouse 5)
|
||||
wait_ms(1000);
|
||||
|
||||
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);
|
||||
switch (handler_id) {
|
||||
case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
|
||||
case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
|
||||
case 0xC4: case 0xC7:
|
||||
is_iso_layout = true;
|
||||
break;
|
||||
default:
|
||||
is_iso_layout = false;
|
||||
break;
|
||||
}
|
||||
xprintf("handler: %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("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_KEYBOARD);
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
|
||||
|
||||
led_set(host_keyboard_leds());
|
||||
|
||||
device_scan();
|
||||
|
||||
// LED off
|
||||
DDRD |= (1<<6); PORTD &= ~(1<<6);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ADB_MOUSE_ENABLE
|
||||
static void mouse_init(uint8_t orig_addr)
|
||||
static void mouse_init(void)
|
||||
{
|
||||
uint16_t reg3;
|
||||
uint8_t mouse_handler;
|
||||
uint8_t addr;
|
||||
|
||||
again:
|
||||
// Move to tmp address 15 to setup mouse function
|
||||
mouse_handler = (reg3 = adb_host_talk(orig_addr, ADB_REG_3)) & 0xFF;
|
||||
if (!reg3) return;
|
||||
dmprintf("addr%d reg3: %04X\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;
|
||||
// Check if there is mouse device at default address 3
|
||||
reg3 = adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_3);
|
||||
if (reg3) {
|
||||
// Move device to tmp address
|
||||
// Collision detection can fail sometimes in fact when two devices are connected on startup
|
||||
// and the devices can be moved to tmp address at same time in the result. In that case
|
||||
// initialization of mouse can fail. To recover this you may have to replug mouse or converter.
|
||||
// It is safe to have just one mouse device, but more than one device can be handled somehow.
|
||||
adb_host_flush(ADB_ADDR_MOUSE);
|
||||
adb_host_listen(ADB_ADDR_MOUSE, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_MOUSE_TMP, 0xFE);
|
||||
adb_host_flush(ADB_ADDR_MOUSE_TMP);
|
||||
}
|
||||
addr = ADB_ADDR_TMP;
|
||||
|
||||
// Check if there is mouse device to setup at temporary address 15
|
||||
mouse_handler = (reg3 = adb_host_talk(ADB_ADDR_MOUSE_TMP, ADB_REG_3)) & 0xFF;
|
||||
if (!reg3) {
|
||||
return;
|
||||
}
|
||||
dmprintf("TMP: reg3:%04X\n", reg3);
|
||||
|
||||
|
||||
detect_again:
|
||||
// Try to escalate into extended/classic2 protocol
|
||||
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;
|
||||
|
||||
adb_host_flush(ADB_ADDR_MOUSE_TMP);
|
||||
adb_host_listen(ADB_ADDR_MOUSE_TMP, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_EXTENDED_MOUSE);
|
||||
mouse_handler = (reg3 = adb_host_talk(ADB_ADDR_MOUSE_TMP, 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;
|
||||
adb_host_flush(ADB_ADDR_MOUSE_TMP);
|
||||
adb_host_listen(ADB_ADDR_MOUSE_TMP, ADB_REG_3, (reg3 >> 8), ADB_HANDLER_CLASSIC2_MOUSE);
|
||||
mouse_handler = (reg3 = adb_host_talk(ADB_ADDR_MOUSE_TMP, ADB_REG_3)) & 0xFF;
|
||||
}
|
||||
dmprintf("addr%d reg3: %04X\n", addr, reg3);
|
||||
|
||||
dmprintf("EXT: reg3:%04X\n", reg3);
|
||||
}
|
||||
|
||||
// Classic Protocol 100cpi
|
||||
if (mouse_handler == ADB_HANDLER_CLASSIC1_MOUSE) {
|
||||
xprintf("Classic 100cpi\n");
|
||||
dmprintf("Classic 100cpi\n");
|
||||
mouse_cpi = 100;
|
||||
}
|
||||
|
||||
// Classic Protocol 200cpi
|
||||
if (mouse_handler == ADB_HANDLER_CLASSIC2_MOUSE) {
|
||||
xprintf("Classic 200cpi\n");
|
||||
dmprintf("Classic 200cpi\n");
|
||||
mouse_cpi = 200;
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +215,7 @@ detect_again:
|
|||
// 7 : num of buttons
|
||||
uint8_t len;
|
||||
uint8_t buf[8];
|
||||
len = adb_host_talk_buf(addr, ADB_REG_1, buf, sizeof(buf));
|
||||
len = adb_host_talk_buf(ADB_ADDR_MOUSE_TMP, ADB_REG_1, buf, sizeof(buf));
|
||||
|
||||
if (len > 5) {
|
||||
mouse_cpi = (buf[4]<<8) | buf[5];
|
||||
|
|
@ -202,15 +224,13 @@ detect_again:
|
|||
}
|
||||
|
||||
if (len) {
|
||||
xprintf("Ext: [", len);
|
||||
for (int8_t i = 0; i < len; i++) xprintf("%02X ", buf[i]);
|
||||
xprintf("] cpi=%d\n", mouse_cpi);
|
||||
dmprintf("EXT: [%02X %02X %02X %02X %02X %02X %02X %02X] cpi=%d\n",
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], 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");
|
||||
dmprintf("TM5: found\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.
|
||||
//
|
||||
|
|
@ -219,77 +239,77 @@ detect_again:
|
|||
// 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);
|
||||
adb_host_flush(ADB_ADDR_MOUSE_TMP);
|
||||
adb_host_listen(ADB_ADDR_MOUSE_TMP, ADB_REG_3, ((reg3 >> 8) & 0xF0) | ADB_ADDR_0, 0xFE);
|
||||
goto again;
|
||||
} else {
|
||||
xprintf("Unknown\n");
|
||||
dmprintf("Unknown\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Kensington Turbo Mouse 5: setup
|
||||
if (mouse_handler == ADB_HANDLER_TURBO_MOUSE) {
|
||||
xprintf("TM5: ext\n");
|
||||
xprintf("TM5: setup\n");
|
||||
|
||||
/* byte0: speed
|
||||
* 0xa0, 0xa5, 0xb0 and 0xb5 seem to work
|
||||
* uppper nibble:
|
||||
* 0x00-70, 0xc0-f0 no movement and button event
|
||||
* 0x80 enables mouse output speed slow
|
||||
* 0x90 enables mouse output
|
||||
* 0xa0 enables mouse output
|
||||
* 0xb0 enables mouse output speed fast -126 to 126
|
||||
* lower nibble:
|
||||
* 0x08 makes cursor not smooth, bit4 should be 0
|
||||
* 0x02 disables button4, bit1 should be 0
|
||||
* how other bits work is not clear.
|
||||
* byte1: button mapping - upper nibble for button1 and lower for button2
|
||||
* 0x14 button1 and button2 mapped as themselves
|
||||
* 0x0 disabled
|
||||
* 0x1 button1
|
||||
* 0x2 button1 toggle
|
||||
* 0x3 no effect key event FFFF
|
||||
* 0x4 button2
|
||||
* 0x5 button2 toggle
|
||||
* 0x6 button3
|
||||
* 0x7 button3 toggle
|
||||
* 0x8 ?toggle weirdly?
|
||||
* 0x9 button4
|
||||
* 0xa button4 toggle
|
||||
* 0xb ?disabled?
|
||||
* 0xc Left
|
||||
* 0xd Right
|
||||
* 0xe Alt+Left
|
||||
* 0xf Alt+Right
|
||||
/* byte0: 0xb5 speed - 0xa0, 0xa5, 0xb0 and 0xb5 seem to work
|
||||
* uppper nibble:
|
||||
* 0x00-70, 0xc0-f0 no movement and button event
|
||||
* 0x80 enables mouse output speed slow
|
||||
* 0x90 enables mouse output
|
||||
* 0xa0 enables mouse output
|
||||
* 0xb0 enables mouse output speed fast -126 to 126
|
||||
* lower nibble:
|
||||
* 0x08 makes cursor not smooth, bit3 should be 0
|
||||
* 0x02 disables button4, bit1 should be 0
|
||||
* how other bits work is not clear.
|
||||
* byte1: 0x14 button mapping - upper nibble for button1 and lower for button2
|
||||
* button1 and button2 mapped as themselves
|
||||
* 0x0 disabled
|
||||
* 0x1 button1
|
||||
* 0x2 button1 toggle
|
||||
* 0x3 no effect key event FFFF
|
||||
* 0x4 button2
|
||||
* 0x5 button2 toggle
|
||||
* 0x6 button3
|
||||
* 0x7 button3 toggle
|
||||
* 0x8 ?toggle weirdly?
|
||||
* 0x9 button4
|
||||
* 0xa button4 toggle
|
||||
* 0xb ?disabled?
|
||||
* 0xc Left
|
||||
* 0xd Right
|
||||
* 0xe Alt+Left
|
||||
* 0xf Alt+Right
|
||||
* byte2: 0x00 - 0x40 on powerup, seems to do nothing
|
||||
* byte3: 0x00 - 0x01 on powerup, seems to do nothing
|
||||
* byte4: button mapping - upper nibble for button3 and lower for button4
|
||||
* 0x69 button3 and button4 mapped as themselves(see byte1)
|
||||
* byte4: 0x69 button mapping - upper nibble for button3 and lower for button4
|
||||
* button3 and button4 mapped as themselves(see byte1)
|
||||
* byte5: 0xff unknown
|
||||
* byte6: 0xff unknown
|
||||
* byte7: 0xff checksum - must be 0xff before calculating
|
||||
* byte7: 0x?? checksum
|
||||
* byte7 = byte0 ^ byte1 ^ byte2 ^ byte3 ^ byte4 ^ byte5 ^ byte6 ^ 0xFF;
|
||||
* https://github.com/NetBSD/src/blob/8966d5b1cf335756dd9bba3331e84c659bf917e1/sys/dev/adb/adb_ktm.c#L181
|
||||
*/
|
||||
//static uint8_t cmd[] = { 0xA5, 0x14, 0x00, 0x00, 0x69, 0xFF, 0xFF, 0xFF };
|
||||
static uint8_t cmd[] = { 0xB5, 0x14, 0x00, 0x00, 0x69, 0xFF, 0xFF, 0xFF };
|
||||
cmd[7] = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5] ^ cmd[6] ^ cmd[7];
|
||||
|
||||
adb_host_flush(addr);
|
||||
adb_host_listen_buf(addr, ADB_REG_2, cmd, sizeof(cmd));
|
||||
uint8_t cmd[] = { 0xB5, 0x14, 0x00, 0x00, 0x69, 0xFF, 0xFF, 0x37 };
|
||||
// cmd[7] = cmd[0] ^ cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5] ^ cmd[6] ^ 0xFF;
|
||||
adb_host_flush(ADB_ADDR_MOUSE_TMP);
|
||||
adb_host_listen_buf(ADB_ADDR_MOUSE_TMP, ADB_REG_2, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
|
||||
// Move to address 10 for mouse polling
|
||||
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_TMP);
|
||||
adb_host_listen(ADB_ADDR_MOUSE_TMP, 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;
|
||||
reg3 = adb_host_talk(ADB_ADDR_MOUSE_TMP, ADB_REG_3);
|
||||
if (reg3) {
|
||||
dmprintf("detect again\n");
|
||||
goto detect_again;
|
||||
dmprintf("POL: fail reg3:%04X\n", reg3);
|
||||
} else {
|
||||
dmprintf("POL: done\n");
|
||||
}
|
||||
|
||||
goto again;
|
||||
device_scan();
|
||||
return;
|
||||
}
|
||||
|
||||
static report_mouse_t mouse_report = {};
|
||||
|
|
@ -315,7 +335,7 @@ void adb_mouse_task(void)
|
|||
if (timer_elapsed(detect_ms) > 1000) {
|
||||
detect_ms = timer_read();
|
||||
// check new device on addr3
|
||||
mouse_init(ADB_ADDR_MOUSE);
|
||||
mouse_init();
|
||||
}
|
||||
|
||||
// Extended Mouse Protocol data can be 2-5 bytes
|
||||
|
|
@ -414,6 +434,11 @@ void adb_mouse_task(void)
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t adb_mouse_buttons(void)
|
||||
{
|
||||
return mouse_report.buttons;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t matrix_scan(void)
|
||||
|
|
@ -440,7 +465,7 @@ uint8_t matrix_scan(void)
|
|||
if (timer_elapsed(tick_ms) < 12) return 0;
|
||||
tick_ms = timer_read();
|
||||
|
||||
codes = adb_host_kbd_recv(ADB_ADDR_KEYBOARD);
|
||||
codes = adb_host_kbd_recv(ADB_ADDR_KBD_POLL);
|
||||
if (codes) xprintf("%04X ", codes);
|
||||
|
||||
// Adjustable keybaord media keys
|
||||
|
|
@ -490,7 +515,13 @@ uint8_t matrix_scan(void)
|
|||
key0 = codes>>8;
|
||||
key1 = codes&0xFF;
|
||||
|
||||
if (codes == 0) { // no keys
|
||||
if (codes == 0) { // no keys
|
||||
static uint16_t detect_ms;
|
||||
if (timer_elapsed(detect_ms) > 1000) {
|
||||
detect_ms = timer_read();
|
||||
// check new device on addr2
|
||||
keyboard_init();
|
||||
}
|
||||
return 0;
|
||||
} else if (codes == 0x7F7F) { // power key press
|
||||
register_key(0x7F);
|
||||
|
|
@ -576,5 +607,5 @@ static void register_key(uint8_t key)
|
|||
|
||||
void led_set(uint8_t usb_led)
|
||||
{
|
||||
adb_host_kbd_led(ADB_ADDR_KEYBOARD, ~usb_led);
|
||||
adb_host_kbd_led(ADB_ADDR_KBD_POLL, ~usb_led);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ TMK_DIR ?= ../../tmk_core
|
|||
TARGET_DIR ?= .
|
||||
|
||||
# project specific files
|
||||
SRC ?= protocol/ibmpc.c \
|
||||
ibmpc_usb.c
|
||||
#SRC ?= protocol/ibmpc.c \
|
||||
# ibmpc_usb.c
|
||||
SRC ?= protocol/ibmpc.cpp \
|
||||
ibmpc_usb.cpp
|
||||
|
||||
CONFIG_H ?= config.h
|
||||
|
||||
|
|
@ -68,19 +70,19 @@ OPT_DEFS += -DSUSPEND_MODE_STANDBY
|
|||
# Build Options
|
||||
# comment out to disable the options.
|
||||
#
|
||||
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 ?= yes # USB Nkey Rollover
|
||||
BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1150)
|
||||
MOUSEKEY_ENABLE ?= yes # Mouse keys(+2200)
|
||||
EXTRAKEY_ENABLE ?= yes # Audio control and System control(+400)
|
||||
CONSOLE_ENABLE ?= yes # Console for debug(+4150)
|
||||
COMMAND_ENABLE ?= no # Commands for debug and configuration(+3600)
|
||||
NKRO_ENABLE ?= yes # USB Nkey Rollover(+350)
|
||||
|
||||
KEYMAP_SECTION_ENABLE ?= yes
|
||||
UNIMAP_ENABLE ?= yes
|
||||
|
||||
# IBMPC Options
|
||||
IBMPC_SECONDARY ?= no # enable secondary interface
|
||||
IBMPC_MOUSE_ENABLE ?= no # enable mouse support
|
||||
IBMPC_SECONDARY ?= yes # enable secondary interface(+800)
|
||||
IBMPC_MOUSE_ENABLE ?= yes # enable mouse support(+2000)
|
||||
|
||||
|
||||
# Optimize size but this may cause error "relocation truncated to fit"
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
# With two interfaces on PS/2 connector
|
||||
TARGET ?= ibmpc_usb_x2
|
||||
MCU = atmega32u2
|
||||
SRC ?= protocol/ibmpc.cpp \
|
||||
ibmpc_usb.cpp
|
||||
|
||||
COMMAND_ENABLE ?= no # Commands for debug and configuration
|
||||
|
||||
IBMPC_SECONDARY ?= yes # enable secondary interface
|
||||
IBMPC_MOUSE_ENABLE ?= yes # enable mouse support
|
||||
|
||||
include Makefile
|
||||
|
|
@ -51,6 +51,8 @@ Firmware
|
|||
|
||||
|
||||
### Build Options
|
||||
Secondary interface and PS/2 mouses can be supported.
|
||||
|
||||
In Makefiile:
|
||||
|
||||
# IBMPC Options
|
||||
|
|
@ -88,21 +90,22 @@ Pull up resistors of 1-4.7K Ohm on both Data and Clock line are recommended, wit
|
|||
|
||||
- Data PD0
|
||||
- Clock PD1
|
||||
- Reset PB6 or PB7 (For some of XT keyboards. Not needed for AT, PS/2 and Terminal)
|
||||
- Reset PB6 or PB7
|
||||
|
||||
For optional secondary interface use these pins.
|
||||
- Data PD2
|
||||
- Clock PD3
|
||||
For optional secondary interface use these pins. See PS/2 connector pinouts below.
|
||||
|
||||
- Data2 PD2
|
||||
- Clock2 PD3
|
||||
|
||||
|
||||
### Reset
|
||||
Old Type-1 IBM XT keyboard and some of XT clones need Reset pin to starup its controller.
|
||||
Connect Reset pin to pin3 of DIN-5(180-degree) connector. This should not harm keyboards which don't require reset,
|
||||
it is safe and recommended to have Reset pin on AT/XT converter.
|
||||
Use pin3 of DIN-5(180-degree) connector for Reset.
|
||||
|
||||
Zenith Z-150 XT and Leading Edge DC-2014 are also known to need this.
|
||||
Reset should not harm keyboards even if they don't require it. It is safe and recommended to have Reset pin on AT/XT converter.
|
||||
|
||||
See this for IBM XT Type-1 vs Type-2: https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol#type-1-vs-type-2
|
||||
Old Type-1 IBM XT keyboard and some of XT clones including Zenith Z-150 XT and Leading Edge DC-2014 are known to need Reset pin. AT, PS/2 and Terminal keyboards don't need it.
|
||||
|
||||
See this for details: https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol#keyboard-hard-reset
|
||||
|
||||
|
||||
### Connector pinouts
|
||||
|
|
@ -124,6 +127,15 @@ See this for IBM XT Type-1 vs Type-2: https://github.com/tmk/tmk_keyboard/wiki/I
|
|||
#### PS/2 - Mini-DIN-6
|
||||
- https://pinouts.ru/InputCables/KeyboardPC6_pinout.shtml
|
||||
|
||||
PS/2 female socket from the front:
|
||||
|
||||
,--_--. 1: Data
|
||||
/ o6 5o \ 2: Data2
|
||||
| o4 3o | 3: GND
|
||||
- 2o o1 - 4: VCC
|
||||
`-___-' 5: Clock
|
||||
6: Clock2
|
||||
|
||||
For secondary interface use pin2 and pin6 for data and clock respectively.
|
||||
You can use PS/2 Y-splitter cable to access secondary interface.
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -21,11 +21,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <avr/interrupt.h>
|
||||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x1bee
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER t.m.k.
|
||||
#define PRODUCT_ID 0x1BEE
|
||||
#define DEVICE_VER 0x0201
|
||||
#define MANUFACTURER TMK
|
||||
#define PRODUCT IBM PC keyboard converter
|
||||
#define DESCRIPTION convert IBM PC keyboard to USB
|
||||
|
||||
|
||||
/* matrix size */
|
||||
|
|
@ -39,12 +38,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
keyboard_report->mods == (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) \
|
||||
)
|
||||
|
||||
|
||||
// CS2 80-prefixed codes support
|
||||
#define CS2_80CODE_SUPPORT
|
||||
|
||||
// G80-2551 terminal keyboard support
|
||||
#define G80_2551_SUPPORT
|
||||
|
||||
// PS/2 Mouse support
|
||||
//#define IBMPC_MOUSE_ENABLE
|
||||
|
||||
// Mouse Extended Report
|
||||
//#define MOUSE_EXT_REPORT
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -85,6 +85,14 @@ action_t action_for_key(uint8_t layer, keypos_t key)
|
|||
return (action_t){ .code = pgm_read_word(&actionmaps[(layer)][key.row & 0x07][key.col & 0x0F]) };
|
||||
}
|
||||
|
||||
#ifdef IBMPC_MOUSE_ENABLE
|
||||
static uint8_t last_buttons;
|
||||
uint8_t ibmpc_mouse_buttons(void)
|
||||
{
|
||||
return last_buttons;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void IBMPCConverter::set_led(uint8_t usb_led)
|
||||
{
|
||||
|
|
@ -137,7 +145,8 @@ uint16_t IBMPCConverter::read_keyboard_id(void)
|
|||
uint16_t id = 0;
|
||||
int16_t code = 0;
|
||||
|
||||
// temporary fix Z-150 AT should response with ID
|
||||
// Z-150 AT doesn't response to ID commnd at all.
|
||||
// https://deskthority.net/viewtopic.php?p=495196#p495196
|
||||
if (ibmpc.protocol == IBMPC_PROTOCOL_AT_Z150) return 0xFFFD;
|
||||
|
||||
// Disable
|
||||
|
|
@ -171,11 +180,15 @@ uint8_t IBMPCConverter::process_interface(void)
|
|||
|
||||
// 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("[RST] ");
|
||||
// Reset
|
||||
state = ERROR;
|
||||
}
|
||||
if (ibmpc.error == IBMPC_ERR_PARITY_AA) {
|
||||
// AT/XT Auto-Switching support
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-Keyboard-Converter#atxt-auto-switching
|
||||
state = ERROR_PARITY_AA;
|
||||
}
|
||||
}
|
||||
|
||||
// clear or process error
|
||||
|
|
@ -205,15 +218,9 @@ uint8_t IBMPCConverter::process_interface(void)
|
|||
switch (state) {
|
||||
case INIT:
|
||||
xprintf("I%u ", timer_read());
|
||||
keyboard_kind = NONE;
|
||||
keyboard_id = 0x0000;
|
||||
current_protocol = 0;
|
||||
|
||||
matrix_clear();
|
||||
|
||||
init_time = timer_read();
|
||||
state = WAIT_SETTLE;
|
||||
ibmpc.host_enable();
|
||||
state = WAIT_SETTLE;
|
||||
break;
|
||||
case WAIT_SETTLE:
|
||||
while (ibmpc.host_recv() != -1) ; // read data
|
||||
|
|
@ -331,11 +338,12 @@ uint8_t IBMPCConverter::process_interface(void)
|
|||
keyboard_kind = PC_AT;
|
||||
}
|
||||
} else if (0xAB90 == keyboard_id || // IBM 5576-002
|
||||
0xAB91 == keyboard_id) { // IBM 5576-003
|
||||
0xAB91 == keyboard_id) { // IBM 5576-003 or Televideo DEC
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-AT-Keyboard-Protocol#ab90
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-AT-Keyboard-Protocol#ab91
|
||||
|
||||
xprintf("\n5576_CS82h:");
|
||||
keyboard_kind = PC_AT;
|
||||
if ((0xFA == ibmpc.host_send(0xF0)) &&
|
||||
(0xFA == ibmpc.host_send(0x82))) {
|
||||
// switch to code set 82h
|
||||
|
|
@ -343,8 +351,18 @@ uint8_t IBMPCConverter::process_interface(void)
|
|||
xprintf("OK ");
|
||||
} else {
|
||||
xprintf("NG ");
|
||||
if (0xAB91 == keyboard_id) {
|
||||
// This must be a Televideo DEC keyboard, which piggybacks on the same keyboard_id as IBM 5576-003
|
||||
// This keyboard normally starts up using code set 1, but we request code set 2 here:
|
||||
if ((0xFA == ibmpc.host_send(0xF0)) &&
|
||||
(0xFA == ibmpc.host_send(0x03))) {
|
||||
xprintf("OK ");
|
||||
keyboard_kind = PC_TERMINAL;
|
||||
} else {
|
||||
xprintf("NG ");
|
||||
}
|
||||
}
|
||||
}
|
||||
keyboard_kind = PC_AT;
|
||||
} else if (0xBFB0 == keyboard_id) { // IBM RT Keyboard
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-AT-Keyboard-Protocol#bfb0
|
||||
// TODO: LED indicator fix
|
||||
|
|
@ -440,7 +458,7 @@ MOUSE_INTELLI:
|
|||
ibmpc.host_send(0xF3); ibmpc.host_send(0xC8);
|
||||
ibmpc.host_send(0xF3); ibmpc.host_send(0xC8);
|
||||
ibmpc.host_send(0xF3); ibmpc.host_send(0x50);
|
||||
mouse_id = ((read_keyboard_id() >> 8) == MOUSE_EXPLORER ? MOUSE_EXPLORER : MOUSE_DEFAULT);
|
||||
mouse_id = ((read_keyboard_id() >> 8) == MOUSE_EXPLORER ? MOUSE_EXPLORER : mouse_id);
|
||||
|
||||
// Not Intellimouse
|
||||
if (mouse_id == 0) {
|
||||
|
|
@ -597,6 +615,7 @@ MOUSE_DONE:
|
|||
mouse_report.v = -CHOP8(v);
|
||||
mouse_report.h = CHOP8(h);
|
||||
host_mouse_send(&mouse_report);
|
||||
last_buttons = mouse_report.buttons;
|
||||
xprintf("M[x:%d y:%d v:%d h:%d b:%02X]\n", mouse_report.x, mouse_report.y,
|
||||
mouse_report.v, mouse_report.h, mouse_report.buttons);
|
||||
break; }
|
||||
|
|
@ -606,8 +625,22 @@ MOUSE_DONE:
|
|||
}
|
||||
}
|
||||
break;
|
||||
case ERROR_PARITY_AA:
|
||||
{
|
||||
xprintf("P%u ", timer_read());
|
||||
// AT/XT Auto-Switching support: Send Resend command to select AT
|
||||
uint16_t code = ibmpc.host_send(0xFE);
|
||||
if (0xAA == code) {
|
||||
state = READ_ID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// FALL THROUGH
|
||||
case ERROR:
|
||||
// something goes wrong
|
||||
xprintf("E%u ", timer_read());
|
||||
// reinit state
|
||||
init();
|
||||
matrix_clear();
|
||||
clear_keyboard();
|
||||
state = INIT;
|
||||
break;
|
||||
|
|
@ -842,13 +875,13 @@ uint8_t IBMPCConverter::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 0x14: return 0x19; // right control
|
||||
case 0x1F: return 0x17; // left GUI
|
||||
case 0x27: return 0x1F; // right GUI
|
||||
case 0x2F: return 0x5C; // apps
|
||||
case 0x2F: return 0x27; // apps
|
||||
case 0x4A: return 0x60; // keypad /
|
||||
case 0x5A: return 0x62; // keypad enter
|
||||
case 0x69: return 0x27; // end
|
||||
case 0x69: return 0x5C; // end
|
||||
case 0x6B: return 0x53; // cursor left
|
||||
case 0x6C: return 0x2F; // home
|
||||
case 0x70: return 0x39; // insert
|
||||
|
|
@ -895,26 +928,57 @@ uint8_t IBMPCConverter::cs2_e0code(uint8_t code) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CS2_80CODE_SUPPORT
|
||||
// 80-prefixed codes
|
||||
uint8_t IBMPCConverter::cs2_80code(uint8_t code) {
|
||||
// Tandberg TDV 5020
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-AT-Keyboard-Protocol#tandberg-tdv-5020
|
||||
switch (code) {
|
||||
case 0x2B: return 0x08; // TDV:MERK (mark) -> F13
|
||||
case 0x34: return 0x10; // TDV:ANGRE (undo) -> F14
|
||||
case 0x33: return 0x18; // TDV:SKRIV (print) -> F15
|
||||
case 0x42: return 0x20; // TDV:SLUTT (end) -> F16
|
||||
case 0x2C: return 0x28; // TDV:STRYK (cut) -> F17
|
||||
case 0x3C: return 0x30; // TDV:KOPI (copy) -> F18
|
||||
case 0x43: return 0x38; // TDV:FLYTT (move) -> F19
|
||||
case 0x4B: return 0x40; // TDV:FELT (cell) -> F20
|
||||
case 0x2A: return 0x48; // TDV:AVSN (paragraph) -> F21
|
||||
case 0x32: return 0x50; // TDV:SETN (sentence) -> F22
|
||||
case 0x3A: return 0x57; // TDV:ORD (word) -> F23
|
||||
case 0x61: return 0x6A; // TDV:⮎ (?) -> JYEN Japanese Yen
|
||||
case 0x1D: return 0x5F; // TDV:HJELP (help) -> F24
|
||||
case 0x24: return 0x17; // TDV:^^^ (?) -> LGUI
|
||||
case 0x44: return 0x65; // TDV:>>/<< (left/right adjust) -> VOLD Volume Down
|
||||
case 0x4D: return 0x6E; // TDV:JUST (adjust) -> VOLU Volume Up
|
||||
case 0x1C: return 0x6F; // TDV:>< <> (center/block) -> MUTE
|
||||
case 0x2D: return 0x51; // TDV:⇟ (three lines down) -> RO Japanese Ro
|
||||
case 0x1B: return 0x1F; // TDV:⇤ (start of line) -> RGUI
|
||||
case 0x23: return 0x27; // TDV:⇥ (end of line) -> APP
|
||||
}
|
||||
return code;
|
||||
}
|
||||
#endif
|
||||
|
||||
// IBM 5576-002/003 Scan code translation
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-AT-Keyboard-Protocol#ibm-5576-code-set-82h
|
||||
uint8_t IBMPCConverter::translate_5576_cs2(uint8_t code) {
|
||||
switch (code) {
|
||||
case 0x11: return 0x0F; // Zenmen -> RALT
|
||||
case 0x13: return 0x11; // Kanji -> LALT
|
||||
case 0x0E: return 0x54; // @
|
||||
case 0x54: return 0x5B; // [
|
||||
case 0x5B: return 0x5D; // ]
|
||||
case 0x5C: return 0x6A; // JYEN
|
||||
case 0x5D: return 0x6A; // JYEN
|
||||
case 0x62: return 0x0E; // Han/Zen -> `~
|
||||
case 0x7C: return 0x77; // Keypad *
|
||||
case 0x0E: return 0x54; // @ -> [
|
||||
case 0x54: return 0x5B; // [ -> ]
|
||||
case 0x5B: return 0x5D; // ] -> Backslash
|
||||
case 0x5C: return 0x6A; // -> JPY
|
||||
case 0x5D: return 0x6A; // ¥ -> JPY
|
||||
case 0x62: return 0x0E; // Han/Zen -> Grave
|
||||
case 0x7C: return 0x77; // Keypad * -> NumLock
|
||||
}
|
||||
return code;
|
||||
}
|
||||
uint8_t IBMPCConverter::translate_5576_cs2_e0(uint8_t code) {
|
||||
switch (code) {
|
||||
case 0x11: return 0x13; // Hiragana -> KANA
|
||||
case 0x41: return 0x7C; // Keypad '
|
||||
case 0x41: return 0x7C; // Keypad , -> Keypad *
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
|
@ -936,6 +1000,11 @@ int8_t IBMPCConverter::process_cs2(uint8_t code)
|
|||
case 0xE1:
|
||||
state_cs2 = CS2_E1;
|
||||
break;
|
||||
#ifdef CS2_80CODE_SUPPORT
|
||||
case 0x80:
|
||||
state_cs2 = CS2_80;
|
||||
break;
|
||||
#endif
|
||||
case 0x83: // F7
|
||||
matrix_make(0x02);
|
||||
state_cs2 = CS2_INIT;
|
||||
|
|
@ -1077,6 +1146,25 @@ int8_t IBMPCConverter::process_cs2(uint8_t code)
|
|||
state_cs2 = CS2_INIT;
|
||||
}
|
||||
break;
|
||||
#ifdef CS2_80CODE_SUPPORT
|
||||
case CS2_80:
|
||||
switch (code) {
|
||||
case 0xF0:
|
||||
state_cs2 = CS2_80_F0;
|
||||
break;
|
||||
default:
|
||||
state_cs2 = CS2_INIT;
|
||||
matrix_make(cs2_80code(code));
|
||||
}
|
||||
break;
|
||||
case CS2_80_F0:
|
||||
switch (code) {
|
||||
default:
|
||||
state_cs2 = CS2_INIT;
|
||||
matrix_break(cs2_80code(code));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
state_cs2 = CS2_INIT;
|
||||
}
|
||||
|
|
@ -1103,6 +1191,38 @@ uint8_t IBMPCConverter::translate_5576_cs3(uint8_t code) {
|
|||
return code;
|
||||
}
|
||||
|
||||
// Televideo DEC Scan code translation
|
||||
uint8_t IBMPCConverter::translate_televideo_dec_cs3(uint8_t code) {
|
||||
switch (code) {
|
||||
case 0x08: return 0x76; // Esc
|
||||
case 0x8D: return 0x77; // Num Lock
|
||||
case 0x8E: return 0x67; // Numeric Keypad Slash
|
||||
case 0x8F: return 0x7F; // Numeric Keypad Asterisk
|
||||
case 0x90: return 0x7B; // Numeric Keypad Minus
|
||||
case 0x6E: return 0x65; // Insert
|
||||
case 0x65: return 0x6d; // Delete
|
||||
case 0x67: return 0x62; // Home
|
||||
case 0x6d: return 0x64; // End
|
||||
case 0x64: return 0x6e; // PageUp
|
||||
case 0x84: return 0x7c; // Numeric Keypad Plus (Legend says minus)
|
||||
case 0x87: return 0x02; // Print Screen
|
||||
case 0x88: return 0x7e; // Scroll Lock
|
||||
case 0x89: return 0x0c; // Pause
|
||||
case 0x8A: return 0x03; // VOLD
|
||||
case 0x8B: return 0x04; // VOLU
|
||||
case 0x8C: return 0x05; // MUTE
|
||||
case 0x85: return 0x08; // F13
|
||||
case 0x86: return 0x10; // F14
|
||||
case 0x91: return 0x01; // LGUI
|
||||
case 0x92: return 0x09; // RGUI
|
||||
case 0x77: return 0x58; // RCTRL
|
||||
case 0x57: return 0x5C; // Backslash
|
||||
case 0x5C: return 0x53; // Non-US Hash
|
||||
case 0x7c: return 0x68; // Kp Comma
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int8_t IBMPCConverter::process_cs3(uint8_t code)
|
||||
{
|
||||
switch (code) {
|
||||
|
|
@ -1120,6 +1240,10 @@ int8_t IBMPCConverter::process_cs3(uint8_t code)
|
|||
if (0xAB92 == keyboard_id) {
|
||||
code = translate_5576_cs3(code);
|
||||
}
|
||||
if (0xAB91 == keyboard_id) {
|
||||
// This must be the Televideo DEC keyboard. (For 5576-003 we don't use scan code set 3)
|
||||
code = translate_televideo_dec_cs3(code);
|
||||
}
|
||||
switch (code) {
|
||||
case 0xF0:
|
||||
state_cs3 = CS3_F0;
|
||||
|
|
@ -1166,6 +1290,10 @@ int8_t IBMPCConverter::process_cs3(uint8_t code)
|
|||
if (0xAB92 == keyboard_id) {
|
||||
code = translate_5576_cs3(code);
|
||||
}
|
||||
if (0xAB91 == keyboard_id) {
|
||||
// This must be the Televideo DEC keyboard. (For 5576-003 we don't use scan code set 3)
|
||||
code = translate_televideo_dec_cs3(code);
|
||||
}
|
||||
switch (code) {
|
||||
case 0x83: // PrintScreen
|
||||
matrix_break(0x02);
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef IBMPC_USB_H
|
||||
#define IBMPC_USB_H
|
||||
|
||||
typedef enum { NONE, PC_XT, PC_AT, PC_TERMINAL, PC_MOUSE } keyboard_kind_t;
|
||||
#define KEYBOARD_KIND_STR(kind) \
|
||||
(kind == PC_XT ? "XT" : \
|
||||
kind == PC_AT ? "AT" : \
|
||||
kind == PC_TERMINAL ? "TERMINAL" : \
|
||||
kind == PC_MOUSE ? "MOUSE" : \
|
||||
"NONE")
|
||||
|
||||
#endif
|
||||
|
|
@ -4,10 +4,18 @@
|
|||
#include <avr/pgmspace.h>
|
||||
#include "matrix.h"
|
||||
#include "unimap_trans.h"
|
||||
#include "ibmpc_usb.h"
|
||||
|
||||
|
||||
|
||||
typedef enum { NONE, PC_XT, PC_AT, PC_TERMINAL, PC_MOUSE } keyboard_kind_t;
|
||||
|
||||
#define KEYBOARD_KIND_STR(kind) \
|
||||
(kind == PC_XT ? "XT" : \
|
||||
kind == PC_AT ? "AT" : \
|
||||
kind == PC_TERMINAL ? "TERMINAL" : \
|
||||
kind == PC_MOUSE ? "MOUSE" : \
|
||||
"NONE")
|
||||
|
||||
#define ID_STR(id) (id == 0xFFFE ? "_????" : \
|
||||
(id == 0xFFFD ? "_Z150" : \
|
||||
(id == 0x0000 ? "_AT84" : \
|
||||
|
|
@ -16,6 +24,10 @@
|
|||
#define ROW(code) ((code>>4)&0x07)
|
||||
#define COL(code) (code&0x0F)
|
||||
|
||||
#ifdef IBMPC_MOUSE_ENABLE
|
||||
extern "C" uint8_t ibmpc_mouse_buttons(void);
|
||||
#endif
|
||||
|
||||
|
||||
class IBMPCConverter {
|
||||
public:
|
||||
|
|
@ -28,6 +40,10 @@ class IBMPCConverter {
|
|||
}
|
||||
|
||||
void init(void) {
|
||||
keyboard_id = 0x0000;
|
||||
keyboard_kind = NONE;
|
||||
current_protocol = 0;
|
||||
matrix_clear();
|
||||
ibmpc.host_init();
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +80,7 @@ class IBMPCConverter {
|
|||
SETUP,
|
||||
LOOP,
|
||||
ERROR,
|
||||
ERROR_PARITY_AA,
|
||||
} state = INIT;
|
||||
|
||||
enum CS1_state {
|
||||
|
|
@ -86,6 +103,10 @@ class IBMPCConverter {
|
|||
CS2_E1_F0,
|
||||
CS2_E1_F0_14,
|
||||
CS2_E1_F0_14_F0,
|
||||
#ifdef CS2_80CODE_SUPPORT
|
||||
CS2_80,
|
||||
CS2_80_F0,
|
||||
#endif
|
||||
} state_cs2 = CS2_INIT;
|
||||
|
||||
enum CS3_state {
|
||||
|
|
@ -103,9 +124,13 @@ class IBMPCConverter {
|
|||
int8_t process_cs3(uint8_t code);
|
||||
uint8_t cs1_e0code(uint8_t code);
|
||||
uint8_t cs2_e0code(uint8_t code);
|
||||
#ifdef CS2_80CODE_SUPPORT
|
||||
uint8_t cs2_80code(uint8_t code);
|
||||
#endif
|
||||
uint8_t translate_5576_cs2(uint8_t code);
|
||||
uint8_t translate_5576_cs2_e0(uint8_t code);
|
||||
uint8_t translate_5576_cs3(uint8_t code);
|
||||
uint8_t translate_televideo_dec_cs3(uint8_t code);
|
||||
|
||||
int16_t read_wait(uint16_t wait_ms);
|
||||
uint16_t read_keyboard_id(void);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
/*
|
||||
* Scan Code Set 1:
|
||||
* 83-key:
|
||||
* IBM XT 83-key:
|
||||
* ,-------. ,--------------------------------------------------------------------------.
|
||||
* | F1| F2| |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| BS |NumLck |ScrLck |
|
||||
* |-------| |--------------------------------------------------------------------------|
|
||||
|
|
@ -60,7 +60,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
* |-----------------------------------------------------------| `-----------' |---------------|
|
||||
* |CapsL | A| S| D| F| G| H| J| K| L| ;| '| #|Entr| | 4| 5| 6|KP,|
|
||||
* |-----------------------------------------------------------| ,---. |---------------|
|
||||
* |Shft| ^a| Z| X| C| V| B| N| M| ,| .| /| RO|Shift | |Up | | 1| 2| 3|Ent|
|
||||
* |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=|
|
||||
* `-----------------------------------------------------------' `-----------' `---------------'
|
||||
|
|
@ -74,17 +74,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
* |-----------------------------------------------------------| |-----------| |---------------|
|
||||
* | 0F | 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 2B | |*53|*4F|*51| | 47| 48| 49| 4E|
|
||||
* |-----------------------------------------------------------| `-----------' |---------------|
|
||||
* | 3A | 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| 28| 56| 1C | | 4B| 4C| 4D| 7E|
|
||||
* | 3A | 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| 28| ^a| 1C | | 4B| 4C| 4D| 7E|
|
||||
* |-----------------------------------------------------------| ,---. |---------------|
|
||||
* | 2A | ^a| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35| 73| 36 | |*48| | 4F| 50| 51|*1C|
|
||||
* | 2A | 56| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35| 73| 36 | |*48| | 4F| 50| 51|*1C|
|
||||
* |-----------------------------------------------------------| ,-----------. |---------------|
|
||||
* | 1D|*5B| 38| 7B | 39 | 79 | 70 |*38|*5C|*5D|*1D| |*4B|*50|*4D| | 52| 53| 59|
|
||||
* `-----------------------------------------------------------' `-----------' `---------------'
|
||||
* *: E0-prefixed codes. See cs1_e0code() for remapping to unimap array.
|
||||
* PrintScreen: E0 37 or 54(with Alt) -> 54
|
||||
* Pause: E1 1D 45 or E0 46(with Ctrl) -> 55
|
||||
* ^a: ISO backslash and US backslash use identical code 2B. [3], [a]
|
||||
* Unsupported codes or error -> 00. UNIMAP_NUBS is unused.
|
||||
* ^a: 2B(ISO XT) is handled as BSLASH. NUHS is unused.
|
||||
* Unsupported codes or error -> 00.
|
||||
*/
|
||||
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 */
|
||||
|
|
@ -97,7 +97,7 @@ const uint8_t PROGMEM unimap_cs1[MATRIX_ROWS][MATRIX_COLS] = {
|
|||
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_P2, UNIMAP_P3, UNIMAP_P0, UNIMAP_PDOT, UNIMAP_PSCR, UNIMAP_PAUSE, UNIMAP_NUBS, 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 */
|
||||
|
|
@ -149,16 +149,16 @@ const uint8_t PROGMEM unimap_cs1[MATRIX_ROWS][MATRIX_COLS] = {
|
|||
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_F14, UNIMAP_LALT, UNIMAP_LSHIFT,UNIMAP_KANA, UNIMAP_LCTL, UNIMAP_Q, UNIMAP_1, UNIMAP_LGUI, /* 10-17 */
|
||||
UNIMAP_F15, UNIMAP_RCTL, 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_APP, /* 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_CAPS, UNIMAP_RSHIFT,UNIMAP_ENTER, UNIMAP_RBRC, UNIMAP_END, 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_MUTE }, /* 68-6F */
|
||||
{ UNIMAP_P0, UNIMAP_PDOT, UNIMAP_P2, UNIMAP_P5, UNIMAP_P6, UNIMAP_P8, UNIMAP_ESC, UNIMAP_NLCK, /* 70-77 */
|
||||
|
|
@ -182,7 +182,7 @@ const uint8_t PROGMEM unimap_cs2[MATRIX_ROWS][MATRIX_COLS] = {
|
|||
* |-------| |-----------------------------------------------------------| ,-----------. |---------------|
|
||||
* |PrS|App| |Shif| \| Z| X| C| V| B| N| M| ,| ,| /| RO| Shift| |Lef|Hom|Rig| | 1| 2| 3|Ent|
|
||||
* |-------| |-----------------------------------------------------------| `-----------' |-----------|---|
|
||||
* |Gui|Gui| |Ctrl| |Alt | Space |Alt | |Ctrl| | RO|Dow|KAN| | ,| 0| .| =|
|
||||
* |Gui|Gui| |Ctrl| | Alt | P, | Space | P= | KANA| Alt | |Ctrl| | RO|Dow|KAN| | ,| 0| .| =|
|
||||
* `-------' `----' `---------------------------------------' `----' ---`---'--- `---------------'
|
||||
*
|
||||
* ,-----------------------------------------------.
|
||||
|
|
@ -191,18 +191,18 @@ const uint8_t PROGMEM unimap_cs2[MATRIX_ROWS][MATRIX_COLS] = {
|
|||
* | 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|
|
||||
* | 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| | 14 | 1C| 1B| 23| 2B| 34| 33| 3B| 42| 4B| 4C| 52| 53| 5A | |-26| 63|-25| | 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|
|
||||
* | 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 | |-16| 60|-1E| | 68| 70| 71| 78|
|
||||
* | 01| 09| | 11 | | 19 | ^85 | 29 | ^86 | 87 | 39 | | 58 | |-16| 60|-1E| | 68| 70| 71| 78|
|
||||
* `-------' `-----' `---------------------------------------' `-----' ---`---'--- `---------------'
|
||||
* *: Special codes remapped 83->02, 84->7F
|
||||
* -: G80-2551 specific 80-prefixed codes remapped: 26->5D, 25->53, 16->51, 1E->00
|
||||
* ^: 5576-001 Japanese keys
|
||||
* 51, 5C, 5D, 68, 78: Hidden keys in IBM 122-key terminal keyboard [7]
|
||||
*/
|
||||
const uint8_t PROGMEM unimap_cs3[MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ CONSOLE_ENABLE ?= yes # Console for debug
|
|||
COMMAND_ENABLE ?= yes # Commands for debug and configuration
|
||||
#NKRO_ENABLE ?= yes # USB Nkey Rollover
|
||||
UNIMAP_ENABLE ?= yes
|
||||
#KYMAP_SECTION_ENABLE ?= yes
|
||||
|
||||
|
||||
# Boot Section Size in bytes
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
PC98 to USB keyboard protocol converter
|
||||
=======================================
|
||||
Target MCU is ATMega32u2 but other USB capable AVR will also work.
|
||||
Main target is TMK prebuilt converter(ATMega32u2) but it will work on dev boards with ATMega32u4.
|
||||
|
||||
To initialize keyboard correctly you have to connect keyboard with converter first and then plug them into USB port.
|
||||
Otherwise, keyboard may not work.
|
||||
|
||||
|
||||
You can buy [TMK prebuilt converter](https://geekhack.org/index.php?topic=72052.0) here to support this project.
|
||||
|
||||
Discuss or report issue on github or [this thread](https://geekhack.org/index.php?topic=110094.0).
|
||||
|
||||
|
||||
|
||||
Connector
|
||||
---------
|
||||
On host/converter:
|
||||
|
|
@ -35,7 +41,6 @@ Wiring: You can change this with editing config.h.
|
|||
|
||||
|
||||
|
||||
|
||||
Protocol
|
||||
--------
|
||||
Signal: Asynchronous, Positive logic, 19200baud, Least bit first
|
||||
|
|
@ -60,7 +65,7 @@ To flash firmware run this command
|
|||
|
||||
$ make dfu
|
||||
|
||||
then push button on converter to flash firmware.
|
||||
then push button on the converter to flash firmware.
|
||||
|
||||
If you are using ATMega32u4 based board use following commands to get firmware HEX file.
|
||||
|
||||
|
|
@ -156,19 +161,22 @@ Its scan code map is very different from standard types. This is not tested.
|
|||
|
||||
Other PC98 converter projects and resource
|
||||
------------------------------------------
|
||||
PC-9800シリーズ テクニカルデータブック HARDWARE 編 1993年 p139, p343
|
||||
https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n151
|
||||
https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n355
|
||||
### TMK wiki
|
||||
- https://github.com/tmk/tmk_keyboard/wiki/PC-9801-Keyboard
|
||||
|
||||
PC98 to USB
|
||||
http://davy.nyacom.net/kbd98usb/
|
||||
### PC-9800シリーズ テクニカルデータブック HARDWARE 編 1993年 p139, p343
|
||||
- https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n151
|
||||
- https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n355
|
||||
|
||||
PC98 to PS/2
|
||||
http://www.tsp.ne.jp/~sawada/mago/c_gka98at.htm
|
||||
http://www.tsp.ne.jp/~sawada/mago/src/gka98at.asm
|
||||
### PC98 to USB
|
||||
- http://davy.nyacom.net/kbd98usb/
|
||||
|
||||
scan code:
|
||||
http://ixsvr.dyndns.org/usb2pc98
|
||||
### PC98 to PS/2
|
||||
- http://www.tsp.ne.jp/~sawada/mago/c_gka98at.htm
|
||||
- http://www.tsp.ne.jp/~sawada/mago/src/gka98at.asm
|
||||
|
||||
### Scan code
|
||||
- http://ixsvr.dyndns.org/usb2pc98
|
||||
|
||||
|
||||
|
||||
|
|
@ -182,9 +190,9 @@ NOTES
|
|||
### RDY
|
||||
PC98 host keeps RDY line high to prevent keyboard from sending data while processing.
|
||||
|
||||
https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n359
|
||||
- https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n359
|
||||
|
||||
PC-9801V keyboard requires RDY pulse as acknowledgement from host, it doesn't next data without this. Dboard doens't need this.
|
||||
PC-9801V keyboard requires RDY pulse as acknowledgement from host, it doesn't next data without this. Dboard doesn't need this.
|
||||
|
||||
|
||||
### Inhibit key repeating
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -123,15 +123,12 @@ RETRY:
|
|||
|
||||
void matrix_init(void)
|
||||
{
|
||||
PC98_RST_DDR |= (1<<PC98_RST_BIT);
|
||||
PC98_RDY_DDR |= (1<<PC98_RDY_BIT);
|
||||
PC98_RTY_DDR |= (1<<PC98_RTY_BIT);
|
||||
PC98_RST_PORT |= (1<<PC98_RST_BIT);
|
||||
PC98_RST_DDR |= (1<<PC98_RST_BIT);
|
||||
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
|
||||
PC98_RDY_DDR |= (1<<PC98_RDY_BIT);
|
||||
PC98_RTY_PORT |= (1<<PC98_RTY_BIT);
|
||||
|
||||
|
||||
serial_init();
|
||||
PC98_RTY_DDR |= (1<<PC98_RTY_BIT);
|
||||
|
||||
// PC98 reset
|
||||
// https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n359
|
||||
|
|
@ -140,6 +137,8 @@ void matrix_init(void)
|
|||
_delay_us(15); // > 13us
|
||||
PC98_RST_PORT |= (1<<PC98_RST_BIT); // RST: high
|
||||
|
||||
serial_init();
|
||||
|
||||
_delay_ms(50);
|
||||
if (pc98_is_newtype()) xprintf("new type\n"); else xprintf("old type\n");
|
||||
pc98_inhibit_repeat();
|
||||
|
|
|
|||
|
|
@ -17,4 +17,8 @@ OPT_DEFS += -DDEBUG_USB_HOST
|
|||
CONSOLE_ENABLE = yes
|
||||
MOUSEKEY_ENABLE = no
|
||||
EXTRAKEY_ENABLE = no
|
||||
COMMAND_ENABLE = no
|
||||
OPT_DEFS += -DNO_ACTION_TAPPING
|
||||
OPT_DEFS += -DNO_ACTION_LAYER
|
||||
OPT_DEFS += -DNO_ACTION_MACRO
|
||||
include Makefile
|
||||
|
|
|
|||
|
|
@ -44,6 +44,14 @@ In case of Leonardo push reset button then run command. Serial port name(COM17)
|
|||
or
|
||||
$ avrdude -patmega32u4 -cavr109 -b57600 -Uflash:w:usb_usb.hex -PCOM17
|
||||
|
||||
To build debug firmware use `master_debug` branch of `USB_Host_Shield_2.0-tmk` submodule
|
||||
|
||||
$ cd tmk_keyboard/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0-tmk
|
||||
$ git chceckout master_debug
|
||||
$ cd tmk_keyboard/converter/usb_usb
|
||||
$ make -f Makefile.debug
|
||||
$ make -f Makefile.debug dfu
|
||||
|
||||
|
||||
|
||||
Limitation
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -21,8 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x005B
|
||||
#define DEVICE_VER 0x0814
|
||||
#define MANUFACTURER t.m.k.
|
||||
#define DEVICE_VER 0x0815
|
||||
#define MANUFACTURER TMK
|
||||
#define PRODUCT USB to USB keyboard converter
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -105,13 +105,13 @@ ifeq (yes,$(strip $(KEYMAP_SECTION_ENABLE)))
|
|||
OPT_DEFS += -DKEYMAP_SECTION_ENABLE
|
||||
|
||||
ifeq ($(strip $(MCU)),atmega32u2)
|
||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
|
||||
EXTRALDFLAGS += -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
|
||||
else ifeq ($(strip $(MCU)),atmega32u4)
|
||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
|
||||
EXTRALDFLAGS += -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
|
||||
else ifeq ($(strip $(MCU)),at90usb1286)
|
||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr51.x
|
||||
EXTRALDFLAGS += -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr51.x
|
||||
else
|
||||
EXTRALDFLAGS = $(error no ldscript for keymap section)
|
||||
EXTRALDFLAGS += $(error no ldscript for keymap section)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -353,8 +353,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define AC_RO ACTION_KEY(KC_INT1)
|
||||
#define AC_KANA ACTION_KEY(KC_INT2)
|
||||
#define AC_JYEN ACTION_KEY(KC_INT3)
|
||||
#define AC_JPY ACTION_KEY(KC_INT3)
|
||||
#define AC_HENK ACTION_KEY(KC_INT4)
|
||||
#define AC_MHEN ACTION_KEY(KC_INT5)
|
||||
#define AC_MACJ ACTION_KEY(KC_LANG1)
|
||||
#define AC_MACE ACTION_KEY(KC_LANG2)
|
||||
/* Korean specific */
|
||||
#define AC_HAEN ACTION_KEY(KC_LANG1)
|
||||
#define AC_HANJ ACTION_KEY(KC_LANG2)
|
||||
/* Keypad */
|
||||
#define AC_P1 ACTION_KEY(KC_KP_1)
|
||||
#define AC_P2 ACTION_KEY(KC_KP_2)
|
||||
|
|
@ -376,6 +382,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define AC_PPLS ACTION_KEY(KC_KP_PLUS)
|
||||
#define AC_PEQL ACTION_KEY(KC_KP_EQUAL)
|
||||
#define AC_PENT ACTION_KEY(KC_KP_ENTER)
|
||||
/* Unix function key */
|
||||
#define AC_EXEC ACTION_KEY(KC_EXECUTE)
|
||||
#define AC_SLCT ACTION_KEY(KC_SELECT)
|
||||
#define AC_AGIN ACTION_KEY(KC_AGAIN)
|
||||
#define AC_PSTE ACTION_KEY(KC_PASTE)
|
||||
/* Mousekey */
|
||||
#define AC_MS_U ACTION_MOUSEKEY(KC_MS_UP)
|
||||
#define AC_MS_D ACTION_MOUSEKEY(KC_MS_DOWN)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "util.h"
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
# include "mousekey.h"
|
||||
#endif
|
||||
#ifdef PS2_MOUSE_ENABLE
|
||||
# include "ps2_mouse.h"
|
||||
#endif
|
||||
#ifdef SERIAL_MOUSE_ENABLE
|
||||
# include "serial_mouse.h"
|
||||
#endif
|
||||
#ifdef ADB_MOUSE_ENABLE
|
||||
# include "adb.h"
|
||||
#endif
|
||||
#ifdef IBMPC_MOUSE_ENABLE
|
||||
uint8_t ibmpc_mouse_buttons(void);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(NKRO_ENABLE) || defined(NKRO_6KRO_ENABLE)
|
||||
bool keyboard_nkro = true;
|
||||
|
|
@ -70,7 +86,26 @@ void host_mouse_send(report_mouse_t *report)
|
|||
report->boot_x = (report->x > 127) ? 127 : ((report->x < -127) ? -127 : report->x);
|
||||
report->boot_y = (report->y > 127) ? 127 : ((report->y < -127) ? -127 : report->y);
|
||||
#endif
|
||||
|
||||
/* Mouse buttons integration */
|
||||
uint8_t b = report->buttons;
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
report->buttons |= mousekey_buttons();
|
||||
#endif
|
||||
#ifdef PS2_MOUSE_ENABLE
|
||||
report->buttons |= ps2_mouse_buttons();
|
||||
#endif
|
||||
#ifdef SERIAL_MOUSE_ENABLE
|
||||
report->buttons |= serial_mouse_buttons();
|
||||
#endif
|
||||
#ifdef ADB_MOUSE_ENABLE
|
||||
report->buttons |= adb_mouse_buttons();
|
||||
#endif
|
||||
#ifdef IBMPC_MOUSE_ENABLE
|
||||
report->buttons |= ibmpc_mouse_buttons();
|
||||
#endif
|
||||
(*driver->send_mouse)(report);
|
||||
report->buttons = b;
|
||||
}
|
||||
|
||||
void host_system_send(uint16_t report)
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define KC_JPY KC_INT3
|
||||
#define KC_HENK KC_INT4
|
||||
#define KC_MHEN KC_INT5
|
||||
#define KC_MACJ KC_LANG1
|
||||
#define KC_MACE KC_LANG2
|
||||
/* Korean specific */
|
||||
#define KC_HAEN KC_LANG1
|
||||
#define KC_HANJ KC_LANG2
|
||||
|
|
|
|||
|
|
@ -182,6 +182,11 @@ void mousekey_clear(void)
|
|||
mousekey_accel = 0;
|
||||
}
|
||||
|
||||
uint8_t mousekey_buttons(void)
|
||||
{
|
||||
return mouse_report.buttons;
|
||||
}
|
||||
|
||||
static void mousekey_debug(void)
|
||||
{
|
||||
if (!debug_mouse) return;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ void mousekey_on(uint8_t code);
|
|||
void mousekey_off(uint8_t code);
|
||||
void mousekey_clear(void);
|
||||
void mousekey_send(void);
|
||||
uint8_t mousekey_buttons(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
#include "util.h"
|
||||
|
||||
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
|
||||
#ifndef NO_PRINT
|
||||
|
|
|
|||
|
|
@ -69,8 +69,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#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_KBD_POLL 9
|
||||
#define ADB_ADDR_MOUSE_POLL 10
|
||||
#define ADB_ADDR_KBD_TMP 14
|
||||
#define ADB_ADDR_MOUSE_TMP 15
|
||||
// Command Type
|
||||
#define ADB_CMD_RESET 0
|
||||
#define ADB_CMD_FLUSH 1
|
||||
|
|
@ -109,6 +111,7 @@ void adb_host_reset_hard(void);
|
|||
void adb_host_kbd_led(uint8_t addr, uint8_t led);
|
||||
void adb_mouse_task(void);
|
||||
void adb_mouse_init(void);
|
||||
uint8_t adb_mouse_buttons(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,394 +0,0 @@
|
|||
/*
|
||||
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 <util/atomic.h>
|
||||
#include "ibmpc.h"
|
||||
#include "debug.h"
|
||||
#include "timer.h"
|
||||
#include "wait.h"
|
||||
#include "ringbuf.h"
|
||||
|
||||
|
||||
#define WAIT(stat, us, err) do { \
|
||||
if (!wait_##stat(us)) { \
|
||||
ibmpc_error = err; \
|
||||
goto ERROR; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
volatile uint16_t ibmpc_isr_debug = 0;
|
||||
volatile uint8_t ibmpc_protocol = IBMPC_PROTOCOL_NO;
|
||||
volatile uint8_t ibmpc_error = IBMPC_ERR_NONE;
|
||||
|
||||
/* buffer for data received from device */
|
||||
#define RINGBUF_SIZE 16
|
||||
static uint8_t rbuf[RINGBUF_SIZE];
|
||||
static ringbuf_t rb = {};
|
||||
|
||||
/* internal state of receiving data */
|
||||
static volatile uint16_t isr_state = 0x8000;
|
||||
static uint8_t timer_start = 0;
|
||||
|
||||
void ibmpc_host_init(void)
|
||||
{
|
||||
// initialize reset pin to HiZ
|
||||
IBMPC_RST_HIZ();
|
||||
inhibit();
|
||||
IBMPC_INT_INIT();
|
||||
IBMPC_INT_OFF();
|
||||
ringbuf_init(&rb, rbuf, RINGBUF_SIZE);
|
||||
}
|
||||
|
||||
void ibmpc_host_enable(void)
|
||||
{
|
||||
IBMPC_INT_ON();
|
||||
idle();
|
||||
}
|
||||
|
||||
void ibmpc_host_disable(void)
|
||||
{
|
||||
IBMPC_INT_OFF();
|
||||
inhibit();
|
||||
}
|
||||
|
||||
int16_t ibmpc_host_send(uint8_t data)
|
||||
{
|
||||
bool parity = true;
|
||||
ibmpc_error = IBMPC_ERR_NONE;
|
||||
uint8_t retry = 0;
|
||||
|
||||
dprintf("w%02X ", data);
|
||||
|
||||
// Not receiving data
|
||||
if (isr_state != 0x8000) dprintf("isr:%04X ", isr_state);
|
||||
while (isr_state != 0x8000) ;
|
||||
|
||||
// Not clock Lo
|
||||
if (!clock_in()) dprintf("c:%u ", wait_clock_hi(1000));
|
||||
|
||||
// Not data Lo
|
||||
if (!data_in()) dprintf("d:%u ", wait_data_hi(1000));
|
||||
|
||||
IBMPC_INT_OFF();
|
||||
|
||||
RETRY:
|
||||
/* terminate a transmission if we have */
|
||||
inhibit();
|
||||
wait_us(200); // [5]p.54
|
||||
|
||||
/* 'Request to Send' and Start bit */
|
||||
data_lo();
|
||||
wait_us(200);
|
||||
clock_hi(); // [5]p.54 [clock low]>100us [5]p.50
|
||||
WAIT(clock_lo, 10000, 1); // [5]p.53, -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, 300, 6);
|
||||
WAIT(data_hi, 300, 7);
|
||||
WAIT(clock_hi, 300, 8);
|
||||
|
||||
// clear buffer to get response correctly
|
||||
ibmpc_host_isr_clear();
|
||||
|
||||
idle();
|
||||
IBMPC_INT_ON();
|
||||
return ibmpc_host_recv_response();
|
||||
ERROR:
|
||||
// Retry for Z-150 AT start bit error
|
||||
if (ibmpc_error == 1 && retry++ < 10) {
|
||||
ibmpc_error = IBMPC_ERR_NONE;
|
||||
dprintf("R ");
|
||||
goto RETRY;
|
||||
}
|
||||
|
||||
ibmpc_error |= IBMPC_ERR_SEND;
|
||||
inhibit();
|
||||
wait_ms(2);
|
||||
idle();
|
||||
IBMPC_INT_ON();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data from keyboard
|
||||
*/
|
||||
int16_t ibmpc_host_recv(void)
|
||||
{
|
||||
int16_t ret = -1;
|
||||
|
||||
// Enable ISR if buffer was full
|
||||
if (ringbuf_is_full(&rb)) {
|
||||
ibmpc_host_isr_clear();
|
||||
IBMPC_INT_ON();
|
||||
idle();
|
||||
}
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
ret = ringbuf_get(&rb);
|
||||
}
|
||||
if (ret != -1) dprintf("r%02X ", ret&0xFF);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int16_t ibmpc_host_recv_response(void)
|
||||
{
|
||||
// Command may take 25ms/20ms at most([5]p.46, [3]p.21)
|
||||
uint8_t retry = 25;
|
||||
int16_t data = -1;
|
||||
while (retry-- && (data = ibmpc_host_recv()) == -1) {
|
||||
wait_ms(1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void ibmpc_host_isr_clear(void)
|
||||
{
|
||||
ibmpc_isr_debug = 0;
|
||||
ibmpc_protocol = 0;
|
||||
ibmpc_error = 0;
|
||||
isr_state = 0x8000;
|
||||
ringbuf_reset(&rb);
|
||||
}
|
||||
|
||||
|
||||
// NOTE: With this ISR data line should be read within 5us after clock falling edge.
|
||||
// Confirmed that ATmega32u4 can read data line in 2.5us from interrupt after
|
||||
// ISR prologue pushs r18, r19, r20, r21, r24, r25 r30 and r31 with GCC 5.4.0
|
||||
ISR(IBMPC_INT_VECT)
|
||||
{
|
||||
uint8_t dbit;
|
||||
dbit = IBMPC_DATA_PIN&(1<<IBMPC_DATA_BIT);
|
||||
|
||||
// Timeout check
|
||||
uint8_t t;
|
||||
// use only the least byte of millisecond timer
|
||||
asm("lds %0, %1" : "=r" (t) : "p" (&timer_count));
|
||||
//t = (uint8_t)timer_count; // compiler uses four registers instead of one
|
||||
if (isr_state == 0x8000) {
|
||||
timer_start = t;
|
||||
} else {
|
||||
// This gives 2.0ms at least before timeout
|
||||
if ((uint8_t)(t - timer_start) >= 3) {
|
||||
ibmpc_isr_debug = isr_state;
|
||||
ibmpc_error = IBMPC_ERR_TIMEOUT;
|
||||
goto ERROR;
|
||||
|
||||
// timeout error recovery - start receiving new data
|
||||
// it seems to work somehow but may not under unstable situation
|
||||
//timer_start = t;
|
||||
//isr_state = 0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
isr_state = isr_state>>1;
|
||||
if (dbit) isr_state |= 0x8000;
|
||||
|
||||
// isr_state: state of receiving data from keyboard
|
||||
//
|
||||
// This should be initialized with 0x8000 before receiving data and
|
||||
// the MSB '*1' works as marker to discrimitate between protocols.
|
||||
// It stores sampled bit at MSB after right shift on each clock falling edge.
|
||||
//
|
||||
// XT protocol has two variants of signaling; XT_IBM and XT_Clone.
|
||||
// XT_IBM uses two start bits 0 and 1 while XT_Clone uses just start bit 1.
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
|
||||
//
|
||||
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
// -----------------------------------------------------
|
||||
// *1 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 Initial state(0x8000)
|
||||
//
|
||||
// x x x x x x x x | 0 0 0 0 0 0 0 0 midway(0-7 bits received)
|
||||
// x x x x x x x x | *1 0 0 0 0 0 0 0 midway(8 bits received)
|
||||
// b6 b5 b4 b3 b2 b1 b0 1 | 0 *1 0 0 0 0 0 0 XT_IBM-midway ^1
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 0 *1 0 0 0 0 0 0 AT-midway ^1
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 *1 0 0 0 0 0 0 XT_Clone-done ^3
|
||||
// b6 b5 b4 b3 b2 b1 b0 1 | 1 *1 0 0 0 0 0 0 XT_IBM-error ^3
|
||||
// pr b7 b6 b5 b4 b3 b2 b1 | 0 0 *1 0 0 0 0 0 AT-midway[b0=0]
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 0 *1 0 0 0 0 0 XT_IBM-done ^2
|
||||
// pr b7 b6 b5 b4 b3 b2 b1 | 1 0 *1 0 0 0 0 0 AT-midway[b0=1] ^2
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 1 *1 0 0 0 0 0 XT_IBM-error-done
|
||||
// x x x x x x x x | x 1 1 0 0 0 0 0 illegal
|
||||
// st pr b7 b6 b5 b4 b3 b2 | b1 b0 0 *1 0 0 0 0 AT-done
|
||||
// x x x x x x x x | x x 1 *1 0 0 0 0 illegal
|
||||
// all other states than above illegal
|
||||
//
|
||||
// ^1: AT and XT_IBM takes same state.
|
||||
// ^2: AT and XT_IBM takes same state in case that AT b0 is 1,
|
||||
// we have to check AT stop bit to discriminate between the two protocol.
|
||||
switch (isr_state & 0xFF) {
|
||||
case 0b00000000:
|
||||
case 0b10000000:
|
||||
case 0b01000000: // ^1
|
||||
case 0b00100000:
|
||||
// midway
|
||||
goto NEXT;
|
||||
break;
|
||||
case 0b11000000: // ^3
|
||||
{
|
||||
uint8_t us = 100;
|
||||
// wait for rising and falling edge of b7 of XT_IBM
|
||||
while (!(IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT)) && us) { wait_us(1); us--; }
|
||||
while ( IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT) && us) { wait_us(1); us--; }
|
||||
|
||||
if (us) {
|
||||
// XT_IBM-error: read start(0) as 1
|
||||
goto NEXT;
|
||||
} else {
|
||||
// XT_Clone-done
|
||||
ibmpc_isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_XT_CLONE;
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0b11100000:
|
||||
// XT_IBM-error-done
|
||||
ibmpc_isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_XT_ERROR;
|
||||
goto DONE;
|
||||
break;
|
||||
case 0b10100000: // ^2
|
||||
{
|
||||
uint8_t us = 100;
|
||||
// wait for rising and falling edge of AT stop bit to discriminate between XT and AT
|
||||
while (!(IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT)) && us) { wait_us(1); us--; }
|
||||
while ( IBMPC_CLOCK_PIN&(1<<IBMPC_CLOCK_BIT) && us) { wait_us(1); us--; }
|
||||
|
||||
if (us) {
|
||||
// found stop bit: AT-midway - process the stop bit in next ISR
|
||||
goto NEXT;
|
||||
} else {
|
||||
// no stop bit: XT_IBM-done
|
||||
ibmpc_isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_XT_IBM;
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0b00010000:
|
||||
case 0b10010000:
|
||||
case 0b01010000:
|
||||
case 0b11010000:
|
||||
// AT-done
|
||||
// TODO: parity check?
|
||||
ibmpc_isr_debug = isr_state;
|
||||
// stop bit check
|
||||
if (isr_state & 0x8000) {
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_AT;
|
||||
} else {
|
||||
// Zenith Z-150 AT(beige/white lable) asserts stop bit as low
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-AT-Keyboard-Protocol#zenith-z-150-beige
|
||||
ibmpc_protocol = IBMPC_PROTOCOL_AT_Z150;
|
||||
}
|
||||
isr_state = isr_state>>6;
|
||||
goto DONE;
|
||||
break;
|
||||
case 0b01100000:
|
||||
case 0b00110000:
|
||||
case 0b10110000:
|
||||
case 0b01110000:
|
||||
case 0b11110000:
|
||||
default: // xxxx_oooo(any 1 in low nibble)
|
||||
// Illegal
|
||||
ibmpc_isr_debug = isr_state;
|
||||
ibmpc_error = IBMPC_ERR_ILLEGAL;
|
||||
goto ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
DONE:
|
||||
// store data
|
||||
ringbuf_push(&rb, isr_state & 0xFF);
|
||||
if (ringbuf_is_full(&rb)) {
|
||||
// just became full
|
||||
// Disable ISR if buffer is full
|
||||
IBMPC_INT_OFF();
|
||||
// inhibit: clock_lo
|
||||
IBMPC_CLOCK_PORT &= ~(1<<IBMPC_CLOCK_BIT);
|
||||
IBMPC_CLOCK_DDR |= (1<<IBMPC_CLOCK_BIT);
|
||||
}
|
||||
if (ringbuf_is_empty(&rb)) {
|
||||
// buffer overflow
|
||||
ibmpc_error = IBMPC_ERR_FULL;
|
||||
}
|
||||
ERROR:
|
||||
// clear for next data
|
||||
isr_state = 0x8000;
|
||||
NEXT:
|
||||
return;
|
||||
}
|
||||
|
||||
/* send LED state to keyboard */
|
||||
void ibmpc_host_set_led(uint8_t led)
|
||||
{
|
||||
if (0xFA == ibmpc_host_send(0xED)) {
|
||||
ibmpc_host_send(led);
|
||||
}
|
||||
}
|
||||
|
|
@ -92,15 +92,12 @@ int16_t IBMPC::host_send(uint8_t data)
|
|||
|
||||
dprintf("w%02X ", data);
|
||||
|
||||
// Not receiving data
|
||||
if (isr_state != 0x8000) dprintf("isr:%04X ", isr_state);
|
||||
while (isr_state != 0x8000) ;
|
||||
|
||||
// Not clock Lo
|
||||
if (!clock_in()) dprintf("c:%u ", wait_clock_hi(1000));
|
||||
|
||||
// Not data Lo
|
||||
if (!data_in()) dprintf("d:%u ", wait_data_hi(1000));
|
||||
// Return when receiving data
|
||||
//if (isr_state & 0x0FFF) {
|
||||
if (isr_state != 0x8000) {
|
||||
dprintf("isr:%04X ", isr_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int_off();
|
||||
|
||||
|
|
@ -113,7 +110,7 @@ RETRY:
|
|||
data_lo();
|
||||
wait_us(200);
|
||||
clock_hi(); // [5]p.54 [clock low]>100us [5]p.50
|
||||
WAIT(clock_lo, 10000, 1); // [5]p.53, -10ms [5]p.50
|
||||
WAIT(clock_lo, 15000, 1); // [5]p.54 T13M, -10ms [5]p.50
|
||||
|
||||
/* Data bit[2-9] */
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
|
|
@ -157,6 +154,7 @@ ERROR:
|
|||
goto RETRY;
|
||||
}
|
||||
|
||||
isr_debug = isr_state;
|
||||
error |= IBMPC_ERR_SEND;
|
||||
inhibit();
|
||||
wait_ms(2);
|
||||
|
|
@ -206,7 +204,7 @@ void IBMPC::host_isr_clear(void)
|
|||
ringbuf_reset();
|
||||
}
|
||||
|
||||
inline void IBMPC::isr(void)
|
||||
void IBMPC::isr(void)
|
||||
{
|
||||
uint8_t dbit;
|
||||
dbit = IBMPC_DATA_PIN&(1<<data_bit);
|
||||
|
|
@ -220,7 +218,7 @@ inline void IBMPC::isr(void)
|
|||
timer_start = t;
|
||||
} else {
|
||||
// This gives 2.0ms at least before timeout
|
||||
if ((uint8_t)(t - timer_start) >= 3) {
|
||||
if ((uint8_t)(t - timer_start) >= 5) {
|
||||
isr_debug = isr_state;
|
||||
error = IBMPC_ERR_TIMEOUT;
|
||||
goto ERROR;
|
||||
|
|
@ -253,13 +251,12 @@ inline void IBMPC::isr(void)
|
|||
// x x x x x x x x | *1 0 0 0 0 0 0 0 midway(8 bits received)
|
||||
// b6 b5 b4 b3 b2 b1 b0 1 | 0 *1 0 0 0 0 0 0 XT_IBM-midway ^1
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 0 *1 0 0 0 0 0 0 AT-midway ^1
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 *1 0 0 0 0 0 0 XT_Clone-done ^3
|
||||
// b6 b5 b4 b3 b2 b1 b0 1 | 1 *1 0 0 0 0 0 0 XT_IBM-error ^3
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 *1 0 0 0 0 0 0 XT_Clone-done
|
||||
// pr b7 b6 b5 b4 b3 b2 b1 | 0 0 *1 0 0 0 0 0 AT-midway[b0=0]
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 0 *1 0 0 0 0 0 XT_IBM-done ^2
|
||||
// pr b7 b6 b5 b4 b3 b2 b1 | 1 0 *1 0 0 0 0 0 AT-midway[b0=1] ^2
|
||||
// b7 b6 b5 b4 b3 b2 b1 b0 | 1 1 *1 0 0 0 0 0 XT_IBM-error-done
|
||||
// x x x x x x x x | 0 1 *1 0 0 0 0 0 illegal
|
||||
// x x x x x x x x | 1 1 *1 0 0 0 0 0 illegal
|
||||
// st pr b7 b6 b5 b4 b3 b2 | b1 b0 0 *1 0 0 0 0 AT-done
|
||||
// x x x x x x x x | x x 1 *1 0 0 0 0 illegal
|
||||
// all other states than above illegal
|
||||
|
|
@ -275,34 +272,11 @@ inline void IBMPC::isr(void)
|
|||
// midway
|
||||
goto NEXT;
|
||||
break;
|
||||
case 0b11000000: // ^3
|
||||
{
|
||||
uint8_t us = 100;
|
||||
// wait for rising and falling edge of b7 of XT_IBM
|
||||
if (!protocol) {
|
||||
while (!(IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
while ( (IBMPC_CLOCK_PIN & clock_mask) && us) { wait_us(1); us--; }
|
||||
} else if (protocol == IBMPC_PROTOCOL_XT_CLONE) {
|
||||
us = 0;
|
||||
}
|
||||
|
||||
if (us) {
|
||||
// XT_IBM-error: read start(0) as 1
|
||||
goto NEXT;
|
||||
} else {
|
||||
// XT_Clone-done
|
||||
isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
protocol = IBMPC_PROTOCOL_XT_CLONE;
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0b11100000:
|
||||
// XT_IBM-error-done
|
||||
case 0b11000000:
|
||||
// XT_Clone-done
|
||||
isr_debug = isr_state;
|
||||
isr_state = isr_state>>8;
|
||||
protocol = IBMPC_PROTOCOL_XT_ERROR;
|
||||
protocol = IBMPC_PROTOCOL_XT_CLONE;
|
||||
goto DONE;
|
||||
break;
|
||||
case 0b10100000: // ^2
|
||||
|
|
@ -326,15 +300,39 @@ inline void IBMPC::isr(void)
|
|||
protocol = IBMPC_PROTOCOL_XT_IBM;
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0b00010000:
|
||||
case 0b10010000:
|
||||
case 0b01010000:
|
||||
case 0b11010000:
|
||||
// AT-done
|
||||
// TODO: parity check?
|
||||
isr_debug = isr_state;
|
||||
|
||||
// Detect AA with parity error for AT/XT Auto-Switching support
|
||||
// https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-Keyboard-Converter#atxt-auto-switching
|
||||
// isr_state: st pr b7 b6 b5 b4 b3 b2 | b1 b0 0 *1 0 0 0 0
|
||||
// 1 '0' 1 0 1 0 1 0 | 1 0 0 *1 0 0 0 0
|
||||
if (isr_state == 0xAA90) {
|
||||
error = IBMPC_ERR_PARITY_AA;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
// parit bit check
|
||||
{
|
||||
// isr_state: st pr b7 b6 b5 b4 b3 b2 | b1 b0 0 *1 0 0 0 0
|
||||
uint8_t p = (isr_state & 0x4000) ? 1 : 0;
|
||||
p ^= (isr_state >> 6);
|
||||
while (p & 0xFE) {
|
||||
p = (p >> 1) ^ (p & 0x01);
|
||||
}
|
||||
|
||||
if (p == 0) {
|
||||
error = IBMPC_ERR_PARITY;
|
||||
goto ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// stop bit check
|
||||
if (isr_state & 0x8000) {
|
||||
protocol = IBMPC_PROTOCOL_AT;
|
||||
|
|
@ -347,6 +345,7 @@ inline void IBMPC::isr(void)
|
|||
goto DONE;
|
||||
break;
|
||||
case 0b01100000:
|
||||
case 0b11100000:
|
||||
case 0b00110000:
|
||||
case 0b10110000:
|
||||
case 0b01110000:
|
||||
|
|
@ -373,7 +372,11 @@ DONE:
|
|||
// buffer overflow
|
||||
error = IBMPC_ERR_FULL;
|
||||
}
|
||||
goto END;
|
||||
ERROR:
|
||||
// inhibit: Use clock_lo() instead of inhibit() for ISR optimization
|
||||
clock_lo();
|
||||
END:
|
||||
// clear for next data
|
||||
isr_state = 0x8000;
|
||||
NEXT:
|
||||
|
|
|
|||
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
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_NO 0
|
||||
#define IBMPC_PROTOCOL_AT 0x10
|
||||
#define IBMPC_PROTOCOL_AT_Z150 0x11
|
||||
#define IBMPC_PROTOCOL_XT 0x20
|
||||
#define IBMPC_PROTOCOL_XT_IBM 0x21
|
||||
#define IBMPC_PROTOCOL_XT_CLONE 0x22
|
||||
#define IBMPC_PROTOCOL_XT_ERROR 0x23
|
||||
|
||||
// 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_ERR_ILLEGAL 0x80
|
||||
#define IBMPC_ERR_FF 0xF0
|
||||
|
||||
#define IBMPC_LED_SCROLL_LOCK 0
|
||||
#define IBMPC_LED_NUM_LOCK 1
|
||||
#define IBMPC_LED_CAPS_LOCK 2
|
||||
|
||||
|
||||
extern volatile uint16_t ibmpc_isr_debug;
|
||||
extern volatile uint8_t ibmpc_protocol;
|
||||
extern volatile uint8_t ibmpc_error;
|
||||
|
||||
void ibmpc_host_init(void);
|
||||
void ibmpc_host_enable(void);
|
||||
void ibmpc_host_disable(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_isr_clear(void);
|
||||
void ibmpc_host_set_led(uint8_t usb_led);
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* static functions
|
||||
*------------------------------------------------------------------*/
|
||||
#if defined(__AVR__)
|
||||
/*
|
||||
* Clock
|
||||
*/
|
||||
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_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(AT), soft reset(XT) */
|
||||
static inline void inhibit(void)
|
||||
{
|
||||
clock_lo();
|
||||
data_hi();
|
||||
}
|
||||
|
||||
/* inhibit device to send(XT) */
|
||||
static inline void inhibit_xt(void)
|
||||
{
|
||||
clock_hi();
|
||||
data_lo();
|
||||
}
|
||||
#endif
|
||||
|
|
@ -75,11 +75,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define IBMPC_PROTOCOL_XT 0x20
|
||||
#define IBMPC_PROTOCOL_XT_IBM 0x21
|
||||
#define IBMPC_PROTOCOL_XT_CLONE 0x22
|
||||
#define IBMPC_PROTOCOL_XT_ERROR 0x23
|
||||
|
||||
// Error numbers
|
||||
#define IBMPC_ERR_NONE 0
|
||||
#define IBMPC_ERR_RECV 0x00
|
||||
#define IBMPC_ERR_PARITY 0x01
|
||||
#define IBMPC_ERR_PARITY_AA 0x02
|
||||
#define IBMPC_ERR_SEND 0x10
|
||||
#define IBMPC_ERR_TIMEOUT 0x20
|
||||
#define IBMPC_ERR_FULL 0x40
|
||||
|
|
@ -118,7 +118,7 @@ class IBMPC
|
|||
clock_mask(1 << clock), data_mask(1 << data) {
|
||||
};
|
||||
|
||||
inline void isr(void) __attribute__((__always_inline__));
|
||||
void isr(void);
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -430,7 +430,8 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.InterfaceNumber = CONSOLE_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 2,
|
||||
//.TotalEndpoints = 2,
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
|
|
@ -460,6 +461,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
|
||||
/*
|
||||
.Console_OUTEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
|
@ -469,6 +471,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
|||
.EndpointSize = CONSOLE_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ typedef struct
|
|||
USB_Descriptor_Interface_t Console_Interface;
|
||||
USB_HID_Descriptor_HID_t Console_HID;
|
||||
USB_Descriptor_Endpoint_t Console_INEndpoint;
|
||||
USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
||||
// USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
||||
#endif
|
||||
|
||||
#if !defined(NO_KEYBOARD) && defined(NKRO_6KRO_ENABLE)
|
||||
|
|
@ -127,8 +127,14 @@ typedef struct
|
|||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
# define CONSOLE_IN_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
# define CONSOLE_OUT_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
// ATMega32U2 doesn't support double bank on endpoint 1 and 2, use 3 or 4
|
||||
# if MOUSE_IN_EPNUM < 2
|
||||
# define CONSOLE_IN_EPNUM 3
|
||||
# define CONSOLE_OUT_EPNUM 3
|
||||
# else
|
||||
# define CONSOLE_IN_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
# define CONSOLE_OUT_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
# endif
|
||||
#else
|
||||
# define CONSOLE_OUT_EPNUM MOUSE_IN_EPNUM
|
||||
#endif
|
||||
|
|
@ -153,7 +159,7 @@ typedef struct
|
|||
#define MOUSE_EPSIZE 8
|
||||
#endif
|
||||
|
||||
#define CONSOLE_EPSIZE 32
|
||||
#define CONSOLE_EPSIZE 64
|
||||
#define NKRO_EPSIZE 32
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -354,9 +354,10 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
|||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
// ATMega32U2 doesn't support double bank on endpoint 1 and 2, use 3 or 4
|
||||
/* Setup Console HID Report Endpoints */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
|
||||
#if 0
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
|
||||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
|
|
@ -761,7 +762,11 @@ int main(void)
|
|||
|
||||
#ifndef NO_USB_STARTUP_WAIT_LOOP
|
||||
/* wait for USB startup */
|
||||
while (USB_DeviceState != DEVICE_STATE_Configured) {
|
||||
while (USB_DeviceState != DEVICE_STATE_Configured
|
||||
#ifdef CONSOLE_ENABLE
|
||||
|| !console_is_ready()
|
||||
#endif
|
||||
) {
|
||||
#if defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
static report_mouse_t mouse_report = {};
|
||||
static uint8_t last_buttons;
|
||||
|
||||
|
||||
static void print_usb_data(void);
|
||||
|
|
@ -161,6 +162,7 @@ void ps2_mouse_task(void)
|
|||
|
||||
|
||||
host_mouse_send(&mouse_report);
|
||||
last_buttons = mouse_report.buttons;
|
||||
print_usb_data();
|
||||
}
|
||||
// clear report
|
||||
|
|
@ -171,6 +173,11 @@ void ps2_mouse_task(void)
|
|||
mouse_report.buttons = 0;
|
||||
}
|
||||
|
||||
uint8_t ps2_mouse_buttons(void)
|
||||
{
|
||||
return last_buttons;
|
||||
}
|
||||
|
||||
static void print_usb_data(void)
|
||||
{
|
||||
if (!debug_mouse) return;
|
||||
|
|
|
|||
|
|
@ -62,5 +62,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
uint8_t ps2_mouse_init(void);
|
||||
void ps2_mouse_task(void);
|
||||
uint8_t ps2_mouse_buttons(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,5 +29,6 @@ static inline uint8_t serial_mouse_init(void)
|
|||
}
|
||||
|
||||
void serial_mouse_task(void);
|
||||
uint8_t serial_mouse_buttons(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#endif
|
||||
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
|
||||
|
||||
static uint8_t last_buttons;
|
||||
static void print_usb_data(const report_mouse_t *report);
|
||||
|
||||
void serial_mouse_task(void)
|
||||
|
|
@ -71,6 +72,7 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +113,12 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
}
|
||||
|
||||
uint8_t serial_mouse_buttons(void)
|
||||
{
|
||||
return last_buttons;
|
||||
}
|
||||
|
||||
static void print_usb_data(const report_mouse_t *report)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
//#define SERIAL_MOUSE_CENTER_SCROLL
|
||||
|
||||
static uint8_t last_buttons;
|
||||
static void print_usb_data(const report_mouse_t *report);
|
||||
|
||||
void serial_mouse_task(void)
|
||||
|
|
@ -78,6 +79,7 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
|
||||
if (buffer[3] || buffer[4]) {
|
||||
report.h = MAX((int8_t)buffer[3], -127);
|
||||
|
|
@ -85,6 +87,7 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -117,9 +120,15 @@ void serial_mouse_task(void)
|
|||
|
||||
print_usb_data(&report);
|
||||
host_mouse_send(&report);
|
||||
last_buttons = report.buttons;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t serial_mouse_buttons(void)
|
||||
{
|
||||
return last_buttons;
|
||||
}
|
||||
|
||||
static void print_usb_data(const report_mouse_t *report)
|
||||
{
|
||||
if (!debug_mouse)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,9 @@ void serial_init(void)
|
|||
}
|
||||
|
||||
// RX ring buffer
|
||||
#ifndef RBUF_SIZE
|
||||
#define RBUF_SIZE 256
|
||||
#endif
|
||||
static uint8_t rbuf[RBUF_SIZE];
|
||||
static uint8_t rbuf_head = 0;
|
||||
static uint8_t rbuf_tail = 0;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 96112d43858b5c5327565c36bd8ea2192ec77d1b
|
||||
Subproject commit e37ed6cf28b45db8022fd513b338d22c5515afed
|
||||
Loading…
Add table
Reference in a new issue