diff --git a/Firmware/PocketVoltex/Config.c b/Firmware/PocketVoltex/Config.c index 34bdb54..5598b27 100644 --- a/Firmware/PocketVoltex/Config.c +++ b/Firmware/PocketVoltex/Config.c @@ -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)); diff --git a/Firmware/PocketVoltex/Config.h b/Firmware/PocketVoltex/Config.h index 01b4e98..5c7d68e 100644 --- a/Firmware/PocketVoltex/Config.h +++ b/Firmware/PocketVoltex/Config.h @@ -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) diff --git a/Firmware/PocketVoltex/Config/LUFAConfig.h b/Firmware/PocketVoltex/Config/LUFAConfig.h index 5fae1fa..87a2de0 100644 --- a/Firmware/PocketVoltex/Config/LUFAConfig.h +++ b/Firmware/PocketVoltex/Config/LUFAConfig.h @@ -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 diff --git a/Firmware/PocketVoltex/Descriptors.c b/Firmware/PocketVoltex/Descriptors.c index 96b70d9..59b3758 100644 --- a/Firmware/PocketVoltex/Descriptors.c +++ b/Firmware/PocketVoltex/Descriptors.c @@ -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) }; diff --git a/Firmware/PocketVoltex/Descriptors.h b/Firmware/PocketVoltex/Descriptors.h index 30bfd96..1c86a31 100644 --- a/Firmware/PocketVoltex/Descriptors.h +++ b/Firmware/PocketVoltex/Descriptors.h @@ -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, diff --git a/Firmware/PocketVoltex/PocketVoltex.c b/Firmware/PocketVoltex/PocketVoltex.c index b8309f3..9b9788e 100644 --- a/Firmware/PocketVoltex/PocketVoltex.c +++ b/Firmware/PocketVoltex/PocketVoltex.c @@ -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--; diff --git a/Firmware/PocketVoltex/PocketVoltex.h b/Firmware/PocketVoltex/PocketVoltex.h index ab803cd..86ac0c2 100644 --- a/Firmware/PocketVoltex/PocketVoltex.h +++ b/Firmware/PocketVoltex/PocketVoltex.h @@ -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_