Creating a keyboard scan matrix with a 74LS42

This one has been a tough one for me to get my head around. Im hoping i could get some help figuring out how to setup a matrix to scan a piano keyboard for MIDI notes. Im using a Teensy 2.0++ a 74LS42 to set the 8 column outputs low one at a time and a 4069 to invert the signal going to the rows (Those chips cant be changed for alternatives) I know i could write 200 if statements to make it work but i know theres a better smarter way of doing this. The main loop is just my test ground trying to get one column to work so dont judge it too much
Any help would be greatly appreciated

//ROWS/////////////////////////////////////////////////////////////////////////////////////////////////////////
//SCAN MATRIX INPUT PINS
const int row0 = 38;
const int row1 = 39;
const int row2 = 40;
const int row3 = 41;
const int row4 = 42;
const int row5 = 43;
const int row6 = 44;
const int row7 = 45;

//COLS/////////////////////////////////////////////////////////////////////////////////////////////////////////
//SCAN MATRIX OUTPUT VALUES
int col = 0;
int n = 0;

//SCAN MATRIX OUTPUT PINS
// The 74LS42 (IC58) link which has four pins
const int pinA = 13;
const int pinB = 14;
const int pinC = 15;
const int pinD = 16;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
//MIDI
uint8_t keyToMidiMap[64];
int noteVelocity = 127;

//BOOLEAN LOGIC TO TELL IF KEY WAS ALREADY PRESSED
boolean keyPressed[64];

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// The 74LS42 (IC58) shift up to next column
void scanColumn() {
  col++; 
  if (col > 8) col = 0;
  Serial.println (col);
  digitalWrite(pinA, col & 1);
  digitalWrite(pinB, col & 2);
  digitalWrite(pinC, col & 4);
  digitalWrite(pinD, col & 8);
  delay(1000);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() { 
  //Serial.println (col);
   
  // Map scan matrix buttons/keys to actual Midi note number. Lowest num 41 corresponds to F MIDI note.
  keyToMidiMap[0] = 48;
  keyToMidiMap[1] = 41;
  keyToMidiMap[2] = 42;
  keyToMidiMap[3] = 43;
  keyToMidiMap[4] = 44;
  keyToMidiMap[5] = 45;
  keyToMidiMap[6] = 46;
  keyToMidiMap[7] = 47;

  keyToMidiMap[8] = 56;
  keyToMidiMap[1 + 8] = 49;
  keyToMidiMap[2 + 8] = 50;
  keyToMidiMap[3 + 8] = 51;
  keyToMidiMap[4 + 8] = 52;
  keyToMidiMap[5 + 8] = 53;
  keyToMidiMap[6 + 8] = 54;
  keyToMidiMap[7 + 8] = 55;

  keyToMidiMap[16] = 64;
  keyToMidiMap[1 + 16] = 57;
  keyToMidiMap[2 + 16] = 58;
  keyToMidiMap[3 + 16] = 59;
  keyToMidiMap[4 + 16] = 60;
  keyToMidiMap[5 + 16] = 61;
  keyToMidiMap[6 + 16] = 62;
  keyToMidiMap[7 + 16] = 63;

  keyToMidiMap[24] = 72;
  keyToMidiMap[1 + 24] = 65;
  keyToMidiMap[2 + 24] = 66;
  keyToMidiMap[3 + 24] = 67;
  keyToMidiMap[4 + 24] = 68;
  keyToMidiMap[5 + 24] = 69;
  keyToMidiMap[6 + 24] = 70;
  keyToMidiMap[7 + 24] = 71;

  keyToMidiMap[32] = 80;
  keyToMidiMap[1 + 32] = 73;
  keyToMidiMap[2 + 32] = 74;
  keyToMidiMap[3 + 32] = 75;
  keyToMidiMap[4 + 32] = 76;
  keyToMidiMap[5 + 32] = 77;
  keyToMidiMap[6 + 32] = 78;
  keyToMidiMap[7 + 32] = 79;

  keyToMidiMap[40] = 88;
  keyToMidiMap[1 + 40] = 81;
  keyToMidiMap[2 + 40] = 82;
  keyToMidiMap[3 + 40] = 83;
  keyToMidiMap[4 + 40] = 84;
  keyToMidiMap[5 + 40] = 85;
  keyToMidiMap[6 + 40] = 86;
  keyToMidiMap[7 + 40] = 87;

  keyToMidiMap[48] = 96;
  keyToMidiMap[1 + 48] = 89;
  keyToMidiMap[2 + 48] = 90;
  keyToMidiMap[3 + 48] = 91;
  keyToMidiMap[4 + 48] = 92;
  keyToMidiMap[5 + 48] = 93;
  keyToMidiMap[6 + 48] = 94;
  keyToMidiMap[7 + 48] = 95;

  keyToMidiMap[56] = 104;
  keyToMidiMap[1 + 56] = 97;
  keyToMidiMap[2 + 56] = 98;
  keyToMidiMap[3 + 56] = 99;
  keyToMidiMap[4 + 56] = 100;
  keyToMidiMap[5 + 56] = 101;
  keyToMidiMap[6 + 56] = 102;
  keyToMidiMap[7 + 56] = 103;
        
  //SCAN MATRIX OUTPUT PINS
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(pinD, OUTPUT);
  
  //SCAN MATRIX INPUT PINS
  pinMode(row0, INPUT);
  pinMode(row1, INPUT);
  pinMode(row2, INPUT);
  pinMode(row3, INPUT);
  pinMode(row4, INPUT);
  pinMode(row5, INPUT);
  pinMode(row6, INPUT);
  pinMode(row7, INPUT);

  Serial.begin(31250);

  delay(1000);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  scanColumn();
  
  if (col <= 7)  {
    // check if any keys were pressed - rows will have HIGH output in this case corresponding
    int groupValue0 = digitalRead(row0);
    int groupValue1 = digitalRead(row1);
    int groupValue2 = digitalRead(row2);
    int groupValue3 = digitalRead(row3);
    int groupValue4 = digitalRead(row4);
    int groupValue5 = digitalRead(row5);
    int groupValue6 = digitalRead(row6);
    int groupValue7 = digitalRead(row7);
    
///////////////////////////////////////////////////////////////////////////////////////////////////////////
    // process if any combination of keys pressed
      if (col == 0 && !keyPressed[col]) {
        keyPressed[col] = true;
        noteOn(0x91, keyToMidiMap[col], noteVelocity);
        }

    //  process if any combination of keys released
    if (col != 0 && keyPressed[col]) {
      keyPressed[col] = false;
      noteOn(0x91, keyToMidiMap[col], 0);
      }
  }

  
///////////////////////////////////////////////////////////////////////////////////////////////////////////  
  //Scan for Transpose/ARP and key assign/ ARP range/ Arp on/ Keytrans
  if (col == 8){
    digitalWrite( 6, HIGH );
    delay(50);
    digitalWrite( 6, LOW );
  }
Serial.println (keyPressed[col]);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
void noteOn(int cmd, int pitch, int velocity) {
  //Serial.println (groupValue);
  //Serial.print("CMD: ");
  //Serial.println(cmd);
  //Serial.print("PITCH:");
  //Serial.println(pitch);
  //Serial.print("VELO:");
  //Serial.println(velocity);
  digitalWrite( 6, HIGH );
  delay(500);
  digitalWrite( 6, LOW );
  delay(500);
}

изображение

byte getRowsValue = PINF; // all Pins from 38 to 45 will read at once. one bit for pressed key
void setup() {
  //Serial.println (col);

  // Map scan matrix buttons/keys to actual Midi note number. Lowest num 41 corresponds to F MIDI note.
...............
..............

  //SCAN MATRIX OUTPUT PINS
  DDRC|=B01111000;

  //SCAN MATRIX INPUT PINS
  DDRF=0;

  Serial.begin(31250);

  delay(1000);
}

Wow thank you i was thinking how to get all the rows under one number. How would this work if multiple (Notes) rows on one column are switched?

  col++;
  if (col > 8) col = 0;
if (col <= 7)  {....
  if (col == 8) {
    digitalWrite( 6, HIGH );
    delay(50);
    digitalWrite( 6, LOW );
  }

why in your code keypresses would read only on 0-7 "col" and on 8 not?

Col 8 that is for another part of the code that will scan buttons for other functions like arpeggio. Its not meant to scan any key notes but i guess it could be rolled into the matrix right?

//ROWS/////////////////////////////////////////////////////////////////////////////////////////////////////////
//SCAN MATRIX INPUT PINS
//const int row0 = 38;
//const int row1 = 39;
//const int row2 = 40;
//const int row3 = 41;
//const int row4 = 42;
//const int row5 = 43;
//const int row6 = 44;
//const int row7 = 45;

//COLS/////////////////////////////////////////////////////////////////////////////////////////////////////////
//SCAN MATRIX OUTPUT VALUES
// 13,14,15,16

///////////////////////////////////////////////////////////////////////////////////////////////////////////
//MIDI
const uint8_t keys = 64;
uint8_t keyToMidiMap[keys];
const int noteVelocity = 127;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  for (byte i = 0; i < keys; i++) { // Map scan matrix buttons/keys to actual Midi note number. Lowest num 41 corresponds to F MIDI note.
    keyToMidiMap[i] = i + 40;
  }
  for (byte i = 0; i < keys; i += 8) {
    keyToMidiMap[i] = i + 48;
  }

  DDRC |= B01111000;//SCAN MATRIX OUTPUT PINS
  DDRF = 0; //SCAN MATRIX INPUT PINS

  Serial.begin(31250);
  delay(1000);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  // The 74LS42 (IC58) shift up to next column
  static byte col = 0;
  col++;
  if (col > 8) col = 0;
  Serial.println (col);
  PORTC &= B10000111;
  PORTC |= (col << 3);
  delay(1000);

  ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  // process if any combination of keys pressed or released

//  byte getRowsValue = PINF; // all Pins from 38 to 45 will read at once. one bit for pressed key

  for (byte b = 0; b < 8; b++) {
    noteOn(0x91, keyToMidiMap[col * 8 + b], (PINF & (1 << (b)) ?noteVelocity: 0)); // here exchange noteVelocity and 0 if key inverted
  }

  ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  //Scan for Transpose/ARP and key assign/ ARP range/ Arp on/ Keytrans
  if (col == 8) {
    digitalWrite( 6, HIGH );
    delay(50);
    digitalWrite( 6, LOW );
  }
  Serial.println (PINF,BIN);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
void noteOn(int cmd, int pitch, int velocity) {
  //Serial.println (groupValue);
  //Serial.print("CMD: ");
  //Serial.println(cmd);
  //Serial.print("PITCH:");
  //Serial.println(pitch);
  //Serial.print("VELO:");
  //Serial.println(velocity);
  digitalWrite( 6, HIGH );
  delay(500);
  digitalWrite( 6, LOW );
  delay(500);
}

Okay im trying to follow along. You really overhauled it so im trying to keep up and understand it. it looks like ill need to add in Boolean logic so it remembers if a note was already off or on so its does transmit a midi message every pass and only transmits when thers a change? Im also using port c as a data bus to communicate with other devices. Can I use DDRF =1; while sending data to stop it from reading any inputs?

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