forked from mfulz_github/qmk_firmware
Compare commits
25 Commits
Author | SHA1 | Date |
---|---|---|
Jack Humbert | d2123f3c07 | |
Jack Humbert | 3996250d81 | |
Jack Humbert | 09ff4b0c99 | |
Jack Humbert | 708bb4f55d | |
a-chol | a80ea8b7cc | |
a-chol | a03d1eb66b | |
a-chol | 92c6466089 | |
a-chol | 16fe12e6b6 | |
a-chol | 1d8102183f | |
a-chol | 476fce8a32 | |
a-chol | 0ce015d0c9 | |
a-chol | c447c4ffd5 | |
a-chol | 887e96cbb2 | |
a-chol | def06b4976 | |
a-chol | 34bedc3787 | |
a-chol | c6c01f9eff | |
a-chol | 86853a4110 | |
a-chol | a8a2825bd4 | |
Nick Brassel | 38cd264dd8 | |
a-chol | 6fd7f9d12f | |
Nick Brassel | 801be60473 | |
a-chol | d88bdc6a1b | |
achol | b030c45705 | |
José Júnior | ee43b338ea | |
achol | 3cf7611139 |
|
@ -22,6 +22,11 @@ QUANTUM_SRC += \
|
||||||
$(QUANTUM_DIR)/keymap_common.c \
|
$(QUANTUM_DIR)/keymap_common.c \
|
||||||
$(QUANTUM_DIR)/keycode_config.c
|
$(QUANTUM_DIR)/keycode_config.c
|
||||||
|
|
||||||
|
KEYBOARD_ENABLE ?= yes
|
||||||
|
ifeq ($(strip $(KEYBOARD_ENABLE)), yes)
|
||||||
|
OPT_DEFS += -DKEYBOARD_ENABLE
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
|
ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), yes)
|
||||||
OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
|
OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
|
||||||
CONSOLE_ENABLE = yes
|
CONSOLE_ENABLE = yes
|
||||||
|
@ -600,3 +605,8 @@ endif
|
||||||
ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
|
ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
|
||||||
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
|
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(SWITCH_CONTROLLER_ENABLE)), yes)
|
||||||
|
OPT_DEFS += -DSWITCH_CONTROLLER_ENABLE
|
||||||
|
OPT_DEFS += -DGAMEPAD_ENABLE
|
||||||
|
endif
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* Copyright 2019 Jack Humbert
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config_common.h"
|
||||||
|
|
||||||
|
/* USB Device descriptor parameter */
|
||||||
|
#define VENDOR_ID 0x0e6f
|
||||||
|
#define PRODUCT_ID 0x0185
|
||||||
|
#define DEVICE_VER 0x0001
|
||||||
|
#define MANUFACTURER QMK
|
||||||
|
#define PRODUCT Proton C
|
||||||
|
#define DESCRIPTION Handwired Gamepad
|
||||||
|
|
||||||
|
/* key matrix size */
|
||||||
|
#define MATRIX_ROWS 1
|
||||||
|
#define MATRIX_COLS 1
|
||||||
|
|
||||||
|
#define DIODE_DIRECTION COL2ROW
|
||||||
|
|
||||||
|
#define MATRIX_COL_PINS { A3 }
|
||||||
|
#define MATRIX_ROW_PINS { A1 }
|
||||||
|
|
||||||
|
/* define if matrix has ghost */
|
||||||
|
//#define MATRIX_HAS_GHOST
|
||||||
|
|
||||||
|
/* Set 0 if debouncing isn't needed */
|
||||||
|
#define DEBOUNCE 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Feature disable options
|
||||||
|
* These options are also useful to firmware size reduction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* disable debug print */
|
||||||
|
//#define NO_DEBUG
|
||||||
|
|
||||||
|
/* disable print */
|
||||||
|
//#define NO_PRINT
|
||||||
|
|
||||||
|
/* disable action features */
|
||||||
|
//#define NO_ACTION_LAYER
|
||||||
|
//#define NO_ACTION_TAPPING
|
||||||
|
//#define NO_ACTION_ONESHOT
|
||||||
|
//#define NO_ACTION_MACRO
|
||||||
|
//#define NO_ACTION_FUNCTION
|
||||||
|
|
||||||
|
#define GAMECUBE_DATA_PIN A2
|
|
@ -0,0 +1,130 @@
|
||||||
|
#include "gc_controller.h"
|
||||||
|
#include "gc_read.h"
|
||||||
|
#include "gamepad.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
uint16_t gamecube_buttons = 0;
|
||||||
|
uint8_t gamecube_joysticks[6] = {0};
|
||||||
|
bool z_button = false;
|
||||||
|
|
||||||
|
report_gamepad_t report = {
|
||||||
|
.Button = 0,
|
||||||
|
.LX = STICK_CENTER,
|
||||||
|
.LY = STICK_CENTER,
|
||||||
|
.RX = STICK_CENTER,
|
||||||
|
.RY = STICK_CENTER,
|
||||||
|
.HAT = HAT_CENTER
|
||||||
|
};
|
||||||
|
|
||||||
|
void board_init(void) {
|
||||||
|
setPinOutput(C13);
|
||||||
|
writePinLow(C13);
|
||||||
|
gamecube_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_init_user(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_scan_user(void) {
|
||||||
|
|
||||||
|
gamecube_scan(&gamecube_buttons, gamecube_joysticks);
|
||||||
|
|
||||||
|
z_button = gamecube_buttons & GAMECUBE_Z;
|
||||||
|
|
||||||
|
// Home & Capture
|
||||||
|
if (gamecube_buttons & GAMECUBE_START) {
|
||||||
|
if (z_button && !(report.Button & SWITCH_HOME))
|
||||||
|
report.Button |= SWITCH_CAPTURE;
|
||||||
|
else
|
||||||
|
report.Button |= SWITCH_HOME;
|
||||||
|
} else {
|
||||||
|
report.Button &= ~SWITCH_HOME;
|
||||||
|
report.Button &= ~SWITCH_CAPTURE;
|
||||||
|
}
|
||||||
|
// Y and L
|
||||||
|
if (gamecube_buttons & GAMECUBE_Y) {
|
||||||
|
if (z_button && !(report.Button & SWITCH_Y))
|
||||||
|
report.Button |= SWITCH_L;
|
||||||
|
else
|
||||||
|
report.Button |= SWITCH_Y;
|
||||||
|
} else {
|
||||||
|
report.Button &= ~SWITCH_Y;
|
||||||
|
report.Button &= ~SWITCH_L;
|
||||||
|
}
|
||||||
|
// X and R
|
||||||
|
if (gamecube_buttons & GAMECUBE_X) {
|
||||||
|
if (z_button && !(report.Button & SWITCH_X))
|
||||||
|
report.Button |= SWITCH_R;
|
||||||
|
else
|
||||||
|
report.Button |= SWITCH_X;
|
||||||
|
} else {
|
||||||
|
report.Button &= ~SWITCH_X;
|
||||||
|
report.Button &= ~SWITCH_R;
|
||||||
|
}
|
||||||
|
// B and -
|
||||||
|
if (gamecube_buttons & GAMECUBE_B) {
|
||||||
|
if (z_button && !(report.Button & SWITCH_B))
|
||||||
|
report.Button |= SWITCH_MINUS;
|
||||||
|
else
|
||||||
|
report.Button |= SWITCH_B;
|
||||||
|
} else {
|
||||||
|
report.Button &= ~SWITCH_B;
|
||||||
|
report.Button &= ~SWITCH_MINUS;
|
||||||
|
}
|
||||||
|
// A and +
|
||||||
|
if (gamecube_buttons & GAMECUBE_A) {
|
||||||
|
if (z_button && !(report.Button & SWITCH_A))
|
||||||
|
report.Button |= SWITCH_PLUS;
|
||||||
|
else
|
||||||
|
report.Button |= SWITCH_A;
|
||||||
|
} else {
|
||||||
|
report.Button &= ~SWITCH_A;
|
||||||
|
report.Button &= ~SWITCH_PLUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamecube_buttons & GAMECUBE_L) {
|
||||||
|
report.Button |= SWITCH_ZL;
|
||||||
|
} else {
|
||||||
|
report.Button &= ~SWITCH_ZL;
|
||||||
|
}
|
||||||
|
if (gamecube_buttons & GAMECUBE_R) {
|
||||||
|
report.Button |= SWITCH_ZR;
|
||||||
|
} else {
|
||||||
|
report.Button &= ~SWITCH_ZR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((gamecube_buttons & GAMECUBE_UP) && (gamecube_buttons & GAMECUBE_RIGHT))
|
||||||
|
report.HAT = HAT_TOP_RIGHT;
|
||||||
|
else if ((gamecube_buttons & GAMECUBE_UP) && (gamecube_buttons & GAMECUBE_LEFT))
|
||||||
|
report.HAT = HAT_TOP_LEFT;
|
||||||
|
else if ((gamecube_buttons & GAMECUBE_DOWN) && (gamecube_buttons & GAMECUBE_RIGHT))
|
||||||
|
report.HAT = HAT_BOTTOM_RIGHT;
|
||||||
|
else if ((gamecube_buttons & GAMECUBE_DOWN) && (gamecube_buttons & GAMECUBE_LEFT))
|
||||||
|
report.HAT = HAT_BOTTOM_LEFT;
|
||||||
|
else if (gamecube_buttons & GAMECUBE_UP)
|
||||||
|
report.HAT = HAT_TOP;
|
||||||
|
else if (gamecube_buttons & GAMECUBE_DOWN)
|
||||||
|
report.HAT = HAT_BOTTOM;
|
||||||
|
else if (gamecube_buttons & GAMECUBE_RIGHT)
|
||||||
|
report.HAT = HAT_RIGHT;
|
||||||
|
else if (gamecube_buttons & GAMECUBE_LEFT)
|
||||||
|
report.HAT = HAT_LEFT;
|
||||||
|
else
|
||||||
|
report.HAT = HAT_CENTER;
|
||||||
|
|
||||||
|
if (report.Button || report.HAT != HAT_CENTER)
|
||||||
|
writePinHigh(C13);
|
||||||
|
else
|
||||||
|
writePinLow(C13);
|
||||||
|
|
||||||
|
// joystick calculations
|
||||||
|
|
||||||
|
report.LX = gamecube_joysticks[0];
|
||||||
|
report.LY = 255 - gamecube_joysticks[1];
|
||||||
|
report.RX = gamecube_joysticks[2];
|
||||||
|
report.RY = 255 - gamecube_joysticks[3];
|
||||||
|
|
||||||
|
send_gamepad(&report);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SWITCH_Y = 0x01,
|
||||||
|
SWITCH_B = 0x02,
|
||||||
|
SWITCH_A = 0x04,
|
||||||
|
SWITCH_X = 0x08,
|
||||||
|
SWITCH_L = 0x10,
|
||||||
|
SWITCH_R = 0x20,
|
||||||
|
SWITCH_ZL = 0x40,
|
||||||
|
SWITCH_ZR = 0x80,
|
||||||
|
SWITCH_MINUS = 0x100,
|
||||||
|
SWITCH_PLUS = 0x200,
|
||||||
|
SWITCH_LCLICK = 0x400,
|
||||||
|
SWITCH_RCLICK = 0x800,
|
||||||
|
SWITCH_HOME = 0x1000,
|
||||||
|
SWITCH_CAPTURE = 0x2000,
|
||||||
|
} SwitchButtons_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GAMECUBE_A = 0b0000000000000001,
|
||||||
|
GAMECUBE_B = 0b0000000000000010,
|
||||||
|
GAMECUBE_X = 0b0000000000000100,
|
||||||
|
GAMECUBE_Y = 0b0000000000001000,
|
||||||
|
GAMECUBE_START = 0b0000000000010000,
|
||||||
|
GAMECUBE_LEFT = 0b0000000100000000,
|
||||||
|
GAMECUBE_RIGHT = 0b0000001000000000,
|
||||||
|
GAMECUBE_DOWN = 0b0000010000000000,
|
||||||
|
GAMECUBE_UP = 0b0000100000000000,
|
||||||
|
GAMECUBE_Z = 0b0001000000000000,
|
||||||
|
GAMECUBE_R = 0b0010000000000000,
|
||||||
|
GAMECUBE_L = 0b0100000000000000,
|
||||||
|
} GamecubeButtons_t;
|
||||||
|
|
||||||
|
#define HAT_TOP 0x00
|
||||||
|
#define HAT_TOP_RIGHT 0x01
|
||||||
|
#define HAT_RIGHT 0x02
|
||||||
|
#define HAT_BOTTOM_RIGHT 0x03
|
||||||
|
#define HAT_BOTTOM 0x04
|
||||||
|
#define HAT_BOTTOM_LEFT 0x05
|
||||||
|
#define HAT_LEFT 0x06
|
||||||
|
#define HAT_TOP_LEFT 0x07
|
||||||
|
#define HAT_CENTER 0x08
|
||||||
|
|
||||||
|
#define STICK_MIN 0
|
||||||
|
#define STICK_CENTER 128
|
||||||
|
#define STICK_MAX 255
|
|
@ -0,0 +1,216 @@
|
||||||
|
#include "gc_read.h"
|
||||||
|
#include "gc_controller.h"
|
||||||
|
|
||||||
|
#define CONTROLLER_TIMEOUT 60
|
||||||
|
|
||||||
|
bool init_message[9] = {0, 0, 0, 0, 0, 0, 0, 0, 1};
|
||||||
|
bool request_message[25] = {
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 1, 1,
|
||||||
|
0, 0, 0, 0, 0, 0, 1, 0, 1};
|
||||||
|
|
||||||
|
void start_message(void) {
|
||||||
|
setPinOutput(GAMECUBE_DATA_PIN);
|
||||||
|
writePinLow(GAMECUBE_DATA_PIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_bit(bool b) {
|
||||||
|
if (b) {
|
||||||
|
writePinLow(GAMECUBE_DATA_PIN);
|
||||||
|
wait_ns(900);
|
||||||
|
writePinHigh(GAMECUBE_DATA_PIN);
|
||||||
|
wait_ns(2900);
|
||||||
|
} else {
|
||||||
|
writePinLow(GAMECUBE_DATA_PIN);
|
||||||
|
wait_ns(2900);
|
||||||
|
writePinHigh(GAMECUBE_DATA_PIN);
|
||||||
|
wait_ns(900);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait_for_ready(void) {
|
||||||
|
setPinInputHigh(GAMECUBE_DATA_PIN);
|
||||||
|
|
||||||
|
// wait for long high
|
||||||
|
uint8_t ready = 0;
|
||||||
|
while (ready < 5) {
|
||||||
|
if (readPin(GAMECUBE_DATA_PIN))
|
||||||
|
ready++;
|
||||||
|
else
|
||||||
|
ready = 0;
|
||||||
|
wait_us(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_message(void) {
|
||||||
|
setPinInputHigh(GAMECUBE_DATA_PIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t buffer[9] = {0};
|
||||||
|
uint16_t buttons_debounce = 0;
|
||||||
|
bool initialised = false;
|
||||||
|
bool calibrated = false;
|
||||||
|
uint8_t mid_values[4] = {128, 128, 128, 128};
|
||||||
|
uint8_t max_values[4] = {210, 210, 210, 210};
|
||||||
|
uint8_t min_values[4] = {35, 35, 35, 35};
|
||||||
|
|
||||||
|
void gamecube_init(void) {
|
||||||
|
setPinInputHigh(GAMECUBE_DATA_PIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gamecube_scan(uint16_t * buttons, uint8_t * joysticks) {
|
||||||
|
bool exiting = false;
|
||||||
|
uint16_t timeout_counter = 0;
|
||||||
|
|
||||||
|
// somehow we're missing the first bit, which can safely be ignored
|
||||||
|
// i'm not sure if it's something with the timing or what
|
||||||
|
uint8_t buffer_bit = 1;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
|
||||||
|
if (!initialised) {
|
||||||
|
wait_for_ready();
|
||||||
|
|
||||||
|
start_message();
|
||||||
|
for (uint8_t i = 0; i < 9; i++)
|
||||||
|
send_bit(init_message[i]);
|
||||||
|
end_message();
|
||||||
|
|
||||||
|
initialised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_ready();
|
||||||
|
|
||||||
|
start_message();
|
||||||
|
for (uint8_t i = 0; i < 25; i++)
|
||||||
|
send_bit(request_message[i]);
|
||||||
|
end_message();
|
||||||
|
|
||||||
|
while (!exiting) {
|
||||||
|
timeout_counter = 0;
|
||||||
|
// wait for low or timeout
|
||||||
|
while (readPin(GAMECUBE_DATA_PIN)) {
|
||||||
|
wait_ns(100);
|
||||||
|
timeout_counter++;
|
||||||
|
if (timeout_counter > CONTROLLER_TIMEOUT) {
|
||||||
|
exiting = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exiting) {
|
||||||
|
// wait for the data part
|
||||||
|
wait_ns(1950);
|
||||||
|
bool b = readPin(GAMECUBE_DATA_PIN);
|
||||||
|
if (b)
|
||||||
|
buffer[buffer_bit / 8] |= (1 << (7 - (buffer_bit % 8)));
|
||||||
|
else
|
||||||
|
buffer[buffer_bit / 8] &= ~(1 << (7 - (buffer_bit % 8)));
|
||||||
|
buffer_bit++;
|
||||||
|
|
||||||
|
// wait for high
|
||||||
|
while (!readPin(GAMECUBE_DATA_PIN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chSysUnlock();
|
||||||
|
|
||||||
|
// basic debouncing for buttons
|
||||||
|
uint16_t combined_buttons = buffer[0] | (buffer[1] << 8);
|
||||||
|
*buttons |= buttons_debounce & combined_buttons;
|
||||||
|
*buttons &= buttons_debounce | combined_buttons;
|
||||||
|
buttons_debounce = combined_buttons;
|
||||||
|
|
||||||
|
if (!calibrated && mid_values[0] > 0) {
|
||||||
|
mid_values[0] = buffer[2];
|
||||||
|
mid_values[1] = buffer[3];
|
||||||
|
mid_values[2] = buffer[4];
|
||||||
|
mid_values[3] = buffer[5];
|
||||||
|
calibrated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_values[0] < buffer[2])
|
||||||
|
max_values[0] = buffer[2];
|
||||||
|
if (max_values[1] < buffer[3])
|
||||||
|
max_values[1] = buffer[3];
|
||||||
|
if (max_values[2] < buffer[4])
|
||||||
|
max_values[2] = buffer[4];
|
||||||
|
if (max_values[3] < buffer[5])
|
||||||
|
max_values[3] = buffer[5];
|
||||||
|
|
||||||
|
if (min_values[0] > buffer[2])
|
||||||
|
min_values[0] = buffer[2];
|
||||||
|
if (min_values[1] > buffer[3])
|
||||||
|
min_values[1] = buffer[3];
|
||||||
|
if (min_values[2] > buffer[4])
|
||||||
|
min_values[2] = buffer[4];
|
||||||
|
if (min_values[3] > buffer[5])
|
||||||
|
min_values[3] = buffer[5];
|
||||||
|
|
||||||
|
// values from my GC controller in Windows
|
||||||
|
// 30 - 138 - 236
|
||||||
|
// 20 - 124 - 225
|
||||||
|
// 37 - 135 - 222
|
||||||
|
// 34 - 126 - 216
|
||||||
|
|
||||||
|
// this should be 127? i don't understand what i'm doing wrong yet
|
||||||
|
#define JOYSTICK_SCALER 180.0
|
||||||
|
|
||||||
|
int32_t lx_temp = (int16_t)buffer[2] - mid_values[0];
|
||||||
|
if (lx_temp > 0)
|
||||||
|
lx_temp *= JOYSTICK_SCALER / (max_values[0]-mid_values[0]);
|
||||||
|
else
|
||||||
|
lx_temp *= JOYSTICK_SCALER / (mid_values[0]-min_values[0]);
|
||||||
|
lx_temp += STICK_CENTER;
|
||||||
|
if (lx_temp > 255)
|
||||||
|
lx_temp = 255;
|
||||||
|
if (lx_temp < 0)
|
||||||
|
lx_temp = 0;
|
||||||
|
|
||||||
|
int32_t ly_temp = (int16_t)buffer[3] - mid_values[1];
|
||||||
|
if (ly_temp > 0)
|
||||||
|
ly_temp *= JOYSTICK_SCALER / (max_values[1]-mid_values[1]);
|
||||||
|
else
|
||||||
|
ly_temp *= JOYSTICK_SCALER / (mid_values[1]-min_values[1]);
|
||||||
|
ly_temp += STICK_CENTER;
|
||||||
|
if (ly_temp > 255)
|
||||||
|
ly_temp = 255;
|
||||||
|
if (ly_temp < 0)
|
||||||
|
ly_temp = 0;
|
||||||
|
|
||||||
|
int32_t rx_temp = (int16_t)buffer[4] - mid_values[2];
|
||||||
|
if (rx_temp > 0)
|
||||||
|
rx_temp *= JOYSTICK_SCALER / (max_values[2]-mid_values[2]);
|
||||||
|
else
|
||||||
|
rx_temp *= JOYSTICK_SCALER / (mid_values[2]-min_values[2]);
|
||||||
|
rx_temp += STICK_CENTER;
|
||||||
|
if (rx_temp > 255)
|
||||||
|
rx_temp = 255;
|
||||||
|
if (rx_temp < 0)
|
||||||
|
rx_temp = 0;
|
||||||
|
|
||||||
|
int32_t ry_temp = (int16_t)buffer[5] - mid_values[3];
|
||||||
|
if (ry_temp > 0)
|
||||||
|
ry_temp *= JOYSTICK_SCALER / (max_values[3]-mid_values[3]);
|
||||||
|
else
|
||||||
|
ry_temp *= JOYSTICK_SCALER / (mid_values[3]-min_values[3]);
|
||||||
|
ry_temp += STICK_CENTER;
|
||||||
|
if (ry_temp > 255)
|
||||||
|
ry_temp = 255;
|
||||||
|
if (ry_temp < 0)
|
||||||
|
ry_temp = 0;
|
||||||
|
|
||||||
|
// checks to avoid a data skip (0 values on input, which aren't possible, i think)
|
||||||
|
if (buffer[2])
|
||||||
|
joysticks[0] = lx_temp;
|
||||||
|
if (buffer[3])
|
||||||
|
joysticks[1] = ly_temp;
|
||||||
|
if (buffer[4])
|
||||||
|
joysticks[2] = rx_temp;
|
||||||
|
if (buffer[5])
|
||||||
|
joysticks[3] = ry_temp;
|
||||||
|
if (buffer[6])
|
||||||
|
joysticks[4] = buffer[6];
|
||||||
|
if (buffer[7])
|
||||||
|
joysticks[5] = buffer[7];
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
|
||||||
|
|
||||||
|
#ifndef NOP_FUDGE
|
||||||
|
# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
|
||||||
|
# define NOP_FUDGE 0.4
|
||||||
|
# else
|
||||||
|
# error("NOP_FUDGE configuration required")
|
||||||
|
# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUMBER_NOPS 6
|
||||||
|
#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE)
|
||||||
|
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
|
||||||
|
#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
|
||||||
|
#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
|
||||||
|
|
||||||
|
#define wait_ns(x) \
|
||||||
|
do { \
|
||||||
|
for (int i = 0; i < NS_TO_CYCLES(x); i++) { \
|
||||||
|
__asm__ volatile("nop\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
"nop\n\t" \
|
||||||
|
"nop\n\t"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
void gamecube_init(void);
|
||||||
|
void gamecube_scan(uint16_t * buttons, uint8_t * joysticks);
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { { { 0 } } };
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
J1 header
|
||||||
|
---------
|
||||||
|
|
||||||
|
|#|Color |Proton C|Description|
|
||||||
|
|-|-------|----|------------|
|
||||||
|
|1|blue |3.3V| |
|
||||||
|
|2|yellow |5V | |
|
||||||
|
|3|red |A2 |Data (3.3V) |
|
||||||
|
|4|green |GND | |
|
||||||
|
|5|white |GND | |
|
||||||
|
|6|black |NC | |
|
|
@ -0,0 +1,15 @@
|
||||||
|
# MCU name
|
||||||
|
MCU = STM32F303
|
||||||
|
|
||||||
|
BACKLIGHT_ENABLE = no
|
||||||
|
MOUSEKEY_ENABLE = no
|
||||||
|
EXTRAKEY_ENABLE = no
|
||||||
|
CONSOLE_ENABLE = no
|
||||||
|
NKRO_ENABLE = no
|
||||||
|
RAW_ENABLE = no
|
||||||
|
MIDI_ENABLE = no
|
||||||
|
VIRTSER_ENABLE = no
|
||||||
|
KEYBOARD_ENABLE = no
|
||||||
|
SWITCH_CONTROLLER_ENABLE = yes
|
||||||
|
|
||||||
|
SRC += gc_read.c
|
|
@ -29,4 +29,4 @@
|
||||||
|
|
||||||
#define RGB_DI_PIN A0
|
#define RGB_DI_PIN A0
|
||||||
|
|
||||||
#define ADC_PIN A0
|
#define ADC_PIN A1
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void send_gamepad(report_gamepad_t *report);
|
||||||
|
void gamepad_ep_task(void);
|
|
@ -30,7 +30,8 @@ enum hid_report_ids {
|
||||||
REPORT_ID_SYSTEM,
|
REPORT_ID_SYSTEM,
|
||||||
REPORT_ID_CONSUMER,
|
REPORT_ID_CONSUMER,
|
||||||
REPORT_ID_NKRO,
|
REPORT_ID_NKRO,
|
||||||
REPORT_ID_JOYSTICK
|
REPORT_ID_JOYSTICK,
|
||||||
|
REPORT_ID_GAMEPAD
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mouse buttons */
|
/* Mouse buttons */
|
||||||
|
@ -198,6 +199,29 @@ typedef struct {
|
||||||
#endif
|
#endif
|
||||||
} __attribute__((packed)) joystick_report_t;
|
} __attribute__((packed)) joystick_report_t;
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
typedef struct {
|
||||||
|
#ifdef SWITCH_CONTROLLER_ENABLE
|
||||||
|
uint16_t Button; // 16 buttons; see JoystickButtons_t for bit mapping
|
||||||
|
uint8_t HAT; // HAT switch; one nibble w/ unused nibble
|
||||||
|
uint8_t LX; // Left Stick X
|
||||||
|
uint8_t LY; // Left Stick Y
|
||||||
|
uint8_t RX; // Right Stick X
|
||||||
|
uint8_t RY; // Right Stick Y
|
||||||
|
uint8_t VendorSpec;
|
||||||
|
#else
|
||||||
|
// TODO add generic gamepad report
|
||||||
|
uint16_t Button; // 16 buttons; see JoystickButtons_t for bit mapping
|
||||||
|
uint8_t HAT; // HAT switch; one nibble w/ unused nibble
|
||||||
|
uint8_t LX; // Left Stick X
|
||||||
|
uint8_t LY; // Left Stick Y
|
||||||
|
uint8_t RX; // Right Stick X
|
||||||
|
uint8_t RY; // Right Stick Y
|
||||||
|
uint8_t VendorSpec;
|
||||||
|
#endif
|
||||||
|
} report_gamepad_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* keycode to system usage */
|
/* keycode to system usage */
|
||||||
static inline uint16_t KEYCODE2SYSTEM(uint8_t key) {
|
static inline uint16_t KEYCODE2SYSTEM(uint8_t key) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|
|
@ -86,10 +86,15 @@ void raw_hid_task(void);
|
||||||
#ifdef CONSOLE_ENABLE
|
#ifdef CONSOLE_ENABLE
|
||||||
void console_task(void);
|
void console_task(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MIDI_ENABLE
|
#ifdef MIDI_ENABLE
|
||||||
void midi_ep_task(void);
|
void midi_ep_task(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
void gamepad_ep_task(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* TESTING
|
/* TESTING
|
||||||
* Amber LED blinker thread, times are in milliseconds.
|
* Amber LED blinker thread, times are in milliseconds.
|
||||||
*/
|
*/
|
||||||
|
@ -258,6 +263,9 @@ int main(void) {
|
||||||
#endif
|
#endif
|
||||||
#ifdef MIDI_ENABLE
|
#ifdef MIDI_ENABLE
|
||||||
midi_ep_task();
|
midi_ep_task();
|
||||||
|
#endif
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
gamepad_ep_task();
|
||||||
#endif
|
#endif
|
||||||
#ifdef VIRTSER_ENABLE
|
#ifdef VIRTSER_ENABLE
|
||||||
virtser_task();
|
virtser_task();
|
||||||
|
|
|
@ -51,6 +51,10 @@ extern keymap_config_t keymap_config;
|
||||||
# include "joystick.h"
|
# include "joystick.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
# include "gamepad.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------------------
|
/* ---------------------------------------------------------
|
||||||
* Global interface variables and declarations
|
* Global interface variables and declarations
|
||||||
* ---------------------------------------------------------
|
* ---------------------------------------------------------
|
||||||
|
@ -109,7 +113,7 @@ static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype
|
||||||
return &desc;
|
return &desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
/* keyboard endpoint state structure */
|
/* keyboard endpoint state structure */
|
||||||
static USBInEndpointState kbd_ep_state;
|
static USBInEndpointState kbd_ep_state;
|
||||||
/* keyboard endpoint initialization structure (IN) - see USBEndpointConfig comment at top of file */
|
/* keyboard endpoint initialization structure (IN) - see USBEndpointConfig comment at top of file */
|
||||||
|
@ -314,6 +318,9 @@ typedef struct {
|
||||||
#endif
|
#endif
|
||||||
#ifdef JOYSTICK_ENABLE
|
#ifdef JOYSTICK_ENABLE
|
||||||
usb_driver_config_t joystick_driver;
|
usb_driver_config_t joystick_driver;
|
||||||
|
#endif
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
usb_driver_config_t gamepad_driver;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
usb_driver_config_t array[0];
|
usb_driver_config_t array[0];
|
||||||
|
@ -359,6 +366,14 @@ static usb_driver_configs_t drivers = {
|
||||||
# define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK
|
# define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK
|
||||||
.joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false),
|
.joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
# define GAMEPAD_IN_CAPACITY 4
|
||||||
|
# define GAMEPAD_OUT_CAPACITY 4
|
||||||
|
# define GAMEPAD_IN_MODE USB_EP_MODE_TYPE_BULK
|
||||||
|
# define GAMEPAD_OUT_MODE USB_EP_MODE_TYPE_BULK
|
||||||
|
.gamepad_driver = QMK_USB_DRIVER_CONFIG(GAMEPAD, 0, false),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
|
#define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
|
||||||
|
@ -378,7 +393,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
|
||||||
case USB_EVENT_CONFIGURED:
|
case USB_EVENT_CONFIGURED:
|
||||||
osalSysLockFromISR();
|
osalSysLockFromISR();
|
||||||
/* Enable the endpoints specified into the configuration. */
|
/* Enable the endpoints specified into the configuration. */
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
|
usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||||
|
@ -491,11 +506,12 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||||
switch (usbp->setup[1]) { /* bRequest */
|
switch (usbp->setup[1]) { /* bRequest */
|
||||||
case HID_GET_REPORT:
|
case HID_GET_REPORT:
|
||||||
switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
|
switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
|
||||||
|
#ifdef KEYBOARD_ENABLE
|
||||||
case KEYBOARD_INTERFACE:
|
case KEYBOARD_INTERFACE:
|
||||||
usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
|
usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||||
case MOUSE_INTERFACE:
|
case MOUSE_INTERFACE:
|
||||||
usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
|
usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
|
||||||
|
@ -511,7 +527,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_GET_PROTOCOL:
|
case HID_GET_PROTOCOL:
|
||||||
if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
|
if ((usbp->setup[4] == 0) && (usbp->setup[5] == 0)) { /* wIndex */
|
||||||
usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
|
usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +544,9 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||||
switch (usbp->setup[1]) { /* bRequest */
|
switch (usbp->setup[1]) { /* bRequest */
|
||||||
case HID_SET_REPORT:
|
case HID_SET_REPORT:
|
||||||
switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
|
switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
|
||||||
|
#ifdef KEYBOARD_ENABLE
|
||||||
case KEYBOARD_INTERFACE:
|
case KEYBOARD_INTERFACE:
|
||||||
|
#endif
|
||||||
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
|
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
|
||||||
case SHARED_INTERFACE:
|
case SHARED_INTERFACE:
|
||||||
#endif
|
#endif
|
||||||
|
@ -539,7 +557,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_SET_PROTOCOL:
|
case HID_SET_PROTOCOL:
|
||||||
if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
|
if ((usbp->setup[4] == 0) && (usbp->setup[5] == 0)) { /* wIndex */
|
||||||
keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
|
keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
|
||||||
#ifdef NKRO_ENABLE
|
#ifdef NKRO_ENABLE
|
||||||
keymap_config.nkro = !!keyboard_protocol;
|
keymap_config.nkro = !!keyboard_protocol;
|
||||||
|
@ -660,7 +678,7 @@ void restart_usb_driver(USBDriver *usbp) {
|
||||||
* ---------------------------------------------------------
|
* ---------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
/* keyboard IN callback hander (a kbd report has made it IN) */
|
/* keyboard IN callback hander (a kbd report has made it IN) */
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
|
void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||||
/* STUB */
|
/* STUB */
|
||||||
(void)usbp;
|
(void)usbp;
|
||||||
|
@ -693,9 +711,11 @@ static void keyboard_idle_timer_cb(void *arg) {
|
||||||
if (keyboard_idle && keyboard_protocol) {
|
if (keyboard_idle && keyboard_protocol) {
|
||||||
#endif /* NKRO_ENABLE */
|
#endif /* NKRO_ENABLE */
|
||||||
/* TODO: are we sure we want the KBD_ENDPOINT? */
|
/* TODO: are we sure we want the KBD_ENDPOINT? */
|
||||||
|
#ifdef KEYBOARD_ENABLE
|
||||||
if (!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
|
if (!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
|
||||||
usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE);
|
usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* rearm the timer */
|
/* rearm the timer */
|
||||||
chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
|
chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
|
||||||
}
|
}
|
||||||
|
@ -711,6 +731,7 @@ uint8_t keyboard_leds(void) { return keyboard_led_state; }
|
||||||
/* prepare and start sending a report IN
|
/* prepare and start sending a report IN
|
||||||
* not callable from ISR or locked state */
|
* not callable from ISR or locked state */
|
||||||
void send_keyboard(report_keyboard_t *report) {
|
void send_keyboard(report_keyboard_t *report) {
|
||||||
|
#ifdef KEYBOARD_ENABLE
|
||||||
osalSysLock();
|
osalSysLock();
|
||||||
if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
|
if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -767,6 +788,7 @@ void send_keyboard(report_keyboard_t *report) {
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
osalSysUnlock();
|
osalSysUnlock();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------
|
/* ---------------------------------------------------------
|
||||||
|
@ -1021,3 +1043,35 @@ void send_joystick_packet(joystick_t *joystick) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
|
||||||
|
void send_gamepad(report_gamepad_t *report) {
|
||||||
|
osalSysLock();
|
||||||
|
if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
|
||||||
|
osalSysUnlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
usbStartTransmitI(&USB_DRIVER, GAMEPAD_IN_EPNUM, (uint8_t *)report, sizeof(report_gamepad_t));
|
||||||
|
osalSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool recv_gamepad_packet(report_gamepad_t *const report) {
|
||||||
|
size_t size = chnReadTimeout(&drivers.gamepad_driver.driver, (uint8_t *)report, sizeof(report_gamepad_t), TIME_IMMEDIATE);
|
||||||
|
return size == sizeof(report_gamepad_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gamepad_ep_task(void) {
|
||||||
|
uint8_t buffer[GAMEPAD_EPSIZE];
|
||||||
|
size_t size = 0;
|
||||||
|
do {
|
||||||
|
size_t size = chnReadTimeout(&drivers.gamepad_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE);
|
||||||
|
if (size > 0) {
|
||||||
|
report_gamepad_t report;
|
||||||
|
recv_gamepad_packet(&report);
|
||||||
|
}
|
||||||
|
} while (size > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -524,6 +524,9 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
|
||||||
/* Setup joystick endpoint */
|
/* Setup joystick endpoint */
|
||||||
ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
|
ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef JOYSTICK_ENABLE
|
||||||
|
ConfigSuccess &= ENDPOINT_CONFIG(JOYSTICK_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, JOYSTICK_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Expose this table in the docs somehow
|
/* FIXME: Expose this table in the docs somehow
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
/*
|
/*
|
||||||
* HID report descriptors
|
* HID report descriptors
|
||||||
*/
|
*/
|
||||||
|
#ifdef KEYBOARD_ENABLE
|
||||||
#ifdef KEYBOARD_SHARED_EP
|
#ifdef KEYBOARD_SHARED_EP
|
||||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
||||||
# define SHARED_REPORT_STARTED
|
# define SHARED_REPORT_STARTED
|
||||||
|
@ -100,6 +101,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#ifndef KEYBOARD_SHARED_EP
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MOUSE_ENABLE
|
#ifdef MOUSE_ENABLE
|
||||||
# ifndef MOUSE_SHARED_EP
|
# ifndef MOUSE_SHARED_EP
|
||||||
|
@ -347,6 +349,64 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
const USB_Descriptor_HIDReport_Datatype_t PROGMEM GamepadReport[] = {
|
||||||
|
HID_RI_USAGE_PAGE(8,1), /* Generic Desktop */
|
||||||
|
HID_RI_USAGE(8,5), /* Joystick */
|
||||||
|
HID_RI_COLLECTION(8,1), /* Application */
|
||||||
|
// Buttons (2 bytes)
|
||||||
|
HID_RI_LOGICAL_MINIMUM(8,0),
|
||||||
|
HID_RI_LOGICAL_MAXIMUM(8,1),
|
||||||
|
HID_RI_PHYSICAL_MINIMUM(8,0),
|
||||||
|
HID_RI_PHYSICAL_MAXIMUM(8,1),
|
||||||
|
// The Switch will allow us to expand the original HORI descriptors to a full 16 buttons.
|
||||||
|
// The Switch will make use of 14 of those buttons.
|
||||||
|
HID_RI_REPORT_SIZE(8,1),
|
||||||
|
HID_RI_REPORT_COUNT(8,16),
|
||||||
|
HID_RI_USAGE_PAGE(8,9),
|
||||||
|
HID_RI_USAGE_MINIMUM(8,1),
|
||||||
|
HID_RI_USAGE_MAXIMUM(8,16),
|
||||||
|
HID_RI_INPUT(8,2),
|
||||||
|
// HAT Switch (1 nibble)
|
||||||
|
HID_RI_USAGE_PAGE(8,1),
|
||||||
|
HID_RI_LOGICAL_MAXIMUM(8,7),
|
||||||
|
HID_RI_PHYSICAL_MAXIMUM(16,315),
|
||||||
|
HID_RI_REPORT_SIZE(8,4),
|
||||||
|
HID_RI_REPORT_COUNT(8,1),
|
||||||
|
HID_RI_UNIT(8,20),
|
||||||
|
HID_RI_USAGE(8,57),
|
||||||
|
HID_RI_INPUT(8,66),
|
||||||
|
// There's an additional nibble here that's utilized as part of the Switch Pro Controller.
|
||||||
|
// I believe this -might- be separate U/D/L/R bits on the Switch Pro Controller, as they're utilized as four button descriptors on the Switch Pro Controller.
|
||||||
|
HID_RI_UNIT(8,0),
|
||||||
|
HID_RI_REPORT_COUNT(8,1),
|
||||||
|
HID_RI_INPUT(8,1),
|
||||||
|
// Joystick (4 bytes)
|
||||||
|
HID_RI_LOGICAL_MAXIMUM(16,255),
|
||||||
|
HID_RI_PHYSICAL_MAXIMUM(16,255),
|
||||||
|
HID_RI_USAGE(8,48),
|
||||||
|
HID_RI_USAGE(8,49),
|
||||||
|
HID_RI_USAGE(8,50),
|
||||||
|
HID_RI_USAGE(8,53),
|
||||||
|
HID_RI_REPORT_SIZE(8,8),
|
||||||
|
HID_RI_REPORT_COUNT(8,4),
|
||||||
|
HID_RI_INPUT(8,2),
|
||||||
|
// ??? Vendor Specific (1 byte)
|
||||||
|
// This byte requires additional investigation.
|
||||||
|
HID_RI_USAGE_PAGE(16,65280),
|
||||||
|
HID_RI_USAGE(8,32),
|
||||||
|
HID_RI_REPORT_COUNT(8,1),
|
||||||
|
HID_RI_INPUT(8,2),
|
||||||
|
// Output (8 bytes)
|
||||||
|
// Original observation of this suggests it to be a mirror of the inputs that we sent.
|
||||||
|
// The Switch requires us to have these descriptors available.
|
||||||
|
HID_RI_USAGE(16,9761),
|
||||||
|
HID_RI_REPORT_COUNT(8,8),
|
||||||
|
HID_RI_OUTPUT(8,2),
|
||||||
|
HID_RI_END_COLLECTION(0),
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device descriptor
|
* Device descriptor
|
||||||
*/
|
*/
|
||||||
|
@ -406,7 +466,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
|
||||||
.ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
|
.ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
|
||||||
.MaxPowerConsumption = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)
|
.MaxPowerConsumption = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)
|
||||||
},
|
},
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
/*
|
/*
|
||||||
* Keyboard
|
* Keyboard
|
||||||
*/
|
*/
|
||||||
|
@ -925,6 +985,56 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
|
||||||
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
|
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
/*
|
||||||
|
* Gamepad
|
||||||
|
*/
|
||||||
|
.Gamepad_Interface = {
|
||||||
|
.Header = {
|
||||||
|
.Size = sizeof(USB_Descriptor_Interface_t),
|
||||||
|
.Type = DTYPE_Interface
|
||||||
|
},
|
||||||
|
.InterfaceNumber = GAMEPAD_INTERFACE,
|
||||||
|
.AlternateSetting = 0x00,
|
||||||
|
.TotalEndpoints = 2,
|
||||||
|
.Class = HID_CSCP_HIDClass,
|
||||||
|
.SubClass = HID_CSCP_NonBootSubclass,
|
||||||
|
.Protocol = HID_CSCP_NonBootProtocol,
|
||||||
|
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||||
|
},
|
||||||
|
.Gamepad_HID = {
|
||||||
|
.Header = {
|
||||||
|
.Size = sizeof(USB_HID_Descriptor_HID_t),
|
||||||
|
.Type = HID_DTYPE_HID
|
||||||
|
},
|
||||||
|
.HIDSpec = VERSION_BCD(1, 1, 1),
|
||||||
|
.CountryCode = 0x00,
|
||||||
|
.TotalReportDescriptors = 1,
|
||||||
|
.HIDReportType = HID_DTYPE_Report,
|
||||||
|
.HIDReportLength = sizeof(GamepadReport)
|
||||||
|
},
|
||||||
|
.Gamepad_INEndpoint = {
|
||||||
|
.Header = {
|
||||||
|
.Size = sizeof(USB_Descriptor_Endpoint_t),
|
||||||
|
.Type = DTYPE_Endpoint
|
||||||
|
},
|
||||||
|
.EndpointAddress = (ENDPOINT_DIR_IN | GAMEPAD_IN_EPNUM),
|
||||||
|
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||||
|
.EndpointSize = GAMEPAD_EPSIZE,
|
||||||
|
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
|
||||||
|
},
|
||||||
|
.Gamepad_OUTEndpoint = {
|
||||||
|
.Header = {
|
||||||
|
.Size = sizeof(USB_Descriptor_Endpoint_t),
|
||||||
|
.Type = DTYPE_Endpoint
|
||||||
|
},
|
||||||
|
.EndpointAddress = (ENDPOINT_DIR_OUT | GAMEPAD_OUT_EPNUM),
|
||||||
|
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||||
|
.EndpointSize = GAMEPAD_EPSIZE,
|
||||||
|
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1019,7 +1129,7 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
|
||||||
break;
|
break;
|
||||||
case HID_DTYPE_HID:
|
case HID_DTYPE_HID:
|
||||||
switch (wIndex) {
|
switch (wIndex) {
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
case KEYBOARD_INTERFACE:
|
case KEYBOARD_INTERFACE:
|
||||||
Address = &ConfigurationDescriptor.Keyboard_HID;
|
Address = &ConfigurationDescriptor.Keyboard_HID;
|
||||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||||
|
@ -1062,13 +1172,19 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
|
||||||
Address = &ConfigurationDescriptor.Joystick_HID;
|
Address = &ConfigurationDescriptor.Joystick_HID;
|
||||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
case GAMEPAD_INTERFACE:
|
||||||
|
Address = &ConfigurationDescriptor.Gamepad_HID;
|
||||||
|
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case HID_DTYPE_Report:
|
case HID_DTYPE_Report:
|
||||||
switch (wIndex) {
|
switch (wIndex) {
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
case KEYBOARD_INTERFACE:
|
case KEYBOARD_INTERFACE:
|
||||||
Address = &KeyboardReport;
|
Address = &KeyboardReport;
|
||||||
Size = sizeof(KeyboardReport);
|
Size = sizeof(KeyboardReport);
|
||||||
|
@ -1112,6 +1228,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
|
||||||
Address = &JoystickReport;
|
Address = &JoystickReport;
|
||||||
Size = sizeof(JoystickReport);
|
Size = sizeof(JoystickReport);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
case GAMEPAD_INTERFACE:
|
||||||
|
Address = &GamepadReport;
|
||||||
|
Size = sizeof(GamepadReport);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
USB_Descriptor_Configuration_Header_t Config;
|
USB_Descriptor_Configuration_Header_t Config;
|
||||||
|
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
// Keyboard HID Interface
|
// Keyboard HID Interface
|
||||||
USB_Descriptor_Interface_t Keyboard_Interface;
|
USB_Descriptor_Interface_t Keyboard_Interface;
|
||||||
USB_HID_Descriptor_HID_t Keyboard_HID;
|
USB_HID_Descriptor_HID_t Keyboard_HID;
|
||||||
|
@ -134,14 +134,26 @@ typedef struct {
|
||||||
USB_Descriptor_Interface_t Joystick_Interface;
|
USB_Descriptor_Interface_t Joystick_Interface;
|
||||||
USB_HID_Descriptor_HID_t Joystick_HID;
|
USB_HID_Descriptor_HID_t Joystick_HID;
|
||||||
USB_Descriptor_Endpoint_t Joystick_INEndpoint;
|
USB_Descriptor_Endpoint_t Joystick_INEndpoint;
|
||||||
|
#ifdef SWITCH_CONTROLLER_ENABLE
|
||||||
|
USB_Descriptor_Endpoint_t Joystick_OUTEndpoint;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
// Gamepad HID Interface
|
||||||
|
USB_Descriptor_Interface_t Gamepad_Interface;
|
||||||
|
USB_HID_Descriptor_HID_t Gamepad_HID;
|
||||||
|
USB_Descriptor_Endpoint_t Gamepad_INEndpoint;
|
||||||
|
USB_Descriptor_Endpoint_t Gamepad_OUTEndpoint;
|
||||||
|
#endif
|
||||||
|
|
||||||
} USB_Descriptor_Configuration_t;
|
} USB_Descriptor_Configuration_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interface indexes
|
* Interface indexes
|
||||||
*/
|
*/
|
||||||
enum usb_interfaces {
|
enum usb_interfaces {
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
KEYBOARD_INTERFACE,
|
KEYBOARD_INTERFACE,
|
||||||
#else
|
#else
|
||||||
SHARED_INTERFACE,
|
SHARED_INTERFACE,
|
||||||
|
@ -177,9 +189,13 @@ enum usb_interfaces {
|
||||||
CDI_INTERFACE,
|
CDI_INTERFACE,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(JOYSTICK_ENABLE)
|
#ifdef JOYSTICK_ENABLE
|
||||||
JOYSTICK_INTERFACE,
|
JOYSTICK_INTERFACE,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
GAMEPAD_INTERFACE,
|
||||||
|
#endif
|
||||||
TOTAL_INTERFACES
|
TOTAL_INTERFACES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,9 +207,10 @@ enum usb_interfaces {
|
||||||
enum usb_endpoints {
|
enum usb_endpoints {
|
||||||
__unused_epnum__ = NEXT_EPNUM, // Endpoint numbering starts at 1
|
__unused_epnum__ = NEXT_EPNUM, // Endpoint numbering starts at 1
|
||||||
|
|
||||||
#ifndef KEYBOARD_SHARED_EP
|
#if !defined(KEYBOARD_SHARED_EP) && defined(KEYBOARD_ENABLE)
|
||||||
KEYBOARD_IN_EPNUM = NEXT_EPNUM,
|
KEYBOARD_IN_EPNUM = NEXT_EPNUM,
|
||||||
#else
|
#endif
|
||||||
|
#ifdef KEYBOARD_SHARED_EP
|
||||||
# define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
|
# define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -259,6 +276,16 @@ enum usb_endpoints {
|
||||||
JOYSTICK_OUT_EPNUM = NEXT_EPNUM,
|
JOYSTICK_OUT_EPNUM = NEXT_EPNUM,
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef JOYSTICK_ENABLE
|
||||||
|
JOYSTICK_IN_EPNUM = NEXT_EPNUM,
|
||||||
|
JOYSTICK_OUT_EPNUM = NEXT_EPNUM,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GAMEPAD_ENABLE
|
||||||
|
GAMEPAD_IN_EPNUM = NEXT_EPNUM,
|
||||||
|
GAMEPAD_OUT_EPNUM = NEXT_EPNUM,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef PROTOCOL_LUFA
|
#ifdef PROTOCOL_LUFA
|
||||||
|
@ -283,6 +310,7 @@ enum usb_endpoints {
|
||||||
#define MIDI_STREAM_EPSIZE 64
|
#define MIDI_STREAM_EPSIZE 64
|
||||||
#define CDC_NOTIFICATION_EPSIZE 8
|
#define CDC_NOTIFICATION_EPSIZE 8
|
||||||
#define CDC_EPSIZE 16
|
#define CDC_EPSIZE 16
|
||||||
|
#define GAMEPAD_EPSIZE 64
|
||||||
#define JOYSTICK_EPSIZE 8
|
#define JOYSTICK_EPSIZE 8
|
||||||
|
|
||||||
uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);
|
uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);
|
||||||
|
|
Loading…
Reference in New Issue