From 9acc900ffb6002ee61dc65ddaf5610c79f03add0 Mon Sep 17 00:00:00 2001 From: tmk Date: Fri, 24 Jan 2020 03:20:14 +0900 Subject: [PATCH] ibmpc: Add two-byte buffer for data received --- converter/ibmpc_usb/ibmpc_usb.c | 38 +++++++---------- tmk_core/protocol/ibmpc.c | 76 +++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 53 deletions(-) diff --git a/converter/ibmpc_usb/ibmpc_usb.c b/converter/ibmpc_usb/ibmpc_usb.c index 696bf904..c7feff76 100644 --- a/converter/ibmpc_usb/ibmpc_usb.c +++ b/converter/ibmpc_usb/ibmpc_usb.c @@ -63,11 +63,12 @@ static uint16_t read_keyboard_id(void) if (code == -1) { id = 0xFFFF; goto DONE; } // XT or No keyboard if (code != 0xFA) { id = 0xFFFE; goto DONE; } // Broken PS/2? - code = read_wait(1000); + // ID takes 500ms max TechRef [8] 4-41 + code = read_wait(500); if (code == -1) { id = 0x0000; goto DONE; } // AT id = (code & 0xFF)<<8; - code = read_wait(1000); + code = read_wait(500); id |= code & 0xFF; DONE: @@ -141,27 +142,26 @@ uint8_t matrix_scan(void) switch (state) { case INIT: + xprintf("S%u\n", timer_read()); ibmpc_protocol = IBMPC_PROTOCOL_AT; keyboard_kind = NONE; keyboard_id = 0x0000; - init_time = timer_read(); - xprintf("I%u\n", init_time); - // re-initialize keyboard + matrix_clear(); + clear_keyboard(); + + // Reset XT-initialize keyboard // XT: hard reset 500ms for IBM XT Type-1 keyboard and clones // XT: soft reset 20ms min(clock Lo) ibmpc_host_disable(); // soft reset: inihibit(clock Lo/Data Hi) IBMPC_RST_LO(); wait_ms(500); IBMPC_RST_HIZ(); - ibmpc_host_enable(); // soft reset: idle(clock Hi/Data Hi) - - // TODO: should in while disabling interrupt? - // clear ISR state after protocol recognition ibmpc_host_isr_clear(); + ibmpc_host_enable(); // soft reset: idle(clock Hi/Data Hi) - matrix_clear(); - clear_keyboard(); + init_time = timer_read(); + xprintf("I%u\n", init_time); state = WAIT_STARTUP; break; @@ -170,19 +170,16 @@ uint8_t matrix_scan(void) // For example, XT/AT sends 'AA' and Terminal sends 'AA BF BF' after BAT // AT 84-key: POR and BAT can take 900-9900ms according to AT TechRef [8] 4-7 // AT 101/102-key: POR and BAT can take 450-2500ms according to AT TechRef [8] 4-39 - // 2) Read and ignore key input by user when signal handling/protocol error occurs + // 2) Read key typed by user after error on protocol or scan code // This can happen in case of keyboard hotswap, unstable hardware, signal integrity problem or bug if (ibmpc_host_recv() != -1 || timer_elapsed(init_time) > 10000) { - // 500ms max wait for ID after AA TechRef [8] 4-41 - // 122-key Terminal 6110345: 1ms wait is enough - wait_ms(100); ibmpc_host_recv(); - wait_ms(100); ibmpc_host_recv(); + xprintf("W%u\n", timer_read()); + // ID takes 500ms max? TechRef [8] 4-41, though, 1ms is enough for 122-key Terminal 6110345 + read_wait(500); // for BF from Terminal + read_wait(500); // for BF from Terminal state = READ_ID; } - - // XT's 'AA' can not be handled correctly because protocol is configured as AT at this point. - // TODO: Check ISR timeout error for XT AA? break; case READ_ID: xprintf("R%u\n", timer_read()); @@ -232,9 +229,6 @@ uint8_t matrix_scan(void) ibmpc_protocol = IBMPC_PROTOCOL_AT; } - // clear ISR state after protocol recognition - ibmpc_host_isr_clear(); - state = LED_SET; break; case LED_SET: diff --git a/tmk_core/protocol/ibmpc.c b/tmk_core/protocol/ibmpc.c index f74a387d..2e1309f8 100644 --- a/tmk_core/protocol/ibmpc.c +++ b/tmk_core/protocol/ibmpc.c @@ -42,7 +42,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include "ringbuf.h" #include "ibmpc.h" #include "debug.h" #include "timer.h" @@ -57,18 +56,20 @@ POSSIBILITY OF SUCH DAMAGE. } while (0) -#define BUF_SIZE 16 -static uint8_t buf[BUF_SIZE]; -static ringbuf_t rb = { - .buffer = buf, - .head = 0, - .tail = 0, - .size_mask = BUF_SIZE - 1 -}; - volatile uint8_t ibmpc_protocol = IBMPC_PROTOCOL_AT; volatile uint8_t ibmpc_error = IBMPC_ERR_NONE; +/* 2-byte buffer for data received from keyhboard + * buffer states: + * FFFF: empty + * FFss: one data + * sstt: two data(full) + * 0xFF can not be stored as data in buffer because it means empty or no data. + */ +static volatile uint16_t recv_data = 0xFFFF; +/* internal state of receiving data */ +static volatile uint16_t isr_data = 0x8000; + void ibmpc_host_init(void) { // initialize reset pin to HiZ @@ -142,7 +143,7 @@ int16_t ibmpc_host_send(uint8_t data) WAIT(data_hi, 50, 9); // clear buffer to get response correctly - ringbuf_reset(&rb); + recv_data = 0xFFFF; ibmpc_host_isr_clear(); idle(); @@ -156,27 +157,28 @@ ERROR: } /* - * Receive data from keyboard with ISR + * Receive data from keyboard */ -static volatile int16_t recv_data = -1; -static volatile uint16_t isr_data = 0x8000; - -void ibmpc_host_isr_clear(void) -{ - isr_data = 0x8000; -} - int16_t ibmpc_host_recv(void) { - int16_t data = 0; + uint16_t data = 0; + uint8_t ret = 0xFF; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { data = recv_data; - recv_data = -1; + if ((data&0xFF00) != 0xFF00) { // recv_data:sstt -> recv_data:FFtt, ret:ss + ret = (data>>8)&0x00FF; + recv_data = data | 0xFF00; + } else if (data != 0xFFFF) { // recv_data:FFss -> recv_data:FFFF, ret:ss + ret = data&0x00FF; + recv_data = data | 0x00FF; + } } - if (data != -1) { - dprintf("r%04X ", data); + + if (ret != 0xFF) { + dprintf("r%02X(%04X) ", ret, recv_data); } - return data; + return ((ret != 0xFF) ? ret : -1); } @@ -191,7 +193,14 @@ int16_t ibmpc_host_recv_response(void) return data; } -// NOTE: to read data line early as possible: +void ibmpc_host_isr_clear(void) +{ + isr_data = 0x8000; + recv_data = 0xFFFF; +} + +// NOTE: With this ISR data line can be read within 2us after clock falling edge. +// To read data line early as possible: // write naked ISR with asembly code to read the line and call C func to do other job? ISR(IBMPC_INT_VECT) { @@ -200,7 +209,7 @@ ISR(IBMPC_INT_VECT) isr_data = isr_data>>1; if (dbit) isr_data |= 0x8000; - // isr_data: + // isr_data: state of receiving data from keyboard // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // ----------------------------------------------------- // Initial: *1 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 @@ -238,7 +247,8 @@ ISR(IBMPC_INT_VECT) break; case 0b11000000: // XT Clone-done - recv_data = (isr_data>>8) & 0xFF; + recv_data = recv_data<<8; + recv_data |= (isr_data>>8) & 0xFF; goto DONE; break; case 0b10100000: @@ -255,7 +265,8 @@ ISR(IBMPC_INT_VECT) } else { // no stop bit // XT-IBM-done - recv_data = (isr_data>>8) & 0xFF; + recv_data = recv_data<<8; + recv_data |= (isr_data>>8) & 0xFF; goto DONE; } } @@ -265,7 +276,8 @@ ISR(IBMPC_INT_VECT) case 0b01010000: case 0b11010000: // AT-done - recv_data = (isr_data>>6) & 0xFF; + recv_data = recv_data<<8; + recv_data |= (isr_data>>6) & 0xFF; goto DONE; break; case 0b01100000: @@ -279,7 +291,9 @@ ISR(IBMPC_INT_VECT) break; } DONE: - // TODO: buffer for recv_data + // TODO: check protocol change to support keyboard howswap + // not correct if there is clock edge within short time like 100us after receving data + // TODO: process error code: 0x00(AT), 0xFF(XT) in particular isr_data = 0x8000; // clear to next data return; } -- 2.46.2