Merge branch 'pc98_update'

This commit is contained in:
tmk 2018-09-08 21:25:41 +09:00
commit 4650d2e575
5 changed files with 100 additions and 170 deletions

View file

@ -1,26 +1,25 @@
# Target file name (without extension). # Target file name (without extension).
TARGET = pc98_usb TARGET ?= pc98_usb
# Directory common source filess exist # Directory common source filess exist
TMK_DIR = ../../tmk_core TMK_DIR ?= ../../tmk_core
# Directory keyboard dependent files exist # Directory keyboard dependent files exist
TARGET_DIR = . TARGET_DIR ?= .
# keyboard dependent files # keyboard dependent files
SRC = matrix.c \ # Add one of lines below to select serial protocol implementation
# protocol/serial_uart.c
# protocol/serial_soft.c
SRC ?= matrix.c \
protocol/serial_uart.c protocol/serial_uart.c
CONFIG_H = config.h CONFIG_H ?= config.h
# MCU name, you MUST set this to match the board you are using # MCU name, you MUST set this to match the board you are using
# type "make clean" after changing this, so all files will be rebuilt # type "make clean" after changing this, so all files will be rebuilt
#MCU = at90usb162 # Teensy 1.0 MCU ?= atmega32u2 # TMK Converter
#MCU = atmega32u4 # Teensy 2.0
#MCU = at90usb646 # Teensy++ 1.0
#MCU = at90usb1286 # Teensy++ 2.0
MCU = atmega32u2 # TMK Converter
# Processor frequency. # Processor frequency.
@ -28,14 +27,14 @@ MCU = atmega32u2 # TMK Converter
# so your program will run at the correct speed. You should also set this # so your program will run at the correct speed. You should also set this
# variable to same clock speed. The _delay_ms() macro uses this, and many # variable to same clock speed. The _delay_ms() macro uses this, and many
# examples use this variable to calculate timings. Do not add a "UL" here. # examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000 F_CPU ?= 16000000
# #
# LUFA specific # LUFA specific
# #
# Target architecture (see library "Board Types" documentation). # Target architecture (see library "Board Types" documentation).
ARCH = AVR8 ARCH ?= AVR8
# Input clock frequency. # Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the # This will define a symbol, F_USB, in all source code files equal to the
@ -48,7 +47,7 @@ ARCH = AVR8
# #
# If no clock division is performed on the input clock inside the AVR (via the # If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. # CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU) F_USB ?= $(F_CPU)
# Interrupt driven control endpoint task # Interrupt driven control endpoint task
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
@ -57,12 +56,12 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Build Options # Build Options
# *Comment out* to disable the options. # *Comment out* to disable the options.
# #
MOUSEKEY_ENABLE = yes # Mouse keys MOUSEKEY_ENABLE ?= yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control EXTRAKEY_ENABLE ?= yes # Audio control and System control
CONSOLE_ENABLE = yes # Console for debug CONSOLE_ENABLE ?= yes # Console for debug
COMMAND_ENABLE = yes # Commands for debug and configuration COMMAND_ENABLE ?= yes # Commands for debug and configuration
#NKRO_ENABLE = yes # USB Nkey Rollover #NKRO_ENABLE ?= yes # USB Nkey Rollover
UNIMAP_ENABLE = yes UNIMAP_ENABLE ?= yes
# Boot Section Size in bytes # Boot Section Size in bytes

View file

@ -25,7 +25,7 @@ Wiring: You can change this with editing config.h.
2 GND GND 2 GND GND
3 ~RDY PD4 3 ~RDY PD4
4 RXD PD2 4 RXD PD2
5 ~RTY PD5 5 ~RTY PD1
6 NC 6 NC
7 NC 7 NC
8 5V VCC 8 5V VCC
@ -42,7 +42,7 @@ Frame format: 1-Start bit(Lo), 8-Data bits, Odd-Parity, 1-Stop bit
Build Firmware Build Firmware
-------------- --------------
Just use 'make' to bild firmware Just use 'make' to bild firmware for TMK PC98 converter.
$ make clean $ make clean
$ make $ make
@ -53,6 +53,12 @@ To flash firmware
then push button on converter to flash firmware. then push button on converter to flash firmware.
If you are using ATMega32u4 based board instead of premade TMK PC98 converter(ATMega32u2) use following commands.
$ make -f Makefile.32u4 clean
$ make -f Makefile.32u4
$ make -f Makefile.32u4 dfu
PC98 Scan Codes PC98 Scan Codes
@ -140,6 +146,10 @@ Its scan code map is very different from standard types. This is not tested.
Other PC98 converter projects and resource 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
PC98 to USB PC98 to USB
http://davy.nyacom.net/kbd98usb/ http://davy.nyacom.net/kbd98usb/
@ -149,3 +159,25 @@ http://www.tsp.ne.jp/~sawada/mago/src/gka98at.asm
scan code: scan code:
http://ixsvr.dyndns.org/usb2pc98 http://ixsvr.dyndns.org/usb2pc98
NOTES
-----
### Tested on
- PC-9801V
- DIGITAL WAVE Dboard
### RDY
Current firmware does not control RDY line and it is drived as low to receive data always. While sending command firmware drive the line high.
PC98 host keeps RDY line high to prevent keyboard from sending data while processing.
https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n359
### Inhibit key repeating
The command(9Ch, 70h) works with Raku Raku keybaord but not with Dboard.
### LED indicater
Dboard has LEDs but it seems to ignore LED control command.

View file

@ -43,7 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define LOCKING_RESYNC_ENABLE #define LOCKING_RESYNC_ENABLE
/* Control LED indicatiors, which doesn't work well with locking support */ /* Control LED indicatiors, which doesn't work well with locking support */
//#define PC98_LED_CONTROL #define PC98_LED_CONTROL
/* PC98 Reset Port shared with TXD */ /* PC98 Reset Port shared with TXD */
@ -64,8 +64,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* asynchronous, positive logic, 19200baud, bit order: LSB first * asynchronous, positive logic, 19200baud, bit order: LSB first
* 1-start bit, 8-data bit, odd parity, 1-stop bit * 1-start bit, 8-data bit, odd parity, 1-stop bit
*/ */
/* /*
* Software Serial * Software Serial
* Add protocol/serial_soft.c to SRC in Makefile
*/ */
#define SERIAL_SOFT_BAUD 19200 #define SERIAL_SOFT_BAUD 19200
#define SERIAL_SOFT_PARITY_ODD #define SERIAL_SOFT_PARITY_ODD
@ -110,6 +112,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* /*
* Hardware Serial(UART) * Hardware Serial(UART)
* Add protocol/serial_uart.c to SRC in Makefile
*/ */
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__)
#define SERIAL_UART_BAUD 19200 #define SERIAL_UART_BAUD 19200

View file

@ -1,115 +0,0 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "util.h"
#include "keymap.h"
/* PC-9801-98-S02 Raku Raku keyboard(Luckyboard) Normal Mode
,---------------------------------------------------------------.
| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 6A| 6B| 36| 37| 3F| 3E|
`---------------------------------------------------------------'
,---------------------------------------------------------------.
| 00| 01| 02| 03| 04| 05| 58| 71| 06| 07| 08| 09| 0A| 0E|
|---------------------------------------------------------------|
| 0F| 10| 11| 12| 13| 14| 3A | 15| 16| 17| 18| 19| 1C|
|---------------------------------------------------------'. |
| 74| 20| 21| 22| 23| 24| 3B | 3C | 25| 26| 27| 28| 29| |
|---------------------------------------------------------------|
| 70| 2A| 2B| 2C| 2D| 2E| 38| 3D | 39| 2F| 30| 31| 32| 33| 70|
`---------------------------------------------------------------'
| 73| 51| 5B| 59| 34| 5A| 35| xx|
`-----------------------------------------------'
xx: 74 35 F4 B5
*/
#define KEYMAP( \
K60, K61, K62, K63, K64, K65, K66, K67, K68, K69, K6A, K6B, K36, K37, K3F, K3E, \
K00, K01, K02, K03, K04, K05, K58, K71, K06, K07, K08, K09, K0A, K0E, \
K0F, K10, K11, K12, K13, K14, K3A, K15, K16, K17, K18, K19, K1C, \
K74, K20, K21, K22, K23, K24, K3B, K3C, K25, K26, K27, K28, K29, \
K70,K2A, K2B, K2C, K2D, K2E, K38, K3D, K39, K2F, K30, K31, K32, K33, \
K73, K51, K5B, K59, K34, K5A, K35 \
) { \
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
{ KC_##K08, KC_##K09, KC_##K0A, KC_NO, KC_NO, KC_NO, KC_##K0E, KC_##K0F }, \
{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
{ KC_##K18, KC_##K19, KC_NO, KC_NO, KC_##K1C, KC_NO, KC_NO, KC_NO }, \
{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
{ KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F }, \
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
{ KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_##K51, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67 }, \
{ KC_##K68, KC_##K69, KC_##K6A, KC_##K6B, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_##K70, KC_##K71, KC_NO, KC_##K73, KC_##K74, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO } \
}
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
,---------------------------------------------------------------.
| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 6A| 6B| 36| 37| 3F| 3E|
`---------------------------------------------------------------'
,---------------------------------------------------------------.
| 00| 01| 02| 03| 04| 05| 58| 71| 06| 07| 08| 09| 0A| 0E|
|---------------------------------------------------------------|
| 0F| 10| 11| 12| 13| 14| 3A | 15| 16| 17| 18| 19| 1C|
|---------------------------------------------------------------|
| 74| 20| 21| 22| 23| 24| MINS| EQL| 25| 26| 27| 28| 29| |
|---------------------------------------------------------------|
| 70| 2A| 2B| 2C| 2D| 2E| 38| 3D | 39| 2F| 30| 31| 32| 33| 70|
`---------------------------------------------------------------'
| 73| 51| 5B| 59| 34| 5A| 35| xx|
`-----------------------------------------------'
*/
KEYMAP(
STOP,PSCR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14,
ESC, 1, 2, 3, 4, 5, LNUM,LCAP, 6, 7, 8, 9, 0, BSPC,
TAB, Q, W, E, R, T, UP, Y, U, I, O, P, ENT,
LCTL, A, S, D, F, G, LEFT, RGHT, H, J, K, L,SCLN,
LSFT, Z, X, C, V, B, INS, DOWN, DEL, N, M,COMM, DOT,SLSH,
LGUI, LALT, LCTL, FN0, SPC, FN0, RALT
),
KEYMAP(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,SLCK,PAUS,
GRV, TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS, TRNS,TRNS,TRNS,MINS, EQL, BSLS,
TRNS, TRNS,TRNS,TRNS,TRNS,TRNS, PGUP, TRNS,TRNS,TRNS,LBRC,RBRC, TRNS,
TRNS, TRNS,TRNS,TRNS,TRNS,TRNS, HOME, END, TRNS,TRNS,TRNS,TRNS,QUOT,
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, PGDN, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS
),
};
/*
* Fn actions
*/
const action_t PROGMEM fn_actions[] = {
ACTION_LAYER_MOMENTARY(1), // FN0
};

View file

@ -68,23 +68,34 @@ static int16_t pc98_wait_response(void)
static void pc98_inhibit_repeat(void) static void pc98_inhibit_repeat(void)
{ {
uint16_t code; uint16_t code;
// clear recv buffer
while (serial_recv()) ;
RETRY: RETRY:
_delay_ms(100);
pc98_send(0x9C); pc98_send(0x9C);
code = pc98_wait_response(); code = pc98_wait_response();
if (code != -1) xprintf("PC98: send 9C: %02X\n", code); if (code != -1) xprintf("PC98: send 9C: %02X\n", code);
if (code != 0xFA) goto RETRY; if (code != 0xFA) goto RETRY;
_delay_ms(100);
pc98_send(0x70); pc98_send(0x70);
code = pc98_wait_response(); code = pc98_wait_response();
if (code != -1) xprintf("PC98: send 70: %02X\n", code); if (code != -1) xprintf("PC98: send 70: %02X\n", code);
if (code != 0xFA) goto RETRY; if (code != 0xFA) goto RETRY;
} }
static uint8_t pc98_led = 0;
static void pc98_led_set(void)
{
uint16_t code;
RETRY:
pc98_send(0x9D);
code = pc98_wait_response();
if (code != -1) xprintf("PC98: send 9D: %02X\n", code);
if (code != 0xFA) goto RETRY;
pc98_send(pc98_led);
code = pc98_wait_response();
if (code != -1) xprintf("PC98: send %02X: %02X\n", pc98_led, code);
if (code != 0xFA) goto RETRY;
}
void matrix_init(void) void matrix_init(void)
{ {
debug_keyboard = true; debug_keyboard = true;
@ -99,36 +110,40 @@ void matrix_init(void)
serial_init(); serial_init();
// PC98 reset // PC98 reset
/* // https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n359
PC98_RST_PORT &= ~(1<<PC98_RST_BIT); PC98_RDY_PORT |= (1<<PC98_RDY_BIT); // RDY: high
_delay_us(15); PC98_RST_PORT &= ~(1<<PC98_RST_BIT); // RST: low
PC98_RST_PORT |= (1<<PC98_RST_BIT); _delay_us(15); // > 13us
_delay_us(13); PC98_RST_PORT |= (1<<PC98_RST_BIT); // RST: high
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
*/
_delay_ms(500); _delay_ms(50);
pc98_inhibit_repeat(); pc98_inhibit_repeat();
// PC98 ready
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
// initialize matrix state: all keys off // initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
debug("init\n"); // ready to receive from keyboard
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT); // RDY: low
print("matrix_init done.\n");
return; return;
} }
uint8_t matrix_scan(void) uint8_t matrix_scan(void)
{ {
uint16_t code; uint16_t code;
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
//_delay_us(30);
code = serial_recv2(); code = serial_recv2();
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT); if (code == -1) {
if (code == -1) return 0; #ifdef PC98_LED_CONTROL
// Before sending command we have to make sure that there is no unprocessed key in queue
// otherwise keys will be missed during sending command
if (pc98_led) {
pc98_led_set();
pc98_led = 0;
}
#endif
return 0;
}
print_hex8(code); print(" "); print_hex8(code); print(" ");
@ -154,15 +169,11 @@ uint8_t matrix_get_row(uint8_t row)
void led_set(uint8_t usb_led) void led_set(uint8_t usb_led)
{ {
#ifdef PC98_LED_CONTROL // https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n161
uint8_t led_state = 0x70; // http://www.webtech.co.jp/company/doc/undocumented_mem/io_kb.txt
if (usb_led & (1<<USB_LED_NUM_LOCK)) led_state |= (1<<0); pc98_led = 0x70;
if (usb_led & (1<<USB_LED_CAPS_LOCK)) led_state |= (1<<2); if (usb_led & (1<<USB_LED_NUM_LOCK)) pc98_led |= (1<<0);
xprintf("led_set: %02X\n", led_state); if (usb_led & (1<<USB_LED_CAPS_LOCK)) pc98_led |= (1<<2);
xprintf("usb_led: %02X\n", usb_led);
pc98_send(0x9D); xprintf("pc98_led: %02X\n", pc98_led);
_delay_ms(100);
pc98_send(led_state);
// responses(FA or FC) will be ignored in matrix_scan()
#endif
} }