From 9e5925118c860aec1c4a68922b22d3167450f963 Mon Sep 17 00:00:00 2001 From: William Toohey Date: Wed, 1 Feb 2017 17:38:43 +1000 Subject: [PATCH] Fix libusb connectivity and add more config stuff --- Firmware/PocketVoltex/Config.c | 3 +- Firmware/PocketVoltex/Config.h | 48 ++++++++++-- Firmware/PocketVoltex/Descriptors.c | 77 ++++++++++--------- Firmware/PocketVoltex/Descriptors.h | 34 ++++----- Firmware/PocketVoltex/PocketVoltex.c | 109 +++++++++++++++++---------- Firmware/PocketVoltex/PocketVoltex.h | 9 --- 6 files changed, 166 insertions(+), 114 deletions(-) diff --git a/Firmware/PocketVoltex/Config.c b/Firmware/PocketVoltex/Config.c index f293adc..cbc5a72 100644 --- a/Firmware/PocketVoltex/Config.c +++ b/Firmware/PocketVoltex/Config.c @@ -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, diff --git a/Firmware/PocketVoltex/Config.h b/Firmware/PocketVoltex/Config.h index a1a0660..01b4e98 100644 --- a/Firmware/PocketVoltex/Config.h +++ b/Firmware/PocketVoltex/Config.h @@ -4,32 +4,66 @@ #include #include #include +#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 \ No newline at end of file diff --git a/Firmware/PocketVoltex/Descriptors.c b/Firmware/PocketVoltex/Descriptors.c index b174f29..5ff46d9 100644 --- a/Firmware/PocketVoltex/Descriptors.c +++ b/Firmware/PocketVoltex/Descriptors.c @@ -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) { diff --git a/Firmware/PocketVoltex/Descriptors.h b/Firmware/PocketVoltex/Descriptors.h index 489bba0..459a7cd 100644 --- a/Firmware/PocketVoltex/Descriptors.h +++ b/Firmware/PocketVoltex/Descriptors.h @@ -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, diff --git a/Firmware/PocketVoltex/PocketVoltex.c b/Firmware/PocketVoltex/PocketVoltex.c index 8b05789..2e165ce 100644 --- a/Firmware/PocketVoltex/PocketVoltex.c +++ b/Firmware/PocketVoltex/PocketVoltex.c @@ -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. */ diff --git a/Firmware/PocketVoltex/PocketVoltex.h b/Firmware/PocketVoltex/PocketVoltex.h index 848a0d0..ab803cd 100644 --- a/Firmware/PocketVoltex/PocketVoltex.h +++ b/Firmware/PocketVoltex/PocketVoltex.h @@ -49,16 +49,7 @@ #include #include - // 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;