]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - converter/pc98_usb/matrix.c
pc98_usb: Fix RDY line and startup for PC-9801V
[max/tmk_keyboard.git] / converter / pc98_usb / matrix.c
index 8833e0a851badc6cc1693771a48fe64e5f07554b..84a29382d52665a3c9d544b568db670596f9e4db 100644 (file)
@@ -22,6 +22,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "print.h"
 #include "util.h"
 #include "matrix.h"
+#include "led.h"
 #include "debug.h"
 #include "protocol/serial.h"
 
@@ -46,53 +47,58 @@ static uint8_t matrix[MATRIX_ROWS];
 #define ROW(code)      ((code>>3)&0xF)
 #define COL(code)      (code&0x07)
 
-static bool is_modified = false;
 
-
-inline
-uint8_t matrix_rows(void)
+static void pc98_send(uint8_t data)
 {
-    return MATRIX_ROWS;
+    PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
+    _delay_ms(1);
+    serial_send(data);
+    _delay_ms(1);
+    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
 }
 
-inline
-uint8_t matrix_cols(void)
+static int16_t pc98_wait_response(void)
 {
-    return MATRIX_COLS;
+    int16_t code = -1;
+    uint8_t timeout = 255;
+    while (timeout-- && (code = serial_recv2()) == -1) _delay_ms(1);
+    return code;
 }
 
 static void pc98_inhibit_repeat(void)
 {
-    uint8_t code;
-
-    while (serial_recv()) ;
+    uint16_t code;
 RETRY:
-    PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
-    _delay_ms(500);
-    serial_send(0x9C);
-
-    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
-    _delay_ms(100);
-    while (!(code = serial_recv())) ;
-    print("PC98: send 9C: "); print_hex8(code); print("\n");
+    pc98_send(0x9C);
+    code = pc98_wait_response();
+    if (code != -1) xprintf("send 9C: %02X\n", code);
+    if (code != 0xFA) return;
+
+    pc98_send(0x70);
+    code = pc98_wait_response();
+    if (code != -1) xprintf("send 70: %02X\n", code);
     if (code != 0xFA) goto RETRY;
+}
 
-
-
-    PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
-    _delay_ms(100);
-    serial_send(0x70);
-
-    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
-    _delay_ms(100);
-    //code = serial_recv();
-    while (!(code = serial_recv())) ;
-    print("PC98: send 70: "); print_hex8(code); print("\n");
+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("send 9D: %02X\n", code);
+    if (code != 0xFA) return;
+
+    pc98_send(pc98_led);
+    code = pc98_wait_response();
+    if (code != -1) xprintf("send %02X: %02X\n", pc98_led, code);
     if (code != 0xFA) goto RETRY;
 }
 
 void matrix_init(void)
 {
+    debug_keyboard = true;
     PC98_RST_DDR |= (1<<PC98_RST_BIT);
     PC98_RDY_DDR |= (1<<PC98_RDY_BIT);
     PC98_RTY_DDR |= (1<<PC98_RTY_BIT);
@@ -104,51 +110,40 @@ void matrix_init(void)
     serial_init();
 
     // PC98 reset
-/*
-    PC98_RST_PORT &= ~(1<<PC98_RST_BIT);
-    _delay_us(15);
-    PC98_RST_PORT |= (1<<PC98_RST_BIT);
-    _delay_us(13);
-    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
-*/
+    // https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n359
+    PC98_RDY_PORT |=  (1<<PC98_RDY_BIT);    // RDY: high
+    PC98_RST_PORT &= ~(1<<PC98_RST_BIT);    // RST: low
+    _delay_us(15);                          // > 13us
+    PC98_RST_PORT |= (1<<PC98_RST_BIT);     // RST: high
 
-    _delay_ms(500);
+    _delay_ms(50);
     pc98_inhibit_repeat();
 
-
-    // PC98 ready
-    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
-
     // initialize matrix state: all keys off
     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;
 }
 
 uint8_t matrix_scan(void)
 {
-    is_modified = false;
-
     uint16_t code;
-    PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
-    _delay_us(30);
     code = serial_recv2();
-    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
-    if (code == -1) return 0;
-
-if (code == 0x60) {
-    pc98_inhibit_repeat();
-
-/*
-    PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
-    _delay_ms(100);
-    serial_send(0x96);
-    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
-*/
-
-    return 0;
-}
+    if (code == -1) {
+#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(" ");
 
@@ -156,33 +151,20 @@ if (code == 0x60) {
         // break code
         if (matrix_is_on(ROW(code), COL(code))) {
             matrix[ROW(code)] &= ~(1<<COL(code));
-            is_modified = true;
         }
     } else {
         // make code
         if (!matrix_is_on(ROW(code), COL(code))) {
             matrix[ROW(code)] |=  (1<<COL(code));
-            is_modified = true;
         }
     }
-    return code;
-}
 
-bool matrix_is_modified(void)
-{
-    return is_modified;
-}
-
-inline
-bool matrix_has_ghost(void)
-{
-    return false;
-}
-
-inline
-bool matrix_is_on(uint8_t row, uint8_t col)
-{
-    return (matrix[row] & (1<<col));
+    // PC-9801V keyboard requires RDY pulse.
+    // This is not optimal place though, it works.
+    PC98_RDY_PORT |=  (1<<PC98_RDY_BIT);    // RDY: high
+    _delay_us(20);
+    PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);    // RDY: low
+    return code;
 }
 
 inline
@@ -191,21 +173,13 @@ uint8_t matrix_get_row(uint8_t row)
     return matrix[row];
 }
 
-void matrix_print(void)
+void led_set(uint8_t usb_led)
 {
-    print("\nr/c 01234567\n");
-    for (uint8_t row = 0; row < matrix_rows(); row++) {
-        phex(row); print(": ");
-        pbin_reverse(matrix_get_row(row));
-        print("\n");
-    }
-}
-
-uint8_t matrix_key_count(void)
-{
-    uint8_t count = 0;
-    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
-        count += bitpop(matrix[i]);
-    }
-    return count;
+    // https://archive.org/stream/PC9800TechnicalDataBookHARDWARE1993/PC-9800TechnicalDataBook_HARDWARE1993#page/n161
+    // http://www.webtech.co.jp/company/doc/undocumented_mem/io_kb.txt
+    pc98_led = 0x70;
+    if (usb_led & (1<<USB_LED_NUM_LOCK))    pc98_led |= (1<<0);
+    if (usb_led & (1<<USB_LED_CAPS_LOCK))   pc98_led |= (1<<2);
+    xprintf("usb_led: %02X\n", usb_led);
+    xprintf("pc98_led: %02X\n", pc98_led);
 }