ibmpc_usb: C++ class for two-interface support
This commit is contained in:
parent
f4f47aaee7
commit
e9dab95909
5 changed files with 1538 additions and 30 deletions
|
|
@ -69,7 +69,7 @@ OPT_DEFS += -DSUSPEND_MODE_STANDBY
|
|||
# comment out to disable the options.
|
||||
#
|
||||
BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
|
||||
MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
|
||||
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
|
||||
|
|
@ -78,6 +78,10 @@ NKRO_ENABLE ?= yes # USB Nkey Rollover
|
|||
KEYMAP_SECTION_ENABLE ?= yes
|
||||
UNIMAP_ENABLE ?= yes
|
||||
|
||||
# IBMPC Options
|
||||
IBMPC_SECONDARY ?= no # enable secondary interface
|
||||
IBMPC_MOUSE_ENABLE ?= no # enable mouse support
|
||||
|
||||
|
||||
# Optimize size but this may cause error "relocation truncated to fit"
|
||||
#EXTRALDFLAGS = -Wl,--relax
|
||||
|
|
@ -102,6 +106,16 @@ else
|
|||
endif
|
||||
|
||||
|
||||
ifeq (yes,$(strip $(IBMPC_SECONDARY)))
|
||||
OPT_DEFS += -DIBMPC_SECONDARY
|
||||
endif
|
||||
|
||||
ifeq (yes,$(strip $(IBMPC_MOUSE_ENABLE)))
|
||||
OPT_DEFS += -DIBMPC_MOUSE_ENABLE
|
||||
OPT_DEFS += -DMOUSE_ENABLE
|
||||
endif
|
||||
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TARGET_DIR)
|
||||
VPATH += $(TMK_DIR)
|
||||
|
|
|
|||
12
converter/ibmpc_usb/Makefile.x2
Normal file
12
converter/ibmpc_usb/Makefile.x2
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# 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
|
||||
|
|
@ -53,56 +53,77 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
* Pin and interrupt configuration
|
||||
*/
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB1286__)
|
||||
/* clock line */
|
||||
// clock requires External Interrupt pin(INT*)
|
||||
#define IBMPC_CLOCK_PORT PORTD
|
||||
#define IBMPC_CLOCK_PIN PIND
|
||||
#define IBMPC_CLOCK_DDR DDRD
|
||||
#define IBMPC_CLOCK_BIT 1
|
||||
/* data line */
|
||||
#define IBMPC_DATA_PORT PORTD
|
||||
#define IBMPC_DATA_PIN PIND
|
||||
#define IBMPC_DATA_DDR DDRD
|
||||
|
||||
// primary interface
|
||||
#define IBMPC_CLOCK_BIT 1
|
||||
#define IBMPC_DATA_BIT 0
|
||||
/* reset line */
|
||||
#define IBMPC_RST_PORT PORTB
|
||||
#define IBMPC_RST_PIN PINB
|
||||
#define IBMPC_RST_DDR DDRB
|
||||
#define IBMPC_RST_BIT1 6
|
||||
#define IBMPC_RST_BIT2 7
|
||||
|
||||
/* reset for XT Type-1 keyboard: low pulse for 500ms */
|
||||
#define IBMPC_RST_HIZ() do { \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT1); \
|
||||
IBMPC_RST_DDR &= ~(1<<IBMPC_RST_BIT1); \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT2); \
|
||||
IBMPC_RST_DDR &= ~(1<<IBMPC_RST_BIT2); \
|
||||
} while (0)
|
||||
|
||||
#define IBMPC_RST_LO() do { \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT1); \
|
||||
IBMPC_RST_DDR |= (1<<IBMPC_RST_BIT1); \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT2); \
|
||||
IBMPC_RST_DDR |= (1<<IBMPC_RST_BIT2); \
|
||||
} while (0)
|
||||
|
||||
/* interrupt for clock line */
|
||||
#define IBMPC_INT_INIT() do { \
|
||||
EICRA |= ((1<<ISC11) | \
|
||||
(0<<ISC10)); \
|
||||
} while (0)
|
||||
|
||||
/* NOTE: clear flag and enabling to ditch unwanted interrupt */
|
||||
#define IBMPC_INT_ON() do { \
|
||||
EIFR |= (1<<INTF1); \
|
||||
EIMSK |= (1<<INT1); \
|
||||
} while (0)
|
||||
|
||||
#define IBMPC_INT_OFF() do { \
|
||||
EIMSK &= ~(1<<INT1); \
|
||||
} while (0)
|
||||
|
||||
#define IBMPC_INT_VECT INT1_vect
|
||||
|
||||
// secondary interface
|
||||
#ifdef IBMPC_SECONDARY
|
||||
#define IBMPC_CLOCK_BIT1 3
|
||||
#define IBMPC_DATA_BIT1 2
|
||||
|
||||
#define IBMPC_INT_INIT1() do { \
|
||||
EICRA |= ((1<<ISC31) | \
|
||||
(0<<ISC30)); \
|
||||
} while (0)
|
||||
#define IBMPC_INT_ON1() do { \
|
||||
EIFR |= (1<<INTF3); \
|
||||
EIMSK |= (1<<INT3); \
|
||||
} while (0)
|
||||
#define IBMPC_INT_OFF1() do { \
|
||||
EIMSK &= ~(1<<INT3); \
|
||||
} while (0)
|
||||
#define IBMPC_INT_VECT1 INT3_vect
|
||||
#endif
|
||||
|
||||
|
||||
/* reset line */
|
||||
#define IBMPC_RST_PORT PORTB
|
||||
#define IBMPC_RST_PIN PINB
|
||||
#define IBMPC_RST_DDR DDRB
|
||||
#define IBMPC_RST_BIT0 6
|
||||
#define IBMPC_RST_BIT1 7
|
||||
|
||||
/* reset for XT Type-1 keyboard: low pulse for 500ms */
|
||||
#define IBMPC_RST_HIZ() do { \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT0); \
|
||||
IBMPC_RST_DDR &= ~(1<<IBMPC_RST_BIT0); \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT1); \
|
||||
IBMPC_RST_DDR &= ~(1<<IBMPC_RST_BIT1); \
|
||||
} while (0)
|
||||
|
||||
#define IBMPC_RST_LO() do { \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT0); \
|
||||
IBMPC_RST_DDR |= (1<<IBMPC_RST_BIT0); \
|
||||
IBMPC_RST_PORT &= ~(1<<IBMPC_RST_BIT1); \
|
||||
IBMPC_RST_DDR |= (1<<IBMPC_RST_BIT1); \
|
||||
} while (0)
|
||||
|
||||
// for debug
|
||||
#define LED_ON() do { DDRD |= (1<<6); PORTD |= (1<<6); } while (0)
|
||||
#define LED_OFF() do { DDRD |= (1<<6); PORTD &= ~(1<<6); } while (0)
|
||||
|
||||
#else
|
||||
#error "No pin configuration in config.h"
|
||||
#endif
|
||||
|
|
|
|||
1297
converter/ibmpc_usb/ibmpc_usb.cpp
Normal file
1297
converter/ibmpc_usb/ibmpc_usb.cpp
Normal file
File diff suppressed because it is too large
Load diff
164
converter/ibmpc_usb/ibmpc_usb.hpp
Normal file
164
converter/ibmpc_usb/ibmpc_usb.hpp
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#ifndef IBMPC_USB_HPP
|
||||
#define IBMPC_USB_HPP
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include "matrix.h"
|
||||
#include "unimap_trans.h"
|
||||
#include "ibmpc_usb.h"
|
||||
|
||||
|
||||
|
||||
#define ID_STR(id) (id == 0xFFFE ? "_????" : \
|
||||
(id == 0xFFFD ? "_Z150" : \
|
||||
(id == 0x0000 ? "_AT84" : \
|
||||
"")))
|
||||
|
||||
#define ROW(code) ((code>>4)&0x07)
|
||||
#define COL(code) (code&0x0F)
|
||||
|
||||
|
||||
class IBMPCConverter {
|
||||
public:
|
||||
static matrix_row_t matrix[MATRIX_ROWS];
|
||||
|
||||
IBMPC &ibmpc;
|
||||
|
||||
IBMPCConverter(IBMPC &_ibmpc) : ibmpc(_ibmpc), keyboard_id(0), keyboard_kind(NONE), current_protocol(0) {
|
||||
matrix_clear();
|
||||
}
|
||||
|
||||
void init(void) {
|
||||
ibmpc.host_init();
|
||||
}
|
||||
|
||||
uint8_t process_interface(void);
|
||||
|
||||
void set_led(uint8_t usb_led);
|
||||
|
||||
static inline void matrix_clear(void) {
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
|
||||
}
|
||||
|
||||
static inline matrix_row_t matrix_get_row(uint8_t row) {
|
||||
return matrix[row];
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
uint16_t keyboard_id = 0x0000;
|
||||
keyboard_kind_t keyboard_kind = NONE;
|
||||
uint8_t current_protocol = 0;
|
||||
uint16_t init_time;
|
||||
|
||||
enum Converter_state {
|
||||
INIT,
|
||||
WAIT_SETTLE,
|
||||
AT_RESET,
|
||||
XT_RESET,
|
||||
XT_RESET_WAIT,
|
||||
XT_RESET_DONE,
|
||||
WAIT_AA,
|
||||
WAIT_AABF,
|
||||
WAIT_AABFBF,
|
||||
READ_ID,
|
||||
SETUP,
|
||||
LOOP,
|
||||
ERROR,
|
||||
} state = INIT;
|
||||
|
||||
enum CS1_state {
|
||||
CS1_INIT,
|
||||
CS1_E0,
|
||||
// Pause: E1 1D 45, E1 9D C5 [a]
|
||||
CS1_E1,
|
||||
CS1_E1_1D,
|
||||
CS1_E1_9D,
|
||||
} state_cs1 = CS1_INIT;
|
||||
|
||||
enum CS2_state {
|
||||
CS2_INIT,
|
||||
CS2_F0,
|
||||
CS2_E0,
|
||||
CS2_E0_F0,
|
||||
// Pause
|
||||
CS2_E1,
|
||||
CS2_E1_14,
|
||||
CS2_E1_F0,
|
||||
CS2_E1_F0_14,
|
||||
CS2_E1_F0_14_F0,
|
||||
} state_cs2 = CS2_INIT;
|
||||
|
||||
enum CS3_state {
|
||||
CS3_READY,
|
||||
CS3_F0,
|
||||
#ifdef G80_2551_SUPPORT
|
||||
// G80-2551 four extra keys around cursor keys
|
||||
CS3_G80,
|
||||
CS3_G80_F0,
|
||||
#endif
|
||||
} state_cs3 = CS3_READY;
|
||||
|
||||
int8_t process_cs1(uint8_t code);
|
||||
int8_t process_cs2(uint8_t code);
|
||||
int8_t process_cs3(uint8_t code);
|
||||
uint8_t cs1_e0code(uint8_t code);
|
||||
uint8_t cs2_e0code(uint8_t code);
|
||||
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);
|
||||
|
||||
int16_t read_wait(uint16_t wait_ms);
|
||||
uint16_t read_keyboard_id(void);
|
||||
|
||||
// translate to Unimap before storing in matrix
|
||||
inline void matrix_make(uint8_t code) {
|
||||
uint8_t u = to_unimap(code);
|
||||
if (u > 0x7F) return;
|
||||
if (!matrix_is_on(ROW(u), COL(u))) {
|
||||
matrix[ROW(u)] |= 1<<COL(u);
|
||||
}
|
||||
}
|
||||
inline void matrix_break(uint8_t code) {
|
||||
uint8_t u = to_unimap(code);
|
||||
if (u > 0x7F) return;
|
||||
if (matrix_is_on(ROW(u), COL(u))) {
|
||||
matrix[ROW(u)] &= ~(1<<COL(u));
|
||||
}
|
||||
}
|
||||
uint8_t to_unimap(uint8_t code) {
|
||||
uint8_t row = ROW(code);
|
||||
uint8_t col = COL(code);
|
||||
switch (keyboard_kind) {
|
||||
case PC_XT:
|
||||
return pgm_read_byte(&unimap_cs1[row][col]);
|
||||
case PC_AT:
|
||||
return pgm_read_byte(&unimap_cs2[row][col]);
|
||||
case PC_TERMINAL:
|
||||
return pgm_read_byte(&unimap_cs3[row][col]);
|
||||
default:
|
||||
return UNIMAP_NO;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IBMPC_MOUSE_ENABLE
|
||||
enum {
|
||||
MOUSE_DEFAULT = 0, // Default three-button
|
||||
MOUSE_INTELLI = 3, // Intellimouse Explorer 3-button & wheel
|
||||
MOUSE_EXPLORER = 4, // Intellimouse Explorer 5-button & wheel
|
||||
MOUSE_LOGITECH = 9 // Logitech PS/2++
|
||||
} mouse_id = MOUSE_DEFAULT;
|
||||
uint8_t mouse_btn = 0;
|
||||
|
||||
void mouse_read_status(uint8_t *s) {
|
||||
ibmpc.host_send(0xE9);
|
||||
s[0] = ibmpc.host_recv_response();
|
||||
s[1] = ibmpc.host_recv_response();
|
||||
s[2] = ibmpc.host_recv_response();
|
||||
xprintf("S[%02X %02X %02X] ", s[0], s[1], s[2]);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
matrix_row_t IBMPCConverter::matrix[MATRIX_ROWS];
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue