Browse Source

Add PS/2 mouse support to connect TrackPoint Unit.

Change build options:  Makefile and config.h. See README.
tags/v1.9
tmk 13 years ago
parent
commit
2a562a4191
27 changed files with 952 additions and 312 deletions
  1. 30
    28
      Makefile.common
  2. 41
    0
      README
  3. 14
    0
      USB_NKRO.txt
  4. 7
    10
      hhkb/Makefile
  5. 40
    0
      hhkb/config.h
  6. 0
    12
      hhkb/controller.h
  7. 1
    2
      hhkb/keymap.c
  8. 2
    3
      hhkb/matrix.c
  9. 18
    13
      jump_bootloader.c
  10. 55
    55
      key_process.c
  11. 7
    6
      macway/Makefile
  12. 38
    0
      macway/config.h
  13. 0
    12
      macway/controller.h
  14. 31
    31
      macway/keymap.c
  15. 32
    68
      macway/matrix.c
  16. 74
    0
      mousekey.c
  17. 11
    0
      mousekey.h
  18. 248
    0
      ps2.c
  19. 72
    0
      ps2.h
  20. 161
    0
      ps2_mouse.c
  21. 26
    0
      ps2_mouse.h
  22. 9
    2
      tmk.c
  23. 8
    8
      usb.c
  24. 5
    5
      usb_keyboard.c
  25. 1
    1
      usb_keyboard.h
  26. 13
    44
      usb_mouse.c
  27. 8
    12
      usb_mouse.h

+ 30
- 28
Makefile.common View File

@@ -62,6 +62,13 @@ SRC = tmk.c \
timer.c \
util.c
SRC += $(TARGET_SRC)
ifdef MOUSEKEY_ENABLE
SRC += mousekey.c
endif
ifdef PS2_MOUSE_ENABLE
SRC += ps2.c \
ps2_mouse.c
endif

# C source file search path
VPATH = $(TARGET_DIR):$(COMMON_DIR)
@@ -119,45 +126,32 @@ EXTRAINCDIRS = $(TARGET_DIR) $(COMMON_DIR)
CSTANDARD = -std=gnu99


# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL
CDEFS += -DDESCRIPTION=$(DESCRIPTION)
CDEFS += -DVENDOR_ID=$(VENDOR_ID)
CDEFS += -DPRODUCT_ID=$(PRODUCT_ID)
CDEFS += -DMANUFACTURER=$(MANUFACTURER)
CDEFS += -DPRODUCT=$(PRODUCT)
ifdef MOUSE_DELAY_TIME
CDEFS += -DMOUSE_DELAY_TIME=$(MOUSE_DELAY_TIME)
OPT_DEFS =
ifdef USB_NKRO_ENABLE
OPT_DEFS += -DUSB_NKRO_ENABLE
endif
ifdef MOUSEKEY_ENABLE
OPT_DEFS += -DMOUSEKEY_ENABLE
endif
ifdef NKRO_ENABLE
CDEFS += -DNKRO_ENABLE
ifdef PS2_MOUSE_ENABLE
OPT_DEFS += -DPS2_MOUSE_ENABLE
endif

# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL
CDEFS += $(OPT_DEFS)


# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)
ADEFS += -DDESCRIPTION=$(DESCRIPTION)
ADEFS += -DVENDOR_ID=$(VENDOR_ID)
ADEFS += -DPRODUCT_ID=$(PRODUCT_ID)
ADEFS += -DMANUFACTURER=$(MANUFACTURER)
ADEFS += -DPRODUCT=$(PRODUCT)
ifdef MOUSE_DELAY_TIME
ADEFS += -DMOUSE_DELAY_TIME=$(MOUSE_DELAY_TIME)
endif
ADEFS += $(OPT_DEFS)


# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL -DDESCRIPTION=$(DESCRIPTION) -DVENDOR_ID=$(VENDOR_ID) -DPRODUCT_ID=$(PRODUCT_ID)
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS
CPPDEFS += -DDESCRIPTION=$(DESCRIPTION)
CPPDEFS += -DVENDOR_ID=$(VENDOR_ID)
CPPDEFS += -DPRODUCT_ID=$(PRODUCT_ID)
CPPDEFS += -DMANUFACTURER=$(MANUFACTURER)
CPPDEFS += -DPRODUCT=$(PRODUCT)
ifdef MOUSE_DELAY_TIME
CPPDEFS += -DMOUSE_DELAY_TIME=$(MOUSE_DELAY_TIME)
endif
CPPDEFS += $(OPT_DEFS)



@@ -186,6 +180,7 @@ CFLAGS += -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(@:%.o=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS += -include config.h


#---------------- Compiler Options C++ ----------------
@@ -213,6 +208,7 @@ CPPFLAGS += -Wundef
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)
CPPFLAGS += -include config.h


#---------------- Assembler Options ----------------
@@ -225,6 +221,7 @@ CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
ASFLAGS += -include config.h


#---------------- Library Options ----------------
@@ -421,6 +418,11 @@ ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build sizeafter end

depend: tmk.c
@echo $<
@echo $(<F)
# $(CC) -E $(ALL_CFLAGS) $<

# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib

+ 41
- 0
README View File

@@ -31,6 +31,47 @@ $ make
http://winavr.sourceforge.net/


Build Options
-------------
Makefile:
Comment out to disable the option
# USB NKey Rollover
USB_NKRO_ENABLE = yes

# mouse keys
MOUSEKEY_ENABLE = yes

# PS/2 mouse support
PS2_MOUSE_ENABLE = yes

config.h:
/* USB ID */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xBEEF
/* device description */
#define MANUFACTURER t.m.k.
#define PRODUCT Macway mod
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod
/* matrix size */
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
/* mouse keys repeat delay */
#define MOUSEKEY_DELAY_TIME 192
/* PS/2 lines */
#define PS2_CLOCK_PORT PORTF
#define PS2_CLOCK_PIN PINF
#define PS2_CLOCK_DDR DDRF
#define PS2_CLOCK_BIT 0
#define PS2_DATA_PORT PORTF
#define PS2_DATA_PIN PINF
#define PS2_DATA_DDR DDRF
#define PS2_DATA_BIT 1


Configuration
-------------


Debuging & Rescue
-----------------
Use PJRC's hid_listen.exe to see debug messages.

+ 14
- 0
USB_NKRO.txt View File

@@ -143,4 +143,18 @@ This problem will be reportedly fixed soon.(2010/12/05)
http://forums.anandtech.com/showpost.php?p=30873364&postcount=17


Tools for testing NKRO
----------------------
Browser App:
http://www.microsoft.com/appliedsciences/content/projects/KeyboardGhostingDemo.aspx
http://random.xem.us/rollover.html

Windows:
AquaKeyTest.exe http://geekhack.org/showthread.php?t=6643

Linux:
xkeycaps
xev
showkeys

EOF

+ 7
- 10
hhkb/Makefile View File

@@ -39,16 +39,6 @@
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------

# TODO: use config.h for build options?
VENDOR_ID = 0xFEED
PRODUCT_ID = 0xCAFE
MANUFACTURER = 't.m.k.'
PRODUCT = 'HHKB Mod'
DESCRIPTION = 't.m.k. firmware for HHKB pro'

MOUSE_DELAY_TIME = 127
NKRO_ENABLE = true

# Target file name (without extension).
TARGET = tmk_hhkb

@@ -78,4 +68,11 @@ MCU = at90usb1286 # Teensy++ 2.0
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000


# Options
# comment out to disable
USB_NKRO_ENABLE = yes
MOUSEKEY_ENABLE = yes
#PS2_MOUSE_ENABLE = yes

include $(COMMON_DIR)/Makefile.common

+ 40
- 0
hhkb/config.h View File

@@ -0,0 +1,40 @@
#ifndef CONFIG_H
#define CONFIG_H

#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xCAFE
#define MANUFACTURER t.m.k.
#define PRODUCT HHKB mod
#define DESCRIPTION t.m.k. keyboard firmware for HHKB mod

/* controller */
#include "controller_teensy.h"

/* matrix size */
#define MATRIX_ROWS 8
#define MATRIX_COLS 8

/* USB NKey Rollover */
#ifdef USB_NKRO_ENABLE
#endif

/* mouse keys */
#ifdef MOUSEKEY_ENABLE
# define MOUSEKEY_DELAY_TIME 192
#endif

/* PS/2 mouse */
#ifdef PS2_MOUSE_ENABLE
/*
# define PS2_CLOCK_PORT PORTF
# define PS2_CLOCK_PIN PINF
# define PS2_CLOCK_DDR DDRF
# define PS2_CLOCK_BIT 0
# define PS2_DATA_PORT PORTF
# define PS2_DATA_PIN PINF
# define PS2_DATA_DDR DDRF
# define PS2_DATA_BIT 1
*/
#endif

#endif

+ 0
- 12
hhkb/controller.h View File

@@ -1,12 +0,0 @@
#ifndef CONTROLLER_H
#define CONTROLLER_H 1

#include "controller_teensy.h"


/* matrix row size */
#define MATRIX_ROWS 8
/* matrix column size */
#define MATRIX_COLS 8

#endif

+ 1
- 2
hhkb/keymap.c View File

@@ -9,7 +9,6 @@
#include "print.h"
#include "debug.h"
#include "util.h"
#include "controller.h"
#include "keymap_skel.h"


@@ -75,7 +74,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
* |-----------------------------------------------------------|
* |Contro| | | | | | *| /|Hom|PgU|Lef|Rig|Enter |
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |xxx|
* `-----------------------------------------------------------'

+ 2
- 3
hhkb/matrix.c View File

@@ -7,7 +7,6 @@
#include <util/delay.h>
#include "print.h"
#include "util.h"
#include "controller.h"
#include "matrix_skel.h"

// matrix is active low. (key on: 0/key off: 1)
@@ -22,7 +21,7 @@
// KEY_PREV: (on: 1/ off: 0)
// PE6,PE7(KEY, KEY_PREV)
#define COL_ENABLE (1<<6)
#define KEY_SELELCT(ROW, COL) (PORTB = COL_ENABLE|(((COL)&0x07)<<3)|((ROW)&0x07))
#define KEY_SELELCT(ROW, COL) (PORTB = (PORTB&(1<<7))|COL_ENABLE|(((COL)&0x07)<<3)|((ROW)&0x07))
#define KEY_ENABLE (PORTB &= ~COL_ENABLE)
#define KEY_UNABLE (PORTB |= COL_ENABLE)
#define KEY_STATE (PINE&(1<<6))
@@ -53,7 +52,7 @@ void matrix_init(void)
{
// row & col output(PB0-6)
DDRB = 0xFF;
PORTB = KEY_SELELCT(0, 0);
KEY_SELELCT(0, 0);
// KEY: input with pullup(PE6)
// KEY_PREV: output(PE7)
DDRE = 0xBF;

+ 18
- 13
jump_bootloader.c View File

@@ -13,23 +13,28 @@ void jump_bootloader(void) {
UCSR1B = 0;
_delay_ms(5);
#if defined(__AVR_AT90USB162__) // Teensy 1.0
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
DDRB = 0; DDRC = 0; DDRD = 0;
TIMSK0 = 0; TIMSK1 = 0;
asm volatile("jmp 0x1F00");
PORTB = 0; PORTC = 0; PORTD = 0;
asm volatile("jmp 0x3E00");
#elif defined(__AVR_ATmega32U4__) // Teensy 2.0
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0;
ADCSRA = 0;
asm volatile("jmp 0x3F00");
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0x7E00");
#elif defined(__AVR_AT90USB646__) // Teensy++ 1.0
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0;
ADCSRA = 0;
asm volatile("jmp 0x7E00");
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0xFC00");
#elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0;
ADCSRA = 0;
asm volatile("jmp 0xFE00");
#endif
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0x1FC00");
#endif
}

+ 55
- 55
key_process.c View File

@@ -15,29 +15,18 @@
#include "layer.h"
#include "matrix_skel.h"
#include "keymap_skel.h"
#include "controller.h"
#include "key_process.h"


#define MOUSE_MOVE_UNIT 10
#define MOUSE_MOVE_ACCEL (mouse_repeat < 50 ? mouse_repeat/5 : 10)

#ifndef MOUSE_DELAY_TIME
# define MOUSE_DELAY_TIME 255
#ifdef MOUSEKEY_ENABLE
# include "mousekey.h"
#endif
#ifdef PS2_MOUSE_ENABLE
# include "ps2_mouse.h"
#endif
#define MOUSE_DELAY_MS (MOUSE_DELAY_TIME >> (mouse_repeat < 5 ? mouse_repeat : 4))


// TODO: refactoring
void proc_matrix(void) {
static int mouse_repeat = 0;

bool modified = false;
uint8_t mouse_btn = 0;
int8_t mouse_x = 0;
int8_t mouse_y = 0;
int8_t mouse_vwheel = 0;
int8_t mouse_hwheel = 0;
uint8_t fn_bits = 0;

matrix_scan();
@@ -73,19 +62,9 @@ void proc_matrix(void) {
} else if (IS_FN(code)) {
fn_bits |= FN_BIT(code);
} else if (IS_MOUSE(code)) {
if (code == MS_UP) mouse_y -= MOUSE_MOVE_UNIT + MOUSE_MOVE_ACCEL;
if (code == MS_DOWN) mouse_y += MOUSE_MOVE_UNIT + MOUSE_MOVE_ACCEL;
if (code == MS_LEFT) mouse_x -= MOUSE_MOVE_UNIT + MOUSE_MOVE_ACCEL;
if (code == MS_RGHT) mouse_x += MOUSE_MOVE_UNIT + MOUSE_MOVE_ACCEL;
if (code == MS_BTN1) mouse_btn |= BIT_BTN1;
if (code == MS_BTN2) mouse_btn |= BIT_BTN2;
if (code == MS_BTN3) mouse_btn |= BIT_BTN3;
if (code == MS_BTN4) mouse_btn |= BIT_BTN4;
if (code == MS_BTN5) mouse_btn |= BIT_BTN5;
if (code == MS_WH_U) mouse_vwheel += 1;
if (code == MS_WH_D) mouse_vwheel -= 1;
if (code == MS_WH_L) mouse_hwheel -= 1;
if (code == MS_WH_R) mouse_hwheel += 1;
#ifdef MOUSEKEY_ENABLE
mousekey_decode(code);
#endif
}

// audio control & system control
@@ -143,13 +122,39 @@ void proc_matrix(void) {
print("t: print timer count\n");
print("s: print status\n");
print("`: toggle protcol(boot/report)\n");
#ifdef NKRO_ENABLE
print("n: toggle NKRO\n");
#ifdef USB_NKRO_ENABLE
print("n: toggle USB_NKRO\n");
#endif
print("ESC: power down/wake up\n");
#ifdef PS2_MOUSE_ENABLE
print("1: ps2_mouse_init \n");
print("2: ps2_mouse_read \n");
#endif
_delay_ms(500);
print_enable = false;
break;
#ifdef PS2_MOUSE_ENABLE
case KB_1:
usb_keyboard_clear_report();
usb_keyboard_send();
print_enable = true;
print("ps2_mouse_init...\n");
_delay_ms(500);
ps2_mouse_init();
break;
case KB_2:
usb_keyboard_clear_report();
usb_keyboard_send();
print_enable = true;
print("ps2_mouse_read[btn x y]: ");
_delay_ms(100);
ps2_mouse_read();
phex(ps2_mouse_btn); print(" ");
phex(ps2_mouse_x); print(" ");
phex(ps2_mouse_y); print("\n");
print("ps2_mouse_error_count: "); phex(ps2_mouse_error_count); print("\n");
break;
#endif
case KB_B: // bootloader
usb_keyboard_clear_report();
usb_keyboard_send();
@@ -243,29 +248,29 @@ void proc_matrix(void) {
print("usb_keyboard_protocol:"); phex(usb_keyboard_protocol); print("\n");
print("usb_keyboard_idle_config:"); phex(usb_keyboard_idle_config); print("\n");
print("usb_keyboard_idle_count:"); phex(usb_keyboard_idle_count); print("\n");
print("mouse_protocol:"); phex(mouse_protocol); print("\n");
if (usb_keyboard_nkro) print("NKRO: enabled\n"); else print("NKRO: disabled\n");
print("usb_mouse_protocol:"); phex(usb_mouse_protocol); print("\n");
if (usb_keyboard_nkro) print("USB_NKRO: enabled\n"); else print("USB_NKRO: disabled\n");
_delay_ms(500);
break;
case KB_GRV:
usb_keyboard_clear_report();
usb_keyboard_send();
usb_keyboard_protocol = !usb_keyboard_protocol;
mouse_protocol = !mouse_protocol;
usb_mouse_protocol = !usb_mouse_protocol;
print("keyboard protcol: ");
if (usb_keyboard_protocol) print("report"); else print("boot");
print("\n");
print("mouse protcol: ");
if (mouse_protocol) print("report"); else print("boot");
if (usb_mouse_protocol) print("report"); else print("boot");
print("\n");
_delay_ms(1000);
break;
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
case KB_N:
usb_keyboard_clear_report();
usb_keyboard_send();
usb_keyboard_nkro = !usb_keyboard_nkro;
if (usb_keyboard_nkro) print("NKRO: enabled\n"); else print("NKRO: disabled\n");
if (usb_keyboard_nkro) print("USB_NKRO: enabled\n"); else print("USB_NKRO: disabled\n");
_delay_ms(1000);
break;
#endif
@@ -283,25 +288,20 @@ void proc_matrix(void) {
}


// send mouse packet to host
if (mouse_x || mouse_y || mouse_vwheel || mouse_hwheel || mouse_btn != mouse_buttons) {
mouse_buttons = mouse_btn;
if (mouse_x && mouse_y)
usb_mouse_move(mouse_x*0.7, mouse_y*0.7, mouse_vwheel, mouse_hwheel);
else
usb_mouse_move(mouse_x, mouse_y, mouse_vwheel, mouse_hwheel);
usb_mouse_print(mouse_x, mouse_y, mouse_vwheel, mouse_hwheel);

// acceleration
_delay_ms(MOUSE_DELAY_MS);
mouse_repeat++;
} else {
mouse_repeat = 0;
}


// send key packet to host
if (modified) {
usb_keyboard_send();
}

#ifdef MOUSEKEY_ENABLE
// mouse keys
mousekey_usb_send();
#endif

#ifdef PS2_MOUSE_ENABLE
// ps2 mouse
//if (ps2_mouse_error_count > 10) {
ps2_mouse_read();
ps2_mouse_usb_send();
//}
#endif
}

+ 7
- 6
macway/Makefile View File

@@ -39,12 +39,6 @@
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------

VENDOR_ID = 0xFEED
PRODUCT_ID = 0xBEEF
MANUFACTURER = 't.m.k.'
PRODUCT = 't.m.k. Macway mod'
DESCRIPTION = 't.m.k. firmware for Macway mod'

# Target file name (without extension).
TARGET = tmk_macway

@@ -74,4 +68,11 @@ MCU = atmega32u4 # Teensy 2.0
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000


# Options
# comment out to disable
#USB_NKRO_ENABLE = yes
MOUSEKEY_ENABLE = yes
PS2_MOUSE_ENABLE = yes

include $(COMMON_DIR)/Makefile.common

+ 38
- 0
macway/config.h View File

@@ -0,0 +1,38 @@
#ifndef CONFIG_H
#define CONFIG_H

#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xBEEF
#define MANUFACTURER t.m.k.
#define PRODUCT Macway mod
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod

/* controller */
#include "controller_teensy.h"

/* matrix size */
#define MATRIX_ROWS 9
#define MATRIX_COLS 8

/* USB NKey Rollover */
#ifdef USB_NKRO_ENABLE
#endif

/* mouse keys */
#ifdef MOUSEKEY_ENABLE
# define MOUSEKEY_DELAY_TIME 192
#endif

/* PS/2 mouse */
#ifdef PS2_MOUSE_ENABLE
# define PS2_CLOCK_PORT PORTF
# define PS2_CLOCK_PIN PINF
# define PS2_CLOCK_DDR DDRF
# define PS2_CLOCK_BIT 0
# define PS2_DATA_PORT PORTF
# define PS2_DATA_PIN PINF
# define PS2_DATA_DDR DDRF
# define PS2_DATA_BIT 1
#endif

#endif

+ 0
- 12
macway/controller.h View File

@@ -1,12 +0,0 @@
#ifndef CONTROLLER_H
#define CONTROLLER_H 1

#include "controller_teensy.h"


/* matrix row size */
#define MATRIX_ROWS 9
/* matrix column size */
#define MATRIX_COLS 8

#endif

+ 31
- 31
macway/keymap.c View File

@@ -10,7 +10,6 @@
#include "print.h"
#include "debug.h"
#include "util.h"
#include "controller.h"
#include "keymap_skel.h"


@@ -40,9 +39,9 @@ static const uint8_t PROGMEM fn_layer[] = { 0, 1, 2, 3, 4, 0, 2, 3 };
static const uint8_t PROGMEM fn_keycode[] = {
KB_NO, // FN_0 [NOT USED]
KB_NO, // FN_1 layer 1
KB_QUOTE, // FN_2 layer 2
KB_SCOLON, // FN_3 layer 3
KB_SPACE, // FN_4 layer 4
KB_SLSH, // FN_2 layer 2
KB_SCLN, // FN_3 layer 3
KB_SPC, // FN_4 layer 4
KB_NO, // FN_5 [NOT USED]
KB_NO, // FN_6 layer 2
KB_NO // FN_7 layer 3
@@ -55,38 +54,38 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| |
* |-----------------------------------------------------' |
* |Contro| A| S| D| F| G| H| J| K| L|Fn3|Fn2|Return |
* |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return |
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn1|
* |-----------------------------------------------------------|
* |Fn7|Gui |Alt |Fn4 |Fn6 |\ |` | | |
* |Fn7|Gui |Alt |Fn4 |Alt |Gui|Fn6|Fn6|Ctr|
* `-----------------------------------------------------------'
*/
KEYMAP(KB_ESC, KB_1, KB_2, KB_3, KB_4, KB_5, KB_6, KB_7, KB_8, KB_9, KB_0, KB_MINS,KB_EQL, KB_BSPC, \
KB_TAB, KB_Q, KB_W, KB_E, KB_R, KB_T, KB_Y, KB_U, KB_I, KB_O, KB_P, KB_LBRC,KB_RBRC, \
KB_LCTL,KB_A, KB_S, KB_D, KB_F, KB_G, KB_H, KB_J, KB_K, KB_L, FN_3, FN_2, KB_ENT, \
KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, KB_SLSH,KB_RSFT,FN_1, \
FN_7, KB_LGUI,KB_LALT,FN_4, FN_6, KB_BSLS,KB_GRV, KB_NO, KB_NO),
KB_LCTL,KB_A, KB_S, KB_D, KB_F, KB_G, KB_H, KB_J, KB_K, KB_L, FN_3, KB_QUOT,KB_ENT, \
KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, FN_2, KB_RSFT,FN_1, \
FN_7, KB_LGUI,KB_LALT,FN_4, KB_RALT,KB_RGUI,FN_6, FN_6, KB_RCTL),


/* Layer 1: HHKB mode (HHKB Fn)
* ,-----------------------------------------------------------.
* |Pow| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
* |-----------------------------------------------------------|
* |Caps | | | | | | | |Psc|Slk|Pus|Up | | |
* |-----------------------------------------------------' |
* |Contro| | | | | | *| /|Hom|PgU|Lef|Rig|Enter |
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |xxx|
* |-----------------------------------------------------------|
* | |Gui |Alt | |Alt | | | | |
* | |Gui |Alt | |Alt |Gui| | |Ctr|
* `-----------------------------------------------------------'
*/
KEYMAP(KB_PWR, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_DEL, \
KEYMAP(KB_ESC, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_DEL, \
KB_CAPS,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_PSCR,KB_SLCK,KB_BRK, KB_UP, KB_NO, \
KB_LCTL,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KP_ASTR,KP_SLSH,KB_HOME,KB_PGUP,KB_LEFT,KB_RGHT,KB_ENT, \
KB_LCTL,KB_VOLD,KB_VOLU,KB_MUTE,KB_NO, KB_NO, KP_ASTR,KP_SLSH,KB_HOME,KB_PGUP,KB_LEFT,KB_RGHT,KB_ENT, \
KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KP_PLUS,KP_MINS,KB_END, KB_PGDN,KB_DOWN,KB_RSFT,FN_1, \
KB_NO, KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_NO, KB_NO, KB_NO, KB_NO),
KB_NO, KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_NO, KB_NO, KB_NO, KB_RCTL),


/* Layer 2: Vi mode (Quote/Rmeta)
@@ -95,27 +94,27 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* | \ |Hom|PgD|Up |PgU|End|Hom|PgD|PgU|End| | | | |
* |-----------------------------------------------------' |
* |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| |xxx| \ |
* |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | | \ |
* |-----------------------------------------------------------|
* |Shift | | | | | |Hom|PgD|PgU|End| |Shift | |
* |Shift | | | | | |Hom|PgD|PgU|End|xxx|Shift | |
* |-----------------------------------------------------------|
* | |Gui |Alt |Space |xxxxx| | | | |
* | |Gui |Alt |Space |Alt |Gui|Fn6|Fn6|Ctr|
* `-----------------------------------------------------------'
*/
KEYMAP(KB_GRV, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_GRV, \
KB_BSLS,KB_HOME,KB_PGDN,KB_UP, KB_PGUP,KB_END, KB_HOME,KB_PGDN,KB_PGUP,KB_END, KB_NO, KB_NO, KB_NO, \
KB_LCTL,KB_NO, KB_LEFT,KB_DOWN,KB_RGHT,KB_NO, KB_LEFT,KB_DOWN,KB_UP, KB_RGHT,KB_NO, FN_2, KB_BSLS, \
KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_RSFT,KB_NO, \
KB_NO, KB_LGUI,KB_LALT,KB_SPC, FN_6, KB_NO, KB_NO, KB_NO, KB_NO),
KB_LCTL,KB_NO, KB_LEFT,KB_DOWN,KB_RGHT,KB_NO, KB_LEFT,KB_DOWN,KB_UP, KB_RGHT,KB_NO, KB_NO, KB_BSLS, \
KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, FN_2, KB_RSFT,KB_NO, \
KB_NO, KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_RGUI,FN_6, FN_6, KB_RCTL),


/* Layer 3: Mouse mode (Semicolon)
* ,-------------------------------------------------------- --.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
* ,-----------------------------------------------------------.
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| ` |
* |-----------------------------------------------------------|
* |Tab |MwL|MwD|McU|MwU|MwR|MwL|MwD|MwU|MwR| | | | |
* | \ |MwL|MwD|McU|MwU|MwR|MwL|MwD|MwU|MwR| | | | |
* |-----------------------------------------------------' |
* |Contro| |McL|McD|McR| |McL|McD|McU|McR|xxx| |Return |
* |Contro| |McL|McD|McR| |McL|McD|McU|McR|xxx| | \ |
* |-----------------------------------------------------------|
* |Shift | | |Mb1|Mb2|Mb3|Mb2|Mb1| | | |Shift | |
* |-----------------------------------------------------------|
@@ -123,9 +122,9 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `-----------------------------------------------------------'
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
*/
KEYMAP(KB_ESC, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_DEL, \
KB_TAB, MS_WH_L,MS_WH_D,MS_UP, MS_WH_U,MS_WH_R,MS_WH_L,MS_WH_D,MS_WH_U,MS_WH_R,KB_NO, KB_NO, KB_NO, \
KB_LCTL,KB_NO, MS_LEFT,MS_DOWN,MS_RGHT,KB_NO, MS_LEFT,MS_DOWN,MS_UP, MS_RGHT,FN_3, KB_NO, KB_ENT, \
KEYMAP(KB_GRV, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_GRV, \
KB_BSLS,MS_WH_L,MS_WH_D,MS_UP, MS_WH_U,MS_WH_R,MS_WH_L,MS_WH_D,MS_WH_U,MS_WH_R,KB_NO, KB_NO, KB_NO, \
KB_LCTL,KB_NO, MS_LEFT,MS_DOWN,MS_RGHT,KB_NO, MS_LEFT,MS_DOWN,MS_UP, MS_RGHT,FN_3, KB_NO, KB_BSLS, \
KB_LSFT,KB_NO, KB_NO, MS_BTN1,MS_BTN2,MS_BTN3,MS_BTN2,MS_BTN1,KB_NO, KB_NO, KB_NO, KB_RSFT,KB_NO, \
FN_7, KB_LGUI,KB_LALT,MS_BTN1,KB_RALT,KB_NO, KB_NO, KB_NO, KB_NO),

@@ -140,14 +139,14 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* |Shift | /| .| ,| M| N| B| V| C| X| Z|Shift | |
* |-----------------------------------------------------------|
* | |Gui |Alt |xxxxxxxxxxxxxxxxxxxxxx|Alt | | | | |
* | |Gui |Alt |xxxxxxxxxxxxxxxxxxxxxx|Alt |Gui| | |Ctr|
* `-----------------------------------------------------------'
*/
KEYMAP(KB_MINS,KB_0, KB_9, KB_8, KB_7, KB_6, KB_5, KB_4, KB_3, KB_2, KB_1, KB_NO, KB_NO, KB_ESC, \
KB_BSPC,KB_P, KB_O, KB_I, KB_U, KB_Y, KB_T, KB_R, KB_E, KB_W, KB_Q, KB_TAB, KB_TAB, \
KB_LCTL,KB_SCLN,KB_L, KB_K, KB_J, KB_H, KB_G, KB_F, KB_D, KB_S, KB_A, KB_RCTL,KB_RCTL, \
KB_LSFT,KB_SLSH,KB_DOT, KB_COMM,KB_M, KB_N, KB_B, KB_V, KB_C, KB_X, KB_Z, KB_RSFT,KB_NO, \
KB_NO, KB_LGUI,KB_LALT,FN_4, KB_RALT,KB_NO, KB_NO, KB_NO, KB_NO),
KB_NO, KB_LGUI,KB_LALT,FN_4, KB_RALT,KB_RGUI,KB_NO, KB_NO, KB_RCTL),
};


@@ -168,5 +167,6 @@ uint8_t keymap_fn_keycode(uint8_t fn_bits)

bool keymap_is_special_mode(uint8_t fn_bits)
{
return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));
//return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));
return (usb_keyboard_mods == (BIT_RSHIFT));
}

+ 32
- 68
macway/matrix.c View File

@@ -7,16 +7,10 @@
#include <util/delay.h>
#include "print.h"
#include "util.h"
#include "controller.h"
#include "matrix_skel.h"

// matrix is active low. (key on: 0/key off: 1)
// row: Hi-Z(unselected)/low output(selected)
// PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7
// col: input w/pullup
// PB0-PB7

// matrix state buffer
// matrix state buffer (key on: 1/key off: 0)
static uint8_t *matrix;
static uint8_t *matrix_prev;
static uint8_t _matrix0[MATRIX_ROWS];
@@ -45,6 +39,7 @@ void matrix_init(void)
{
// initialize row and col
unselect_rows();
// Input with pull-up(DDR:0, PORT:1)
DDRB = 0x00;
PORTB = 0xFF;

@@ -64,11 +59,12 @@ int matrix_scan(void)
matrix = tmp;

for (int i = 0; i < MATRIX_ROWS; i++) {
unselect_rows();
select_row(i);
_delay_us(30); // without this wait read unstable value.
matrix[i] = ~read_col();
unselect_rows();
}
unselect_rows();
return 1;
}

@@ -145,88 +141,56 @@ static uint8_t read_col(void)

static void unselect_rows(void)
{
DDRD = 0x00;
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
// Hi-Z(DDR:0, PORT:0) to unselect
DDRC &= ~0b11000000; // PC: 7,6
PORTC &= ~0b11000000;
DDRD &= ~0b11000111; // PD: 7,6,2,1,0
PORTD &= ~0b11000111;
DDRF &= ~0b11000000; // PF: 7,6
PORTF &= ~0b11000000;
}

static void select_row(uint8_t row)
{
// Output low(DDR:1, PORT:0) to select
// row: 0 1 2 3 4 5 6 7 8
// pin: PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7
switch (row) {
case 0:
DDRD = (1<<0);
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
DDRD |= (1<<0);
PORTD &= ~(1<<0);
break;
case 1:
DDRD = 0x00;
PORTD = 0x00;
DDRC = (1<<7);
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
DDRC |= (1<<7);
PORTC &= ~(1<<7);
break;
case 2:
DDRD = (1<<7);
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
DDRD |= (1<<7);
PORTD &= ~(1<<7);
break;
case 3:
DDRD = 0x00;
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = (1<<6);
PORTF = 0x00;
DDRF |= (1<<6);
PORTF &= ~(1<<6);
break;
case 4:
DDRD = (1<<6);
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
DDRD |= (1<<6);
PORTD &= ~(1<<6);
break;
case 5:
DDRD = (1<<1);
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
DDRD |= (1<<1);
PORTD &= ~(1<<1);
break;
case 6:
DDRD = (1<<2);
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
DDRD |= (1<<2);
PORTD &= ~(1<<2);
break;
case 7:
DDRD = 0x00;
PORTD = 0x00;
DDRC = (1<<6);
PORTC = 0x00;
DDRF = 0x00;
PORTF = 0x00;
DDRC |= (1<<6);
PORTC &= ~(1<<6);
break;
case 8:
DDRD = 0x00;
PORTD = 0x00;
DDRC = 0x00;
PORTC = 0x00;
DDRF = (1<<7);
PORTF = 0x00;
DDRF |= (1<<7);
PORTF &= ~(1<<7);
break;
}
}

+ 74
- 0
mousekey.c View File

@@ -0,0 +1,74 @@
#include <stdint.h>
#include <util/delay.h>
#include "usb_keycodes.h"
#include "usb_mouse.h"
#include "mousekey.h"


static int8_t mousekey_x = 0;
static int8_t mousekey_y = 0;
static int8_t mousekey_v = 0;
static int8_t mousekey_h = 0;
static uint8_t mousekey_btn = 0;
static uint8_t mousekey_btn_prev = 0;
static uint8_t mousekey_repeat = 0;


/*
* TODO: fix acceleration algorithm
* see wikipedia http://en.wikipedia.org/wiki/Mouse_keys
*/
#ifndef MOUSEKEY_DELAY_TIME
# define MOUSEKEY_DELAY_TIME 255
#endif


static inline uint8_t move_unit(void)
{
return 10 + (mousekey_repeat < 50 ? mousekey_repeat/5 : 10);
}

void mousekey_decode(uint8_t code)
{
if (code == MS_UP) mousekey_y -= move_unit();
else if (code == MS_DOWN) mousekey_y += move_unit();
else if (code == MS_LEFT) mousekey_x -= move_unit();
else if (code == MS_RGHT) mousekey_x += move_unit();
else if (code == MS_BTN1) mousekey_btn |= MOUSE_BTN1;
else if (code == MS_BTN2) mousekey_btn |= MOUSE_BTN2;
else if (code == MS_BTN3) mousekey_btn |= MOUSE_BTN3;
else if (code == MS_BTN4) mousekey_btn |= MOUSE_BTN4;
else if (code == MS_BTN5) mousekey_btn |= MOUSE_BTN5;
else if (code == MS_WH_U) mousekey_v += 1;
else if (code == MS_WH_D) mousekey_v -= 1;
else if (code == MS_WH_L) mousekey_h -= 1;
else if (code == MS_WH_R) mousekey_h += 1;
}

bool mousekey_changed(void)
{
return (mousekey_x || mousekey_y || mousekey_v || mousekey_h || mousekey_btn != mousekey_btn_prev);
}

void mousekey_usb_send(void)
{
if (mousekey_changed()) {
mousekey_btn_prev = mousekey_btn;
if (mousekey_x && mousekey_y)
usb_mouse_send(mousekey_x*0.7, mousekey_y*0.7, mousekey_v, mousekey_h, mousekey_btn);
else
usb_mouse_send(mousekey_x, mousekey_y, mousekey_v, mousekey_h, mousekey_btn);

usb_mouse_print(mousekey_x, mousekey_y, mousekey_v, mousekey_h, mousekey_btn);

_delay_ms(MOUSEKEY_DELAY_TIME >> (mousekey_repeat < 5 ? mousekey_repeat : 4));
mousekey_repeat++;
} else {
mousekey_repeat = 0;
}
mousekey_x = 0;
mousekey_y = 0;
mousekey_v = 0;
mousekey_h = 0;
mousekey_btn = 0;
}

+ 11
- 0
mousekey.h View File

@@ -0,0 +1,11 @@
#ifndef MOUSEKEY_H
#define MOUSEKEY_H

#include <stdbool.h>

void mousekey_decode(uint8_t code);
bool mousekey_changed(void);
void mousekey_usb_send(void);

#endif


+ 248
- 0
ps2.c View File

@@ -0,0 +1,248 @@
/*
Copyright (c) 2010 Jun WAKO <[email protected]>

This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
GPL-compatible, and OK to use in both free and proprietary applications.
Additions and corrections to this file are welcome.


Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.

* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "ps2.h"
#include "print.h"
#include "debug.h"


static inline void clock_lo(void);
static inline void clock_hi(void);
static inline bool clock_in(void);
static inline void data_lo(void);
static inline void data_hi(void);
static inline bool data_in(void);
static inline uint16_t wait_clock_lo(uint16_t us);
static inline uint16_t wait_clock_hi(uint16_t us);
static inline uint16_t wait_data_lo(uint16_t us);
static inline uint16_t wait_data_hi(uint16_t us);


/*
Primitive PS/2 Library for AVR
==============================
Host side is only supported now.


I/O control
-----------
High state is asserted by input with pull up.


PS/2 References
---------------
http://www.computer-engineering.org/ps2protocol/
http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
*/


#define WAIT(stat, us, err) do { \
if (!wait_##stat(us)) { \
ps2_error = err; \
goto ERROR; \
} \
} while (0)

#define WAIT_NORETRY(stat, us, err) do { \
if (!wait_##stat(us)) { \
ps2_error = err; \
return 0; \
} \
} while (0)


uint8_t ps2_error = PS2_ERR_NONE;


void ps2_host_init(void)
{
/* inhibit */
clock_lo();
data_hi();
}

uint8_t ps2_host_send(uint8_t data)
{
bool parity = true;
ps2_error = 0;

/* request to send */
clock_lo();
data_lo();
_delay_us(100);
/* start bit [1] */
clock_hi();
WAIT(clock_lo, 15000, 1);
/* data [2-9] */
for (uint8_t i = 0; i < 8; i++) {
if (data&(1<<i)) {
parity = !parity;
data_hi();
} else {
data_lo();
}
WAIT(clock_hi, 50, 2);
WAIT(clock_lo, 50, 3);
}
/* parity [10] */
if (parity) { data_hi(); } else { data_lo(); }
WAIT(clock_hi, 50, 4);
WAIT(clock_lo, 50, 5);
/* stop bit [11] */
data_hi();
/* ack [12] */
WAIT(data_lo, 50, 6);
WAIT(clock_lo, 50, 7);
WAIT(clock_hi, 50, 8);
WAIT(data_hi, 50, 9);

/* inhibit device to send */
clock_lo();

return 1;
ERROR:
return 0;
}

uint8_t ps2_host_recv(void)
{
uint8_t data = 0;
bool parity = true;
ps2_error = 0;

/* cancel to sync */
clock_lo();
_delay_us(100);

/* release lines(idle state) */
clock_hi();
data_hi();

/* start bit [1] */
WAIT(clock_lo, 20000, 1);
WAIT(data_lo, 1, 2);
WAIT(clock_hi, 50, 3);

/* data [2-9] */
for (uint8_t i = 0; i < 8; i++) {
WAIT(clock_lo, 50, 4);
if (data_in()) {
parity = !parity;
data |= (1<<i);
}
WAIT(clock_hi, 50, 5);
}

/* parity [10] */
WAIT(clock_lo, 50, 6);
if (data_in() != parity) {
ps2_error = PS2_ERR_PARITY;
goto ERROR;
}
WAIT(clock_hi, 50, 7);

/* stop bit [11] */
WAIT(clock_lo, 50, 8);
WAIT(data_hi, 1, 9);
WAIT(clock_hi, 50, 10);

/* inhibit device to send */
clock_lo();

return data;
ERROR:
return 0;
}


static inline void clock_lo()
{
PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT);
}
static inline void clock_hi()
{
/* input with pull up */
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
}
static inline bool clock_in()
{
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
}
static inline void data_lo()
{
PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
PS2_DATA_DDR |= (1<<PS2_DATA_BIT);
}
static inline void data_hi()
{
/* input with pull up */
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
}
static inline bool data_in()
{
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
}

static inline uint16_t wait_clock_lo(uint16_t us)
{
while (clock_in() && us) { asm(""); _delay_us(1); us--; }
return us;
}
static inline uint16_t wait_clock_hi(uint16_t us)
{
while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
return us;
}
static inline uint16_t wait_data_lo(uint16_t us)
{
while (data_in() && us) { asm(""); _delay_us(1); us--; }
return us;
}
static inline uint16_t wait_data_hi(uint16_t us)
{
while (!data_in() && us) { asm(""); _delay_us(1); us--; }
return us;
}

+ 72
- 0
ps2.h View File

@@ -0,0 +1,72 @@
/*
Copyright (c) 2010 Jun WAKO <[email protected]>

This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
GPL-compatible, and OK to use in both free and proprietary applications.
Additions and corrections to this file are welcome.


Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.

* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PS2_H
#define PS2_H
/*
* Primitive PS/2 Library for AVR
*/


/* port settings for clock and data line */
#if !(defined(PS2_CLOCK_PORT) && \
defined(PS2_CLOCK_PIN) && \
defined(PS2_CLOCK_DDR) && \
defined(PS2_CLOCK_BIT))
# error "PS/2 clock port setting is required in config.h"
#endif

#if !(defined(PS2_DATA_PORT) && \
defined(PS2_DATA_PIN) && \
defined(PS2_DATA_DDR) && \
defined(PS2_DATA_BIT))
# error "PS/2 data port setting is required in config.h"
#endif

#define PS2_ERR_NONE 0
#define PS2_ERR_PARITY 0x10


extern uint8_t ps2_error;

/* host side */
void ps2_host_init(void);
uint8_t ps2_host_send(uint8_t);
uint8_t ps2_host_recv(void);

/* TODO: device side */

#endif

+ 161
- 0
ps2_mouse.c View File

@@ -0,0 +1,161 @@
#include <stdbool.h>
#include<avr/io.h>
#include<util/delay.h>
#include "ps2.h"
#include "ps2_mouse.h"
#include "usb_mouse.h"

#define PS2_MOUSE_DEBUG
#ifdef PS2_MOUSE_DEBUG
# include "print.h"
# include "debug.h"
#else
# define print(s)
# define phex(h)
# define phex16(h)
#endif

/*
TODO
----
- Error handling
- Stream mode
- Tracpoint command support: needed
- Middle button + move = Wheel traslation
*/
uint8_t ps2_mouse_x = 0;
uint8_t ps2_mouse_y = 0;
uint8_t ps2_mouse_btn = 0;
uint8_t ps2_mouse_error_count = 0;
static uint8_t ps2_mouse_btn_prev = 0;

void ps2_mouse_init(void) {
uint8_t rcv;

// Reset
rcv = ps2_host_send(0xFF);
print("ps2_mouse_init: send 0xFF: ");
phex(ps2_error); print("\n");

// ACK
rcv = ps2_host_recv();
print("ps2_mouse_init: read ACK: ");
phex(rcv); phex(ps2_error); print("\n");

// BAT takes some time
_delay_ms(100);
rcv = ps2_host_recv();
print("ps2_mouse_init: read BAT: ");
phex(rcv); phex(ps2_error); print("\n");

// Device ID
rcv = ps2_host_recv();
print("ps2_mouse_init: read DevID: ");
phex(rcv); phex(ps2_error); print("\n");

// Enable data reporting
ps2_host_send(0xF4);
print("ps2_mouse_init: send 0xF4: ");
phex(ps2_error); print("\n");

// ACK
rcv = ps2_host_recv();
print("ps2_mouse_init: read ACK: ");
phex(rcv); phex(ps2_error); print("\n");

// Set Remote mode
ps2_host_send(0xF0);
print("ps2_mouse_init: send 0xF0: ");
phex(ps2_error); print("\n");

// ACK
rcv = ps2_host_recv();
print("ps2_mouse_init: read ACK: ");
phex(rcv); phex(ps2_error); print("\n");

if (ps2_error) ps2_mouse_error_count++;
}

/*
Data format:
bit: 7 6 5 4 3 2 1 0
-----------------------------------------------------------------------
0 btn: Yovflw Xovflw Ysign Xsign 1 Middle Right Left
1 x: X movement(0-255)
2 y: Y movement(0-255)
*/
void ps2_mouse_read(void)
{
uint8_t rcv;

ps2_host_send(0xEB);
rcv=ps2_host_recv();
if(rcv==0xFA) {
ps2_mouse_btn = ps2_host_recv();
ps2_mouse_x = ps2_host_recv();
ps2_mouse_y = ps2_host_recv();
}
if (ps2_error) ps2_mouse_error_count++;
}

bool ps2_mouse_changed(void)
{
return (ps2_mouse_x || ps2_mouse_y || (ps2_mouse_btn & PS2_MOUSE_BTN_MASK) != ps2_mouse_btn_prev);
}

#define PS2_MOUSE_SCROLL_BUTTON 0x04
void ps2_mouse_usb_send(void)
{
static bool scrolled = false;
if (ps2_mouse_changed()) {
int8_t x, y, v, h;
x = y = v = h = 0;

// convert scale of X, Y: PS/2(-256/255) -> USB(-127/127)
if (ps2_mouse_btn & (1<<PS2_MOUSE_X_SIGN))
x = ps2_mouse_x > 128 ? (int8_t)ps2_mouse_x : -127;
else
x = ps2_mouse_x < 128 ? (int8_t)ps2_mouse_x : 127;

if (ps2_mouse_btn & (1<<PS2_MOUSE_Y_SIGN))
y = ps2_mouse_y > 128 ? (int8_t)ps2_mouse_y : -127;
else
y = ps2_mouse_y < 128 ? (int8_t)ps2_mouse_y : 127;

// Y is needed to reverse
y = -y;

if (ps2_mouse_btn & PS2_MOUSE_SCROLL_BUTTON) {
// scroll
if (x > 0 || x < 0) h = (x > 64 ? 64 : (x < -64 ? -64 :x));
if (y > 0 || y < 0) v = (y > 64 ? 64 : (y < -64 ? -64 :y));
if (h || v) {
scrolled = true;
usb_mouse_send(0,0, -v/16, h/16, 0);
_delay_ms(100);
}
} else if (!scrolled && (ps2_mouse_btn_prev & PS2_MOUSE_SCROLL_BUTTON)) {
usb_mouse_send(0,0,0,0, PS2_MOUSE_SCROLL_BUTTON);
_delay_ms(100);
usb_mouse_send(0,0,0,0, 0);
} else {
scrolled = false;
usb_mouse_send(x, y, 0, 0, ps2_mouse_btn & PS2_MOUSE_BTN_MASK);
}

ps2_mouse_btn_prev = (ps2_mouse_btn & PS2_MOUSE_BTN_MASK);
ps2_mouse_print();
}
ps2_mouse_x = 0;
ps2_mouse_y = 0;
ps2_mouse_btn = 0;
}

void ps2_mouse_print(void)
{
if (!debug_mouse) return;
print("ps2_mouse[btn|x y]: ");
phex(ps2_mouse_btn); print("|");
phex(ps2_mouse_x); print(" ");
phex(ps2_mouse_y); print("\n");
}

+ 26
- 0
ps2_mouse.h View File

@@ -0,0 +1,26 @@
#ifndef PS2_MOUSE_H
#define PS2_MOUSE_H

#include <stdbool.h>

#define PS2_MOUSE_BTN_MASK 0x07
#define PS2_MOUSE_BTN_LEFT 0
#define PS2_MOUSE_BTN_RIGHT 1
#define PS2_MOUSE_BTN_MIDDLE 2
#define PS2_MOUSE_X_SIGN 4
#define PS2_MOUSE_Y_SIGN 5
#define PS2_MOUSE_X_OVFLW 6
#define PS2_MOUSE_Y_OVFLW 7

extern uint8_t ps2_mouse_x;
extern uint8_t ps2_mouse_y;
extern uint8_t ps2_mouse_btn;
extern uint8_t ps2_mouse_error_count;

void ps2_mouse_init(void);
void ps2_mouse_read(void);
bool ps2_mouse_changed(void);
void ps2_mouse_usb_send(void);
void ps2_mouse_print(void);

#endif

+ 9
- 2
tmk.c View File

@@ -34,9 +34,12 @@
#include "print.h"
#include "debug.h"
#include "util.h"
#include "controller.h"
#include "timer.h"
#include "jump_bootloader.h"
#ifdef PS2_MOUSE_ENABLE
# include "ps2.h"
# include "ps2_mouse.h"
#endif


#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
@@ -91,8 +94,12 @@ int main(void)
jump_bootloader(); // not return
}

#ifdef PS2_MOUSE_ENABLE
ps2_host_init();
ps2_mouse_init();
#endif

while (1) {
proc_matrix();
_delay_ms(2);
}
}

+ 8
- 8
usb.c View File

@@ -94,7 +94,7 @@ static const uint8_t PROGMEM endpoint_config_table[] = {
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5
#else
0, // 5
@@ -168,7 +168,7 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = {
0x81, 0x00, // Input (Data, Array),
0xc0 // End Collection
};
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
static uint8_t PROGMEM keyboard2_hid_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
@@ -336,7 +336,7 @@ static uint8_t PROGMEM extra_hid_report_desc[] = {
#define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*1+9)
#define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*2+9)
#define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*3+9)
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
# define NUM_INTERFACES 5
# define KBD2_HID_DESC_OFFSET (9+(9+9+7)*4+9)
#else
@@ -468,7 +468,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
EXTRA_SIZE, 0, // wMaxPacketSize
10, // bInterval

#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
@@ -543,7 +543,7 @@ static struct descriptor_list_struct {
{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
{0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
{0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9},
{0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)},
#endif
@@ -884,7 +884,7 @@ ISR(USB_COM_vect)
if (bRequest == HID_GET_REPORT) {
if (wValue == HID_REPORT_INPUT) {
usb_wait_in_ready();
UEDATX = mouse_buttons;
UEDATX = 0;
UEDATX = 0;
UEDATX = 0;
UEDATX = 0;
@@ -900,14 +900,14 @@ ISR(USB_COM_vect)
}
if (bRequest == HID_GET_PROTOCOL) {
usb_wait_in_ready();
UEDATX = mouse_protocol;
UEDATX = usb_mouse_protocol;
usb_send_in();
return;
}
}
if (bmRequestType == 0x21) {
if (bRequest == HID_SET_PROTOCOL) {
mouse_protocol = wValue;
usb_mouse_protocol = wValue;
usb_send_in();
return;
}

+ 5
- 5
usb_keyboard.c View File

@@ -28,7 +28,7 @@ uint8_t usb_keyboard_idle_count=0;
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
volatile uint8_t usb_keyboard_leds=0;

// enable NKRO
// enable USB NKRO
bool usb_keyboard_nkro = false;


@@ -42,7 +42,7 @@ int8_t usb_keyboard_send_report(usb_keyboard_report_t *report)
{
int8_t result = 0;

#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
if (usb_keyboard_nkro)
result = _send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS);
else
@@ -106,7 +106,7 @@ static inline void _add_key_byte(uint8_t code);
static inline void _add_key_bit(uint8_t code);
void usb_keyboard_add_key(uint8_t code)
{
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
if (usb_keyboard_nkro) {
_add_key_bit(code);
return;
@@ -131,7 +131,7 @@ void usb_keyboard_del_code(uint8_t code)

void usb_keyboard_del_key(uint8_t code)
{
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
if ((code>>3) < KEYS_MAX) {
usb_keyboard_keys[code>>3] &= ~(1<<(code&7));
}
@@ -169,7 +169,7 @@ bool usb_keyboard_has_mod(void)

uint8_t usb_keyboard_get_key(void)
{
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
if (usb_keyboard_nkro) {
uint8_t i = 0;
for (; i < KEYS_MAX && !usb_keyboard_keys[i]; i++);

+ 1
- 1
usb_keyboard.h View File

@@ -13,7 +13,7 @@
#define KBD_REPORT_KEYS (KBD_SIZE - 2)

// secondary keyboard
#ifdef NKRO_ENABLE
#ifdef USB_NKRO_ENABLE
#define KBD2_INTERFACE 4
#define KBD2_ENDPOINT 5
#define KBD2_SIZE 16

+ 13
- 44
usb_mouse.c View File

@@ -5,40 +5,18 @@
#include "debug.h"


static bool is_sent = false;
uint8_t usb_mouse_protocol=1;

// which buttons are currently pressed
uint8_t mouse_buttons=0;

// protocol setting from the host. We use exactly the same report
// either way, so this variable only stores the setting since we
// are required to be able to report which setting is in use.
uint8_t mouse_protocol=1;


// Set the mouse buttons. To create a "click", 2 calls are needed,
// one to push the button down and the second to release it
int8_t usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right)
{
uint8_t mask=0;

if (left) mask |= 1;
if (middle) mask |= 4;
if (right) mask |= 2;
mouse_buttons = mask;
return usb_mouse_move(0, 0, 0, 0);
}

// Move the mouse. x, y and wheel are -127 to 127. Use 0 for no movement.
int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel, int8_t hwheel)
int8_t usb_mouse_send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons)
{
uint8_t intr_state, timeout;

if (!usb_configured()) return -1;
if (x == -128) x = -127;
if (y == -128) y = -127;
if (wheel == -128) wheel = -127;
if (hwheel == -128) hwheel = -127;
if (wheel_v == -128) wheel_v = -127;
if (wheel_h == -128) wheel_h = -127;
intr_state = SREG;
cli();
UENUM = MOUSE_ENDPOINT;
@@ -56,34 +34,25 @@ int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel, int8_t hwheel)
cli();
UENUM = MOUSE_ENDPOINT;
}
UEDATX = mouse_buttons;
UEDATX = buttons;
UEDATX = x;
UEDATX = y;
if (mouse_protocol) {
UEDATX = wheel;
UEDATX = hwheel;
if (usb_mouse_protocol) {
UEDATX = wheel_v;
UEDATX = wheel_h;
}
UEINTX = 0x3A;
SREG = intr_state;
is_sent = true;
return 0;
}

void usb_mouse_clear(void) {
is_sent = false;
}

bool usb_mouse_is_sent(void) {
return is_sent;
}

void usb_mouse_print(int8_t mouse_x, int8_t mouse_y, int8_t wheel_v, int8_t wheel_h) {
void usb_mouse_print(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons) {
if (!debug_mouse) return;
print("mouse btn|x y v h: ");
phex(mouse_buttons); print("|");
phex(mouse_x); print(" ");
phex(mouse_y); print(" ");
print("usb_mouse[btn|x y v h]: ");
phex(buttons); print("|");
phex(x); print(" ");
phex(y); print(" ");
phex(wheel_v); print(" ");
phex(wheel_h); print("\n");
}

+ 8
- 12
usb_mouse.h View File

@@ -11,21 +11,17 @@
#define MOUSE_SIZE 8
#define MOUSE_BUFFER EP_DOUBLE_BUFFER

#define BIT_BTN1 (1<<0)
#define BIT_BTN2 (1<<1)
#define BIT_BTN3 (1<<2)
#define BIT_BTN4 (1<<3)
#define BIT_BTN5 (1<<4)
#define MOUSE_BTN1 (1<<0)
#define MOUSE_BTN2 (1<<1)
#define MOUSE_BTN3 (1<<2)
#define MOUSE_BTN4 (1<<3)
#define MOUSE_BTN5 (1<<4)


extern uint8_t mouse_buttons;
extern uint8_t mouse_protocol;
extern uint8_t usb_mouse_protocol;


int8_t usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right);
int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel, int8_t hwheel);
void usb_mouse_clear(void);
bool usb_mouse_is_sent(void);
void usb_mouse_print(int8_t mouse_x, int8_t mouse_y, int8_t wheel_v, int8_t wheel_h);
int8_t usb_mouse_send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons);
void usb_mouse_print(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons);

#endif

Loading…
Cancel
Save