Would like help modifying a line in example

I'm trying to send MIDI over USB through a host shield, and it works if I use the exact command in the example file (big surprise):

Midi.SendData((uint8_t*)"\xc0\x02");

but I need to replace the x02 with a variable. I've tried everything I can think of, but the bottom line is that I don't understand why the message itself is in quotations, or how to make a portion of the message be a variable. All my attempts have either not compiled or not worked.

Any advice would be hugely appreciated.

Make an array:

uint8_t cmdNL[ ] = { 0xc0, 0x02, 0x0a }       // see if this works below or...
uint8_t cmdLF[ ] = { 0xc0, 0x02, 0x0d }       // ...see if this works below
                                              // ('m not sure about the string terminator)
Midi.SendData( (uint8_t*)cmdNL);              // one of these should...
Midi.SendData( (uint8_t*)cmdLF);              // ...reproduce your example code

// So, which ever one worked, use that array and do:
cmdXX[1] = 0xff;     // to replace the 0x02 (0xff of course is what ever code you really want)

unsigned char var = <whatever>;     // if you really need a variable
cmdXX[1] = var;

MIDI doesn’t use CR or LF at the end of a message.

uint8_t midi_cmd[3] = {0xC0, 0x02, 0};
uint8_t program_number;

program_number = 4;

// Change program number to 4
midi_cmd[1] = program_number;

Midi.SendData(midi_cmd);

Pete

P.S. Which MIDI library are you using? I can't find a SendData method.

Pete

Thanks for the help, guys! It looks like the concept I was missing was to use an array to make the message include multiple values.

The library I am using is USB Host Shield 2.0 from felis at github.

Looks like the library figures out the length of the message. In this specific case, 0xC0 is a Program Change message which is two bytes long, so the null at the end isn't required. If you were sending a Note On, for example, it would need to be 3 bytes long.

Pete

I gave the above code a shot just before bed (much to my wife's disdain), and it didn't work, so I'll give it some monkeying tomorrow, given your latest advice. Now I'll be armed with a bit more of an idea of what to look for while snoodging through the library.

Came back to fix that. What the hell was I thinking?

okay, here’s the latest attempt:

void SendMIDI(byte patchNumber)             // function that gets called in the loop
{ Usb.Task(); 
    uint8_t midi_cmd[2] = {0xC0, 0x01};
    midi_cmd[1] = patchNumber;
    Midi.SendData(midi_cmd);
    delay(10);  
}

   // This is one of the Button Push If statements in the loop code.

   if(patchPinValPrev < 30)
   { if(patchPinVal > 0)
      { if(patchPinVal >= (40 - variance) && patchPinVal <= (40 + variance))          
                                                  // if Patch 4 button was pushed
        { prog = bank * 4 + 3;          // a bank is 4 programs, so multiply the bank by 4 and add 3.
          segWrite(prog);                  //   function that drives 7segment display (works)
           
          SendMIDI(prog);
        }

The 7 Segment display is working fine, so the problem can be narrowed down to the SendMIDI function.

Got it working!

It's always the little things, right?

I had to change: Midi.SendData(midi_cmd);

to: Midi.SendData((uint8_t*)midi_cmd);

You were right, boolrules, although I have no idea what the difference is. Would anyone mind explaining why the (uint8_t*) has to be included in the message, and what the asterisk is for? I thought the message itself was declared as a uint8_t in the function.

In case anyone in the future looks through this thread for advice,

The line of code: Usb.Task();

Has to be moved to the main loop. I had it in the function for sending a message, and that made the arduino reset after sending each message.

For anyone who might care, here is what the code is doing: https://youtu.be/I1dUdkRuq4c

I don't think the uint8_t is required there. It should be part of the function prototype, but you don't see those in Arduino :( Look in the Midi lib.for the reason why. (It's probably a void type there.) Sorry, I don't know anything about the USB lib.

The library declares the first argument as uint8_t *dataptr. If you declared midi_cmd the same way I did:

uint8_t midi_cmd[3] = {0xC0, 0x02, 0};

then midi_cmd is implicitly (uint8_t *), in which case I don't know why you had to cast the argument to (uint8_t *).

Pete

The asterisk says that midi_cmd is a pointer to at least one (usually an array of) uint8_t item.

Pete

I don't think I messed it up by making it 2 bytes long instead of three, but it definitely didn't work until I added the extra (uint8_t*) into the SendData message.

This is it now, functioning beautifully:

void SendMIDI(byte PatchNumber)             
{  if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
   {  uint8_t midi_cmd[2] = {0xC0, 0x01};      
      midi_cmd[1] = PatchNumber;              
      Midi.SendData((uint8_t*)midi_cmd);      
      delay(10); 
   } 
}