USB MIDI with toggle for button mapping

Hello all. I am building a usb MIDI controller for making drum tracks to back my guitar recordings. I am using a Pro Micro and successfully made a prototype like a simple 10 button arcade fightstick or launchpad.
Here is the code I am using

/*
   Based on example code linked below by Arturo Guadalupi, 4/10/15

   Sparkfun Pro Micro board was used.

   http://www.arduino.cc/en/Tutorial/MidiDevice
*/

#include "MIDIUSB.h"
#include "PitchToNote.h"
#define NUM_BUTTONS  10

const int button1 = 2;
const int button2 = 3;
const int button3 = 4;
const int button4 = 5;
const int button5 = 6;
const int button6 = 7;
const int button7 = 8;
const int button8 = 9;
const int button9 = 10;
const int button10 = 14;
const int buttons[NUM_BUTTONS] = {button1, button2, button3, button4, button5, button6, button7, button8, button9, button10};
const byte notePitches[NUM_BUTTONS] = {pitchC2, pitchD2b, pitchD2, pitchE2b, pitchE2, pitchF2, pitchG2b, pitchG2, pitchA2b, pitchA2};

int notesTime[NUM_BUTTONS];
int pressedButtons = 0x00;
int previousButtons = 0x00;
int intensity;

void setup() {
  for (int i = 0; i < NUM_BUTTONS; i++)
    pinMode(buttons[i], INPUT_PULLUP);
}


void loop() {
  readButtons();
  playNotes();
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void readButtons()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (digitalRead(buttons[i]) == LOW)
    {
      bitWrite(pressedButtons, i, 1);
      delay(2);
    }
    else
      bitWrite(pressedButtons, i, 0);
  }
}

void playNotes()
{
  for (int i = 0; i < NUM_BUTTONS; i++)
  {
    if (bitRead(pressedButtons, i) != bitRead(previousButtons, i))
    {
      if (bitRead(pressedButtons, i))
      {
        bitWrite(previousButtons, i , 1);
        noteOn(0, notePitches[i], 100);
        MidiUSB.flush();
      }
      else
      {
        bitWrite(previousButtons, i , 0);
        noteOff(0, notePitches[i], 0);
        MidiUSB.flush();
      }
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

Works fine. But now I want to add maybe a SPDT switch or another button to act as a “toggle” for the button mapping. Example is if button1 plays the C note, and then i press the toggle switch, now it changes mode and button1 now plays a different note.
How would you do this? I am a complete novice, I have only a vague understanding of code. I just copied the code I use. Any help is appreciated. Thank you!

So let's check. Do you mean you want to transpose all the buttons so 1 becomes say E and 2 becomes F, 3 is F# etc. And when you talk about 'modes' are there only two modes and the new button just switches between them?

You currently have C2 to A2 in semitones (I suspect that should really be C2-A3, but it's your controller). What are the pitches of the other mode?

Steve

Hi thanks for the reply. Yes the toggle just switches to two modes or maybe to make it much simpler, just switches up an octave and when press again switches back. im writing metal so i need quite a number of cymbals etc and some of them are mapped to a different octave, i am hardware restrained ATM hence only ten buttons and this is just a quick and dirty project of mine.

Thanks for noticing that it should be c2-a3. i will polish the code. anyway, yes if i toggle then button1 now becomes c3, button2 is d3b.. and so on.

Also which would be more practical in terms of coding it? a momentary button or an SPDT switch? i guess if i knew how to code id go with spdt switch, wire the 2 terminals to a pin each in the arduino, the middle pole wired to ground. and as long as one of the terminals is grounded then the buttons should be set to an octave, and vice versa. ANyway TIA

The SPDT switch is easy though it needs 2 pins. Your two switch positions could set a variable "transpose" to either 0 or 12 because to go up an octave you just need to add 12 to the note.. Then

        noteOn(0, notePitches[i], 100);

Change to

        noteOn(0, notePitches[i]+transpose, 100);

And change the noteOff similarly

That should do it. Or if you go with the button then each time it's pressed set transpose to 0 or 12, whichever it isn't now.

Steve

Thank you, that gives me a better idea how to do it. I'll look up how to set variables and where in the code it should go. Thanks!

update, i made it work. uses one pin and ground. switch will just act as on/off.
i used this and added it to the code.

int transpose;

void setup() {
  // put your setup code here, to run once:
pinMode (15, INPUT_PULLUP);

}

void loop() {
  // put your main code here, to run repeatedly:
    if (digitalRead(15) == LOW)
      {(transpose = 12);}
     else
     (transpose = 0);
}

thanks. these are the first lines of code that i wrote myself :slight_smile:

Congratulations. It's always a pleasure to meet someone who follows up on suggestions, thinks about them and then gets things working.

Steve

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.