Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make USB HID period configurable (and default is now 8ms) #998

Merged
merged 12 commits into from
Sep 26, 2020
Merged
2 changes: 2 additions & 0 deletions src/protocol/exports.ld
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ EXTERN(TELEMETRY_SetUpdated)

EXTERN(USB_Enable)
EXTERN(USB_Disable)
EXTERN(HID_SetInterval)
EXTERN(HID_prevXferComplete)

EXTERN(usbd_dev)
EXTERN(USB_Product_Name)
Expand Down
73 changes: 68 additions & 5 deletions src/protocol/usbhid.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,28 @@
#include "mixer.h"
#include "config/model.h"

static const char * const usbhid_opts[] = {
_tr_noop("Period (Hz)"), "125", "250", "500", "1000", NULL,
NULL
};
enum {
PROTO_OPTS_PERIOD,
LAST_PROTO_OPT,
};
ctassert(LAST_PROTO_OPT <= NUM_PROTO_OPTS, too_many_protocol_opts);

# define USBHID_PERIOD_MAX_INDEX 3
static u16 period_index_to_ms(s16 idx)
{
switch (idx) {
case 3: return 1;
case 2: return 2;
case 1: return 4;
default: return 8;
}
return 8;
}

//To change USBHID_MAX_CHANNELS you must change the Report_Descriptor in hid_usb_desc.c as well
#define USBHID_ANALOG_CHANNELS 8
#define USBHID_DIGITAL_CHANNELS 4
Expand All @@ -29,7 +51,6 @@
//if sizeof(packet) changes, must change wMaxPacketSize to match in Joystick_ConfigDescriptor
static s8 packet[USBHID_ANALOG_CHANNELS + 1];
static u8 num_channels;
extern void HID_Write(s8 *packet, u8 size);

static void build_data_pkt()
{
Expand Down Expand Up @@ -57,13 +78,47 @@ static void build_data_pkt()
packet[USBHID_ANALOG_CHANNELS] = digital;
}

static enum {
ST_DATA1,
ST_DATA2,
} state;

static u16 mixer_runtime;
// ms suffix on usbhid_period_ms to indicate that it's in milliseconds not microseconds like other protocols
static u16 usbhid_period_ms;
static u16 usbhid_cb()
{
build_data_pkt();

HID_Write(packet, sizeof(packet));
// wait until endpoint is ready for writing before preparing data
// if the host is polling slower than our clock, this will just delay us a bit
// it does increase the chance of mixers not completing in time for 1ms period though...
if (!HID_prevXferComplete) return 100;

u16 protoopts_period = period_index_to_ms(Model.proto_opts[PROTO_OPTS_PERIOD]);
if (usbhid_period_ms != protoopts_period) {
usbhid_period_ms = protoopts_period;
// HID should be restarted when period changes
// this lets us update the endpoint descriptor's bInterval field
HID_Disable();
HID_SetInterval(usbhid_period_ms);
HID_Enable();
}
switch (state) {
case ST_DATA1:
CLOCK_RunMixer(); // clears mixer_sync, which is then set when mixer update complete
state = ST_DATA2;
return mixer_runtime;

return 50000;
case ST_DATA2:
if (mixer_sync != MIX_DONE && mixer_runtime < 2000) mixer_runtime += 50;
build_data_pkt();
HID_Write(packet, sizeof(packet));
state = ST_DATA1;
// return with - 200 in case host is polling slightly faster than our clock
// this doesn't guarantee perfect timing, but it should be sufficient to
// catch most variations and get us back to waiting for the host
return usbhid_period_ms * 1000 - mixer_runtime - 200;
}
return usbhid_period_ms * 1000 - 200; // avoid compiler warning
}

static void deinit()
Expand All @@ -75,7 +130,11 @@ static void deinit()
static void initialize()
{
CLOCK_StopTimer();
state = ST_DATA1;
mixer_runtime = 50;
num_channels = Model.num_channels;
usbhid_period_ms = period_index_to_ms(Model.proto_opts[PROTO_OPTS_PERIOD]);
HID_SetInterval(usbhid_period_ms);
HID_Enable();
CLOCK_StartTimer(1000, usbhid_cb);
}
Expand All @@ -91,6 +150,10 @@ uintptr_t USBHID_Cmds(enum ProtoCmds cmd)
case PROTOCMD_DEFAULT_NUMCHAN: return 6;
case PROTOCMD_CHANNELMAP: return UNCHG;
case PROTOCMD_TELEMETRYSTATE: return PROTO_TELEM_UNSUPPORTED;
case PROTOCMD_GETOPTIONS:
if (Model.proto_opts[PROTO_OPTS_PERIOD] > USBHID_PERIOD_MAX_INDEX)
Model.proto_opts[PROTO_OPTS_PERIOD] = USBHID_PERIOD_MAX_INDEX;
return (uintptr_t)usbhid_opts;
default: break;
}
return 0;
Expand Down
3 changes: 3 additions & 0 deletions src/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,11 @@ void USB_Disable();
void USB_HandleISR();
void USB_Connect();

void HID_SetInterval(u8 interval);
void HID_Enable();
void HID_Disable();
void HID_Write(s8 *packet, u8 size);
extern volatile u8 HID_prevXferComplete;

void MSC_Enable();
void MSC_Disable();
Expand Down
4 changes: 4 additions & 0 deletions src/target/drivers/mcu/emu/stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ void TxName(u8 *var, int len) {
}
void MSC_Enable() {}
void MSC_Disable() {}
void HID_SetInterval(u8 interval) {
(void)interval;
}
void HID_Enable() {}
void HID_Disable() {}
void HID_Write(s8 *pkt, u8 size) {
(void)pkt;
(void)size;
}
volatile u8 HID_prevXferComplete;
void Initialize_ButtonMatrix() {}
void PWR_Init(void) {}
unsigned PWR_ReadVoltage() { return (DEFAULT_BATTERY_ALARM + 1000); }
Expand Down
22 changes: 14 additions & 8 deletions src/target/drivers/usb/devo_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static const char * const usb_strings[] = {
DeviationVersion
};

static volatile u8 usb_preXferComplete;
volatile u8 HID_prevXferComplete;

static const uint8_t hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
Expand Down Expand Up @@ -72,13 +72,14 @@ static const struct {
}
};

static const struct usb_endpoint_descriptor hid_endpoint = {
// this is no longer const so that bInterval can be modified at runtime
struct usb_endpoint_descriptor hid_endpoint = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x81,
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 9,
.bInterval = 0x20,
.bInterval = 8,
};

static const struct usb_interface_descriptor hid_iface = {
Expand Down Expand Up @@ -136,7 +137,7 @@ static void hid_callback(usbd_device *usbd_dev, uint8_t ep)
(void)usbd_dev;
(void)ep;

usb_preXferComplete = 1;
HID_prevXferComplete = 1;
}

static void hid_set_config(usbd_device *dev, uint16_t wValue)
Expand All @@ -152,7 +153,7 @@ static void hid_set_config(usbd_device *dev, uint16_t wValue)
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
hid_control_request);

usb_preXferComplete = 1;
HID_prevXferComplete = 1;
}

static void HID_Init()
Expand All @@ -165,14 +166,19 @@ static void HID_Init()

void HID_Write(s8 *packet, u8 size)
{
if (usb_preXferComplete) {
usb_preXferComplete = 0;
if (HID_prevXferComplete) {
HID_prevXferComplete = 0;
usbd_ep_write_packet(usbd_dev, 0x81, packet, size);
}
}

void HID_SetInterval(u8 interval)
{
hid_endpoint.bInterval = interval;
}

void HID_Enable() {
usb_preXferComplete = 0;
HID_prevXferComplete = 0;
USB_Enable(1);
HID_Init();
}
Expand Down
4 changes: 4 additions & 0 deletions src/target/tx/opentx/t12/x9d_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ void USB_Enable(unsigned use_interrupt) {
(void)use_interrupt;
}
void USB_Disable() {}
void HID_SetInterval(u8 interval) {
(void)interval;
}
void HID_Enable() {}
void HID_Disable() {}
void HID_Write(s8 *pkt, u8 size) {
(void)pkt;
(void)size;
}
volatile u8 HID_prevXferComplete;
void SOUND_Init() {}
void SOUND_SetFrequency(unsigned frequency, unsigned volume) {
(void)frequency;
Expand Down
4 changes: 4 additions & 0 deletions src/target/tx/opentx/x9d/x9d_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
#include "common.h"
void MSC_Enable() {}
void MSC_Disable() {}
void HID_SetInterval(u8 interval) {
(void)interval;
}
void HID_Enable() {}
void HID_Disable() {}
void HID_Write(s8 *pkt, u8 size) {
(void)pkt;
(void)size;
}
volatile u8 HID_prevXferComplete;
void SOUND_Init() {}
void SOUND_SetFrequency(unsigned frequency, unsigned volume) {
(void)frequency;
Expand Down
4 changes: 4 additions & 0 deletions src/target/tx/other/test/test_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,16 @@ void TxName(u8 *var, int len) {
}
void MSC_Enable() {}
void MSC_Disable() {}
void HID_SetInterval(u8 interval) {
(void)interval;
}
void HID_Enable() {}
void HID_Disable() {}
void HID_Write(s8 *pkt, u8 size) {
(void)pkt;
(void)size;
}
volatile u8 HID_prevXferComplete;
void Initialize_ButtonMatrix() {}
void PWR_Init(void) {}
unsigned PWR_ReadVoltage() { return (DEFAULT_BATTERY_ALARM + 1000); }
Expand Down