Add joystick interface, fix STALL bugs maybe

This commit is contained in:
William Toohey
2017-02-16 01:39:42 +10:00
parent b802aad1de
commit 6533026b51
7 changed files with 161 additions and 126 deletions
+20 -8
View File
@@ -5,7 +5,12 @@
#define MAGIC_NUMBER 42
static sdvx_config_t defaults PROGMEM = {
uint8_t firstRun EEMEM; // init to 255
sdvx_config_t eeConfig EEMEM;
sdvx_config_t sdvxConfig;
static const PROGMEM sdvx_config_t defaults = {
.switches = {
HID_KEYBOARD_SC_Z,
HID_KEYBOARD_SC_X,
@@ -13,20 +18,27 @@ static sdvx_config_t defaults PROGMEM = {
HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK,
HID_KEYBOARD_SC_C,
HID_KEYBOARD_SC_M,
HID_KEYBOARD_SC_ENTER},
//.ledsOn = true,
HID_KEYBOARD_SC_ENTER,
HID_KEYBOARD_SC_KEYPAD_PLUS}, // macro
.btColour = {BRIGHTNESS_MAX, BRIGHTNESS_MAX, BRIGHTNESS_MAX}, // white
.fxColour = {BRIGHTNESS_MAX, BRIGHTNESS_MAX/4, 0}, // orange
.knobColours = {
{0,BRIGHTNESS_MAX,BRIGHTNESS_MAX}, // aqua
{BRIGHTNESS_MAX,0,BRIGHTNESS_MAX} // pink
},
.lightsOn = 1,
.hidLights = 1,
.keyLights = 1,
.knobLights = 1,
.lightPattern = FOLLOWER,
.macroClick = HID_KEYBOARD_SC_KEYPAD_PLUS,
.macroPin = {HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT,
HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT,
HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT,
HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT}
.joystickMode = 1,
};
uint8_t firstRun EEMEM; // init to 255
sdvx_config_t eeConfig EEMEM;
sdvx_config_t sdvxConfig;
void InitConfig(void) {
if (eeprom_read_byte(&firstRun) != MAGIC_NUMBER) { // store defaults
memcpy_P(&sdvxConfig, &defaults, sizeof(sdvx_config_t));
+8 -5
View File
@@ -8,6 +8,7 @@
// 7 gameplay switches + macro combo switch
#define SWITCH_COUNT 8
#define JOYSTICK_PPR (24 * 4)
#define MAGIC_RESET_NUMBER 42
// divide by 10 for actual version
#define FIRMWARE_VERSION 1
@@ -21,15 +22,17 @@ typedef struct {
RGB_t btColour;
RGB_t fxColour;
RGB_t knobColours[2];
bool lightsOn;
bool hidLights;
bool keyLights;
bool knobLights;
uint8_t lightsOn;
uint8_t hidLights;
uint8_t keyLights;
uint8_t knobLights;
uint8_t lightPattern;
// When tapping or long-pressing the macro key
uint8_t macroClick;
uint8_t macroHold;
uint8_t macroPin[4];
} sdvx_config_t;
uint8_t joystickMode;
} ATTR_PACKED sdvx_config_t;
#define CONFIG_BYTES sizeof(sdvx_config_t)
+1 -1
View File
@@ -67,7 +67,7 @@
#define USE_FLASH_DESCRIPTORS
// #define USE_EEPROM_DESCRIPTORS
// #define NO_INTERNAL_SERIAL
#define FIXED_CONTROL_ENDPOINT_SIZE 8
#define FIXED_CONTROL_ENDPOINT_SIZE 64
// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
#define FIXED_NUM_CONFIGURATIONS 1
// #define CONTROL_ONLY_DEVICE
+30
View File
@@ -100,6 +100,36 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM InputsReport[] =
HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0),
/* Joystick report adjusted from HID_DESCRIPTOR_JOYSTICK */
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RI_USAGE(8, 0x05), /* Game pad */
HID_RI_COLLECTION(8, 0x01), /* Application */
HID_RI_REPORT_ID(8, HID_REPORTID_JoystickReport),
HID_RI_USAGE(8, 0x01), /* Pointer */
HID_RI_COLLECTION(8, 0x00), /* Physical */
HID_RI_USAGE(8, 0x30), /* X axis */
HID_RI_USAGE(8, 0x31), /* Y axis */
HID_RI_LOGICAL_MINIMUM(16, 0),
HID_RI_LOGICAL_MAXIMUM(16, JOYSTICK_PPR-1),
HID_RI_PHYSICAL_MINIMUM(16, -1),
HID_RI_PHYSICAL_MAXIMUM(16, 1),
HID_RI_REPORT_COUNT(8, 2), /* 2 axis */
HID_RI_REPORT_SIZE(8, 8),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0),
HID_RI_USAGE_PAGE(8, 0x09), /* Button */
HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */
HID_RI_USAGE_MAXIMUM(8, SWITCH_COUNT), /* Button x */
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_REPORT_COUNT(8, SWITCH_COUNT),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_REPORT_SIZE(8, (SWITCH_COUNT % 8) ? (8 - (SWITCH_COUNT % 8)) : 0),
HID_RI_REPORT_COUNT(8, 0x01),
HID_RI_INPUT(8, HID_IOF_CONSTANT),
HID_RI_END_COLLECTION(0)
};
+12 -42
View File
@@ -1,38 +1,3 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for Descriptors.c.
*/
#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_
@@ -102,6 +67,7 @@
{
HID_REPORTID_MouseReport = 0x01,
HID_REPORTID_KeyboardReport = 0x02,
HID_REPORTID_JoystickReport = 0x03,
} HID_Report_IDs;
/* Macros: */
@@ -111,15 +77,19 @@
#define LED_EPADDR (ENDPOINT_DIR_IN | 4)
// the board only supports endpoints of 8, 16, 32 or 64 bytes
#define ROUND_UP(bytes) (bytes <= 8 ? 8 : \
bytes <= 16 ? 16 : \
bytes <= 32 ? 32 : 64) // if it's larger than 64 bytes, you're out of luck
#define ROUND_UP(bytes) ((bytes) <= 8 ? 8 : \
(bytes) <= 16 ? 16 : \
(bytes) <= 32 ? 32 : 64) // if it's larger than 64 bytes, you're out of luck
// acts like a union, mouse is 8 bytes
#define INPUTS_EPSIZE ROUND_UP(MAX(SWITCH_COUNT + 2, 8))
#define LED_EPSIZE ROUND_UP(LED_TOTAL_COUNT)
/* acts like a union
* keyboard is switches + modifiers and reserved byte
* mouse is 8 bytes
* joystick is 2 axis + buttons as bitmask
* add 1 for report ID */
#define INPUTS_EPSIZE ROUND_UP(1+MAX(MAX(SWITCH_COUNT + 2, 8), 3 + SWITCH_COUNT/8))
#define LED_EPSIZE ROUND_UP(LED_TOTAL_COUNT)
// ignoring board limits, bulk endpoints MUST be 8, 16, 32 or 64 bytes
#define CONFIG_EPSIZE ROUND_UP(COMMAND_BYTES)
#define CONFIG_EPSIZE ROUND_UP(COMMAND_BYTES+1)
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+90 -35
View File
@@ -20,6 +20,21 @@
// How long to wait before moving to internal lighting
#define HID_LED_TIMEOUT 2000
// If I add more buttons with the macro key I don't need to care
#if SWITCH_COUNT <= 8
#define SWITCH_BITMASK_UINT uint8_t
#elif SWITCH_COUNT <= 16
#define SWITCH_BITMASK_UINT uint16_t
#else
#error TOO MANY SWITCHES
#endif
typedef struct
{
int8_t X; // VOL-L
int8_t Y; // VOL-R
SWITCH_BITMASK_UINT Buttons; // bitmask
} Joystick_Report_t;
typedef struct
{
uint8_t Modifier; // Keyboard modifier byte indicating pressed modifier keys (\c HID_KEYBOARD_MODIFER_* masks)
@@ -33,12 +48,11 @@ typedef struct
uint8_t btFx[6];
} LED_Report_t;
/** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */
static uint8_t PrevInputsHIDReportBuffer[MAX(sizeof(Keyboard_Report_t), sizeof(USB_MouseReport_Data_t))];
static uint8_t PrevLEDHIDReportBuffer[sizeof(LED_Report_t)];
static uint8_t sendKeyboard = 0;
static uint8_t updateLEDs = 1;
static int8_t joystickKnobs[2] = {0, 0};
/** LUFA HID Class driver interface configuration and state information. This structure is
* passed to all HID Class driver functions, so that multiple instances of the same class
@@ -55,8 +69,8 @@ USB_ClassInfo_HID_Device_t Inputs_HID_Interface =
.Size = INPUTS_EPSIZE,
.Banks = 1,
},
.PrevReportINBuffer = PrevInputsHIDReportBuffer,
.PrevReportINBufferSize = sizeof(PrevInputsHIDReportBuffer),
.PrevReportINBuffer = NULL,
.PrevReportINBufferSize = MAX(MAX(sizeof(Keyboard_Report_t), sizeof(Joystick_Report_t)), sizeof(USB_MouseReport_Data_t)),
},
};
@@ -247,51 +261,92 @@ bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDIn
{
if(ReportType != HID_REPORT_ITEM_In || HIDInterfaceInfo != &Inputs_HID_Interface) {
*ReportSize = 0;
return false;
return true;
}
sendKeyboard ^= 1;
if (sendKeyboard) {
// nothing requested so let's make our own
if(*ReportID == 0) {
// Always runs because we can have KB macros even with joystick
sendKeyboard ^= 1;
if(sendKeyboard) {
*ReportID = HID_REPORTID_KeyboardReport;
} else {
if(sdvxConfig.joystickMode) {
*ReportID = HID_REPORTID_JoystickReport;
} else {
*ReportID = HID_REPORTID_MouseReport;
}
}
}
if(*ReportID == HID_REPORTID_KeyboardReport) {
Keyboard_Report_t* KeyboardReport = (Keyboard_Report_t*)ReportData;
// Only the first 4 bytes are read by bemanitools, so let's use the first
uint8_t macroUpdated = macro_make_report(&KeyboardReport->KeyCode[0]);
update_switches();
if(!switchesChanged && !macroUpdated) {
if(!macroUpdated && (sdvxConfig.joystickMode || !switchesChanged)) {
*ReportSize = 0;
return false;
return true;
}
// NOTE: using SWITCH_COUNT-1 so we don't write the report for the macro pin
for(uint8_t i = 0; i < SWITCH_COUNT-1; i++) {
// i+1 to take care of the shift from above
KeyboardReport->KeyCode[i+1] = switches[i].state ? sdvxConfig.switches[i] : 0;
switches[i].lastReport = switches[i].state;
// Update blinkenlights
if(switches[i].state) {
//if(sdvxConfig.ledsOn) {
// // TODO
//}
if(!sdvxConfig.joystickMode) {
// NOTE: using SWITCH_COUNT-1 so we don't write the report for the macro pin
for(uint8_t i = 0; i < SWITCH_COUNT-1; i++) {
// i+1 to take care of the shift from above
KeyboardReport->KeyCode[i+1] = switches[i].state ? sdvxConfig.switches[i] : 0;
switches[i].lastReport = switches[i].state;
}
switchesChanged = 0;
}
*ReportID = HID_REPORTID_KeyboardReport;
*ReportSize = sizeof(Keyboard_Report_t);
switchesChanged = 0;
} else {
USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;
MouseReport->X = encoder_get(0);
MouseReport->Y = encoder_get(1);
led_knobs_update(MouseReport->X, MouseReport->Y);
int8_t x = encoder_get(0);
int8_t y = encoder_get(1);
led_knobs_update(x, y);
encoder_set(0, 0);
encoder_set(1, 0);
if(*ReportID == HID_REPORTID_MouseReport) {
if(x == 0 && y == 0) {
*ReportSize = 0;
return true;
}
USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;
MouseReport->X = x;
MouseReport->Y = y;
*ReportID = HID_REPORTID_MouseReport;
*ReportSize = sizeof(USB_MouseReport_Data_t);
*ReportSize = sizeof(USB_MouseReport_Data_t);
} else { // joystick
if(x == 0 && y == 0 && !switchesChanged) {
*ReportSize = 0;
return true;
}
Joystick_Report_t* JoyReport = (Joystick_Report_t*)ReportData;
joystickKnobs[0] += x;
joystickKnobs[1] += y;
for(uint8_t i = 0; i < 2; i++) {
if(joystickKnobs[i] < 0)
joystickKnobs[i] += JOYSTICK_PPR;
if(joystickKnobs[i] >= JOYSTICK_PPR)
joystickKnobs[i] -= JOYSTICK_PPR;
}
JoyReport->X = joystickKnobs[0];
JoyReport->Y = joystickKnobs[1];
// going backwards to make bitshifts nice
for(int8_t i = SWITCH_COUNT-1; i >= 0; i--) {
JoyReport->Buttons <<= 1;
JoyReport->Buttons |= switches[i].state;
switches[i].lastReport = switches[i].state;
}
switchesChanged = 0;
*ReportSize = sizeof(Joystick_Report_t);
}
}
return true;
}
@@ -376,6 +431,8 @@ void EVENT_USB_Device_ControlRequest(void)
/** Event handler for the USB device Start Of Frame event. */
void EVENT_USB_Device_StartOfFrame(void)
{
update_switches();
macro_on_frame(&switches[SWITCH_COUNT-1]);
HID_Device_MillisecondElapsed(&Inputs_HID_Interface);
HID_Device_MillisecondElapsed(&LED_HID_Interface);
@@ -389,8 +446,6 @@ void EVENT_USB_Device_StartOfFrame(void)
updateLEDs = 1;
}
macro_on_frame(&switches[SWITCH_COUNT-1]);
for(int i = 0; i < SWITCH_COUNT; i++) {
if(switches[i].debounce) {
switches[i].debounce--;
-35
View File
@@ -1,38 +1,3 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for Keyboard.c.
*/
#ifndef _KEYBOARD_H_
#define _KEYBOARD_H_