Help with code for keyscan-matrix

Hello lovely forum. I have started a project to make a MIDI keyboard controller, keypad library didn’t offer more than 12 notes so I had to start on my own code. I am using a Arduino (original) MKRzero. My matrix scan code seems to have a problem, when I press a key the column above the actual column also registers. So it seems to jump somewhere in the code, this is the first time I have a array only for debouncing so there is probably some problems there. I have tried this without the actual keyboard and just jumping with wires and it gives the same problem with column above the actual column. I suspect the problem is somewhere in the mathematical operations of the matrix and maybe the fact that the mkrzero is really fast?Thank you in advance for help
Code: https://gist.github.com/brorgustav/ac2089083cbd08884b0ef51554893606

or:

#include "MIDIUSB.h"
#define debug SERIAL_PORT_MONITOR
#define ledPin A2
#define Keys 32
#define debugStart 
//comment out to disable delay and printing during setup, 
//the purpose is to show the pins for matrix through l2c

const int rows[] = {5, 4, 3, 2, 1, 0, 21, 20};
const int cols[] = {6, 8, 10, 12, 7, 9, 11, 13};
const int rowCount = 8;
const int colCount = 8;

//Loop count and delay variables
//Loopcount
unsigned long startTime;
unsigned long loopCount = 0;
unsigned long looptimer = 0;
//Delay
int printTime = 30;
int printDelay = 600;
unsigned long time_now = 0;

//Debounce variables
int debounceSampleMax = 40; // number of millis/samples to consider before declaring a debounced input
int debounceRead[colCount][rowCount];           // the current value read from the input pin
int debounceState[colCount][rowCount];    // the debounced input value
int debounceSampleCount[colCount][rowCount];       // how many times we have seen new value
long debounceTime[colCount][rowCount];         // the last time the output pin was sampled
//

//Normal rows: {8,9,10,11,12,13,14,15};
//Inverted rows:{15,14,13,12,11,10,9,8};

const int keynote[colCount][rowCount] = {
{1,9,17,25,33,41,49,57},
{2,10,18,26,34,42,50,58},
{3,11,19,27,35,43,51,59},
{4,12,20,28,36,44,52,60},
{5,13,21,29,37,45,53,61},
{6,14,22,30,38,46,54,62},
{7,15,23,31,39,47,55,63},
{8,16,24,32,40,48,56,64}
};
int firstKey=36;
int num_keys = Keys;
int channel=0;
int keys[colCount][rowCount];
int keys_prev[colCount][rowCount];
int noteIndex[48];
int noteCount;

void setup() {
  debug.begin(115200);
  // use default address 0
  //  pinMode(0, INPUT);
  // pinMode(0, HIGH);  // turn on a 100K pullup internally
#ifdef debugStart
  delay(2500);
  debug.println("*****************START*******************");
#endif
  for (int x = 0; x < rowCount; x++) {
#ifdef debugStart
    debug.print(x + 1);    debug.print("/");   debug.print(rowCount);
    debug.print(": "); debug.print("Pin #");  debug.print(rows[x]); debug.println(" as input");
    debug.println("************************************");
    delay(250);
#endif
    pinMode(rows[x], INPUT);
     delay(100);

  }

  for (int x = 0; x < colCount; x++) {
#ifdef debugStart
    debug.print(x + 1);
    debug.print("/");
    debug.print(colCount);
    debug.print(": ");
    debug.print("Pin #"); debug.print(cols[x]); debug.println(" as input-pullup");
    debug.println("************************************");
     delay(250);
#endif
    delay(100);
    pinMode(cols[x], INPUT_PULLUP);



  }

}

void scanMatrix()
{
    for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
        for (int colIndex=0; colIndex < colCount; colIndex++) {  
          int rx=keys[colIndex][rowIndex];
          debounceMatrix(colIndex, rowIndex, rx);
        }   
    }
}

void readMatrix() {
  for (int colIndex = 0; colIndex < colCount; colIndex++) {
    // col: set to output to low
    int curCol = cols[colIndex];
    pinMode(curCol, OUTPUT);
    digitalWrite(curCol, LOW);
    // row: interate through the rows
    for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
      int rowCol = rows[rowIndex];
      pinMode(rowCol, INPUT_PULLUP);
               keys[colIndex][rowIndex] = digitalRead(rowCol);
      //int rx=digitalRead(rowCol);
      
      pinMode(rowCol, INPUT);
        //    debounceMatrix(colIndex, rowIndex, rx);
    }
    // disable the column
    pinMode(curCol, INPUT);
  }
}

  
void debounceMatrix(int colIndex, int rowIndex , int rx)
{
//  if (rowCol != keys_prev[colIndex][rowIndex]) //If the rowCol (state) is different from last time scanned
//  {
      // If we have gone on to the next millisecond
  if(millis() != debounceTime[colIndex][rowIndex])
  {
               keys[colIndex][rowIndex] = rx;
    if(rx == keys_prev[colIndex][rowIndex] && debounceSampleCount[colIndex][rowIndex] > 0)
    {
      debounceSampleCount[colIndex][rowIndex]--;
      //debounceSampleCount[colIndex][rowIndex]=debounceSampleCount[colIndex][rowIndex]-1;
    }
    if(rx != keys_prev[colIndex][rowIndex])
    {
            debounceSampleCount[colIndex][rowIndex]++;
       //debounceSampleCount[colIndex][rowIndex]=debounceSampleCount[colIndex][rowIndex]+1; 
    }
    // If the Input has shown the same value for long enough let's switch it
    if(debounceSampleCount[colIndex][rowIndex] >= debounceSampleMax)
    {
                    debounceSampleCount[colIndex][rowIndex] = 0;
                   keys_prev[colIndex][rowIndex] = rx;
                   showMatrix(colIndex, rowIndex, rx);
  //  debug.print("KEY STATE IS DIFFERENT: "); debug.print("current="); debug.print(rx); debug.print("//"); //ebug.print("last known="); debug.println(keys_prev[colIndex][rowIndex]);
    }
    debounceTime[colIndex][rowIndex] = millis();
  }                  // keys_prev[colIndex][rowIndex] = rowCol; //save the new state
  }

void showMatrix(int colIndex, int rowIndex, int rx)
{
  debug.print("column[");
    debug.print(colIndex);
      debug.print("] row[");
        debug.print(rowIndex);
          debug.print("]");
            debug.print(" = ");
              debug.println(rx);
}

void noteOn(int channel, int pitch, int velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
      MidiUSB.flush();
                debug.print("MIDI | NOTE ON: ");
          debug.print(pitch);
                debug.print(" / ");
              debug.println(pitch, HEX);
}

void noteOff(int channel, int pitch, int velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
      MidiUSB.flush();
                debug.print("MIDI | NOTE OFF: ");
          debug.print(pitch);
                debug.print(" / ");
              debug.println(pitch, HEX);
}

void loop() {
  readMatrix();
  scanMatrix();
}

keypad library didn’t offer more than 12 notes

what do you mean by that??

keypad library didn't offer more than 12 notes

That must mean that my 16 key keypad does not work.

What a nuisance

Sorry maybe I was not clear with it! I mean polyphony as in simultaneous pressed keys

Isn’t 10 enough? (I’ve only 10 fingers)

MIDI pianos use 2 buttons for one key, to determine the velocity/intensity of the playing you program it to measure the time between, so 5 note-keys occupy 10 buttons inside the matrix

Have you considered the possibility of modifying the keypad library to allow for more keys ?

How many simultaneous keys do you need to allow for ?

16 at least, as many as possible would be the best since its for a MIDI keyboard. I don't know what limits the keypad librarys ability to not have more multiple presses, I have checked the source code a little bit but didn't get any clarity. Also I like the idea to learn how a matrix works and have full control over it incase something needs to be changed or if something isn't working

that's the start of the Keypad.h file:

#define LIST_MAX 10		// Max number of keys on the active list.
#define MAPSIZE 10		// MAPSIZE is the number of rows (times 16 columns)

you could try to change LIST_MAX

Thank you it seems to work! But why does it define how many Rows in MAPSIZE and why is it times 16 columns?

I want to make this project easy for beginners so if it requires redefining in libraries it makes its less accessible. Im still open for support on the key matrix code since I want to learn how to make my own without being dependant on other libraries

brorgustav:
Thank you it seems to work! But why does it define how many Rows in MAPSIZE and why is it times 16 columns?

They use bits to represent columns apparently. if you look at the code they have uint bitMap[MAPSIZE]; // 10 row x 16 column array of bits. Except Due which has 32 columnsSince a uint on UNO, MEGA are 16 bit that gives you 16 columns. The Due is a 32 bit architecture and an uint is thus 32 bit, hence the comment (to be honest, they should have used uint16_t or uint32_t to set the number of columns right)

brorgustav:
I want to make this project easy for beginners so if it requires redefining in libraries it makes its less accessible. Im still open for support on the key matrix code since I want to learn how to make my own without being dependant on other libraries

you could duplicate the 4 files of the library, modify a bit the name (but give credit where credit is due) and embed that into your protect (put the files in the same directory, next to your .ino sketch) . instead of doing#include <Keypad.h>at the top of your sketch, you do a #include "GustavKeypad.h" with quotes instead of angle brackets.