Hello,
I'm trying to make a MIDI controller to rescue an old 61-key CASIO keyboard.
Actually, I plan to use it as a normal keyboard, I do not intend to use it as a synthesizer, so after researching, I found that using a MIDI controller as an interface is a viable option.
Based on different tutorials, basically the EvanKale YouTube channel and https://www.musiconerd.com, I have managed to make the 8 x 8 matrix of my keyboard work with its corresponding notes, however, there is a slight delay between the moment the key is pressed and the sound emission (latency).
I have read that it is necessary to use an Arduino based on an ATMEGA32u4 so that it can be recognized as HID, so I am using an Arduino Leonardo.
In order to use the 8x8 array of the switch matrix (keys), I use a 74HC595:
--- 8 pins connected to the inputs Q0, Q1 ... Q7 of the 74HC595
--- 8 pins with Pull Down resistance, connected directly to the Arduino
--- 3 pins (Latch, Clock and Data) connected to 3 digital inputs of the Arduino
I also want to mention that I do not use any "delay".
I hope you can help me, I need to operate the keyboard without any delay.
Thank you very much for your attention, I am not an expert in programming, but I believe that with your good advice I can achieve it. Greetings.
I attach my code.
//PullDownTest With MIDIUSB library
#include "MIDIUSB.h"
#define NUM_ROWS 8
#define NUM_COLS 8
// Row input pins
const int row1Pin = 2;
const int row2Pin = 3;
const int row3Pin = 4;
const int row4Pin = 5;
const int row5Pin = 6;
const int row6Pin = 7;
const int row7Pin = 8;
const int row8Pin = 9;
// 74HC595 pins
const int dataPin = 11;
const int latchPin = 12;
const int clockPin = 13;
boolean keyPressed[NUM_ROWS][NUM_COLS];
uint8_t keyToMidiMap[NUM_ROWS][NUM_COLS];
// bitmasks for scanning columns
int bits[] =
{
B00000001,
B00000010,
B00000100,
B00001000,
B00010000,
B00100000,
B01000000,
B10000000
};
void noteOn(byte channel, byte pitch1,byte pitch2, byte velocity) {
byte pitch=(keyToMidiMap[pitch1][pitch2]);
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
void noteOff(byte channel, byte pitch1, byte pitch2, byte velocity) {
byte pitch=(keyToMidiMap[pitch1][pitch2]);
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(event);
}
void setup()
{
//Serial.begin(250000);
int note = 48;
for(int colCtr = 0; colCtr < NUM_COLS; ++colCtr)
{
for(int rowCtr = 0; rowCtr < NUM_ROWS; ++rowCtr)
{
keyPressed[rowCtr][colCtr] = false;
keyToMidiMap[rowCtr][colCtr] = note;
note++;
}
}
// setup pins output/input mode
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(row1Pin, INPUT);
pinMode(row2Pin, INPUT);
pinMode(row3Pin, INPUT);
pinMode(row4Pin, INPUT);
pinMode(row5Pin, INPUT);
pinMode(row6Pin, INPUT);
pinMode(row7Pin, INPUT);
pinMode(row8Pin, INPUT);
}
void loop()
{
for (int colCtr = 0; colCtr < NUM_COLS; ++colCtr)
{
//scan next column
scanColumn(colCtr);
//get row values at this column
int rowValue[NUM_ROWS];
rowValue[0] = digitalRead(row1Pin);
rowValue[1] = digitalRead(row2Pin);
rowValue[2] = digitalRead(row3Pin);
rowValue[3] = digitalRead(row4Pin);
rowValue[4] = digitalRead(row5Pin);
rowValue[5] = digitalRead(row6Pin);
rowValue[6] = digitalRead(row7Pin);
rowValue[7] = digitalRead(row8Pin);
// process keys pressed
for(int rowCtr=0; rowCtr<NUM_ROWS; ++rowCtr)
{
if(rowValue[rowCtr] != 0 && !keyPressed[rowCtr][colCtr])
{
keyPressed[rowCtr][colCtr] = true;
noteOn(11, rowCtr,colCtr, 127); // channel, note, velocity
MidiUSB.flush();
}
}
// process keys released
for(int rowCtr=0; rowCtr<NUM_ROWS; ++rowCtr)
{
if(rowValue[rowCtr] == 0 && keyPressed[rowCtr][colCtr])
{
keyPressed[rowCtr][colCtr] = false;
noteOff(11, rowCtr,colCtr, 127); // channel, note, velocity
MidiUSB.flush();
}
}
}
}
void scanColumn(int colNum)
{
digitalWrite(latchPin, LOW);
if(0 <= colNum && colNum <= 9)
{
shiftOut(dataPin, clockPin, MSBFIRST, bits[colNum]); //shift register
}
else
{
shiftOut(dataPin, clockPin, MSBFIRST, B00000000); //shift register
}
digitalWrite(latchPin, HIGH);
}