Adding MIDI input to pre-MIDI synthesizer with matrix keyboard

Hi,

I am currently repairing an old pre-MIDI synthesizer which I’d like to add external MIDI control to. I’m just wondering if it’s possible with Arduino (it feels like something it should excel at but I’ve trawled through the forum and haven’t found any threads for MIDI ‘in’, so forgive me if this has been covered previously).

The synthesizer I’m working on has an 8x7 active-high keyboard matrix. Actually, it’s mostly a 8x6 matrix, however the top key (C) has its own data line. Lines KD1 to KD8 are select lines and lines B1 to B7 are data lines.

At the moment I’d just like to know whether this is possible and, if so, it’d be really helpful if I could be pointed towards any threads/resources which exist dealing with it.

Thanks!

EDIT: Thanks el_sepremo for the heads up - “‘there’s an error in the diagram. Where it says “Triggers all F and E across the KBD” it should say "F and B’.”

I’ve never tried to do this so can’t help with the specifics. But FYI I notice there’s an error in the diagram. Where it says “Triggers all F and E across the KBD” it should say “F and B”.

Pete

What do you mean by external MIDI control? Should the keyboard play notes when you send MIDI data to it, or should the keyboard output MIDI messages when you press a key?

Thanks for the replies, guys.

@PieterP: I'd like the synthesizer to respond to MIDI, not for the keyboard to output MIDI data. So, basically, a MIDI retrofit for the keyboard.

You may already be familiar with how keyboard matrices work, but just in case: The key scanner MPU in the synthesizer emits a regular 5V pulse along its Select lines. The select lines pulses are not emitted concurrently but at timing intervals relative to one another (e.g. at 20μS intervals). It also monitors on its Data lines for 5V (0V at default). When a key is depressed, the keyscanner receives 5V into its Data lines and it calculates which Select line the pulse is coming from.

So, say for example there are two Select lines and two Data lines and we have keys A1 and B1 on Select line 1 and keys A2 and B2 on select line 2. Both A keys are on Data line 1, and both B keys are on Data line 2. So when key A1 is depressed, the circuit is completed and the keyscanner receives a 5V pulse into Data line 1. It then checks which select line the pulse came from and assigns the note value to the synthesizer.

What I would like to do is use the Arduino to convert MIDI data into 5V pulses. However, it would need to be able to monitor the Select lines in the synthesizer so that it could output the 5V so that it is in time with the correct Select line's pulse. So the Arduino would have 8 inputs from the Select lines, and 7 outputs to the Data lines. I think.

Hope this helps and is clear enough.

pinksoir: @PieterP: I'd like the synthesizer to respond to MIDI, not for the keyboard to output MIDI data. So, basically, a MIDI retrofit for the keyboard.

Don't you think that sampling would be easier? :)

But no one's gonna stop you from modding it just for fun of course. I think an Arduino should be able to handle that, if you make your program fast enough. Take a look at direct port manipulation, for example and use (pin change) interrupts on the 8 select lines. You'll probably have to write your own MIDI in function: if the byte you read from the Serial port has a 1 as MSB, it's a status byte (the start of a MIDI message). This byte contains the message type (note on or off) and the channel (you could probably ignore this). The next byte should have a 0 as MSB, and contains the note number. Use this data to update an 8-byte array with note states (using some bitwise operations and logic). In most cases, you can probably ignore the third byte, it's the velocity. However, some MIDI devices send a note on with velocity = 0 instead of a note off. This can be very frustrating. In your ISR (interrupt service routine, the piece of code that executes when one of the 8 select lines changes state), use direct port manipulation to determine which one of the 8 lines (0-7) is high or low, and use that number as the index of your note states array. Then output the contents of the byte to the right pins. If you use clever wiring, you can output 6 bits at once, using direct port manipulation. Using bitshifts and bitmasks, you can get the right bits to the proper output register. It would be convenient if the Uno had 8-bit output registers, but only PORTD has 8 bits, but you can't use pin 0 and 1, because you're already using them for Serial (MIDI) communication.

Hope this helps! Pieter

Thank PieterP, that's all super helpful. Thank you so much for taking the time. It's great to know that this might be possible with Arduino. .

Haha. Yes, sampling would be easier, but far less satisfying!

On a serious note ( ;) ) though, a MIDI retrofit would allow me to play sequences into the synthesizer while tweaking it in real time, which is the goal. There was a universal retrofit for matrix keyboard synthesizers available previously but it seems to have gone out of production.

Here is a guide for doing something similar to what I want using a programmable EPROM and custom pcb:

http://www.maxmidi.com/diy/sk1/article.html

I hope that explains the project a little better than my post above.

EDIT:

Further reading on direct port manipulation seems like it is the way to go.

I presume I can ignore any MIDI data that I don't want. Specifically, the MIDI note numbers I'll be interested in will be C2 to C6 or (I think. MIDI note numbers 48 and 96) as the keyboard on the synthesizer is only 49 keys. Anything outside that range would be useless as it would be beyond that which the key scanner could use

A couple of power questions:

1) The digital IO pins on an Arduino won't output 5V, right? So I'd need to build a circuit to send the voltage back to the key scanner.

2) It's possible to power the Arduino with 5V from USB but not advised to power it from a 5V PSU. Is this because of incorrect voltage/polarity concerns? I'd like to power it from the 5V rails on the synthesizer.

pinksoir: 1) The digital IO pins on an Arduino won't output 5V, right? So I'd need to build a circuit to send the voltage back to the key scanner.

Actually, they will output 5V. They have push-pull drivers built-in. An Arduino pin has 4 states: low output, high output, input Hi-Z and input pull-up. Output low means that it's connected to ground (internally), so it outputs 0v, and can sink current; output high means that it's connected to 5v (internally), and it can source current. Input Hi-Z means that it's practically not connected to either ground or 5v; input pull-up means that the pin is connected to 5v, but through a resistor (inside of the Arduino). This means that it can source only very little current, but the voltage is still 5v, so the Arduino will register it as a HIGH input.

You should use a series resistor for your seven output pins, maybe something like 470Ω (= ~10mA@5V) to protect the Arduino and the keyboard's MCU: it should be high enough to limit the current flowing out of the Arduino pin, but low enough to overcome the pull-down resistors of the keyboard. The reason is that if you press one of the keys while the Arduino outputs 0V, it will connect the output pin of the Arduino to the select line, which is driven high (5V) by the keyboards MCU. This is a dead short, resulting in a high current flow, possibly damaging the Arduino and/or the keyboard. You could also just drive a data line high (output) to enable a key, and set it to input Hi-Z to disable a key, however, this means you have to write to two registers to change the state (both the data direction register and the data register).

pinksoir: 2) It's possible to power the Arduino with 5V from USB but not advised to power it from a 5V PSU. Is this because of incorrect voltage/polarity concerns? I'd like to power it from the 5V rails on the synthesizer.

If the 5V rail is stable enough, that shoudn't be a problem. Connect it to the 5V pin on the Arduino, not Vin (otherwise it will go through the on-board 5v regulator, dropping the voltage below 5v). Watch the polarity though, reverse polarity will kill the Arduino instantly (the barrel jack has reverse power protection using a diode, but the 5V and Vin pins don't).

Pieter

Watch the polarity though, reverse polarity will kill the Arduino instantly

While being excellent advice I have found the Arduino to be remarkably robust when it comes to short periods of reverse voltage.

Once again PieterP, thanks so much for the help. This is all very useful advice. I'm excited to try to put this into practice! I'm still in the process of bringing the synthesizer back to life, and once that's done (hopefully it can be done!) I'll start putting the project and code together.

Code updated to use nested for loops and 2D array for notes. This is probably not the best way to do it.

Is it possible to do direct port manipulation in this way? I presume I would have to define the ports to be directly manipulated and then put those in an array if I were to do it… Or maybe not. I’m new at this.

EDIT: new code below.

So, after working on the synth for months, I’ve finally brought it back to life. I learned a bunch about electronics while I did it, and best of all it works!

Anyway. I’m getting ready to add a MIDI input to it. I’ll have to check again with my scope, but the scan frequency is about 2us. I’m not sure if Arduino will be fast enough…

So far, this is the code I have:

#include <MIDI.h>                                            

#define LED 13                                                // LED = Pin 13

int datPins[] = {2, 3, 4, 5, 6, 7};                           // Array of data pins (Arduino pins 2-7)
int datPinCount = 6;                                          // Data line pin count

int selPins[] = {9, 10, 11, 12, 14, 15, 16, 17};              // Array of select lines (Arduino pins 9-12 and 14-17)
int selPinCount  = 8;                                         // Select line pin count

int selVals[] = {0, 0, 0, 0, 0, 0, 0, 0};                     // Initial values of select pins (low)

                                                              // MIDI note numbers per data and select line (6x8)
int notes[8][6] = {
  {48, 49, 50, 51, 52, 53},          
  {54, 55, 56, 57, 58, 59},
  {60, 61, 62, 63, 64, 65},
  {66, 67, 68, 69, 70, 71},
  {72, 73, 74, 75, 76, 77},
  {78, 79, 80, 81, 82, 83},
  {84, 85, 86, 87, 88, 89},
  {90, 91, 92, 93, 94, 95}
};


// -----------------------------------------------------------------------------------------------------

MIDI_CREATE_DEFAULT_INSTANCE();                               // Create an instance of the library with default name, 
                                                              // serial port and settings.

void readSelect(){                                            // Read Select lines
  for (int thisPin = 0; thisPin < selPinCount; thisPin++) { 
      selVals[thisPin] = digitalRead(selPins[thisPin]);
  }
}

// -----------------------------------------------------------------------------------------------------

// ForNoteON will be called by Midi Library when MIDI NOTE ON message is received.
// Bytes for Channel, Pitch, and Velocity.

void ForNoteOn(byte channel, byte pitch, byte velocity) {
   
  digitalWrite(LED,HIGH);                                     // LED on

  readSelect();                                               // Read Select lines
  
  for (int select = 0; select < selPinCount; select++) {      // For each select line (1-8) 
    if (selVals[select] > 0) {                                // If that select line is HIGH
      for (int n = 0; n < datPinCount; n++) {                 // Then for each note 'n' (1-6) in each array in notes 
        if (notes[select][n] == pitch) {                      // if the nth note in the array corresponding to the select line number (1-8) is equal to the MIDI note
          digitalWrite(datPins[n], HIGH);                     // write to equivalent nth data line (1-6) to turn on note.
          //break;
        }        
      }
    }
  }  
}

// -----------------------------------------------------------------------------------------------------

// ForNoteOFF will be called by the Midi Library when MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *


void ForNoteOff(byte channel, byte pitch, byte velocity) {
   
  digitalWrite(LED,LOW);                                      // LED off

  readSelect();                                               // Read Select lines
  
  for (int select = 0; select < selPinCount; select++) {      // For each select line (1-8)
    if (selVals[select] > 0) {                                // If that select line is HIGH
      for (int n = 0; n < datPinCount; n++) {                 // Then for each note 'n' (1-6) in each array in notes 
        if (notes[select][n] == pitch) {                      // if the nth note in the array corresponding to the select line number (1-8) is equal to the MIDI note
          digitalWrite(datPins[n], LOW);                      // write to equivalent nth data line (1-6) to turn off note.
          //break;
        }        
      }
    }
  }  
}

// -----------------------------------------------------------------------------------------------------

void setup() {
  
  pinMode (LED, OUTPUT);                                     
  
  for (int datPin = 0; datPin < datPinCount; datPin++) {     // Set data lines to output
    pinMode(datPins[datPin], OUTPUT);
    digitalWrite(datPins[datPin], LOW);
  }
  
  for (int selPin = 0; selPin < selPinCount; selPin++) {     // Set select lines to input
    pinMode(selPins[selPin], INPUT);
  }

  
  MIDI.begin(MIDI_CHANNEL_OMNI);                             // Initialize the Midi Library.
                                                             // OMNI = listen to all channels.   
                                                             // MIDI.begin(2) = channel 2 only, etc.
  
  MIDI.setHandleNoteOn(ForNoteOn);                           // Important!! Tells Midi Library 
                                                             // which function to call on NOTE ON command.
 
  MIDI.setHandleNoteOff(ForNoteOff);                         // Tells Midi Library to call
                                                             // "ForNoteOff" on NOTE OFF command.
}

// -----------------------------------------------------------------------------------------------------

void loop() {                                                // Main loop
  MIDI.read();                                               // Continuously check if Midi data has been received.
}

OK, I'm starting to look at DPM and bitwise operations now. The code I put up before would work conceptually, but using digitalRead and digitalWrite will most likely be too slow.

Which means I have to think about how to best implement this.

I have a basic understanding of how to use DPM to activate pins (pretty straightforward), but I'm trying to get my head around how to use the incoming MIDI data combined with reading the input pins to update e.g., PORTD.

PieterP: Take a look at direct port manipulation, for example and use (pin change) interrupts on the 8 select lines. You'll probably have to write your own MIDI in function: if the byte you read from the Serial port has a 1 as MSB, it's a status byte (the start of a MIDI message). This byte contains the message type (note on or off) and the channel (you could probably ignore this).

OK, so the first byte will be e.g., 1001---- (note on and whatever channel number). This will be followed by two more bytes, the note number (0-127), and then the velocity (0-127).

The next byte should have a 0 as MSB, and contains the note number. Use this data to update an 8-byte array with note states (using some bitwise operations and logic). In most cases, you can probably ignore the third byte, it's the velocity. However, some MIDI devices send a note on with velocity = 0 instead of a note off. This can be very frustrating.

I'll ignore velocity and concentrate just on note on/off for now.

I'm confused a little bit here, though. Why would I need an 8 byte array? There are 6 data lines and 8 select lines. I'll be 'monitoring' the select lines using DPM and the 6 data lines will be activated based on the MIDI data and the select line activity. Would I need a 6 byte array in that case (for note states)?

So an example of my array would be:

dataPins[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000}
selectPins[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000}

I would also need to monitor the select lines. I could use an 8 byte array for this. However, because there may only be 6 bits per byte, I'd have to use two port registers in this array. I'm unsure how to achieve this...

In your ISR (interrupt service routine, the piece of code that executes when one of the 8 select lines changes state), use direct port manipulation to determine which one of the 8 lines (0-7) is high or low, and use that number as the index of your note states array. Then output the contents of the byte to the right pins. If you use clever wiring, you can output 6 bits at once, using direct port manipulation. Using bitshifts and bitmasks, you can get the right bits to the proper output register. It would be convenient if the Uno had 8-bit output registers, but only PORTD has 8 bits, but you can't use pin 0 and 1, because you're already using them for Serial (MIDI) communication.

I'm unsure how I would go about using the note byte data to update the appropriate byte in the array above. Let's say I receive middle C or note number 60, which is 00111100. Let''s presume that PORTD is the output and PORTC is the input. In this case, when select line 3 is active (PORTC = B00000100), and I receive middle C (00111100), in the array above, I want:

PORTD = dataPins[6];

So something like:

if (PORTC == selectPins[6] && note == 60) {
  PORTD = dataPins[6];
}

I could of course do this for all possible notes, but it's going to be a loooot of code. I'd also have to do the same for note off messages. I could also use a 2D array of midi notes, each array being 6 bytes to correspond to the dataPins[] array. I could then do a nested for loop.

However, because I'm hoping to be able to use polyphony, I'd have to be able to combine the dataPins[] array bytes somehow, probably using | logic. In this case I'd need to store and update a variable which contains the current byte being output to the register.

You mention bitwise operations and logic. I'm not sure how I'd go about this in this situation though.

Sorry, this post has a lot of rubber ducking. I'd really appreciate any help though!

I could of course do this for all possible notes, but it's going to be a loooot of code.

It will be no more code to do one than to do 80 notes. Use arrays and loops.

Grumpy_Mike: It will be no more code to do one than to do 80 notes. Use arrays and loops.

Thanks. An issue might be that I need to split the select lines between two registers because each register can only look after 6 bytes, and the select lines require 8 bytes. Or is it? I guess I could just do another loop for the two extra bytes.

The other issue is that I need for the program to work with polyphony. So I would need to combine bytes using OR logic. I'm not really sure how I can do this. Maybe store the current byte as a variable? I'm not sure. Thinking out loud here...

and the select lines require 8 bytes.

Are you sure, that would give you 256 inputs. No schematic posted so can't tell what you are doing.

The other issue is that I need for the program to work with polyphony.

That again is down to the actual circuit you are using but I can't see the problem unless the keys are in a matrix.

I guess I could just do another loop for the two extra bytes.

Why? I can't see the problem.

Grumpy_Mike: Are you sure, that would give you 256 inputs. No schematic posted so can't tell what you are doing.

The select lines will be scanned using direct port manipulation. Thus lines 0-5 will be:

B00000001 B00000010 B00000100 B00001000 B00010000 B00100000

As Arduino Uno only allows 6 bytes per register, I would need to use two bytes in another register. Thus a for loop would not be possible for all 8 necessary bytes.

That again is down to the actual circuit you are using but I can't see the problem unless the keys are in a matrix.

The keys are indeed in a matrix. The key is in the thread title :)

Sorry, the image I had hotlinked to in the OP was removed, but I've updated it now with the original schematic of the keyboard matrix.

Here is some code which uses DPM and logic to activate/deactivate ports based on select line activity and note state.

byte incomingByte;              // Incoming MIDI data
byte note;                      // The second byte of incoming MIDI data
 
int action = 2;                 //0 = note off ; 1 = note on ; 2 = Do nothing


byte currentByte = B00000000;    // This is the byte that will be stored and updated through using the dataPin array below.

// The dataPinsOn array holds the bytes which represent the data line states for 'note on' on pins D1-D7.
// Th dataPinsOff array holds the bytes which represent the data line states for 'note off' on pins D1-D7.

byte dataPinsOn[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000}; 
byte dataPinsOff[] = {B11111110, B11111101, B11111011, B11110111, B11101111, B11011111};

// selectPins arrays = states of the select (input) lines 0-7. 
// Check the states of pins to determine when to send 
// currentByte to PORTD.

byte selectPins1[] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000};
byte selectPins2[] = {B00000001, B00000010};

// notesX[] = MIDI note numbers 
// notesX[1] =/= dataPinsOn[1], notesX[4] =/= dataPinsOn[4], etc.

int notes0[] = {48, 49, 50, 51, 52, 53};          
int notes1[] = {54, 55, 56, 57, 58, 59};
int notes2[] = {60, 61, 62, 63, 64, 65};
int notes3[] = {66, 67, 68, 69, 70, 71};
int notes4[] = {72, 73, 74, 75, 76, 77};
int notes5[] = {78, 79, 80, 81, 82, 83};
int notes6[] = {84, 85, 86, 87, 88, 89};
int notes7[] = {90, 91, 92, 93, 94, 95};


void setup() {

  Serial.begin(31250);              // Start listening on the serial port
  
  DDRD = DDRD | B11111100;          // Set pins D1-D7 as write, and leave pins 0 & 1 as is (RX/TX)
  DDRC = B000000;                   // Set pins C0-C5 to read. These are select lines 0-5.
  DDRB = B000000;                   // Set pins B0-B5 to read. Only B0 & B1 will be used. These are select lines 6 & 7.
}


void loop () {
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
  
    // Wait for as status-byte, channel 1, note on or off
    if (incomingByte == 144){       // If status-byte is note on message starting 
      action = 1;  
    }
    else if (incomingByte == 128){  // If status-byte is note off message starting
      action = 0;    
    }
    
    // if we received a "note off", we wait for which note (databyte)
    else if ( (action == 0) && (note == 0) ){ 
      note = incomingByte;
      noteOff(note);
      note = 0;
      action = 2;
    }

    // if we received a "note on", we wait for the note (databyte)
    else if ( (action == 1) && (note == 0) ){ 
      note = incomingByte;
      noteOn(note);
      //note = 0;
    }

    else{
      // Do nothing
    }
  }
}

void noteOn(byte note){
  
  for (int thisNote = 0; thisNote < 6; thisNote ++) {             // For each note 0-5 (in the array notes0) 
    if (notes0[thisNote] == note && PINC == selectPins1[0]) {     // If that note == the MIDI note number AND select line 0 is high,
      currentByte = (currentByte | dataPinsOn[thisNote]);         // Then update (logic OR)currentByte with the corresponding byte from dataPinsOn
      PORTD = currentByte;                                        // Write PORTD with currentByte.
    }
    else {                                                        // Otherwise
      currentByte = B00000000;                                    // If/either note != note number and/or the right select line is not high, currentByte is 0
      PORTD = currentByte;                                        // And PORTD should be written low/0.
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {             // Here be boilerplate
    if (notes1[thisNote] == note && PINC == selectPins1[1]) {
      currentByte = (currentByte | dataPinsOn[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes2[thisNote] == note && PINC == selectPins1[2]) {
      currentByte = (currentByte | dataPinsOn[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes3[thisNote] == note && PINC == selectPins1[3]) {
      currentByte = (currentByte | dataPinsOn[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes4[thisNote] == note && PINC == selectPins1[4]) {
      currentByte = (currentByte | dataPinsOn[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes5[thisNote] == note && PINC == selectPins1[5]) {
      currentByte = (currentByte | dataPinsOn[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes6[thisNote] == note && PINB == selectPins1[0]) {
      currentByte = (currentByte | dataPinsOn[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes7[thisNote] == note && PINB == selectPins1[1]) {
      currentByte = (currentByte | dataPinsOn[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }
}

void noteOff(byte note){
  
  for (int thisNote = 0; thisNote < 6; thisNote ++) {             // For each note 0-5 (in the array notes0) 
    if (notes0[thisNote] == note && PINC == selectPins1[0]) {     // If that note == the MIDI note number AND select line 0 is high,
      currentByte = (currentByte & dataPinsOff[thisNote]);        // Then update (logic AND)currentByte with the corresponding byte from dataPinsOn
      PORTD = currentByte;                                        // Write PORTD with currentByte.
    }
    else {                                                        // Otherwise
      currentByte = B00000000;                                    // If/either note != note number and/or the right select line is not high, currentByte is 0
      PORTD = currentByte;                                        // And PORTD should be written low/0.
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {             // Here be boilerplate
    if (notes1[thisNote] == note && PINC == selectPins1[1]) {
      currentByte = (currentByte & dataPinsOff[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes2[thisNote] == note && PINC == selectPins1[2]) {
      currentByte = (currentByte & dataPinsOff[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes3[thisNote] == note && PINC == selectPins1[3]) {
      currentByte = (currentByte & dataPinsOff[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes4[thisNote] == note && PINC == selectPins1[4]) {
      currentByte = (currentByte & dataPinsOff[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes5[thisNote] == note && PINC == selectPins1[5]) {
      currentByte = (currentByte & dataPinsOff[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes6[thisNote] == note && PINB == selectPins1[0]) {
      currentByte = (currentByte & dataPinsOff[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }

  for (int thisNote = 0; thisNote < 6; thisNote ++) {
    if (notes7[thisNote] == note && PINB == selectPins1[1]) {
      currentByte = (currentByte & dataPinsOff[thisNote]);
      PORTD = currentByte;
    }
    else {
      currentByte = B00000000;
      PORTD = currentByte;
    }
  }
}

As Arduino Uno only allows 6 bytes per register, I would need to use two bytes in another register. Thus a for loop would not be possible for all 8 necessary bytes.

No you don't get it. A simple if statement inside the loop can call up other registers, even bit patterns when the loop index goes above 6.

Hi all!

I'm facing this exact same challenge with very little knowledge about arduino, how did you get on with your project pinksoir? Any advice you could pass over?