xt_usb: read data on falling edge soft/hard reset

See https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
- read data on falling edge of clock
- add soft reset and hard reset
This commit is contained in:
tmk 2018-02-28 15:48:06 +09:00
parent 3526fcaf15
commit 8a92f254e1
6 changed files with 78 additions and 39 deletions

View file

@ -11,7 +11,9 @@ TMK_DIR = ../../tmk_core
TARGET_DIR = . TARGET_DIR = .
# project specific files # project specific files
SRC = matrix.c \ SRC = protocol/xt_interrupt.c \
protocol/xt_io_avr.c \
matrix.c \
led.c led.c
ifdef KEYMAP ifdef KEYMAP
@ -61,7 +63,7 @@ ARCH = AVR8
F_USB = $(F_CPU) F_USB = $(F_CPU)
# Interrupt driven control endpoint task(+60) # Interrupt driven control endpoint task(+60)
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Boot Section Size in *bytes* # Boot Section Size in *bytes*
@ -71,6 +73,7 @@ F_USB = $(F_CPU)
# LUFA bootloader 4096 # LUFA bootloader 4096
# USBaspLoader 2048 # USBaspLoader 2048
OPT_DEFS += -DBOOTLOADER_SIZE=512 OPT_DEFS += -DBOOTLOADER_SIZE=512
#OPT_DEFS += -DBOOTLOADER_SIZE=4096
# Build Options # Build Options
@ -84,11 +87,6 @@ COMMAND_ENABLE = yes # Commands for debug and configuration
NKRO_ENABLE = yes # USB Nkey Rollover NKRO_ENABLE = yes # USB Nkey Rollover
# XT/2 Options
#
XT_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin
# Optimize size but this may cause error "relocation truncated to fit" # Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax #EXTRALDFLAGS = -Wl,--relax

View file

@ -45,8 +45,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* /*
* XT Pin interrupt * XT Pin interrupt
*/ */
#ifdef XT_USE_INT
/* uses INT1 for clock line(ATMega32U4) */
#define XT_CLOCK_PORT PORTD #define XT_CLOCK_PORT PORTD
#define XT_CLOCK_PIN PIND #define XT_CLOCK_PIN PIND
#define XT_CLOCK_DDR DDRD #define XT_CLOCK_DDR DDRD
@ -55,9 +53,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define XT_DATA_PIN PIND #define XT_DATA_PIN PIND
#define XT_DATA_DDR DDRD #define XT_DATA_DDR DDRD
#define XT_DATA_BIT 0 #define XT_DATA_BIT 0
#define XT_RST_PORT PORTB
#define XT_RST_PIN PINB
#define XT_RST_DDR DDRB
#define XT_RST_BIT 7
/* hard reset: low pulse for 500ms and after that HiZ for safety */
#define XT_RESET() do { \
XT_RST_PORT &= ~(1<<XT_RST_BIT); \
XT_RST_DDR |= (1<<XT_RST_BIT); \
_delay_ms(500); \
XT_RST_DDR &= ~(1<<XT_RST_BIT); \
} while (0)
/* INT1 for falling edge of clock line */
#define XT_INT_INIT() do { \ #define XT_INT_INIT() do { \
EICRA |= ((1<<ISC11) | \ EICRA |= ((1<<ISC11) | \
(1<<ISC10)); \ (0<<ISC10)); \
} while (0) } while (0)
#define XT_INT_ON() do { \ #define XT_INT_ON() do { \
EIMSK |= (1<<INT1); \ EIMSK |= (1<<INT1); \
@ -66,6 +78,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
EIMSK &= ~(1<<INT1); \ EIMSK &= ~(1<<INT1); \
} while (0) } while (0)
#define XT_INT_VECT INT1_vect #define XT_INT_VECT INT1_vect
#endif
#endif #endif

View file

@ -26,13 +26,6 @@ ifeq (yes,$(strip $(PS2_USE_USART)))
endif endif
ifeq (yes,$(strip $(XT_USE_INT)))
SRC += protocol/xt_interrupt.c
SRC += protocol/xt_io_avr.c
OPT_DEFS += -DXT_USE_INT
endif
ifeq (yes,$(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE))) ifeq (yes,$(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE)))
SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c
OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \ OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \

View file

@ -51,6 +51,17 @@ POSSIBILITY OF SUCH DAMAGE.
void xt_host_init(void) void xt_host_init(void)
{ {
XT_INT_INIT(); XT_INT_INIT();
/* hard reset */
#ifdef XT_RESET
XT_RESET();
#endif
/* soft reset: pull clock line down for 20ms */
XT_INT_OFF();
data_lo(); clock_lo();
_delay_ms(20);
data_in(); clock_in();
XT_INT_ON(); XT_INT_ON();
} }
@ -66,29 +77,40 @@ uint8_t xt_host_recv(void)
ISR(XT_INT_VECT) ISR(XT_INT_VECT)
{ {
static uint8_t state = 0; /*
* XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data,
* which should be read on falling edge of clock.
*
* start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7
*
* Original IBM XT keyboard sends start(0) bit while some of clones don't.
* Start(0) bit is read as low on data line while start(1) as high.
*
* https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
*/
static enum {
START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, END
} state = START;
static uint8_t data = 0; static uint8_t data = 0;
if (state == 0) { // This is needed if using PCINT which can be called on both falling and rising edge
if (data_in()) if (clock_in()) return;
state++;
} else if (state >= 1 && state <= 8) { switch (state) {
wait_clock_lo(20); case START:
// ignore start(0) bit
if (!data_in()) return;
break;
case BIT0 ... BIT7:
data >>= 1; data >>= 1;
if (data_in()) if (data_in())
data |= 0x80; data |= 0x80;
if (state == 8) break;
goto END;
state++;
} else {
goto DONE;
} }
goto RETURN; if (++state == END) {
END:
pbuf_enqueue(data); pbuf_enqueue(data);
DONE: state = START;
state = 0;
data = 0; data = 0;
RETURN: }
return; return;
} }

View file

@ -4,4 +4,7 @@
bool clock_in(void); bool clock_in(void);
bool data_in(void); bool data_in(void);
void clock_lo(void);
void data_lo(void);
#endif #endif

View file

@ -32,3 +32,15 @@ bool data_in(void)
_delay_us(1); _delay_us(1);
return XT_DATA_PIN&(1<<XT_DATA_BIT); return XT_DATA_PIN&(1<<XT_DATA_BIT);
} }
void clock_lo(void)
{
XT_CLOCK_PORT &= ~(1<<XT_CLOCK_BIT);
XT_CLOCK_DDR |= (1<<XT_CLOCK_BIT);
}
void data_lo(void)
{
XT_DATA_PORT &= ~(1<<XT_DATA_BIT);
XT_DATA_DDR |= (1<<XT_DATA_BIT);
}