Skip to content

Instantly share code, notes, and snippets.

@Informatic
Created October 18, 2014 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Informatic/4c09a718e0206214657c to your computer and use it in GitHub Desktop.
Save Informatic/4c09a718e0206214657c to your computer and use it in GitHub Desktop.
Simple hacked key matrix toy keyboard with PSP analog stick as pitchbend/mod controller.
const int ROWS_COUNT = 4;
const int COLS_COUNT = 8;
const int ANALOG_COUNT = 2;
// Internal reserved CC ID for pitchbend (which isn't really a CC, but, welp)
const int CC_PITCHBEND = 128;
const int midiChannel = 0;
const int midiVelocity = 127;
const int midiBaseNote = 52;
const int rowsPins[ROWS_COUNT] = {
15, 14, 16, 10
};
const int colsPins[COLS_COUNT] = {
2, 3, 4, 5, 6, 7, 8, 9
};
const int analogPins[ANALOG_COUNT] = {
A0, A1
};
const int analogCC[ANALOG_COUNT] = {
CC_PITCHBEND, 1
};
// Analog calibration data
int analogMax[ANALOG_COUNT] = {830, 890};
int analogMin[ANALOG_COUNT] = {180, 240};
void setup() {
Serial.begin(31250);
Serial1.begin(31250);
for(int p = 0; p < ROWS_COUNT; p++) {
pinMode(rowsPins[p], INPUT);
digitalWrite(rowsPins[p], HIGH);
}
for(int p = 0; p < COLS_COUNT; p++) {
pinMode(colsPins[p], INPUT_PULLUP);
}
}
// State variables
int currentRow = 0;
int state[ROWS_COUNT] = { // FIXME: we assume COLS_COUNT is 8
0, 0, 0, 0
};
int analogState[ANALOG_COUNT] = {
0, 0
};
void loop() {
pinMode(rowsPins[currentRow], OUTPUT);
for(int p = 0; p < COLS_COUNT; p++) {
bool newState = digitalRead(colsPins[p]) == LOW;
if(((state[currentRow] >> p) & 1) != newState) {
int midiNote = currentRow*COLS_COUNT + (8-p) + midiBaseNote;
if(newState) {
Serial.write(0x90 + midiChannel);
Serial1.write(0x90 + midiChannel);
} else {
Serial.write(0x80 + midiChannel);
Serial1.write(0x80 + midiChannel);
}
Serial.write(midiNote);
Serial1.write(midiNote);
Serial.write(midiVelocity);
Serial1.write(midiVelocity);
state[currentRow] ^= 1 << p;
}
}
// FIXME: Is it really needed? pinMode(..., OUTPUT); pulls it low anyway.
digitalWrite(rowsPins[currentRow], HIGH);
pinMode(rowsPins[currentRow], INPUT);
currentRow = (currentRow+1) % ROWS_COUNT;
// Update analog controls every ROWS_COUNT interations. (FIXME: shall we use for(...) instead?)
if(currentRow == 0) {
for(int p = 0; p < ANALOG_COUNT; p++) {
int reading = analogRead(analogPins[p]);
if(reading != analogState[p]) {
if(analogCC[p] == CC_PITCHBEND) {
int transformed = map(reading, analogMin[p], analogMax[p], 0, 0x2000);
Serial.write(0xe0 + midiChannel);
Serial.write(transformed & 0x7f);
Serial.write((transformed >> 7) & 0x7f);
} else {
int transformed = map(reading, analogMin[p], analogMax[p], 0, 127);
Serial.write(0xb0 + midiChannel);
Serial.write(analogCC[p]);
Serial.write(transformed);
}
analogState[p] = reading;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment