Advertisement
Guest User

Untitled

a guest
May 15th, 2025
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <SPI.h>
  2. #include <Wire.h>
  3. #include <Adafruit_GFX.h>
  4. #include <Adafruit_SSD1306.h>
  5.  
  6. // #define WIRE Wire1  //only if display needs it.
  7. #define SCREEN_WIDTH 128     // OLED display width, in pixels
  8. #define SCREEN_HEIGHT 64     // OLED display height, in pixels
  9. #define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)
  10. #define SCREEN_ADDRESS 0x3C  ///< See datasheet for Address; 0x3D for 128x64, 0x3C for OLED FeatherWing 128x32
  11. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  12.  
  13. // Screen buttons
  14. const int buttonAPin = 0;
  15. const int buttonBPin = 1;
  16. const int buttonCPin = 2;
  17. int buttonAState;
  18. int buttonBState;
  19. int buttonCState;
  20. int lastButtonAState;
  21. int lastButtonBState;
  22. int lastButtonCState;
  23. unsigned long lastDebounceATime = 0;
  24. unsigned long lastDebounceBTime = 0;
  25. unsigned long lastDebounceCTime = 0;
  26. unsigned long debounceDelay = 50;
  27.  
  28. int userChannel = 1;
  29. int userProgOffset = 0;
  30.  
  31. #include <MIDI.h>
  32.  
  33. #if defined(USE_TINYUSB_HOST) || !defined(USE_TINYUSB)
  34. #error "Please use the Menu to select Tools->USB Stack: Adafruit TinyUSB"
  35. #endif
  36. #include "pio_usb.h"
  37. #define HOST_PIN_DP 16  // Pin used as D+ for host, D- = D+ + 1
  38. #include "EZ_USB_MIDI_HOST.h"
  39.  
  40. // USB Host object
  41. Adafruit_USBH_Host USBHost;
  42.  
  43. USING_NAMESPACE_MIDI
  44. USING_NAMESPACE_EZ_USB_MIDI_HOST
  45.  
  46. RPPICOMIDI_EZ_USB_MIDI_HOST_INSTANCE(usbhMIDI, MidiHostSettingsDefault)
  47.  
  48. Adafruit_USBD_MIDI usb_midi;                                  // USB MIDI object
  49. MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, MIDIusb);  // USB MIDI
  50. MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDIuart);      // Serial MIDI over MIDI FeatherWing
  51.  
  52. static uint8_t midiDevAddr = 0;
  53.  
  54. static bool core0_booting = true;
  55. static bool core1_booting = true;
  56.  
  57. /* MIDI IN MESSAGE REPORTING */
  58. static void onMidiError(int8_t errCode) {
  59.   Serial.printf("MIDI Errors: %s %s %s\r\n", (errCode & (1UL << ErrorParse)) ? "Parse" : "",
  60.                 (errCode & (1UL << ErrorActiveSensingTimeout)) ? "Active Sensing Timeout" : "",
  61.                 (errCode & (1UL << WarningSplitSysEx)) ? "Split SysEx" : "");
  62. }
  63. int last_cc_cntrl = 1;
  64.  
  65. static void onControlChange(Channel channel, byte controller, byte value) {
  66.   MIDIusb.sendControlChange(controller, value, userChannel);
  67.   MIDIuart.sendControlChange(controller, value, userChannel);
  68.   Serial.printf("Ch %u CC#%u=%u\r\n", userChannel, controller, value);
  69.   if (last_cc_cntrl != controller) {
  70.     display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
  71.     display.setTextWrap(false);
  72.     display.setCursor(0, 12);
  73.     display.printf("CC# %u                \r\n", controller);
  74.     display.display();
  75.     last_cc_cntrl = controller;
  76.   }
  77. }
  78.  
  79. static void onMidiClock() {
  80.   Serial.printf("Clock\r\n");
  81.   MIDIusb.sendClock();
  82.   MIDIuart.sendClock();
  83. }
  84.  
  85. static void onMidiStart() {
  86.   Serial.printf("Start\r\n");
  87.   MIDIusb.sendStart();
  88.   MIDIuart.sendStart();
  89. }
  90.  
  91. static void onMidiContinue() {
  92.   Serial.printf("Cont\r\n");
  93.   MIDIusb.sendContinue();
  94.   MIDIuart.sendContinue();
  95. }
  96.  
  97. static void onMidiStop() {
  98.   Serial.printf("Stop\r\n");
  99.   MIDIusb.sendStop();
  100.   MIDIuart.sendStop();
  101. }
  102.  
  103. static void onActiveSense() {
  104.   Serial.printf("ASen\r\n");
  105. }
  106.  
  107. static void onSystemReset() {
  108.   Serial.printf("SysRst\r\n");
  109. }
  110.  
  111. static void onMidiTick() {
  112.   Serial.printf("Tick\r\n");
  113. }
  114.  
  115. static void onMidiInWriteFail(uint8_t devAddr, uint8_t cable, bool fifoOverflow) {
  116.   if (fifoOverflow)
  117.     Serial.printf("Dev %u cable %u: MIDI IN FIFO overflow\r\n", devAddr, cable);
  118.   else
  119.     Serial.printf("Dev %u cable %u: MIDI IN FIFO error\r\n", devAddr, cable);
  120. }
  121.  
  122. static void registerMidiInCallbacks() {
  123.   auto intf = usbhMIDI.getInterfaceFromDeviceAndCable(midiDevAddr, 0);
  124.   if (intf == nullptr)
  125.     return;
  126.   intf->setHandleControlChange(onControlChange);  // 0xB0
  127.   intf->setHandleClock(onMidiClock);              // 0xF8
  128.   // 0xF9 as 10ms Tick is not MIDI 1.0 standard but implemented in the Arduino MIDI Library
  129.   intf->setHandleTick(onMidiTick);              // 0xF9
  130.   intf->setHandleStart(onMidiStart);            // 0xFA
  131.   intf->setHandleContinue(onMidiContinue);      // 0xFB
  132.   intf->setHandleStop(onMidiStop);              // 0xFC
  133.   intf->setHandleActiveSensing(onActiveSense);  // 0xFE
  134.   intf->setHandleSystemReset(onSystemReset);    // 0xFF
  135.   intf->setHandleError(onMidiError);
  136.  
  137.   auto dev = usbhMIDI.getDevFromDevAddr(midiDevAddr);
  138.   if (dev == nullptr)
  139.     return;
  140.   dev->setOnMidiInWriteFail(onMidiInWriteFail);
  141. }
  142.  
  143. /* CONNECTION MANAGEMENT */
  144. static void onMIDIconnect(uint8_t devAddr, uint8_t nInCables, uint8_t nOutCables) {
  145.   Serial.printf("MIDI device at address %u has %u IN cables and %u OUT cables\r\n", devAddr, nInCables, nOutCables);
  146.   midiDevAddr = devAddr;
  147.   registerMidiInCallbacks();
  148. }
  149.  
  150. static void onMIDIdisconnect(uint8_t devAddr) {
  151.   Serial.printf("MIDI device at address %u unplugged\r\n", devAddr);
  152.   midiDevAddr = 0;
  153. }
  154.  
  155. /* MAIN LOOP FUNCTIONS */
  156.  
  157. static void blinkLED(void) {
  158.   const uint32_t intervalMs = 1000;
  159.   static uint32_t startMs = 0;
  160.  
  161.   static bool ledState = false;
  162.   if (millis() - startMs < intervalMs)
  163.     return;
  164.   startMs += intervalMs;
  165.  
  166.   ledState = !ledState;
  167.   digitalWrite(LED_BUILTIN, ledState ? HIGH : LOW);
  168. }
  169.  
  170. // core1's setup
  171. void setup1() {
  172. #if ARDUINO_ADAFRUIT_FEATHER_RP2040_USB_HOST
  173.   pinMode(18, OUTPUT);  // Sets pin USB_HOST_5V_POWER to HIGH to enable USB power
  174.   digitalWrite(18, HIGH);
  175. #endif
  176.  
  177.   // while(!Serial);   // wait for native usb
  178.   Serial.println("Core1 setup to run TinyUSB host with pio-usb\r\n");
  179.  
  180.   // Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
  181.   uint32_t cpu_hz = clock_get_hz(clk_sys);
  182.   if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
  183.     delay(2000);  // wait for native usb
  184.     Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
  185.     Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
  186.     while (1)
  187.       delay(1);
  188.   }
  189.  
  190.   pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
  191.   pio_cfg.pin_dp = HOST_PIN_DP;
  192.  
  193.   USBHost.configure_pio_usb(1, &pio_cfg);
  194.   // run host stack on controller (rhport) 1
  195.   // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
  196.   // host bit-banging processing work done in core1 to free up core0 for other work
  197.   usbhMIDI.begin(&USBHost, 1, onMIDIconnect, onMIDIdisconnect);
  198.   core1_booting = false;
  199.   while (core0_booting)
  200.     ;
  201. }
  202.  
  203. // core1's loop
  204. void loop1() {
  205.   USBHost.task();
  206. }
  207.  
  208. void setup() {
  209.   TinyUSBDevice.setManufacturerDescriptor("LarsCo");
  210.   TinyUSBDevice.setProductDescriptor("MIDI Masseuse");
  211.   Serial.begin(115200);
  212.   if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
  213.     Serial.println(F("SSD1306 allocation failed"));
  214.     for (;;)
  215.       ;  // Don't proceed, loop forever
  216.   }
  217.  
  218.   // Show initial display buffer contents on the screen --
  219.   // the library initializes this with an Adafruit splash screen.
  220.   display.display();
  221.   delay(2000);  // Pause for 2 seconds
  222.   // Clear the buffer
  223.   display.clearDisplay();
  224.   display.display();
  225.  
  226.   display.setTextSize(1);
  227.   display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
  228.   display.setCursor(0, 0);
  229.   display.print("USB MIDI Messenger");
  230.   display.setCursor(0, 12);
  231.   display.print("Ch x > 1  Note_ CC#_\r\n");
  232.   display.setCursor(0, 24);
  233.   display.printf("Progs %u-%u     \r\n", userProgOffset, (userProgOffset + 7));
  234.   display.display();
  235.  
  236.   pinMode(buttonAPin, INPUT_PULLUP);
  237.   pinMode(buttonBPin, INPUT_PULLUP);  // OLED button B as a 100k pullup on it on 128x32 FW
  238.   pinMode(buttonCPin, INPUT_PULLUP);
  239.  
  240.   MIDIusb.begin();
  241.   MIDIusb.turnThruOff();  // turn off echo
  242.  
  243.   MIDIuart.begin(MIDI_CHANNEL_OMNI);  // don't forget OMNI
  244.  
  245.   //     while(!Serial);   // wait for serial port
  246.   pinMode(LED_BUILTIN, OUTPUT);
  247.   Serial.println("USB Host to MIDI Messenger\r\n");
  248.   core0_booting = false;
  249.   while (core1_booting)
  250.     ;
  251. }
  252.  
  253. void loop() {
  254.   // Handle any incoming data; triggers MIDI IN callbacks
  255.   usbhMIDI.readAll();
  256.   // Do other processing that might generate pending MIDI OUT data
  257.  
  258.   // Tell the USB Host to send as much pending MIDI OUT data as possible
  259.   usbhMIDI.writeFlushAll();
  260.  
  261.   // Do other non-USB host processing
  262.   blinkLED();
  263.  
  264.   int readingA = digitalRead(buttonAPin);
  265.   int readingB = digitalRead(buttonBPin);
  266.   int readingC = digitalRead(buttonCPin);
  267.  
  268.   if (readingA != lastButtonAState) {
  269.     lastDebounceATime = millis();
  270.   }
  271.   if (readingB != lastButtonBState) {
  272.     lastDebounceBTime = millis();
  273.   }
  274.   if (readingC != lastButtonCState) {
  275.     lastDebounceCTime = millis();
  276.   }
  277.  
  278.   if ((millis() - lastDebounceATime) > debounceDelay) {
  279.     if (readingA != buttonAState) {
  280.       buttonAState = readingA;
  281.  
  282.       if (buttonAState == LOW)  // Botão pressionado
  283.       {
  284.         onControlChange(1, 48, 127);
  285.         Serial.printf("PRE ON");
  286.         display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
  287.         display.setCursor(0, 12);
  288.         display.printf("CC 48 = 127");
  289.         display.display();
  290.       } else if (buttonAState == HIGH)  // Botão solto
  291.       {
  292.         onControlChange(1, 48, 0);
  293.         Serial.printf("PRE OFF");
  294.         display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
  295.         display.setCursor(0, 12);
  296.         display.printf("CC 48 = 0 ");
  297.         display.display();
  298.       }
  299.     }
  300.   }
  301.  
  302.   lastButtonAState = readingA;
  303.   lastButtonBState = readingB;
  304.   lastButtonCState = readingC;
  305. }
  306.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement