Created
October 18, 2014 21:07
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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