I need a sharp set of eyes Please! Serial to Midi conversion

Hey peeps, so I've got this sketch here that I was hoping someone could let me know if I'm missing something... I've got a controller connected to Serial3 which most of the code revolves around, but I am looking to add another controller to Serial1. Data is sending and receiving between the existing controller and Serial3 just fine, but for some reason, the second controller, connected to Serial1 isn't transmitting data out of Serial0 like the other one is sucessfully doing.

I suspect it has to do with the messages sending from the second controller being 'NoteOff' messages, additionally, it appears that this second controller is only sending 2 byte messages. In this case, I am trying to program only one button push, the controller sends 0x80 0x44. Look for "void PTHandleNoteOff":

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, controller);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, transport);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, pt);

byte lastChannel = 0;
byte pp[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

void ControllerHandleCC(byte channel, byte pitch, byte velocity) {
  //Mute Press
  if(pitch == 0x46 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-1,1);
    pt.send(midi::ControlChange,0x2F,0x42,1);
  }
  //Solo Press
  else if(pitch == 0x47 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-1,1);
    pt.send(midi::ControlChange,0x2F,0x43,1);
  }
  //Fader first
  else if(pitch == 0x07)
  {
    pp[channel-0x01] = velocity;
  }
  //Fader second
  else if(pitch == 0x27)
  {
    byte qq = velocity;
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x40,1);
    pt.send(midi::ControlChange,channel-0x01,pp[channel-0x01],1);
    pt.send(midi::ControlChange,channel-0x01+0x20,qq,1);
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x00,1);
    pp[channel-0x01] = 0x00;
  }
  //Select Press Ch
  else if(pitch == 0x49 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x41,1);
  }
  //Rec Press Ch
  else if(pitch == 0x48 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x47,1);
  }
  //Send Flip
  else if((pitch == 0x70 || pitch == 0x71 || pitch == 0x72 || pitch == 0x73) && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0B,1);
    pt.send(midi::ControlChange,0x2F,0x44 + 0x73 - pitch,1);
    pt.send(midi::ControlChange,0x0F,0x0C,1);
    pt.send(midi::ControlChange,0x2F,0x43,1);
  }
  else
  {
    // Conversion rules are not defined -> ignore    
    // pt.send(midi::ControlChange,pitch,velocity,1);
  }
}

void PTHandleCC(byte channel, byte pitch, byte velocity) {
  //Effect Control
  if(pitch == 0x0C)
  {
    lastChannel = velocity + 1;
  }
  else if(pitch == 0x2C)
  {
    if (lastChannel > 0x08)
      // Out of range -> ignore pair
      return;
      
    byte data1, data2;
    
    //Mute Press Ch
    if(velocity == 0x42)
    {
      data1 = 0x46;
      data2 = 0x7F;
    }
    else if(velocity == 0x02)
    {
      data1 = 0x46;
      data2 = 0x00;
    }
    //Solo Press Ch
    else if(velocity == 0x43)
    {
      data1 = 0x47;
      data2 = 0x7F;
    }
    else if(velocity == 0x03)
    {
      data1 = 0x47;
      data2 = 0x00;
    }
    //Select Press Ch
    else if(velocity == 0x41)
    {
      data1 = 0x49;
      data2 = 0x7F;
    }
    else if(velocity == 0x01)
    {
      data1 = 0x49;
      data2 = 0x00;
    }
    //Rec Press Ch
    else if(velocity == 0x47)
    {
      data1 = 0x48;
      data2 = 0x7F;
    }
    else if(velocity == 0x07)
    {
      data1 = 0x48;
      data2 = 0x00;
    } 
    else
      // Conversion rules are not defined -> ignore
      return;
    
    controller.send(midi::ControlChange,data1,data2,lastChannel);
  }
  else if(pitch == 0x00 || pitch == 0x01 || pitch == 0x02 || pitch == 0x03 || pitch == 0x04 || pitch == 0x05 || pitch == 0x06 || pitch == 0x07)
  {
    controller.send(midi::ControlChange,0x07,velocity,pitch + 0x01);
  }
  else if(pitch == 0x20 || pitch == 0x21 || pitch == 0x22 || pitch == 0x23 || pitch == 0x24 || pitch == 0x25 || pitch == 0x26 || pitch == 0x27)
  {
    controller.send(midi::ControlChange,0x27,velocity,pitch - 0x20 + 0x01);
  }
  else
  {
    // Conversion rules are not defined -> ignore
    // controller.send(midi::ControlChange,pitch,velocity,1);
  }
}

void PTHandleNoteOff(byte channel, byte pitch, byte velocity) {

    if(pitch == 0x44)
 {
    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x44,1);
 }
}

void setup()
{
    // Initiate MIDI communications, listen to all channels
    controller.begin(MIDI_CHANNEL_OMNI);
    transport.begin(MIDI_CHANNEL_OMNI);
    pt.begin(MIDI_CHANNEL_OMNI);
    
    Serial3.begin(38400);
    Serial1.begin(9600);
    
    controller.setThruFilterMode(midi::Off);
    pt.setThruFilterMode(midi::Off);
    transport.setThruFilterMode(midi::Off);

    pt.setHandleControlChange(PTHandleCC);
    transport.setHandleNoteOff(PTHandleNoteOff);
        
    controller.setHandleControlChange(ControllerHandleCC);

}

void loop()
{
  controller.read();
  transport.read();
  pt.read();
}

This data type worries me, as a byte can only hold 8 bits, or a maximum integer value of 255.

byte pp[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

But you are trying to assign hex values (okay, they are set 0, but ...) which holds 16 bits or a max integer of 65535

This is a type mismatch.

If you want to use hex vaules, you should use the type word, not byte.

Anders53:
If you want to use hex vaules, you should use the type word, not byte.

I don't completely understand, could you give me an alternative example?

Anders53:
This data type worries me, as a byte can only hold 8 bits, or a maximum integer value of 255.

byte pp[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

But you are trying to assign hex values (okay, they are set 0, but ...) which holds 16 bits or a max integer of 65535

This is a type mismatch.

If you want to use hex vaules, you should use the type word, not byte.

No, the 0x is just a prefix symbol. Two hex digits such as 00 make a byte.
But you can just say

byte pp[8] = {0};

and be done with it.

but for some reason, the second controller, connected to Serial1 isn't transmitting data out of Serial0 like the other one is sucessfully doing.

Why would the device connected to Serial1 transmit data out of Serial? It looks to me like the device connected to Serial1 should transmit SOME data coming in on Serial.

Why do you call Serial1.begin() and Serial3.begin() in setup(), but not Serial.begin()?

The Mega is configured with Hiduino, it shows up as a midi device on my PC, and it automatically reads and transmits any data on Serial0. Serial3 is transmitting and receiving from Serial0,and I am looking to do the same with Serial1...

    pt.setHandleControlChange(PTHandleCC);
    transport.setHandleNoteOff(PTHandleNoteOff);
        
    controller.setHandleControlChange(ControllerHandleCC);

Why the differences?

I suspect it has to do with the messages sending from the second controller being 'NoteOff' messages,

Because that is the only type of messages you deal with, on Serial1. And, only for one pitch.

additionally, it appears that this second controller is only sending 2 byte messages.

These two?

    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x44,1);

Something is confusing me. So, the controller TX Rx is connected to Serial1. Its output is sending the 2 byte message {0x80 0x44} out to Serial1. When the arduino sees that message, it needs to send out of Serial0;

pt.send(midi::ControlChange,0x0F,0x0E,1);
pt.send(midi::ControlChange,0x2F,0x44,1);

pt.send will send the message out USB to the PC, only if it receives 0x80 0x44.

Like here, the controller connected to Serial3 reads 0x46 0x7F and sends it's pt.send message to Serial0

void ControllerHandleCC(byte channel, byte pitch, byte velocity) {
//Mute Press
if(pitch == 0x46 && velocity == 0x7F)
{
pt.send(midi::ControlChange,0x0F,channel-1,1);
pt.send(midi::ControlChange,0x2F,0x42,1);

How would Serial1 or Serial3 know to receive Serial0, and send out data, not just echoing data to Serial0?

controller.send

transport.setThruFilterMode(midi::Off);

This line tells the driver that you are going to handle all incoming messages by yourself.

Dang. Very frustrating... I really feel like i've got this set up right. If I code

if (Serial1.available() > 0){
    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x44,1);

I receive the signal from Serial1 and it outputs Serial0 like it should. But if I try to be specific, it doesn't go:

void TransportHandleNoteOff(byte channel, byte pitch, byte velocity){
    //Play Transport Button
  if (pitch == 0x44 && velocity == 0x00){
   
    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x44,1);
    }

}

Here's the sketch again... i've been making changes so hopefully it's really just a simple error somewhere :slightly_frowning_face:

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, controller);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, transport);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, pt);

int ledPin =  13;

int ledState = LOW;//current state of the LED
unsigned long timeOfLastLedEvent = 0;//the last time the LED was updated

int intervalON = 5;//how long we want the LED to stay on
int intervalOFF = 1;//how long we want the LED to stay off

byte lastChannel = 0;
byte ct_pp[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
byte tr_pp[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

void ControllerHandleCC(byte channel, byte pitch, byte velocity) {
  //Mute Press
  if(pitch == 0x46 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-1,1);
    pt.send(midi::ControlChange,0x2F,0x42,1);
  }
  //Solo Press
  else if(pitch == 0x47 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-1,1);
    pt.send(midi::ControlChange,0x2F,0x43,1);
  }
  //Fader first
  else if(pitch == 0x07)
  {
    ct_pp[channel-0x01] = velocity;
  }
  //Fader second
  else if(pitch == 0x27)
  {
    byte qq = velocity;

    pt.send(midi::ControlChange,channel-0x01,ct_pp[channel-0x01],1);
    pt.send(midi::ControlChange,channel-0x01+0x20,qq,1);

    ct_pp[channel-0x01] = 0x00;
  }
  //Select Press Ch
  else if(pitch == 0x49 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x41,1);
  }
  //Rec Press Ch
  else if(pitch == 0x48 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x47,1);
  }
     //Fader Touch
  else if(pitch == 0x4A && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x40,1);
  }
     //Fader Release
  else if(pitch == 0x4A && velocity == 0x00)
  {
    pt.send(midi::ControlChange,0x0F,channel-0x01,1);
    pt.send(midi::ControlChange,0x2F,0x00,1);
  }
    //Master Rec Press
  else if(pitch == 0x73 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x45,1);
  }
    //Master Play Press
  else if(pitch == 0x72 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x44,1);
  }
      //Master Stop Press
  else if(pitch == 0x71 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0D,1);
    pt.send(midi::ControlChange,0x2F,0x46,1);
        controller.send(midi::ControlChange,0x71,0x7F,1);
    delay(800);
    controller.send(midi::ControlChange,0x71,0x00,1);
  }
                    //Loop
  else if(pitch == 0x70 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0D,1);
    pt.send(midi::ControlChange,0x2F,0x45,1);
    controller.send(midi::ControlChange,0x70,0x7F,1);
    delay(800);
    controller.send(midi::ControlChange,0x70,0x00,1);
  }
  

      //Channel Bank Left
  else if(pitch == 0x79 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0A,1);
    pt.send(midi::ControlChange,0x2F,0x40,1);
  }
        //Channel Bank Right
  else if(pitch == 0x7A && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0A,1);
    pt.send(midi::ControlChange,0x2F,0x42,1);
  }

  else
  {
    // Conversion rules are not defined -> ignore    
    // pt.send(midi::ControlChange,pitch,velocity,1);
  }
}

void PTHandleCC(byte channel, byte pitch, byte velocity) {
//----------------------------------------------------------------------------------  
  //Master Record
  if(pitch == 0x2C && velocity == 0x45)
  {
    controller.send(midi::ControlChange,0x73,0x7F,1);
  }
  else if(pitch == 0x2C && velocity == 0x05)
  {
    controller.send(midi::ControlChange,0x73,0x00,1);
  }
    //Master Play
  if(pitch == 0x2C && velocity == 0x44)
  {
    controller.send(midi::ControlChange,0x72,0x7F,1);
  }
  else if(pitch == 0x2C && velocity == 0x04)
  {
    controller.send(midi::ControlChange,0x72,0x00,1);
  }
      //Master Stop
  if((pitch == 0x0C && velocity == 0x0E)&&(pitch == 0x2C && velocity == 0x43))
  {
    controller.send(midi::ControlChange,0x71,0x7F,1);
  }
  else if((pitch == 0x0C && velocity == 0x0E)&&(pitch == 0x2C && velocity == 0x03))
  {
    controller.send(midi::ControlChange,0x71,0x00,1);
  }

//-------------------------------------------------------------------    
    
   //Effect Control
  else if(pitch == 0x0C)
  {
    lastChannel = velocity + 1;
  }
  else if(pitch == 0x2C)
  {
    if (lastChannel > 0x08)
      // Out of range -> ignore pair
      return;
      
    byte data1, data2;
    
    //Mute Press Ch
    if(velocity == 0x42)
    {
      data1 = 0x46;
      data2 = 0x7F;
    }
    else if(velocity == 0x02)
    {
      data1 = 0x46;
      data2 = 0x00;
    }
    //Solo Press Ch
    else if(velocity == 0x43)
    {
      data1 = 0x47;
      data2 = 0x7F;
    }
    else if(velocity == 0x03)
    {
      data1 = 0x47;
      data2 = 0x00;
    }
    //Select Press Ch
    else if(velocity == 0x41)
    {
      data1 = 0x49;
      data2 = 0x7F;
    }
    else if(velocity == 0x01)
    {
      data1 = 0x49;
      data2 = 0x00;
    }
    //Rec Press Ch
    else if(velocity == 0x47)
    {
      data1 = 0x48;
      data2 = 0x7F;
    }
    else if(velocity == 0x07)
    {
      data1 = 0x48;
      data2 = 0x00;
    } 
    else
      // Conversion rules are not defined -> ignore
      return;
    
    controller.send(midi::ControlChange,data1,data2,lastChannel);
  }
  else if(pitch == 0x00 || pitch == 0x01 || pitch == 0x02 || pitch == 0x03 || pitch == 0x04 || pitch == 0x05 || pitch == 0x06 || pitch == 0x07)
  {
    controller.send(midi::ControlChange,0x07,velocity,pitch + 0x01);
  }
  else if(pitch == 0x20 || pitch == 0x21 || pitch == 0x22 || pitch == 0x23 || pitch == 0x24 || pitch == 0x25 || pitch == 0x26 || pitch == 0x27)
  {
    controller.send(midi::ControlChange,0x27,velocity,pitch - 0x20 + 0x01);
  }
  else
  {
    // Conversion rules are not defined -> ignore
    // controller.send(midi::ControlChange,pitch,velocity,1);
  }
}


void TransportHandleNoteOff(byte channel, byte pitch, byte velocity){
    //Play Transport Button
  if (pitch == 0x44 && velocity == 0x00){
   
    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x44,1);
    }

}


void setup()
{
    // Initiate MIDI communications, listen to all channels
    controller.begin(MIDI_CHANNEL_OMNI);
    transport.begin(MIDI_CHANNEL_OMNI);
    pt.begin(MIDI_CHANNEL_OMNI);
    
      pinMode(ledPin, OUTPUT);  
      digitalWrite(ledPin, ledState); 
    
    Serial3.begin(38400);
    Serial1.begin(300);
    
    controller.setThruFilterMode(midi::Off);
    transport.setThruFilterMode(midi::Off);
    pt.setThruFilterMode(midi::Off);

    pt.setHandleControlChange(PTHandleCC);
    
    transport.setHandleNoteOff(TransportHandleNoteOff);
    
    controller.setHandleControlChange(ControllerHandleCC);
  
}

void loop()
{
  controller.read();
  transport.read();
  pt.read();
  
      unsigned long currentMillis = millis();
  
  if (Serial.available() > 0){//if the LED is already off
    if (currentMillis - timeOfLastLedEvent > intervalOFF){//and enough time has passed
      digitalWrite(ledPin, HIGH);//turn it on
      ledState = HIGH;//store its current state
      timeOfLastLedEvent = currentMillis;//update the time of this new event
    }
  } else {//if the LED is already on
    if (currentMillis - timeOfLastLedEvent > intervalON){
      digitalWrite(ledPin, LOW);
      ledState = LOW;
      timeOfLastLedEvent = currentMillis;
    }
  }
}

ibanman555:
The Mega is configured with Hiduino, it shows up as a midi device on my PC, and it automatically reads and transmits any data on Serial0. Serial3 is transmitting and receiving from Serial0,and I am looking to do the same with Serial1...

You can't turn Serial3 into a USB HID MIDI device. That package works only on the USB / serial processor not the Arduino processor.

I didn't say I was

Grumpy_Mike:
You can't turn Serial3 into a USB HID MIDI device. That package works only on the USB / serial processor not the Arduino processor.

I didn't say I was. I understand how Hiduino works, and since the 16u2 is connected to Serial0 I/O it sends and receives midi data from the USB <> Mega. The sketch works as it should 100% with the exclusion of anything "transport". That's what I'm trying to figure out.

If you're saying you can't receive serial data from Serial3 and output Serial0/usb, this is proof you can.

I have tried my old eyes on your code.

I had to reformat it, otherwise I got lost in your data setup if structures.
Look at the code, its easier to read than explaining a lot.
I found a few curly brackets which I really were in doubt where they belonged.
It could have been one problem.
I tried my best to section it correct, and that is where you should examine the code.

I just hate to use locals and declares in the middle of the code.
Therefore I moved all variable declarations up as globals.
The functions and calls were corrected accordingly, as you dont need to transfer global parameters between functions.
They are already known where ever you are in your code.

A few if statements were modified to a range decision, rather than a long list of expressions.
Time intervals are always in mS, when using millis().
It looks like you have interpreted this in Seconds, as the LED state was never changed long enough to see it.

The - // (any text or code) - structure comments out to end of that single line only

If you want to comment out a section of code you should use this structure

/*
(any number of lines containing text or code)
*/

Pls report back and knock me down, I'm still on the steep part of my code learning curve, but really want to help.

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, controller);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, transport);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, pt);

const byte ledPin                = 13;    // LED out on pin 13
const int intervalON             = 5000;  // how long we want the LED to stay on in mS
const int intervalOFF            = 1000;  // how long we want the LED to stay off in mS
byte lastChannel                 = 0;
byte channel, pitch, velocity    = 0;
byte qq, data1, data2            = 0;
boolean ledState                 = LOW;   //current state of the LED
unsigned long timeOfLastLedEvent = 0;     // the last time in mS the LED was updated
unsigned long currentMillis      = 0;     // holds timer value in mS

byte ct_pp[]                     = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
byte tr_pp[]                     = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

void setup()
{
  // *** Initiate MIDI communications, listen to all channels
  controller.begin(MIDI_CHANNEL_OMNI);
  transport.begin(MIDI_CHANNEL_OMNI);
  pt.begin(MIDI_CHANNEL_OMNI);
  
  pinMode(ledPin, OUTPUT);  
  digitalWrite(ledPin, ledState); 
  
  Serial3.begin(38400);
  Serial1.begin(300);
  Serial.begin(9600);
  
  controller.setThruFilterMode(midi::Off);
  transport.setThruFilterMode(midi::Off);
  pt.setThruFilterMode(midi::Off);

  pt.setHandleControlChange(PTHandleCC);
  transport.setHandleNoteOff(TransportHandleNoteOff);
  controller.setHandleControlChange(ControllerHandleCC);
}

void loop()
{
  controller.read();
  transport.read();
  pt.read();
  currentMillis = millis();
  
  if (Serial.available() > 0)
  {                                                         // if the LED is already off
    if (currentMillis - timeOfLastLedEvent > intervalOFF)   // and enough time has passed
    {                                                       
      digitalWrite(ledPin, HIGH);                           // turn it on
      ledState = HIGH;                                      // store its current state
      timeOfLastLedEvent = currentMillis;                   // update the time of this new event
    }
  } 
  else
  {                                                         // if the LED is already on
    if (currentMillis - timeOfLastLedEvent > intervalON)    // and enough time has passed
    {
      digitalWrite(ledPin, LOW);                            // turn it off
      ledState = LOW;                                       // store its current state
      timeOfLastLedEvent = currentMillis;                   // update the time of this new event
    }
  }
}

void ControllerHandleCC()
{
  // *** Mute Press
  if(pitch == 0x46 && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,channel-1,1); pt.send(midi::ControlChange,0x2F,0x42,1);}

  // *** Solo Press
  else if(pitch == 0x47 && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,channel-1,1); pt.send(midi::ControlChange,0x2F,0x43,1);}

  // *** Fader first
  else if(pitch == 0x07) ct_pp[channel-0x01] = velocity;

  // *** Fader second
  else if(pitch == 0x27)
  {
    qq = velocity;
    pt.send(midi::ControlChange,channel-0x01,ct_pp[channel-0x01],1);
    pt.send(midi::ControlChange,channel-0x01+0x20,qq,1);
    ct_pp[channel-0x01] = 0x00;
  }

  // *** Select Press Ch
  else if(pitch == 0x49 && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,channel-0x01,1); pt.send(midi::ControlChange,0x2F,0x41,1);}

  // *** Rec Press Ch
  else if(pitch == 0x48 && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,channel-0x01,1); pt.send(midi::ControlChange,0x2F,0x47,1);}

  // *** Fader Touch
  else if(pitch == 0x4A && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,channel-0x01,1); pt.send(midi::ControlChange,0x2F,0x40,1);}

  // *** Fader Release
  else if(pitch == 0x4A && velocity == 0x00){pt.send(midi::ControlChange,0x0F,channel-0x01,1); pt.send(midi::ControlChange,0x2F,0x00,1);}

  // *** Master Rec Press
  else if(pitch == 0x73 && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,0x0E,1); pt.send(midi::ControlChange,0x2F,0x45,1);}

  // *** Master Play Press
  else if(pitch == 0x72 && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,0x0E,1); pt.send(midi::ControlChange,0x2F,0x44,1);}

  // *** Master Stop Press
  else if(pitch == 0x71 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0D,1);
    pt.send(midi::ControlChange,0x2F,0x46,1);
    controller.send(midi::ControlChange,0x71,0x7F,1);
    delay(800);
    controller.send(midi::ControlChange,0x71,0x00,1);
  }

  // *** Loop
  else if(pitch == 0x70 && velocity == 0x7F)
  {
    pt.send(midi::ControlChange,0x0F,0x0D,1);
    pt.send(midi::ControlChange,0x2F,0x45,1);
    controller.send(midi::ControlChange,0x70,0x7F,1);
    delay(800);
    controller.send(midi::ControlChange,0x70,0x00,1);
  }

  // *** Channel Bank Left
  else if(pitch == 0x79 && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,0x0A,1); pt.send(midi::ControlChange,0x2F,0x40,1);}
  
  // *** Channel Bank Right
  else if(pitch == 0x7A && velocity == 0x7F){pt.send(midi::ControlChange,0x0F,0x0A,1); pt.send(midi::ControlChange,0x2F,0x42,1);}
  
  // *** Conversion rules are not defined -> ignore
  // else pt.send(midi::ControlChange,pitch,velocity,1);
}

void PTHandleCC()
{
  // *** Master Record
  if(pitch == 0x2C && velocity == 0x45) controller.send(midi::ControlChange,0x73,0x7F,1);
  else if(pitch == 0x2C && velocity == 0x05) controller.send(midi::ControlChange,0x73,0x00,1);

  // *** Master Play
  if(pitch == 0x2C && velocity == 0x44) controller.send(midi::ControlChange,0x72,0x7F,1);
  else if(pitch == 0x2C && velocity == 0x04) controller.send(midi::ControlChange,0x72,0x00,1);

  // *** Master Stop
  if(pitch == 0x0C && velocity == 0x0E && pitch == 0x2C && velocity == 0x43) controller.send(midi::ControlChange,0x71,0x7F,1);
  else if(pitch == 0x0C && velocity == 0x0E && pitch == 0x2C && velocity == 0x03) controller.send(midi::ControlChange,0x71,0x00,1);

  // *** Effect Control
  else if(pitch == 0x0C) lastChannel = velocity + 1;
  
  else if(pitch == 0x2C)
  {
    // *** Out of range -> ignore pair
    if (lastChannel > 0x08) return;
        
    // *** Mute Press Ch
    if(velocity == 0x42) {data1 = 0x46; data2 = 0x7F;}
    else if(velocity == 0x02){data1 = 0x46; data2 = 0x00;}
    
    // *** Solo Press Ch
    else if(velocity == 0x43){data1 = 0x47; data2 = 0x7F;}
    else if(velocity == 0x03){data1 = 0x47; data2 = 0x00;}

    // *** Select Press Ch
    else if(velocity == 0x41){data1 = 0x49; data2 = 0x7F;}
    else if(velocity == 0x01){data1 = 0x49; data2 = 0x00;}
    
    // *** Rec Press Ch
    else if(velocity == 0x47){data1 = 0x48; data2 = 0x7F;}
    else if(velocity == 0x07){data1 = 0x48; data2 = 0x00;} 
    
    // ***   Conversion rules are not defined -> ignore
    else return;
    
    // ***  Conversion rules OK, send Midi data
    controller.send(midi::ControlChange,data1,data2,lastChannel);
  }
  
  else if(pitch >= 0x00 && pitch <= 0x07) controller.send(midi::ControlChange,0x07,velocity,pitch + 0x01);
  else if(pitch >= 0x20 && pitch <= 0x27) controller.send(midi::ControlChange,0x27,velocity,pitch - 0x20 + 0x01);

  // *** Conversion rules are not defined -> ignore
  // else controller.send(midi::ControlChange,pitch,velocity,1);
}

void TransportHandleNoteOff()
{
  // *** Play Transport Button
  if (pitch == 0x44 && velocity == 0x00)
  {
    pt.send(midi::ControlChange,0x0F,0x0E,1);
    pt.send(midi::ControlChange,0x2F,0x44,1);
  }
}

You do realize that you don't have to use hex values for absolutely everything?
As in:

  else if (pitch == 0x07) ct_pp[channel - 0x01] = velocity;

where the 0x01 is just changing from channel number to a zero indexed array, it is more indicative of the actual intent to say:

  else if (pitch == 0x07) ct_pp[channel - 1] = velocity;

Anders53:
I have tried my old eyes on your code.

Thanks so much my friend for helping and suggesting alternative methods of coding... I will test this.

aarg:
You do realize that you don't have to use hex values for absolutely everything?

I didn't realize, but that's OK as I'm sure it provides the same function either way, plus it's easier for me to keep track of since I choose to use full hex in my code.

Anders53:
Pls report back and knock me down, I'm still on the steep part of my code learning curve, but really want to help.

This isn't actually compiling for me...

I'm not certain which version of MIDI.h library you have imported ?
As your original code wont compile either this end.
I looked for general compiler errors, until I was stuck with the midi object names not defined.
And both sketches are stuck with these compiler errors.

About the on/off intervals - they are actually set to a few milliseconds in the loop ?
As I figured out its the time delay between each command sent to midi.
Which makes it nonsens to blink the LED slowly to see it.
It would instead light up continously on your original settings, indicating midi are active.

Oh yeah that makes sense. Which version of midi.h are you using? I think I should update :cold_sweat:

The led job in the loop is just there to illuminate pin 13 when there is activity on Serial0.Its is set as quickly as possible to illuminate the LED but prevent latency. Its just a novelty and will be deleted in the future.