1+ // SPDX-FileCopyrightText: 2025 John Park and Tod Kurt
2+ //
3+ // SPDX-License-Identifier: MIT
4+
5+ // Use a DMX controller to drive NeoPixel strips
6+ // Arduino Uno or Metro 328 + Conceptinetics DMX Shield
7+ // Recieves incoming DMX messages from controller, translates to NeoPixel
8+
9+ // MIDIHost2Host -- Connect two USB-MIDI host devices together
10+ // 2019 @todbot / Tod E. Kurt
11+ // 2025 @johnedgarpark / John E. Park
12+ // This sketch is meant to be installed on two Adafruit QT Py RP2040s.
13+ // The connections between the two QT Py RP2040s are
14+ // QTPyA Gnd ----- QTPyB Gnd
15+ // QTPyA TX ----- QTPyB RX
16+ // QTPyA RX ----- QTPyB TX
17+ // except it's done w PIO over the stemma qt cable (remove red wire first)
18+
19+
20+ // When compiling:
21+ // Install libraries: Adafruit_TinyUSB & MIDI
22+ // Be sure to have updated all boards and libraries
23+ // Select "Tools" -> "USB Stack" -> "TinyUSB"
24+
25+ // The following libraries are required:
26+ // Adafruit_TinyUSB library by Adafruit
27+ // https://github.com/adafruit/Adafruit_TinyUSB_Arduino
28+ // MIDI Library by Forty Seven Effects
29+ // https://github.com/FortySevenEffects/arduino_midi_library
30+
31+
32+ #include < Arduino.h>
33+ #include < Adafruit_TinyUSB.h>
34+ #include < MIDI.h>
35+ #include < Adafruit_NeoPixel.h>
36+
37+ // Adjust these for flashing the two different boards either "red" or "blue"
38+ #define RED_BOARD
39+ // #define BLUE_BOARD
40+
41+
42+
43+ // Color definitions
44+ uint32_t RED = 0xCC0000 ;
45+ uint32_t DIM_RED = 0x3F0000 ; // 25% brightness red
46+ uint32_t GREEN = 0x00DD00 ;
47+ uint32_t BLUE = 0x0000CC ;
48+ uint32_t DIM_BLUE = 0x00003F ; // 25% brightness blue
49+ uint32_t YELLOW = 0xAAAA00 ;
50+ char mfgstr[32 ] = " Lars Productions" ;
51+ #ifdef RED_BOARD
52+ char prodstr[32 ] = " QTHost2 Red" ;
53+ uint32_t LED_COLOR = RED;
54+ uint32_t LED_DIM_COLOR = DIM_RED;
55+ SerialPIO pioserial (23 , 22 );
56+ #else
57+ char prodstr[32 ] = " QTHost2 Blue" ;
58+ uint32_t LED_COLOR = BLUE;
59+ uint32_t LED_DIM_COLOR = DIM_BLUE;
60+ SerialPIO pioserial (22 , 23 );
61+ #endif
62+
63+
64+ // NeoPixel settings
65+ #define NUM_PIXELS 1
66+
67+ // NeoPixel RGB LED
68+ Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
69+
70+ bool led_on = false ;
71+ uint32_t led_time;
72+ uint32_t led_on_time = 50 ; // how long LED should blink
73+ uint32_t last_color = LED_DIM_COLOR; // Track last active color
74+
75+ // USB MIDI object
76+ Adafruit_USBD_MIDI usb_midi;
77+
78+ // Create instance of Arduino MIDI library,
79+ // and attach usb_midi as the transport.
80+ // MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, midiA);
81+ MIDI_CREATE_INSTANCE (Adafruit_USBD_MIDI, usb_midi, midiA);
82+
83+ // Create instance of Arduino MIDI library,
84+ // and attach HardwareSerial Serial1 (TrinketM0 pins 3 & 4 or TX/RX on a QT Py, this is automatic)
85+ MIDI_CREATE_INSTANCE (HardwareSerial, pioserial, midiB);
86+
87+
88+ void setup ()
89+ {
90+
91+
92+ #if defined(NEOPIXEL_POWER)
93+ // If this board has a power control pin, we must set it to output and high
94+ // in order to enable the NeoPixels. We put this in an #if defined so it can
95+ // be reused for other boards without compilation errors
96+ pinMode (NEOPIXEL_POWER, OUTPUT);
97+ digitalWrite (NEOPIXEL_POWER, HIGH);
98+ #endif
99+ pixels.begin ();
100+ pixels.setBrightness (60 );
101+ set_pixel (YELLOW);
102+
103+ USBDevice.setManufacturerDescriptor (mfgstr);
104+ USBDevice.setProductDescriptor (prodstr);
105+
106+ // Initialize MIDI, and listen to all MIDI channels
107+ // This will also call usb_midi's and Serial1's begin()
108+ midiA.begin (MIDI_CHANNEL_OMNI);
109+ midiB.begin (MIDI_CHANNEL_OMNI);
110+
111+ midiA.turnThruOff ();
112+ midiB.turnThruOff ();
113+
114+ // Serial.begin(115200);
115+
116+ // wait until device mounted
117+ while ( !USBDevice.mounted () ) delay (1 );
118+ set_pixel (LED_COLOR);
119+ }
120+
121+ void loop ()
122+ {
123+ // read any new MIDI messages
124+ if ( midiA.read () ) {
125+ midiB.send (midiA.getType (),
126+ midiA.getData1 (),
127+ midiA.getData2 (),
128+ midiA.getChannel ());
129+ last_color = LED_DIM_COLOR; // Update last color to red
130+ pixel_on (LED_COLOR);
131+ // Serial.println("midiA");
132+ }
133+
134+ if ( midiB.read () ) {
135+ midiA.send (midiB.getType (),
136+ midiB.getData1 (),
137+ midiB.getData2 (),
138+ midiB.getChannel ());
139+ last_color = LED_DIM_COLOR; // Update last color to blue
140+ pixel_on (LED_COLOR);
141+ // Serial.println("midiB");
142+ }
143+
144+ pixel_check ();
145+ }
146+
147+ void pixel_check () {
148+ if ( led_on && (millis () - led_time) > led_on_time ) {
149+ led_on = false ;
150+ set_pixel (last_color); // Return to dimmed version of last active color
151+ }
152+ }
153+
154+ void pixel_on (uint32_t color) {
155+ set_pixel (color);
156+ led_on = true ;
157+ led_time = millis ();
158+ }
159+
160+ void set_pixel (uint32_t color) {
161+ pixels.setPixelColor (0 , color);
162+ pixels.show ();
163+ }
0 commit comments