diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/host/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | examples/host/midi2_host/CMakeLists.txt | 38 | ||||
| -rw-r--r-- | examples/host/midi2_host/Makefile | 27 | ||||
| -rw-r--r-- | examples/host/midi2_host/src/display.c | 221 | ||||
| -rw-r--r-- | examples/host/midi2_host/src/display.h | 54 | ||||
| -rw-r--r-- | examples/host/midi2_host/src/font5x7.h | 107 | ||||
| -rw-r--r-- | examples/host/midi2_host/src/main.c | 326 | ||||
| -rw-r--r-- | examples/host/midi2_host/src/tusb_config.h | 91 |
8 files changed, 1 insertions, 865 deletions
diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 7c74e3c73..2cf2c10af 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -13,7 +13,7 @@ set(EXAMPLE_LIST device_info hid_controller midi_rx - midi2_host + midi2_host_feather msc_file_explorer msc_file_explorer_freertos ) diff --git a/examples/host/midi2_host/CMakeLists.txt b/examples/host/midi2_host/CMakeLists.txt deleted file mode 100644 index cd70d122a..000000000 --- a/examples/host/midi2_host/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) - -project(midi2_host C CXX ASM) - -family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}) - -# This example requires PIO-USB and Pico SDK (I2C, SSD1306 display) -if(NOT FAMILY STREQUAL "rp2040") - return() -endif() - -add_executable(${PROJECT_NAME}) - -target_sources(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/display.c -) - -target_include_directories(${PROJECT_NAME} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src -) - -family_configure_host_example(${PROJECT_NAME} noos) - -# Waveshare RP2350-USB-A: PIO-USB on GP12/GP13 -target_compile_definitions(${PROJECT_NAME} PRIVATE - PIO_USB_DP_PIN_DEFAULT=12 -) -target_compile_options(${PROJECT_NAME} PRIVATE - -Wno-type-limits -) - -# SSD1306 display (I2C) -target_link_libraries(${PROJECT_NAME} PUBLIC - hardware_i2c -) diff --git a/examples/host/midi2_host/Makefile b/examples/host/midi2_host/Makefile deleted file mode 100644 index 2b4660516..000000000 --- a/examples/host/midi2_host/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# This example requires RP2040/RP2350 (PIO-USB, Pico SDK I2C, SSD1306 display) -ifeq (,$(findstring rp2040,$(FAMILY))) -$(info Skipping midi2_host: requires FAMILY=rp2040) -all: - @: -.DEFAULT: - @: -else - -include ../../../hw/bsp/family_support.mk - -INC += \ - src \ - -# Example source -EXAMPLE_SOURCE += \ - src/main.c \ - src/display.c \ - -SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) - -# Suppress pre-existing warning -CFLAGS_GCC += -Wno-type-limits - -include ../../../hw/bsp/family_rules.mk - -endif diff --git a/examples/host/midi2_host/src/display.c b/examples/host/midi2_host/src/display.c deleted file mode 100644 index 4745c2961..000000000 --- a/examples/host/midi2_host/src/display.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2026 Saulo Verissimo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// SSD1306 OLED display driver (128x64, I2C) for MIDI 2.0 Host example. -// Minimal text-only implementation, no graphics library. -// I2C0: SDA = GP4, SCL = GP5, Address = 0x3C - -#include "display.h" -#include <stdio.h> -#include <string.h> -#include "pico/stdlib.h" -#include "hardware/i2c.h" -#include "hardware/gpio.h" - -#define I2C_PORT i2c0 -#define I2C_SDA 4 -#define I2C_SCL 5 -#define I2C_FREQ 400000 -#define SSD1306_ADDR 0x3C - -#define SCR_W 128 -#define SCR_H 64 -#define PAGES (SCR_H / 8) // 8 pages -#define CHARS_PER_LINE 21 // 128 / 6 = 21 chars - -// Framebuffer -static uint8_t fb[SCR_W * PAGES]; - -// Log buffer -#define LOG_LINES 3 -static char log_lines[LOG_LINES][CHARS_PER_LINE + 1]; -static int log_count = 0; - -// Status line -static char status_text[CHARS_PER_LINE + 1] = ""; - -//--------------------------------------------------------------------+ -// Minimal 5x7 font (ASCII 32-126) -//--------------------------------------------------------------------+ -#include "font5x7.h" - -//--------------------------------------------------------------------+ -// SSD1306 I2C commands -//--------------------------------------------------------------------+ - -static void ssd_cmd(uint8_t cmd) { - uint8_t buf[2] = { 0x00, cmd }; // Co=0, D/C=0 - i2c_write_blocking(I2C_PORT, SSD1306_ADDR, buf, 2, false); -} - -static void ssd_data(const uint8_t* data, size_t len) { - uint8_t buf[SCR_W + 1]; - buf[0] = 0x40; // Co=0, D/C=1 - size_t chunk = (len > SCR_W) ? SCR_W : len; - memcpy(buf + 1, data, chunk); - i2c_write_blocking(I2C_PORT, SSD1306_ADDR, buf, chunk + 1, false); -} - -static void ssd_flush(void) { - ssd_cmd(0x21); ssd_cmd(0); ssd_cmd(127); // Column range - ssd_cmd(0x22); ssd_cmd(0); ssd_cmd(7); // Page range - for (int page = 0; page < PAGES; page++) { - ssd_data(&fb[page * SCR_W], SCR_W); - } -} - -//--------------------------------------------------------------------+ -// Framebuffer drawing -//--------------------------------------------------------------------+ - -static void fb_clear(void) { - memset(fb, 0, sizeof(fb)); -} - -static void fb_char(int x, int y, char c) { - if (c < 32 || c > 126) c = '?'; - const uint8_t* glyph = font5x7 + (c - 32) * 5; - int page = y / 8; - int bit_offset = y % 8; - - if (page >= PAGES || x + 5 > SCR_W) return; - - for (int col = 0; col < 5; col++) { - uint8_t column_data = glyph[col]; - fb[(page * SCR_W) + x + col] |= (uint8_t)(column_data << bit_offset); - if (bit_offset > 0 && page + 1 < PAGES) { - fb[((page + 1) * SCR_W) + x + col] |= (uint8_t)(column_data >> (8 - bit_offset)); - } - } -} - -static void fb_string(int x, int y, const char* str) { - while (*str) { - fb_char(x, y, *str); - x += 6; - if (x + 6 > SCR_W) break; - str++; - } -} - -//--------------------------------------------------------------------+ -// Display API -//--------------------------------------------------------------------+ - -void display_init(void) { - i2c_init(I2C_PORT, I2C_FREQ); - gpio_set_function(I2C_SDA, GPIO_FUNC_I2C); - gpio_set_function(I2C_SCL, GPIO_FUNC_I2C); - gpio_pull_up(I2C_SDA); - gpio_pull_up(I2C_SCL); - - sleep_ms(100); - - // SSD1306 init sequence - ssd_cmd(0xAE); // Display off - ssd_cmd(0xD5); ssd_cmd(0x80); // Clock div - ssd_cmd(0xA8); ssd_cmd(0x3F); // Multiplex 64 - ssd_cmd(0xD3); ssd_cmd(0x00); // Display offset - ssd_cmd(0x40); // Start line 0 - ssd_cmd(0x8D); ssd_cmd(0x14); // Charge pump on - ssd_cmd(0x20); ssd_cmd(0x00); // Horizontal addressing - ssd_cmd(0xA1); // Segment remap - ssd_cmd(0xC8); // COM scan direction - ssd_cmd(0xDA); ssd_cmd(0x12); // COM pins - ssd_cmd(0x81); ssd_cmd(0xCF); // Contrast - ssd_cmd(0xD9); ssd_cmd(0xF1); // Pre-charge - ssd_cmd(0xDB); ssd_cmd(0x40); // VCOMH deselect - ssd_cmd(0xA4); // Display from RAM - ssd_cmd(0xA6); // Normal display - ssd_cmd(0xAF); // Display on - - fb_clear(); - fb_string(0, 0, "MIDI 2.0 Host"); - ssd_flush(); -} - -void display_checklist_update(const checklist_t* ck) { - struct { const char* label; bool ok; } items[] = { - { "PWR", ck->pwr_on }, - { "TinyUSB", ck->tusb_init }, - { "USB bus", ck->bus_active }, - { "Device", ck->device_connected }, - { "Descript", ck->descriptor_parsed }, - { "Alt1 UMP", ck->alt_setting_ok }, - { "Mount", ck->mounted }, - { "RX UMP", ck->receiving }, - }; - - // Clear checklist area (lines 1-4, two columns) - for (int p = 1; p <= 4; p++) { - memset(&fb[p * SCR_W], 0, SCR_W); - } - - for (int i = 0; i < 8; i++) { - int col = (i < 4) ? 0 : 64; - int row = (i < 4) ? i : i - 4; - int y = 9 + row * 8; - char line[12]; - snprintf(line, sizeof(line), "%s %s", items[i].ok ? "OK" : "..", items[i].label); - fb_string(col, y, line); - } - - ssd_flush(); -} - -void display_log(const char* text, uint16_t color) { - (void)color; // SSD1306 is monochrome - - if (log_count >= LOG_LINES) { - for (int i = 0; i < LOG_LINES - 1; i++) { - strncpy(log_lines[i], log_lines[i + 1], CHARS_PER_LINE); - log_lines[i][CHARS_PER_LINE] = '\0'; - } - log_count = LOG_LINES - 1; - } - - strncpy(log_lines[log_count], text, CHARS_PER_LINE); - log_lines[log_count][CHARS_PER_LINE] = '\0'; - log_count++; - - // Draw log area (pages 5-6, y=40-55) - memset(&fb[5 * SCR_W], 0, SCR_W); - memset(&fb[6 * SCR_W], 0, SCR_W); - - for (int i = 0; i < log_count && i < LOG_LINES; i++) { - fb_string(0, 41 + i * 8, log_lines[i]); - } - - ssd_flush(); -} - -void display_status(const char* text) { - strncpy(status_text, text, CHARS_PER_LINE); - status_text[CHARS_PER_LINE] = '\0'; - - // Status on last page (y=56) - memset(&fb[7 * SCR_W], 0, SCR_W); - fb_string(0, 56, status_text); - ssd_flush(); -} diff --git a/examples/host/midi2_host/src/display.h b/examples/host/midi2_host/src/display.h deleted file mode 100644 index a8b0a4b5e..000000000 --- a/examples/host/midi2_host/src/display.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2026 Saulo Verissimo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef DISPLAY_H_ -#define DISPLAY_H_ - -#include <stdint.h> -#include <stdbool.h> - -typedef struct { - bool pwr_on; - bool tusb_init; - bool bus_active; - bool device_connected; - bool descriptor_parsed; - bool alt_setting_ok; - bool mounted; - bool receiving; -} checklist_t; - -// Initialize SSD1306 display (I2C on GP4/GP5) -void display_init(void); - -// Redraw the checklist area (top portion) -void display_checklist_update(const checklist_t* ck); - -// Add a line to the scrolling log area -void display_log(const char* text, uint16_t color); - -// Update the status bar (bottom line) -void display_status(const char* text); - -#endif diff --git a/examples/host/midi2_host/src/font5x7.h b/examples/host/midi2_host/src/font5x7.h deleted file mode 100644 index e515faac1..000000000 --- a/examples/host/midi2_host/src/font5x7.h +++ /dev/null @@ -1,107 +0,0 @@ -// Minimal 5x7 font, ASCII 32-126. Public domain. -// 5 bytes per character (5 columns, 7 rows, LSB=top row) - -#ifndef FONT5X7_H_ -#define FONT5X7_H_ - -#include <stdint.h> - -static const uint8_t font5x7[] = { - 0x00,0x00,0x00,0x00,0x00, // 32 (space) - 0x00,0x00,0x5F,0x00,0x00, // 33 ! - 0x00,0x07,0x00,0x07,0x00, // 34 " - 0x14,0x7F,0x14,0x7F,0x14, // 35 # - 0x24,0x2A,0x7F,0x2A,0x12, // 36 $ - 0x23,0x13,0x08,0x64,0x62, // 37 % - 0x36,0x49,0x55,0x22,0x50, // 38 & - 0x00,0x05,0x03,0x00,0x00, // 39 ' - 0x00,0x1C,0x22,0x41,0x00, // 40 ( - 0x00,0x41,0x22,0x1C,0x00, // 41 ) - 0x08,0x2A,0x1C,0x2A,0x08, // 42 * - 0x08,0x08,0x3E,0x08,0x08, // 43 + - 0x00,0x50,0x30,0x00,0x00, // 44 , - 0x08,0x08,0x08,0x08,0x08, // 45 - - 0x00,0x60,0x60,0x00,0x00, // 46 . - 0x20,0x10,0x08,0x04,0x02, // 47 / - 0x3E,0x51,0x49,0x45,0x3E, // 48 0 - 0x00,0x42,0x7F,0x40,0x00, // 49 1 - 0x42,0x61,0x51,0x49,0x46, // 50 2 - 0x21,0x41,0x45,0x4B,0x31, // 51 3 - 0x18,0x14,0x12,0x7F,0x10, // 52 4 - 0x27,0x45,0x45,0x45,0x39, // 53 5 - 0x3C,0x4A,0x49,0x49,0x30, // 54 6 - 0x01,0x71,0x09,0x05,0x03, // 55 7 - 0x36,0x49,0x49,0x49,0x36, // 56 8 - 0x06,0x49,0x49,0x29,0x1E, // 57 9 - 0x00,0x36,0x36,0x00,0x00, // 58 : - 0x00,0x56,0x36,0x00,0x00, // 59 ; - 0x00,0x08,0x14,0x22,0x41, // 60 < - 0x14,0x14,0x14,0x14,0x14, // 61 = - 0x41,0x22,0x14,0x08,0x00, // 62 > - 0x02,0x01,0x51,0x09,0x06, // 63 ? - 0x32,0x49,0x79,0x41,0x3E, // 64 @ - 0x7E,0x11,0x11,0x11,0x7E, // 65 A - 0x7F,0x49,0x49,0x49,0x36, // 66 B - 0x3E,0x41,0x41,0x41,0x22, // 67 C - 0x7F,0x41,0x41,0x22,0x1C, // 68 D - 0x7F,0x49,0x49,0x49,0x41, // 69 E - 0x7F,0x09,0x09,0x01,0x01, // 70 F - 0x3E,0x41,0x41,0x51,0x32, // 71 G - 0x7F,0x08,0x08,0x08,0x7F, // 72 H - 0x00,0x41,0x7F,0x41,0x00, // 73 I - 0x20,0x40,0x41,0x3F,0x01, // 74 J - 0x7F,0x08,0x14,0x22,0x41, // 75 K - 0x7F,0x40,0x40,0x40,0x40, // 76 L - 0x7F,0x02,0x04,0x02,0x7F, // 77 M - 0x7F,0x04,0x08,0x10,0x7F, // 78 N - 0x3E,0x41,0x41,0x41,0x3E, // 79 O - 0x7F,0x09,0x09,0x09,0x06, // 80 P - 0x3E,0x41,0x51,0x21,0x5E, // 81 Q - 0x7F,0x09,0x19,0x29,0x46, // 82 R - 0x46,0x49,0x49,0x49,0x31, // 83 S - 0x01,0x01,0x7F,0x01,0x01, // 84 T - 0x3F,0x40,0x40,0x40,0x3F, // 85 U - 0x1F,0x20,0x40,0x20,0x1F, // 86 V - 0x7F,0x20,0x18,0x20,0x7F, // 87 W - 0x63,0x14,0x08,0x14,0x63, // 88 X - 0x03,0x04,0x78,0x04,0x03, // 89 Y - 0x61,0x51,0x49,0x45,0x43, // 90 Z - 0x00,0x00,0x7F,0x41,0x41, // 91 [ - 0x02,0x04,0x08,0x10,0x20, // 92 backslash - 0x41,0x41,0x7F,0x00,0x00, // 93 ] - 0x04,0x02,0x01,0x02,0x04, // 94 ^ - 0x40,0x40,0x40,0x40,0x40, // 95 _ - 0x00,0x01,0x02,0x04,0x00, // 96 ` - 0x20,0x54,0x54,0x54,0x78, // 97 a - 0x7F,0x48,0x44,0x44,0x38, // 98 b - 0x38,0x44,0x44,0x44,0x20, // 99 c - 0x38,0x44,0x44,0x48,0x7F, // 100 d - 0x38,0x54,0x54,0x54,0x18, // 101 e - 0x08,0x7E,0x09,0x01,0x02, // 102 f - 0x08,0x14,0x54,0x54,0x3C, // 103 g - 0x7F,0x08,0x04,0x04,0x78, // 104 h - 0x00,0x44,0x7D,0x40,0x00, // 105 i - 0x20,0x40,0x44,0x3D,0x00, // 106 j - 0x00,0x7F,0x10,0x28,0x44, // 107 k - 0x00,0x41,0x7F,0x40,0x00, // 108 l - 0x7C,0x04,0x18,0x04,0x78, // 109 m - 0x7C,0x08,0x04,0x04,0x78, // 110 n - 0x38,0x44,0x44,0x44,0x38, // 111 o - 0x7C,0x14,0x14,0x14,0x08, // 112 p - 0x08,0x14,0x14,0x18,0x7C, // 113 q - 0x7C,0x08,0x04,0x04,0x08, // 114 r - 0x48,0x54,0x54,0x54,0x20, // 115 s - 0x04,0x3F,0x44,0x40,0x20, // 116 t - 0x3C,0x40,0x40,0x20,0x7C, // 117 u - 0x1C,0x20,0x40,0x20,0x1C, // 118 v - 0x3C,0x40,0x30,0x40,0x3C, // 119 w - 0x44,0x28,0x10,0x28,0x44, // 120 x - 0x0C,0x50,0x50,0x50,0x3C, // 121 y - 0x44,0x64,0x54,0x4C,0x44, // 122 z - 0x00,0x08,0x36,0x41,0x00, // 123 { - 0x00,0x00,0x7F,0x00,0x00, // 124 | - 0x00,0x41,0x36,0x08,0x00, // 125 } - 0x10,0x08,0x08,0x10,0x08, // 126 ~ -}; - -#endif diff --git a/examples/host/midi2_host/src/main.c b/examples/host/midi2_host/src/main.c deleted file mode 100644 index e23fbfc87..000000000 --- a/examples/host/midi2_host/src/main.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2026 Saulo Verissimo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// MIDI 2.0 Host Receiver Example -// -// Receives UMP from a MIDI 2.0 Device via PIO-USB Host. -// SSD1306 OLED (I2C, 128x64) shows boot checklist then received UMP messages. - -#include <stdio.h> -#include <string.h> -#include "bsp/board_api.h" -#include "tusb.h" -#include "class/midi/midi2_host.h" -#include "class/midi/midi.h" -#include "display.h" - -//--------------------------------------------------------------------+ -// Checklist state -//--------------------------------------------------------------------+ - -static checklist_t ck = { 0 }; -static uint32_t note_count = 0; -static uint8_t midi2_idx = 0xFF; // invalid until mount - -//--------------------------------------------------------------------+ -// Note name helper -//--------------------------------------------------------------------+ - -static const char* NOTE_NAMES[] = { - "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" -}; - -static void note_name(uint8_t pitch, char* buf, size_t len) { - int octave = (pitch / 12) - 1; - snprintf(buf, len, "%s%d", NOTE_NAMES[pitch % 12], octave); -} - -//--------------------------------------------------------------------+ -// UMP Message Type names -//--------------------------------------------------------------------+ - -static const char* mt_name(uint8_t mt) { - switch (mt) { - case 0x0: return "Utility"; - case 0x1: return "System"; - case 0x2: return "M1 CVM"; - case 0x3: return "SysEx7"; - case 0x4: return "M2 CVM"; - case 0x5: return "SysEx8"; - case 0xD: return "Flex"; - case 0xF: return "Stream"; - default: return "?"; - } -} - -//--------------------------------------------------------------------+ -// UMP decoder - extract and display MIDI 2.0 messages -//--------------------------------------------------------------------+ - -static void decode_ump(const uint32_t* words, uint8_t word_count) { - uint8_t mt = (uint8_t)((words[0] >> 28) & 0x0F); - char line[64]; - - if (mt == 0x4 && word_count >= 2) { - // MIDI 2.0 Channel Voice Message - uint8_t status = (uint8_t)((words[0] >> 20) & 0x0F); - uint8_t channel = (uint8_t)((words[0] >> 16) & 0x0F); - - switch (status) { - case 0x9: { // Note On - uint8_t pitch = (uint8_t)((words[0] >> 8) & 0x7F); - uint16_t vel = (uint16_t)((words[1] >> 16) & 0xFFFF); - char nn[6]; - note_name(pitch, nn, sizeof(nn)); - snprintf(line, sizeof(line), "NoteOn %s ch%u vel=0x%04X", nn, channel, vel); - display_log(line, 0x07E0); // green - note_count++; - break; - } - case 0x8: { // Note Off - uint8_t pitch = (uint8_t)((words[0] >> 8) & 0x7F); - char nn[6]; - note_name(pitch, nn, sizeof(nn)); - snprintf(line, sizeof(line), "NoteOff %s ch%u", nn, channel); - display_log(line, 0x8410); // grey - break; - } - case 0xB: { // CC - uint8_t idx = (uint8_t)((words[0] >> 8) & 0x7F); - snprintf(line, sizeof(line), "CC%-3u = 0x%08lX", idx, (unsigned long)words[1]); - display_log(line, 0x001F); // blue - break; - } - case 0xC: { // Program Change - uint8_t prog = (uint8_t)((words[1] >> 24) & 0x7F); - snprintf(line, sizeof(line), "ProgChg %u", prog); - display_log(line, 0xFFE0); // yellow - break; - } - case 0xE: { // Pitch Bend - snprintf(line, sizeof(line), "PBend = 0x%08lX", (unsigned long)words[1]); - display_log(line, 0xF81F); // magenta - break; - } - case 0xD: { // Channel Pressure - snprintf(line, sizeof(line), "CPress = 0x%08lX", (unsigned long)words[1]); - display_log(line, 0xFC10); // orange - break; - } - case 0xA: { // Poly Pressure - uint8_t pitch = (uint8_t)((words[0] >> 8) & 0x7F); - char nn[6]; - note_name(pitch, nn, sizeof(nn)); - snprintf(line, sizeof(line), "PolyP %s = 0x%08lX", nn, (unsigned long)words[1]); - display_log(line, 0xFC10); - break; - } - case 0xF: { // Per-Note Management - uint8_t pitch = (uint8_t)((words[0] >> 8) & 0x7F); - uint8_t flags = (uint8_t)(words[0] & 0xFF); - snprintf(line, sizeof(line), "PN-Mgmt note=%u flags=0x%02X", pitch, flags); - display_log(line, 0x07FF); // cyan - break; - } - default: { - snprintf(line, sizeof(line), "M2CVM status=0x%X", status); - display_log(line, 0xFFFF); - break; - } - } - } else if (mt == 0x0) { - // Utility (JR Timestamp, NOOP) - uint8_t status = (uint8_t)((words[0] >> 20) & 0x0F); - if (status == 0x2) { - uint16_t ts = words[0] & 0xFFFF; - snprintf(line, sizeof(line), "JR-TS = 0x%04X", ts); - display_log(line, 0x8410); - } - } else { - snprintf(line, sizeof(line), "MT=0x%X (%s) w0=0x%08lX", - mt, mt_name(mt), (unsigned long)words[0]); - display_log(line, 0xFFFF); - } -} - -//--------------------------------------------------------------------+ -// MIDI 2.0 Host Callbacks -//--------------------------------------------------------------------+ - -void tuh_midi2_descriptor_cb(uint8_t idx, const tuh_midi2_descriptor_cb_t* d) { - (void)idx; - ck.descriptor_parsed = true; - char line[48]; - - snprintf(line, sizeof(line), "bcdMSC=0x%02X%02X proto=%s", - d->bcdMSC_hi, d->bcdMSC_lo, - d->protocol_version ? "MIDI2" : "MIDI1"); - display_log(line, 0x07E0); - - snprintf(line, sizeof(line), "Cables: RX=%u TX=%u", - d->rx_cable_count, d->tx_cable_count); - display_log(line, 0x07E0); - - display_checklist_update(&ck); -} - -void tuh_midi2_mount_cb(uint8_t idx, const tuh_midi2_mount_cb_t* m) { - midi2_idx = idx; - ck.alt_setting_ok = true; - ck.mounted = true; - - char line[48]; - snprintf(line, sizeof(line), "Mounted addr=%u alt=%u", - m->daddr, m->alt_setting_active); - display_log(line, 0x07E0); - - if (m->protocol_version) { - display_log("MIDI 2.0 ready", 0x07E0); - } else { - display_log("MIDI 1.0 only", 0xFFE0); - } - - display_checklist_update(&ck); -} - -void tuh_midi2_rx_cb(uint8_t idx, uint32_t xferred_bytes) { - (void)xferred_bytes; - if (!ck.receiving) { - ck.receiving = true; - display_checklist_update(&ck); - } - - uint32_t words[16]; - while (1) { - uint32_t n = tuh_midi2_ump_read(idx, words, 16); - if (n == 0) break; - - // Decode complete UMP messages - uint32_t i = 0; - while (i < n) { - uint8_t mt = (uint8_t)((words[i] >> 28) & 0x0F); - uint8_t wc = midi2_ump_word_count(mt); - if (i + wc > n) break; - decode_ump(&words[i], wc); - i += wc; - } - } -} - -void tuh_midi2_tx_cb(uint8_t idx, uint32_t xferred_bytes) { - (void)idx; (void)xferred_bytes; -} - -void tuh_midi2_umount_cb(uint8_t idx) { - (void)idx; - midi2_idx = 0xFF; - ck.device_connected = false; - ck.descriptor_parsed = false; - ck.alt_setting_ok = false; - ck.mounted = false; - ck.receiving = false; - note_count = 0; - - display_log("Device disconnected", 0xF800); - display_checklist_update(&ck); -} - -//--------------------------------------------------------------------+ -// Main -//--------------------------------------------------------------------+ - -int main(void) { - board_init(); - - display_init(); - - ck.pwr_on = true; - display_checklist_update(&ck); - - // Init TinyUSB Host (BSP handles PIO-USB configuration via tuh_configure) - tusb_rhport_init_t host_init = { - .role = TUSB_ROLE_HOST, - .speed = TUSB_SPEED_FULL, - }; - tusb_init(BOARD_TUH_RHPORT, &host_init); - - ck.tusb_init = true; - ck.bus_active = true; - display_checklist_update(&ck); - - char dbg[40]; - snprintf(dbg, sizeof(dbg), "RHPORT=%u PIO_USB=%u", - BOARD_TUH_RHPORT, CFG_TUH_RPI_PIO_USB); - display_log(dbg, 0xFFE0); // yellow - display_status("Waiting for device..."); - - uint32_t last_status_ms = 0; - static uint32_t loop_count = 0; - - while (1) { - tuh_task(); - loop_count++; - - // Update status every 2 seconds - uint32_t now = tusb_time_millis_api(); - if (now - last_status_ms > 2000) { - last_status_ms = now; - char line[22]; - if (ck.receiving) { - snprintf(line, sizeof(line), "Notes:%lu", (unsigned long)note_count); - } else if (ck.mounted) { - snprintf(line, sizeof(line), "Mounted OK!"); - } else if (ck.device_connected) { - snprintf(line, sizeof(line), "Dev found, mounting.."); - } else { - snprintf(line, sizeof(line), "Wait.. t=%lu", (unsigned long)(now/1000)); - } - display_status(line); - } - } - - return 0; -} - -// Generic USB device mount/unmount (any class) -void tuh_mount_cb(uint8_t daddr) { - char line[32]; - uint16_t vid, pid; - tuh_vid_pid_get(daddr, &vid, &pid); - snprintf(line, sizeof(line), "USB %04X:%04X a%u", vid, pid, daddr); - display_log(line, 0x07E0); - ck.device_connected = true; - display_checklist_update(&ck); -} - -void tuh_umount_cb(uint8_t daddr) { - (void)daddr; - display_log("USB disconnected", 0xF800); - ck.device_connected = false; - ck.descriptor_parsed = false; - ck.alt_setting_ok = false; - ck.mounted = false; - ck.receiving = false; - display_checklist_update(&ck); -} diff --git a/examples/host/midi2_host/src/tusb_config.h b/examples/host/midi2_host/src/tusb_config.h deleted file mode 100644 index 650df97e1..000000000 --- a/examples/host/midi2_host/src/tusb_config.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2026 Saulo Verissimo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TUSB_CONFIG_H_ -#define TUSB_CONFIG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -//-------------------------------------------------------------------- -// Common Configuration -//-------------------------------------------------------------------- - -#ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined -#endif - -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE -#endif - -#ifndef CFG_TUSB_DEBUG -#define CFG_TUSB_DEBUG 0 -#endif - -#ifndef CFG_TUH_MEM_SECTION -#define CFG_TUH_MEM_SECTION -#endif - -#ifndef CFG_TUH_MEM_ALIGN -#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4))) -#endif - -//-------------------------------------------------------------------- -// Host Configuration -// Waveshare RP2350-USB-A: PIO-USB on GP12/GP13 (USB-A Host port) -//-------------------------------------------------------------------- - -#define CFG_TUH_ENABLED 1 - -// PIO-USB Host on rhport 1 (USB-A connector on GP12/GP13) -#define CFG_TUH_RPI_PIO_USB 1 -#define BOARD_TUH_RHPORT 1 - -#ifndef BOARD_TUH_MAX_SPEED -#define BOARD_TUH_MAX_SPEED OPT_MODE_FULL_SPEED -#endif - -#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED - -//-------------------------------------------------------------------- -// Driver Configuration -//-------------------------------------------------------------------- - -#define CFG_TUH_ENUMERATION_BUFSIZE 256 - -#define CFG_TUH_HUB 0 -#define CFG_TUH_DEVICE_MAX 1 - -// MIDI 2.0 Host -#define CFG_TUH_MIDI2 1 -#define CFG_TUH_MIDI2_RX_BUFSIZE 512 -#define CFG_TUH_MIDI2_TX_BUFSIZE 512 - -#ifdef __cplusplus -} -#endif - -#endif |
