mirror of
https://github.com/mon/PocketVoltex.git
synced 2026-09-22 22:57:58 +03:00
Fix libusb connectivity and add more config stuff
This commit is contained in:
@@ -14,8 +14,7 @@ static sdvx_config_t defaults PROGMEM = {
|
||||
HID_KEYBOARD_SC_C,
|
||||
HID_KEYBOARD_SC_M,
|
||||
HID_KEYBOARD_SC_ENTER},
|
||||
.ledsOn = true,
|
||||
.debounce = 30,
|
||||
//.ledsOn = true,
|
||||
.macroClick = HID_KEYBOARD_SC_KEYPAD_PLUS,
|
||||
.macroPin = {HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT,
|
||||
HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT,
|
||||
|
||||
@@ -4,32 +4,66 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include "LED.h"
|
||||
|
||||
// 7 gameplay switches + macro combo switch
|
||||
#define SWITCH_COUNT 8
|
||||
#define MAGIC_RESET_NUMBER 42
|
||||
// divide by 10 for actual version
|
||||
#define FIRMWARE_VERSION 1
|
||||
|
||||
// not configurable since they're all the same switches
|
||||
#define SWITCH_DEBOUNCE 30
|
||||
|
||||
typedef struct {
|
||||
// used to reboot into programming mode
|
||||
uint8_t reboot;
|
||||
uint8_t version;
|
||||
// SWITCH ORDER: A-D, FXL-R, START
|
||||
uint8_t switches[SWITCH_COUNT];
|
||||
bool ledsOn;
|
||||
uint8_t debounce;
|
||||
RGB_t btColour;
|
||||
RGB_t fxColour;
|
||||
RGB_t knobColours[2];
|
||||
bool lightsOn;
|
||||
bool hidLights;
|
||||
bool keyLights;
|
||||
bool knobLights;
|
||||
uint8_t lightPattern;
|
||||
// When tapping or long-pressing the macro key
|
||||
uint8_t macroClick;
|
||||
uint8_t macroPin[4];
|
||||
} sdvx_config_t;
|
||||
|
||||
// + 1 for some reason
|
||||
// TODO: what is the reason
|
||||
#define CONFIG_BYTES sizeof(sdvx_config_t)
|
||||
|
||||
typedef struct {
|
||||
uint8_t version;
|
||||
uint16_t serial;
|
||||
} version_t;
|
||||
|
||||
typedef enum {
|
||||
GETCONFIG = 1,
|
||||
SETCONFIG = 2,
|
||||
RESET = MAGIC_RESET_NUMBER
|
||||
} command_action_t;
|
||||
|
||||
typedef enum {
|
||||
RESPOND = 0,
|
||||
IGNORE,
|
||||
REBOOT
|
||||
} command_response_t;
|
||||
|
||||
typedef struct {
|
||||
command_action_t command;
|
||||
union {
|
||||
sdvx_config_t config;
|
||||
version_t version;
|
||||
} data;
|
||||
} command_t;
|
||||
|
||||
#define COMMAND_BYTES sizeof(command_t)
|
||||
|
||||
extern sdvx_config_t sdvxConfig;
|
||||
|
||||
extern void InitConfig(void);
|
||||
extern void SetConfig(sdvx_config_t* config);
|
||||
extern command_response_t HandleConfig(uint8_t* buffer);
|
||||
|
||||
#endif
|
||||
@@ -129,7 +129,45 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
|
||||
.MaxPowerConsumption = USB_CONFIG_POWER_MA(500)
|
||||
},
|
||||
|
||||
.Config_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = INTERFACE_ID_Config,
|
||||
.AlternateSetting = 0,
|
||||
|
||||
.TotalEndpoints = 2,
|
||||
|
||||
.Class = 0xFF,
|
||||
.SubClass = 0xFF,
|
||||
.Protocol = 0xFF,
|
||||
|
||||
.InterfaceStrIndex = STRING_ID_Config
|
||||
},
|
||||
|
||||
.Config_DataInEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = CONFIG_IN_EPADDR,
|
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = CONFIG_EPSIZE,
|
||||
// ignored but required
|
||||
.PollingIntervalMS = 0x05
|
||||
},
|
||||
|
||||
.Config_DataOutEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = CONFIG_OUT_EPADDR,
|
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = CONFIG_EPSIZE,
|
||||
// ignored but required
|
||||
.PollingIntervalMS = 0x05
|
||||
},
|
||||
|
||||
.HID1_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
@@ -240,44 +278,6 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
.EndpointSize = LED_EPSIZE,
|
||||
.PollingIntervalMS = 255
|
||||
},
|
||||
|
||||
.Config_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = INTERFACE_ID_Config,
|
||||
.AlternateSetting = 0,
|
||||
|
||||
.TotalEndpoints = 2,
|
||||
|
||||
.Class = 0xFF,
|
||||
.SubClass = 0xFF,
|
||||
.Protocol = 0xFF,
|
||||
|
||||
.InterfaceStrIndex = STRING_ID_Config
|
||||
},
|
||||
|
||||
.Config_DataInEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = CONFIG_IN_EPADDR,
|
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = CONFIG_EPSIZE,
|
||||
// ignored but required
|
||||
.PollingIntervalMS = 0x05
|
||||
},
|
||||
|
||||
.Config_DataOutEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = CONFIG_OUT_EPADDR,
|
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = CONFIG_EPSIZE,
|
||||
// ignored but required
|
||||
.PollingIntervalMS = 0x05
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -332,7 +332,6 @@ void USB_Process_BOS(void) {
|
||||
USB_ControlRequest.bmRequestType != (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE)) {
|
||||
return;
|
||||
}
|
||||
led_set_all(16,16,16);
|
||||
switch(USB_ControlRequest.bRequest) {
|
||||
case WEBUSB_ID:
|
||||
switch(USB_ControlRequest.wIndex) {
|
||||
|
||||
@@ -52,7 +52,12 @@
|
||||
typedef struct
|
||||
{
|
||||
USB_Descriptor_Configuration_Header_t Config;
|
||||
|
||||
|
||||
// Config interface as we can't talk to composite directly
|
||||
USB_Descriptor_Interface_t Config_Interface;
|
||||
USB_Descriptor_Endpoint_t Config_DataInEndpoint;
|
||||
USB_Descriptor_Endpoint_t Config_DataOutEndpoint;
|
||||
|
||||
// Keyboard HID Interface
|
||||
USB_Descriptor_Interface_t HID1_Interface;
|
||||
USB_HID_Descriptor_HID_t HID1_KeyboardHID;
|
||||
@@ -67,21 +72,16 @@
|
||||
USB_Descriptor_Interface_t HID3_Interface;
|
||||
USB_HID_Descriptor_HID_t HID3_LEDHID;
|
||||
USB_Descriptor_Endpoint_t HID3_ReportINEndpoint;
|
||||
|
||||
// Config interface as we can't talk to composite directly
|
||||
USB_Descriptor_Interface_t Config_Interface;
|
||||
USB_Descriptor_Endpoint_t Config_DataInEndpoint;
|
||||
USB_Descriptor_Endpoint_t Config_DataOutEndpoint;
|
||||
} USB_Descriptor_Configuration_t;
|
||||
|
||||
/** Enum for the device interface descriptor IDs within the device.
|
||||
*/
|
||||
enum InterfaceDescriptors_t
|
||||
{
|
||||
INTERFACE_ID_Keyboard = 0, /**< Keyboard interface descriptor ID */
|
||||
INTERFACE_ID_Mouse = 1, /**< Mouse interface descriptor ID */
|
||||
INTERFACE_ID_LED = 2, /**< LED interface descriptor ID */
|
||||
INTERFACE_ID_Config = 3 /**< Config interface descriptor ID */
|
||||
INTERFACE_ID_Config = 0, /**< Config interface descriptor ID */
|
||||
INTERFACE_ID_Keyboard = 1, /**< Keyboard interface descriptor ID */
|
||||
INTERFACE_ID_Mouse = 2, /**< Mouse interface descriptor ID */
|
||||
INTERFACE_ID_LED = 3, /**< LED interface descriptor ID */
|
||||
};
|
||||
|
||||
/** Enum for the device string descriptor IDs within the device. Each string descriptor should
|
||||
@@ -104,19 +104,19 @@
|
||||
};
|
||||
|
||||
/* Macros: */
|
||||
#define KEYBOARD_EPADDR (ENDPOINT_DIR_IN | 1)
|
||||
#define MOUSE_IN_EPADDR (ENDPOINT_DIR_IN | 2)
|
||||
#define LED_EPADDR (ENDPOINT_DIR_IN | 3)
|
||||
#define CONFIG_IN_EPADDR (ENDPOINT_DIR_IN | 4)
|
||||
#define CONFIG_IN_EPADDR (ENDPOINT_DIR_IN | 1)
|
||||
#define CONFIG_OUT_EPADDR (ENDPOINT_DIR_OUT | 5)
|
||||
#define KEYBOARD_EPADDR (ENDPOINT_DIR_IN | 2)
|
||||
#define MOUSE_IN_EPADDR (ENDPOINT_DIR_IN | 3)
|
||||
#define LED_EPADDR (ENDPOINT_DIR_IN | 4)
|
||||
|
||||
#define KEYBOARD_EPSIZE SWITCH_COUNT + 2
|
||||
#define MOUSE_EPSIZE 8
|
||||
#define LED_EPSIZE LED_TOTAL_COUNT
|
||||
// MUST be 8, 16, 32 or 64 bytes
|
||||
#define CONFIG_EPSIZE CONFIG_BYTES <= 8 ? 8 : \
|
||||
CONFIG_BYTES <= 16 ? 16 : \
|
||||
CONFIG_BYTES <= 32 ? 32 : 64 // if it's larger than 64 bytes, you're out of luck
|
||||
#define CONFIG_EPSIZE COMMAND_BYTES <= 8 ? 8 : \
|
||||
COMMAND_BYTES <= 16 ? 16 : \
|
||||
COMMAND_BYTES <= 32 ? 32 : 64 // if it's larger than 64 bytes, you're out of luck
|
||||
|
||||
/* Function Prototypes: */
|
||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||
|
||||
@@ -5,7 +5,14 @@
|
||||
#include "LEDPatterns.h"
|
||||
#include "Macro.h"
|
||||
|
||||
#define READ_SWITCH(x) (!(*pins[switches[x].switchPort] & _BV(switches[x].switchPin)))
|
||||
#define LOAD_SWITCH(source, sourceBit, result, resultBit) result |= !((source) & _BV(sourceBit)) << resultBit
|
||||
// B 0,1
|
||||
#define SWITCH_MASKB 0b00000011
|
||||
// C 1,2
|
||||
#define SWITCH_MASKC 0b00000110
|
||||
// D 4,5,6,7
|
||||
#define SWITCH_MASKD 0b11110000
|
||||
|
||||
#define MAGIC_BOOT_KEY 0xDEADBE7A
|
||||
// offset * word size
|
||||
#define BOOTLOADER_START_ADDRESS (0x1c00 * 2)
|
||||
@@ -83,20 +90,7 @@ USB_ClassInfo_HID_Device_t LED_HID_Interface =
|
||||
},
|
||||
};
|
||||
|
||||
static volatile uint8_t *ports[] = {&PORTB, &PORTC, &PORTD};
|
||||
static volatile uint8_t *pins[] = {&PINB, &PINC, &PIND};
|
||||
static volatile uint8_t *ddrs[] = {&DDRB, &DDRC, &DDRD};
|
||||
|
||||
static switch_t switches[SWITCH_COUNT] = {
|
||||
{B, 1}, // A
|
||||
{D, 7}, // B
|
||||
{D, 5}, // C
|
||||
{D, 4}, // D
|
||||
{B, 0}, // FX L
|
||||
{D, 6}, // FX R
|
||||
{C, 2}, // START
|
||||
{C, 1} // Macro key
|
||||
};
|
||||
static switch_t switches[SWITCH_COUNT];
|
||||
static uint8_t switchesChanged = 1;
|
||||
|
||||
// Set to max already so we have our init flash
|
||||
@@ -126,16 +120,38 @@ void RebootToBootloader(void) {
|
||||
while(1);
|
||||
}
|
||||
|
||||
/* This is verbose and annoying but the nice method wastes 30 bytes of RAM */
|
||||
uint8_t load_switches(void) {
|
||||
uint8_t tmp;
|
||||
uint8_t result = 0;
|
||||
|
||||
tmp = PINB;
|
||||
LOAD_SWITCH(tmp, 1, result, 0); // PINB1, A
|
||||
LOAD_SWITCH(tmp, 0, result, 4); // PINB0, FX L
|
||||
tmp = PINC;
|
||||
LOAD_SWITCH(tmp, 2, result, 6); // PINC2, START
|
||||
LOAD_SWITCH(tmp, 1, result, 7); // PINC1, MACRO
|
||||
tmp = PIND;
|
||||
LOAD_SWITCH(tmp, 7, result, 1); // PIND7, B
|
||||
LOAD_SWITCH(tmp, 5, result, 2); // PIND5, C
|
||||
LOAD_SWITCH(tmp, 4, result, 3); // PIND4, D
|
||||
LOAD_SWITCH(tmp, 6, result, 5); // PIND6, FX L
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void update_switches(void) {
|
||||
uint8_t i, newState;
|
||||
uint8_t switchRead = load_switches();
|
||||
|
||||
for(i = 0; i < SWITCH_COUNT; i++) {
|
||||
newState = READ_SWITCH(i);
|
||||
newState = switchRead & 1;
|
||||
if(!switches[i].debounce && newState != switches[i].lastReport) {
|
||||
switches[i].state = newState;
|
||||
switches[i].debounce = sdvxConfig.debounce;
|
||||
switches[i].debounce = SWITCH_DEBOUNCE;
|
||||
switchesChanged = 1;
|
||||
}
|
||||
switchRead >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,17 +175,27 @@ int main(void)
|
||||
HID_Device_USBTask(&LED_HID_Interface);
|
||||
USB_USBTask();
|
||||
|
||||
//uint8_t ReceivedData[VENDOR_IO_EPSIZE];
|
||||
//memset(ReceivedData, 0x00, sizeof(ReceivedData));
|
||||
//
|
||||
Endpoint_SelectEndpoint(CONFIG_OUT_EPADDR);
|
||||
if (Endpoint_IsOUTReceived()) {
|
||||
// Endpoint_Read_Stream_LE(ReceivedData, VENDOR_IO_EPSIZE, NULL);
|
||||
uint8_t ReceivedData[CONFIG_EPSIZE];
|
||||
Endpoint_Read_Stream_LE(ReceivedData, CONFIG_EPSIZE, NULL);
|
||||
Endpoint_ClearOUT();
|
||||
//
|
||||
// Endpoint_SelectEndpoint(VENDOR_IN_EPADDR);
|
||||
// Endpoint_Write_Stream_LE(ReceivedData, VENDOR_IO_EPSIZE, NULL);
|
||||
// Endpoint_ClearIN();
|
||||
|
||||
command_response_t respond = HandleConfig(ReceivedData);
|
||||
switch(respond) {
|
||||
// we are returning the requested data
|
||||
case RESPOND:
|
||||
Endpoint_SelectEndpoint(CONFIG_IN_EPADDR);
|
||||
Endpoint_Write_Stream_LE(ReceivedData, CONFIG_EPSIZE, NULL);
|
||||
Endpoint_ClearIN();
|
||||
break;
|
||||
case REBOOT:
|
||||
RebootToBootloader();
|
||||
break;
|
||||
// no data to return
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,16 +213,20 @@ void SetupHardware()
|
||||
switches[i].state = 0;
|
||||
switches[i].lastReport = 0;
|
||||
switches[i].debounce = 0;
|
||||
// setup switches to be inputs
|
||||
*ddrs[switches[i].switchPort] &= ~_BV(switches[i].switchPin);
|
||||
// with internal pullups
|
||||
*ports[switches[i].switchPort] |= _BV(switches[i].switchPin);
|
||||
}
|
||||
// Inputs
|
||||
DDRB &= ~SWITCH_MASKB;
|
||||
DDRC &= ~SWITCH_MASKC;
|
||||
DDRD &= ~SWITCH_MASKD;
|
||||
// Pullups
|
||||
PORTB |= SWITCH_MASKB;
|
||||
PORTC |= SWITCH_MASKC;
|
||||
// RESET has its own pullup
|
||||
*ports[switches[SWITCH_COUNT-1].switchPort] &= ~_BV(switches[SWITCH_COUNT-1].switchPin);
|
||||
PORTC &= ~_BV(1);
|
||||
PORTD |= SWITCH_MASKD;
|
||||
|
||||
// RESET held while plugging in
|
||||
if(READ_SWITCH(SWITCH_COUNT-1)) {
|
||||
if(!(PINC & _BV(1))) {
|
||||
RebootToBootloader();
|
||||
}
|
||||
|
||||
@@ -246,9 +276,9 @@ bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDIn
|
||||
switches[i].lastReport = switches[i].state;
|
||||
// Update blinkenlights
|
||||
if(switches[i].state) {
|
||||
if(sdvxConfig.ledsOn) {
|
||||
// TODO
|
||||
}
|
||||
//if(sdvxConfig.ledsOn) {
|
||||
// // TODO
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +302,6 @@ bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDIn
|
||||
}
|
||||
*ReportSize = 0;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/** HID class driver callback function for the processing of HID reports from the host.
|
||||
@@ -321,17 +350,17 @@ void EVENT_USB_Device_Connect(void)
|
||||
/** Event handler for the library USB Disconnection event. */
|
||||
void EVENT_USB_Device_Disconnect(void)
|
||||
{
|
||||
|
||||
led_set_all(0,0,0);
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Configuration Changed event. */
|
||||
void EVENT_USB_Device_ConfigurationChanged(void)
|
||||
{
|
||||
Endpoint_ConfigureEndpoint(CONFIG_IN_EPADDR, EP_TYPE_BULK, CONFIG_EPSIZE, 1);
|
||||
Endpoint_ConfigureEndpoint(CONFIG_OUT_EPADDR, EP_TYPE_BULK, CONFIG_EPSIZE, 1);
|
||||
HID_Device_ConfigureEndpoints(&Keyboard_HID_Interface);
|
||||
HID_Device_ConfigureEndpoints(&Mouse_HID_Interface);
|
||||
HID_Device_ConfigureEndpoints(&LED_HID_Interface);
|
||||
Endpoint_ConfigureEndpoint(CONFIG_IN_EPADDR, EP_TYPE_BULK, CONFIG_EPSIZE, 1);
|
||||
Endpoint_ConfigureEndpoint(CONFIG_OUT_EPADDR, EP_TYPE_BULK, CONFIG_EPSIZE, 1);
|
||||
|
||||
USB_Device_EnableSOFEvents();
|
||||
}
|
||||
@@ -340,9 +369,9 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
||||
void EVENT_USB_Device_ControlRequest(void)
|
||||
{
|
||||
USB_Process_BOS();
|
||||
HID_Device_ProcessControlRequest(&Keyboard_HID_Interface);
|
||||
HID_Device_ProcessControlRequest(&Keyboard_HID_Interface);
|
||||
HID_Device_ProcessControlRequest(&Mouse_HID_Interface);
|
||||
HID_Device_ProcessControlRequest(&LED_HID_Interface);
|
||||
HID_Device_ProcessControlRequest(&LED_HID_Interface);
|
||||
}
|
||||
|
||||
/** Event handler for the USB device Start Of Frame event. */
|
||||
|
||||
@@ -49,16 +49,7 @@
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include <LUFA/Platform/Platform.h>
|
||||
|
||||
// NOTE: atemga16u2 does not have a PORTA
|
||||
typedef enum {
|
||||
B = 0,
|
||||
C,
|
||||
D
|
||||
} port_t;
|
||||
|
||||
typedef struct {
|
||||
port_t switchPort;
|
||||
uint8_t switchPin;
|
||||
uint8_t state;
|
||||
uint8_t lastReport;
|
||||
uint8_t debounce;
|
||||
|
||||
Reference in New Issue
Block a user