ibmpc_usb: C++ class for two-interface support

This commit is contained in:
tmk 2021-07-04 22:01:38 +09:00
parent f4f47aaee7
commit e9dab95909
5 changed files with 1538 additions and 30 deletions

View file

@ -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)

View 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

View file

@ -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

File diff suppressed because it is too large Load diff

View 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