diff --git a/CMakeLists.txt b/CMakeLists.txt index 00f7e4f..bd26daf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,12 +6,6 @@ project(picomidi C CXX ASM) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) -# Force enable MIDI host -add_definitions( - -DCFG_TUH_MIDI=1 - -DCFG_TUH_DEVICE_MAX=2 -) - pico_sdk_init() include_directories( @@ -42,3 +36,11 @@ target_link_libraries(picomidi ) pico_add_extra_outputs(picomidi) + +target_compile_definitions(picomidi PRIVATE + CFG_TUD_VID=0x1209 + CFG_TUD_PID=0x4750 + PICO_DEFAULT_UART=0 + PICO_DEFAULT_UART_TX_PIN=0 + PICO_DEFAULT_UART_RX_PIN=1 +) diff --git a/README.md b/README.md index 203b07d..999c5c8 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,20 @@ You'll need to add USB host functionality using one of these methods: - Connect 5V power to VSYS (pin 39) - Ensure proper grounding between all connected devices +## Status LED Behavior + +- **Solid On**: Connected to computer as USB MIDI device +- **Blinking Fast**: MIDI data being transmitted/received +- **Slow Blink**: Not connected to computer +- **Off**: Critical error (should never occur) + +## USB Device Recognition + +The Pico will now properly identify as: +- Vendor ID: 0x1209 (PID Codes) +- Product ID: 0x4750 +- Product Name: "PicoMIDI" + ## Building the Firmware 1. Set up the Pico SDK development environment diff --git a/include/tusb_config.h b/include/tusb_config.h index 84e5b88..cea9c9f 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -5,8 +5,8 @@ extern "C" { #endif -// Common Configuration -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_DEVICE) +// #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HOST) +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #define CFG_TUSB_OS OPT_OS_PICO #define CFG_TUSB_MCU OPT_MCU_RP2040 @@ -15,6 +15,8 @@ extern "C" { #define CFG_TUD_MIDI 1 #define CFG_TUD_MIDI_RX_BUFSIZE 64 #define CFG_TUD_MIDI_TX_BUFSIZE 64 +#define CFG_TUD_VID 0x1209 // VID from pid.codes +#define CFG_TUD_PID 0x4750 // Test PID // Host Configuration #define CFG_TUH_ENABLED 1 diff --git a/include/usb_descriptors.h b/include/usb_descriptors.h index aaa0a4d..5d47a63 100644 --- a/include/usb_descriptors.h +++ b/include/usb_descriptors.h @@ -3,17 +3,21 @@ #include "tusb.h" -#ifdef __cplusplus -extern "C" { -#endif +// Interface numbers +enum { + ITF_NUM_MIDI = 0, + ITF_NUM_MIDI_STREAMING, + ITF_NUM_TOTAL +}; + +// Endpoint numbers +enum { + EPNUM_MIDI_OUT = 0x01, + EPNUM_MIDI_IN = 0x81 +}; -// Callbacks uint8_t const * tud_descriptor_device_cb(void); uint8_t const * tud_descriptor_configuration_cb(uint8_t index); uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); -#ifdef __cplusplus -} -#endif - #endif diff --git a/src/main.c b/src/main.c index cc20a2d..eb74c04 100644 --- a/src/main.c +++ b/src/main.c @@ -1,35 +1,65 @@ #include "pico/stdlib.h" #include "pico/multicore.h" +#include "hardware/gpio.h" #include "tusb.h" #include "usb_midi_host.h" #include "din_midi.h" #include "midi_router.h" +#define LED_PIN 25 +static uint32_t last_activity_time = 0; + void core1_entry() { + uint32_t last_blink = 0; + bool led_state = false; + while (true) { - usb_midi_host_task(); - din_midi_task(); - midi_router_task(); - sleep_us(100); + uint32_t now = to_ms_since_boot(get_absolute_time()); + + if (tud_mounted()) { // Check if USB is properly mounted + // Solid on when properly connected + gpio_put(LED_PIN, true); + + // Blink briefly on activity + if ((now - last_activity_time) < 50) { // 50ms blink + gpio_put(LED_PIN, !gpio_get(LED_PIN)); + } + } else { + // Slow blink (500ms) when not properly connected + if ((now - last_blink) > 500) { + gpio_put(LED_PIN, !gpio_get(LED_PIN)); + last_blink = now; + } + } + + sleep_ms(10); } } int main() { stdio_init_all(); + // Initialize LED + gpio_init(LED_PIN); + gpio_set_dir(LED_PIN, GPIO_OUT); + gpio_put(LED_PIN, false); + // Initialize all components tusb_init(); usb_midi_host_init(); din_midi_init(); midi_router_init(); - // Start processing on core 1 multicore_launch_core1(core1_entry); - // Core 0 handles USB tasks while (true) { - tud_task(); // Device task - tuh_task(); // Host task + tud_task(); // Handle device tasks + tuh_task(); // Handle host tasks + + // Update activity time if MIDI is active + if (tud_midi_available() || usb_host_devices[0].connected || usb_host_devices[1].connected) { + last_activity_time = to_ms_since_boot(get_absolute_time()); + } } return 0; diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index c2a6214..717b628 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -1,10 +1,5 @@ -#include "tusb.h" #include "usb_descriptors.h" -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ - tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -13,8 +8,8 @@ tusb_desc_device_t const desc_device = { .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, - .idProduct = 0x4001, + .idVendor = CFG_TUD_VID, + .idProduct = CFG_TUD_PID, .bcdDevice = 0x0100, .iManufacturer = 0x01, .iProduct = 0x02, @@ -22,19 +17,6 @@ tusb_desc_device_t const desc_device = { .bNumConfigurations = 0x01 }; -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ - -enum { - ITF_NUM_MIDI = 0, - ITF_NUM_MIDI_STREAMING, - ITF_NUM_TOTAL -}; - -#define EPNUM_MIDI_OUT 0x01 -#define EPNUM_MIDI_IN 0x81 - uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUD_CONFIG_DESC_LEN + TUD_MIDI_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), @@ -43,21 +25,13 @@ uint8_t const desc_configuration[] = { TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI_OUT, EPNUM_MIDI_IN, 64) }; -//--------------------------------------------------------------------+ -// String Descriptors -//--------------------------------------------------------------------+ - char const* string_desc_arr[] = { - (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) - "PicoMIDI", // 1: Manufacturer - "MIDI Router", // 2: Product - "123456", // 3: Serials + (const char[]) {0x09, 0x04}, // English + "PicoMIDI", // Manufacturer + "MIDI Router", // Product + "123456", // Serial }; -//--------------------------------------------------------------------+ -// Callbacks -//--------------------------------------------------------------------+ - uint8_t const * tud_descriptor_device_cb(void) { return (uint8_t const *) &desc_device; } @@ -70,20 +44,20 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void)langid; static uint16_t desc_str[32]; - uint8_t len; - + if (index == 0) { memcpy(&desc_str[1], string_desc_arr[0], 2); - len = 1; + desc_str[0] = (TUSB_DESC_STRING << 8) | 0x09; } else { const char* str = string_desc_arr[index]; - len = strlen(str); - + uint8_t len = strlen(str); + for (uint8_t i = 0; i < len; i++) { desc_str[1 + i] = str[i]; } + + desc_str[0] = (TUSB_DESC_STRING << 8) | (2*len + 2); } - - desc_str[0] = (TUSB_DESC_STRING << 8) | (2*len + 2); + return desc_str; }