Firmware working

This commit is contained in:
whowechina
2024-10-06 23:02:54 +08:00
parent 286769ea6f
commit 2a2f5a353e
16 changed files with 197 additions and 461 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ function(make_firmware board board_def)
pico_sdk_init()
add_executable(${board}
main.c light.c button.c spin.c save.c config.c commands.c cli.c
tmag5273.c hid.c usb_descriptors.c)
tmag5273.c usb_descriptors.c)
target_compile_definitions(${board} PUBLIC ${board_def})
pico_enable_stdio_usb(${board} 1)
pico_enable_stdio_uart(${board} 0)
+1 -1
View File
@@ -14,7 +14,7 @@
#define BUS_I2C_FREQ 400*1000
#define SPIN_DEF { 13, 12, 11, 10, 9 }
#define BUTTON_DEF { 16, 17, 18, 19, 20, 21, 22, 2 }
#define BUTTON_DEF { 16, 17, 18, 19, 20, 22, 21, 2 }
#else
+33 -29
View File
@@ -32,9 +32,15 @@ static void disp_hid()
musec_cfg->hid.nkro ? "on" : "off" );
}
static void disp_spin()
{
printf("[Spin]\n");
printf(" Units per turn: %d.\n", musec_cfg->spin.units_per_turn);
}
void handle_display(int argc, char *argv[])
{
const char *usage = "Usage: display [light|hid\n";
const char *usage = "Usage: display [light|spin|hid]\n";
if (argc > 1) {
printf(usage);
return;
@@ -42,16 +48,20 @@ void handle_display(int argc, char *argv[])
if (argc == 0) {
disp_light();
disp_spin();
disp_hid();
return;
}
const char *choices[] = {"light", "hid" };
const char *choices[] = {"light", "spin", "hid" };
switch (cli_match_prefix(choices, count_of(choices), argv[0])) {
case 0:
disp_light();
break;
case 1:
disp_spin();
break;
case 2:
disp_hid();
break;
default:
@@ -96,6 +106,26 @@ static void handle_level(int argc, char *argv[])
disp_light();
}
static void handle_spin(int argc, char *argv[])
{
const char *usage = "Usage: spin <units_per_turn>\n"
" units_per_turn: 20..255\n";
if (argc != 1) {
printf(usage);
return;
}
int units = cli_extract_non_neg_int(argv[0], 0);
if ((units < 20) || (units > 255)) {
printf(usage);
return;
}
musec_cfg->spin.units_per_turn = units;
config_changed();
disp_spin();
}
static void handle_hid(int argc, char *argv[])
{
const char *usage = "Usage: hid <joy|nkro|both>\n";
@@ -128,38 +158,12 @@ static void handle_factory_reset()
printf("Factory reset done.\n");
}
static void handle_i2c(int argc, char *argv[])
{
if (argc != 1) {
return;
}
const char *choices[] = {"set", "read", "change"};
int match = cli_match_prefix(choices, count_of(choices), argv[0]);
if (match < 0) {
return;
}
if (match == 0) {
} else if (match == 1) {
for (int i = 0; i <= 0x1c; i++) {
printf("0x%02x:%02x\n", i, tmag5273_read_reg(i));
}
uint16_t angle = tmag5273_read_angle();
printf("angle: %d (%04x)\n", angle, angle);
} else if (match == 2) {
tmag5273_change_addr(0x12);
}
}
void commands_init()
{
cli_register("display", handle_display, "Display all config.");
cli_register("level", handle_level, "Set LED brightness level.");
cli_register("spin", handle_spin, "Set spin rate.");
cli_register("hid", handle_hid, "Set HID mode.");
cli_register("save", handle_save, "Save config to flash.");
cli_register("i2c", handle_i2c, "I2C test.");
cli_register("factory", handle_factory_reset, "Reset everything to default.");
}
+2 -14
View File
@@ -12,20 +12,8 @@
musec_cfg_t *musec_cfg;
static musec_cfg_t default_cfg = {
.lever = {
2000, 2500, 0,
},
.light = {
.level = 128,
.reserved = { 0 },
},
.tof = {
.roi = 12,
.reserved = { 0 },
},
.sound = {
.volume = 127,
.reserved = { 0 },
.spin = {
.units_per_turn = 80,
},
.hid = {
.joy = 1,
+2 -13
View File
@@ -16,24 +16,13 @@ typedef struct {
typedef struct __attribute__((packed)) {
struct {
uint16_t min;
uint16_t max;
uint8_t invert:1;
uint8_t reserved:7;
} lever;
uint8_t units_per_turn;
} spin;
struct {
rgb_hsv_t colors[12];
uint8_t level;
uint8_t reserved[15];
} light;
struct {
uint8_t volume;
uint8_t reserved[3];
} sound;
struct {
uint8_t roi;
uint8_t reserved[7];
} tof;
struct {
uint8_t joy : 4;
uint8_t nkro : 4;
-154
View File
@@ -1,154 +0,0 @@
#include <stdint.h>
#include <stdbool.h>
#include "board_defs.h"
#include "tusb.h"
#include "usb_descriptors.h"
#include "button.h"
#include "config.h"
#include "light.h"
#include "hid.h"
struct __attribute__((packed)) {
uint16_t adcs[8];
uint16_t spinners[4];
uint16_t chutes[2];
uint16_t buttons[2];
uint8_t system_status;
uint8_t usb_status;
uint8_t padding[29];
} hid_joy;
struct __attribute__((packed)) {
uint8_t modifier;
uint8_t keymap[15];
} hid_nkro;
static void gen_hid_analogs()
{
}
static void gen_hid_buttons()
{
const static struct {
uint8_t group;
uint8_t bit;
} button_to_io4_map[] = {
{ 0, 0 }, { 0, 5 }, { 0, 4 }, // Left ABC
{ 0, 1 }, { 1, 0 }, { 0, 15 }, // Right ABC
{ 1, 14 }, { 0, 13 }, // AUX 12
};
uint16_t buttons = button_read();
hid_joy.buttons[0] = 0;
hid_joy.buttons[1] = 0;
for (int i = 0; i < button_num(); i++) {
uint8_t group = button_to_io4_map[i].group;
uint8_t bit = button_to_io4_map[i].bit;
if (buttons & (1 << i)) {
hid_joy.buttons[group] |= (1 << bit);
}
}
}
static void gen_hid_coins()
{
}
static void report_usb_hid()
{
if (tud_hid_ready()) {
if (musec_cfg->hid.joy || musec_runtime.key_stuck) {
gen_hid_analogs();
gen_hid_buttons();
gen_hid_coins();
tud_hid_n_report(0, REPORT_ID_JOYSTICK, &hid_joy, sizeof(hid_joy));
}
if (musec_cfg->hid.nkro && !musec_runtime.key_stuck) {
tud_hid_n_report(1, 0, &hid_nkro, sizeof(hid_nkro));
}
}
}
static void gen_nkro_report()
{
if (!musec_cfg->hid.nkro) {
return;
}
return;
const char keymap[] = "\x1a\x08\x07\x06\x1b\x1d\x04\x14\x20\x3a\x3b\x3c";
uint16_t buttons = button_read();
for (int i = 0; i < button_num(); i++) {
uint8_t code = keymap[i];
uint8_t byte = code / 8;
uint8_t bit = code % 8;
if (buttons & (1 << i)) {
hid_nkro.keymap[byte] |= (1 << bit);
} else {
hid_nkro.keymap[byte] &= ~(1 << bit);
}
}
}
void hid_update()
{
gen_nkro_report();
report_usb_hid();
}
typedef struct __attribute__((packed)) {
uint8_t report_id;
uint8_t cmd;
uint8_t payload[62];
} hid_output_t;
static void update_led(const uint8_t data[4])
{
const uint8_t led_bit[18] = { 30, 31, 28, 26, 27, 29, 23, 25, 24,
20, 22, 21, 17, 19, 18, 14, 16, 15 };
uint32_t leds = (data[0] << 24) | (data[1] << 16) |
(data[2] << 8) | data[3];
for (uint8_t i = 0; i < 6; i++) {
bool r = leds & (1 << led_bit[i * 3 + 1]);
bool g = leds & (1 << led_bit[i * 3 + 2]);
bool b = leds & (1 << led_bit[i * 3]);
uint32_t color = rgb32(r ? 0xff : 0, g ? 0xff : 0, b ? 0xff : 0, false);
light_set_main(i, color, true);
}
}
void hid_proc(const uint8_t *data, uint8_t len)
{
hid_output_t *output = (hid_output_t *)data;
if (output->report_id == REPORT_ID_OUTPUT) {
switch (output->cmd) {
case 0x01: // Set Timeout
case 0x02: // Set Sampling Count
hid_joy.system_status = 0x30;
printf("USB set timeout/sampling\n");
break;
case 0x03: // Clear Board Status
hid_joy.chutes[0] = 0;
hid_joy.chutes[1] = 0;
hid_joy.system_status = 0x00;
printf("USB clear status\n");
break;
case 0x04: // Set General Output
// LED
update_led(output->payload);
break;
case 0x41: // I don't know what this is
break;
default:
printf("USB unknown cmd: %d\n", output->cmd);
break;
}
}
}
-12
View File
@@ -1,12 +0,0 @@
/*
* HID Report Functions
* WHowe <github.com/whowechina>
*/
#ifndef HID_H_
#define HID_H_
void hid_update();
void hid_proc(const uint8_t *data, uint8_t len);
#endif
+25 -47
View File
@@ -20,9 +20,9 @@
#include "board_defs.h"
#include "config.h"
#define HID_TIMEOUT 300*1000*1000
#define HID_TIMEOUT 10*1000*1000
static uint32_t buf_rgb[37]; // left 3 + right 3 + button 4 * 7 + indicator 5
static uint32_t buf_rgb[22]; // button 4 * 5 + aux * 2
static inline uint32_t _rgb32(uint32_t c1, uint32_t c2, uint32_t c3, bool gamma_fix)
{
@@ -131,64 +131,42 @@ void light_set(uint8_t index, uint32_t color)
buf_rgb[index] = apply_level(color);
}
void light_set_main(uint8_t index, uint32_t color, bool hid)
static bool bypass_check(bool hid)
{
static uint64_t hid_timeout = 0;
uint64_t now = time_us_64();
if (!hid && (now < hid_timeout)) {
if (hid) {
hid_timeout = now + HID_TIMEOUT;
return false;
}
return now < hid_timeout;
}
void light_set_main(uint8_t index, uint32_t color, bool hid)
{
if (bypass_check(hid)) {
return;
}
if (hid) {
hid_timeout = time_us_64() + HID_TIMEOUT;
}
if (index < 3) {
light_set(index * 4 + 4, color);
light_set(index * 4 + 5, color);
light_set(index * 4 + 6, color);
light_set(index * 4 + 7, color);
} else if (index < 6) {
light_set(index * 4 + 9, color);
light_set(index * 4 + 10, color);
light_set(index * 4 + 11, color);
light_set(index * 4 + 12, color);
for (int i = 0; i < 4; i++) {
light_set(index * 4 + i, color);
}
}
void light_set_aux(uint8_t index, uint32_t color)
void light_set_start(uint32_t color, bool hid)
{
if (index == 0) {
light_set(0, color);
} else if (index == 1) {
light_set(36, color);
if (bypass_check(hid)) {
return;
}
light_set(20, color);
}
void light_set_wad(uint8_t index, uint32_t color)
void light_set_aux(uint32_t color, bool hid)
{
if (index == 0) {
light_set(1, color);
light_set(2, color);
light_set(3, color);
} else if (index == 1) {
light_set(33, color);
light_set(34, color);
light_set(35, color);
}
}
void light_set_pos(uint8_t pos, uint32_t color)
{
pos = pos * 5 / 256;
for (int i = 0; i < 5; i++) {
light_set(16 + i, (i == pos) ? color : 0);
}
}
void light_set_aime(uint32_t color)
{
for (int i = 0; i < 5; i++) {
light_set(16 + i, color);
if (bypass_check(hid)) {
return;
}
light_set(21, color);
}
+2 -4
View File
@@ -20,10 +20,8 @@ uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v);
uint32_t load_color(const rgb_hsv_t *color);
void light_set_main(uint8_t index, uint32_t color, bool hid);
void light_set_aux(uint8_t index, uint32_t color);
void light_set_wad(uint8_t index, uint32_t color);
void light_set_pos(uint8_t pos, uint32_t color);
void light_set_aime(uint32_t color);
void light_set_start(uint32_t color, bool hid);
void light_set_aux(uint32_t color, bool hid);
void light_set(uint8_t index, uint32_t color);
+34 -16
View File
@@ -28,14 +28,24 @@
#include "cli.h"
#include "commands.h"
#include "hid.h"
#include "light.h"
#include "button.h"
#include "spin.h"
static void run_lights()
{
uint32_t phase = time_us_32() >> 16;
uint16_t button = button_read();
for (int i = 0; i < 5; i++) {
uint32_t color = rgb32_from_hsv(phase + i * 35, 255, 255);
if (button & (1 << i)) {
color = rgb32(255, 255, 255, false);
}
light_set_main(i, color, false);
}
light_set_start((button & 0x20) ? 0xffffff : rgb32(255, 10, 10, false), false);
light_set_aux((button & 0x40) ? 0xffffff : rgb32(180, 180, 10, false), false);
}
static mutex_t core1_io_lock;
@@ -52,14 +62,21 @@ static void core1_loop()
}
}
static void read_spin()
struct __attribute__((packed)) {
uint8_t buttons;
uint8_t joy[6];
} hid_report = {0};
static void hid_update()
{
for (int i = 0; i < spin_num(); i++) {
uint16_t angle = spin_read(i);
float deg = angle / 16.0f;
printf(" %d:%7.2f", i, deg);
uint16_t buttons = button_read();
hid_report.buttons = buttons;
for (int i = 0; i < 5; i++) {
hid_report.joy[i] = spin_units(i);
}
if (tud_hid_ready()) {
tud_hid_n_report(0, REPORT_ID_JOYSTICK, &hid_report, sizeof(hid_report));
}
printf("\n");
}
static void core0_loop()
@@ -76,7 +93,6 @@ static void core0_loop()
spin_update();
hid_update();
read_spin();
sleep_us(900);
}
@@ -138,12 +154,6 @@ int main(void)
return 0;
}
struct __attribute__((packed)) {
uint16_t buttons;
uint8_t HAT;
uint32_t axis;
} hid_joy_out = {0};
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
@@ -161,5 +171,13 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
hid_report_type_t report_type, uint8_t const *buffer,
uint16_t bufsize)
{
hid_proc(buffer, bufsize);
if ((report_id == REPORT_ID_LIGHTS) && (bufsize >= 18)) {
printf("Set from USB %d-%d: %d\n", report_id, report_type, bufsize);
for (int i = 0; i < 5; i++) {
uint32_t color = rgb32(buffer[i * 3], buffer[i * 3 + 1], buffer[i * 3 + 2], false);
light_set_main(i, color, true);
}
light_set_start(rgb32(buffer[15], buffer[16], buffer[17], false), true);
light_set_aux(rgb32(buffer[15], buffer[16], buffer[17], false), true);
}
}
+27
View File
@@ -19,6 +19,7 @@
#include "tmag5273.h"
static const uint8_t spin_enablers[] = SPIN_DEF;
const uint16_t FULL_SCALE = 360 * 16;
#define SPIN_NUM (count_of(spin_enablers))
@@ -41,6 +42,11 @@ void spin_init()
tmag5273_init(i, BUS_I2C);
tmag5273_init_sensor();
}
if (musec_cfg->spin.units_per_turn == 0) {
musec_cfg->spin.units_per_turn = 80;
config_changed();
}
}
uint8_t spin_num()
@@ -65,3 +71,24 @@ uint16_t spin_read(uint8_t index)
}
return spin_reading[index];
}
uint16_t spin_units(uint8_t index)
{
static uint16_t last[SPIN_NUM] = {0};
static int counter[SPIN_NUM] = {0};
int delta = spin_reading[index] - last[index];
if (delta > FULL_SCALE / 2) {
delta -= FULL_SCALE;
} else if (delta < -FULL_SCALE / 2) {
delta += FULL_SCALE;
}
int resolution = FULL_SCALE / musec_cfg->spin.units_per_turn;
if ((delta <= -resolution) || (delta >= resolution)) {
last[index] = spin_reading[index];
counter[index] += delta;
}
return counter[index] * musec_cfg->spin.units_per_turn / FULL_SCALE;
}
+1
View File
@@ -14,5 +14,6 @@ void spin_init();
uint8_t spin_num();
void spin_update();
uint16_t spin_read(uint8_t index);
uint16_t spin_units(uint8_t index);
#endif
+1
View File
@@ -89,6 +89,7 @@ bool tmag5273_init_sensor()
{
tmag5273_write_reg(0x03, 0x01 << 2); // Enable angle calculation
tmag5273_write_reg(0x02, 0x03 << 4); // X-Y
tmag5273_write_reg(0x00, 0x03 << 2); // 8x average mode
tmag5273_write_reg(0x01, 0x02); // Continuous mode
return true;
}
+2 -2
View File
@@ -96,8 +96,8 @@ extern "C" {
#endif
//------------- CLASS -------------//
#define CFG_TUD_HID 2
#define CFG_TUD_CDC 2
#define CFG_TUD_HID 1
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
+32 -39
View File
@@ -36,7 +36,7 @@ tusb_desc_device_t desc_device_joy = {
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = 0x0ca3,
.idVendor = 0xcabe,
.idProduct = 0x0021,
.bcdDevice = 0x0100,
@@ -59,10 +59,7 @@ uint8_t const* tud_descriptor_device_cb(void) {
uint8_t const desc_hid_report_joy[] = {
MUSEC_PICO_REPORT_DESC_JOYSTICK,
};
uint8_t const desc_hid_report_nkro[] = {
MUSEC_PICO_REPORT_DESC_NKRO,
MUSEC_PICO_REPORT_DESC_LIGHTS,
};
// Invoked when received GET HID REPORT DESCRIPTOR
@@ -73,8 +70,6 @@ uint8_t const* tud_hid_descriptor_report_cb(uint8_t itf)
switch (itf) {
case 0:
return desc_hid_report_joy;
case 1:
return desc_hid_report_nkro;
default:
return NULL;
}
@@ -83,28 +78,18 @@ uint8_t const* tud_hid_descriptor_report_cb(uint8_t itf)
// Configuration Descriptor
//--------------------------------------------------------------------+
enum { ITF_NUM_JOY, ITF_NUM_NKRO,
ITF_NUM_CLI, ITF_NUM_CLI_DATA, ITF_NUM_AIME, ITF_NUM_AIME_DATA,
ITF_NUM_TOTAL };
enum { ITF_NUM_JOY, ITF_NUM_CLI, ITF_NUM_CLI_DATA, ITF_NUM_TOTAL };
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + \
TUD_HID_INOUT_DESC_LEN * 1 + \
TUD_HID_DESC_LEN * 1 + \
TUD_CDC_DESC_LEN * 2)
TUD_CDC_DESC_LEN * 1)
#define EPNUM_JOY_OUT 0x01
#define EPNUM_JOY_IN 0x81
#define EPNUM_NKRO 0x87
#define EPNUM_JOY 0x81
#define EPNUM_CLI_NOTIF 0x89
#define EPNUM_CLI_OUT 0x0a
#define EPNUM_CLI_IN 0x8a
#define EPNUM_AIME_NOTIF 0x8b
#define EPNUM_AIME_OUT 0x0c
#define EPNUM_AIME_IN 0x8c
uint8_t const desc_configuration_joy[] = {
// Config number, interface count, string index, total length, attribute,
// power in mA
@@ -113,20 +98,12 @@ uint8_t const desc_configuration_joy[] = {
// Interface number, string index, protocol, report descriptor len, EP In
// address, size & polling interval
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_JOY, 4, HID_ITF_PROTOCOL_NONE,
sizeof(desc_hid_report_joy), EPNUM_JOY_OUT, EPNUM_JOY_IN,
TUD_HID_DESCRIPTOR(ITF_NUM_JOY, 4, HID_ITF_PROTOCOL_NONE,
sizeof(desc_hid_report_joy), EPNUM_JOY,
CFG_TUD_HID_EP_BUFSIZE, 1),
TUD_HID_DESCRIPTOR(ITF_NUM_NKRO, 5, HID_ITF_PROTOCOL_NONE,
sizeof(desc_hid_report_nkro), EPNUM_NKRO,
CFG_TUD_HID_EP_BUFSIZE, 1),
TUD_CDC_DESCRIPTOR(ITF_NUM_CLI, 6, EPNUM_CLI_NOTIF,
TUD_CDC_DESCRIPTOR(ITF_NUM_CLI, 5, EPNUM_CLI_NOTIF,
8, EPNUM_CLI_OUT, EPNUM_CLI_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_AIME, 7, EPNUM_AIME_NOTIF,
8, EPNUM_AIME_OUT, EPNUM_AIME_IN, 64),
};
// Invoked when received GET CONFIGURATION DESCRIPTOR
@@ -143,13 +120,29 @@ static char serial_number_str[24] = "123456\0";
static const char *string_desc_arr[] = {
(const char[]){0x09, 0x04}, // 0: is supported language is English (0x0409)
"SEGA", // 1: Manufacturer
"Musec Pico", // 2: Product
serial_number_str, // 3: Serials, use chip ID
"I/O CONTROL BD;15257;01;90;1831;6679A;00;GOUT=14_ADIN=8,E_ROTIN=4_COININ=2_SWIN=2,E_UQ1=41,6;",
"Musec Pico NKRO",
"Musec Pico CLI",
"Mai Pico AIME Port",
"WHowe", // 1: Manufacturer
"Musec Pico", // 2: Product
serial_number_str, // 3: Serials, use chip ID
"Musec Pico Joystick",
"Musec Pico CLI Port",
"Spinner 1 R",
"Spinner 1 G",
"Spinner 1 B",
"Spinner 2 R",
"Spinner 2 G",
"Spinner 2 B",
"Spinner 3 R",
"Spinner 3 G",
"Spinner 3 B",
"Spinner 4 R",
"Spinner 4 G",
"Spinner 4 B",
"Spinner 5 R",
"Spinner 5 G",
"Spinner 5 B",
"Title R",
"Title G",
"Title B",
};
// Invoked when received GET STRING DESCRIPTOR request
+34 -129
View File
@@ -6,7 +6,7 @@
enum {
REPORT_ID_JOYSTICK = 1,
REPORT_ID_OUTPUT = 16,
REPORT_ID_LIGHTS,
};
// because they are missing from tusb_hid.h
@@ -17,135 +17,40 @@ enum {
#define HID_STRING_MAXIMUM(x) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, 1)
#define HID_STRING_MAXIMUM_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, n)
// Joystick Report Descriptor to Emulate IO4
#define MUSEC_PICO_REPORT_DESC_JOYSTICK \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_JOYSTICK), \
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
HID_REPORT_ID(REPORT_ID_JOYSTICK) \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_X), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_Y), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_X), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_Y), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_X), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_Y), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_X), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_Y), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_RX), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_RY), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_RX), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_RY), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_SLIDER), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(16), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_SLIDER), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(48), HID_REPORT_SIZE(1), \
HID_USAGE_MIN_N(1, 2), HID_USAGE_MAX_N(48, 2), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(232), \
HID_INPUT(HID_CONSTANT | HID_ABSOLUTE), \
\
HID_USAGE_PAGE_N(0xffa0, 2), \
HID_USAGE(0x00), \
HID_REPORT_ID(REPORT_ID_OUTPUT) \
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
HID_USAGE(0x00), \
HID_LOGICAL_MIN(0), HID_LOGICAL_MAX(255), \
HID_REPORT_COUNT(63), HID_REPORT_SIZE(8), \
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
HID_COLLECTION_END, \
#define MUSEC_PICO_REPORT_DESC_JOYSTICK \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_JOYSTICK), \
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
HID_REPORT_ID(REPORT_ID_JOYSTICK) \
HID_USAGE_PAGE(HID_USAGE_PAGE_BUTTON), \
HID_USAGE_MIN(1), HID_USAGE_MAX(8), \
HID_LOGICAL_MIN(0), HID_LOGICAL_MAX(1), \
HID_REPORT_COUNT(8), HID_REPORT_SIZE(1), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
HID_USAGE(HID_USAGE_DESKTOP_X), HID_USAGE(HID_USAGE_DESKTOP_Y), \
HID_USAGE(HID_USAGE_DESKTOP_Z), \
HID_USAGE(HID_USAGE_DESKTOP_RX), HID_USAGE(HID_USAGE_DESKTOP_RY), \
HID_USAGE(HID_USAGE_DESKTOP_RZ), \
HID_REPORT_COUNT(6), HID_REPORT_SIZE(8), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
HID_COLLECTION_END
#define MUSEC_PICO_REPORT_DESC_NKRO \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
/* Modifier */ \
HID_REPORT_SIZE(1), \
HID_REPORT_COUNT(8), \
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
HID_USAGE_MIN(224), \
HID_USAGE_MAX(231), \
HID_LOGICAL_MIN(0), \
HID_LOGICAL_MAX(1), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
/* LED output that we don't care */ \
HID_REPORT_COUNT(5), \
HID_REPORT_SIZE(1), \
HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \
HID_USAGE_MIN(1), \
HID_USAGE_MAX(5), \
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
HID_REPORT_COUNT(1), \
HID_REPORT_SIZE(3), \
HID_OUTPUT(HID_CONSTANT), \
/* Full Keyboard Bitmap */ \
HID_REPORT_SIZE(1), \
HID_REPORT_COUNT(120), \
HID_LOGICAL_MIN(0), \
HID_LOGICAL_MAX(1), \
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
HID_USAGE_MIN(0), \
HID_USAGE_MAX(119), \
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
HID_COLLECTION_END
// HID_REPORT_ID(REPORT_ID_NKRO)
#define MUSEC_PICO_REPORT_DESC_LIGHTS \
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
HID_USAGE(0x00), \
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
HID_REPORT_ID(REPORT_ID_LIGHTS) \
HID_REPORT_COUNT(18), HID_REPORT_SIZE(8), \
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
HID_STRING_MINIMUM(6), HID_STRING_MAXIMUM(23), \
HID_USAGE_MIN(1), HID_USAGE_MAX(255), \
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
HID_REPORT_COUNT(1), \
HID_REPORT_SIZE(8), /*Padding*/ \
HID_INPUT(HID_CONSTANT | HID_VARIABLE | HID_ABSOLUTE), \
HID_COLLECTION_END
#endif /* USB_DESCRIPTORS_H_ */