KSP-30-Hack/midikeys.ino

218 lines
6.5 KiB
Arduino
Raw Normal View History

2021-08-24 13:42:16 +02:00
#include <USB-MIDI.h>
USBMIDI_CREATE_DEFAULT_INSTANCE();
2021-08-14 00:26:54 +02:00
/*****************************************************************************/
/* Pins */
/*****************************************************************************/
2021-08-24 12:45:03 +02:00
#include "./pro_micro.h"
2021-08-14 11:01:19 +02:00
2021-08-14 00:26:54 +02:00
/*****************************************************************************/
/* Convenience */
/*****************************************************************************/
constexpr int col_pins[] = {KD1, KD2, KD3, KD4, KD5, KD6, KD7, KD8};
2021-08-14 11:28:21 +02:00
constexpr int num_col_pins = sizeof(col_pins) / sizeof(col_pins[0]);
constexpr int num_half_pins = num_col_pins / 2;
2021-08-14 00:26:54 +02:00
// first hit
constexpr int first_col[] = {KD1, KD2, KD3, KD4};
// second hit
2021-08-14 11:15:31 +02:00
constexpr int second_col[] = {KD5, KD6, KD7, KD8};
2021-08-14 00:26:54 +02:00
constexpr int selector_pins[] = {SA1, SA2, SA3, SA4, SA5};
2021-08-14 11:28:21 +02:00
constexpr int num_selector_pins = sizeof(selector_pins) / sizeof(selector_pins[0]);
2021-08-14 00:26:54 +02:00
2021-08-14 11:15:31 +02:00
enum Range { LO = 0, MID, HI };
2021-08-14 00:26:54 +02:00
constexpr Range ranges[] = {Range::LO, Range::MID, Range::HI};
// rows in range
2021-08-14 11:15:31 +02:00
constexpr int rows[] = {8, 8, 6};
constexpr int range_offsets[] = {0, rows[1] * num_half_pins,
rows[0] * num_half_pins +
rows[1] * num_half_pins};
2021-08-14 00:26:54 +02:00
/*****************************************************************************/
/* Keys/Notes */
/*****************************************************************************/
constexpr int midi_base = 21;
constexpr int num_keys = 88;
/*****************************************************************************/
/* Velocity */
/*****************************************************************************/
2021-08-24 14:02:42 +02:00
constexpr double min_velocity = 0.00001;
constexpr double max_velocity = 0.00024;
2021-08-14 00:26:54 +02:00
/*****************************************************************************/
/* Keyscanning */
/*****************************************************************************/
void select_range(Range range) {
2021-08-14 11:15:31 +02:00
switch (range) {
2021-08-14 00:26:54 +02:00
case Range::LO:
digitalWrite(RS1, LOW);
digitalWrite(RS2, LOW);
break;
case Range::MID:
digitalWrite(RS1, HIGH);
digitalWrite(RS2, LOW);
break;
case Range::HI:
digitalWrite(RS1, LOW);
digitalWrite(RS2, HIGH);
break;
}
}
void select_row(int row) {
digitalWrite(SEL_A, row & 1);
row >>= 1;
digitalWrite(SEL_B, row & 1);
row >>= 1;
digitalWrite(SEL_C, row & 1);
}
// UNUSED
/* int scan_row(bool second) { */
/* const int (&pins)[num_half_pins] = second ? second_col : first_col; */
/* for(int i= 0; i < num_half_pins; i++) { */
/* if (!digitalRead(pins[i])) */
/* return i; */
/* } */
/* return -1; */
/* } */
int get_midi_note(Range range, int row, int col) {
return midi_base + row * num_half_pins + col + range_offsets[range];
}
char midi_velocity(double velocity) {
2021-08-24 14:02:42 +02:00
return constrain((constrain(velocity, min_velocity, max_velocity) - min_velocity) /
(max_velocity - min_velocity) * 127, 1, 127);
2021-08-14 00:26:54 +02:00
}
2021-08-14 11:01:19 +02:00
/*****************************************************************************/
/* State */
/*****************************************************************************/
2021-08-14 00:26:54 +02:00
unsigned long S1[num_keys]; // timer value for first hit or 0
2021-08-14 11:15:31 +02:00
bool S2[num_keys]; // whether key is pressed
2021-08-14 11:01:19 +02:00
bool SSTE_PRESSED = false;
2021-08-14 00:26:54 +02:00
void setup() {
/***************************************************************************/
/* Serial */
/***************************************************************************/
2021-08-24 13:42:16 +02:00
Serial.begin(115200);
2021-08-14 00:26:54 +02:00
/***************************************************************************/
/* Pins */
/***************************************************************************/
for (int i = 0; i < num_col_pins; i++) {
pinMode(col_pins[i], INPUT_PULLUP);
}
for (int i = 0; i < num_selector_pins; i++) {
pinMode(selector_pins[i], OUTPUT);
}
for (int i = 0; i < num_keys; i++) {
S2[i] = false;
}
2021-08-14 11:01:19 +02:00
// Pedal
pinMode(SSTE, INPUT_PULLUP);
2021-08-14 00:26:54 +02:00
digitalWrite(RS1, LOW);
digitalWrite(RS2, LOW);
digitalWrite(SEL_A, LOW);
digitalWrite(SEL_B, LOW);
digitalWrite(SEL_C, LOW);
2021-08-24 13:42:16 +02:00
/***************************************************************************/
/* Midi */
/***************************************************************************/
MIDI.begin();
Serial.println("Keyboard ready.");
2021-08-14 00:26:54 +02:00
}
2021-08-14 11:14:47 +02:00
void send_note_down(int key, double velocity) {
Serial.print("Key DOWN: ");
2021-08-14 11:01:19 +02:00
Serial.print(key);
Serial.print(" ");
Serial.println(midi_velocity(velocity), DEC);
2021-08-24 13:42:16 +02:00
MIDI.sendNoteOn(midi_base + key, midi_velocity(velocity), 1);
2021-08-14 11:01:19 +02:00
}
2021-08-14 11:14:47 +02:00
void send_note_up(int key) {
Serial.print("Key UP: ");
Serial.println(key);
2021-08-24 13:52:46 +02:00
MIDI.sendNoteOff(midi_base + key, 55, 1);
2021-08-14 11:14:47 +02:00
}
2021-08-14 11:01:19 +02:00
void send_pedal(bool down) {
if (down)
Serial.println("SSTE DOWN");
else
Serial.println("SSTE UP");
}
2021-08-14 00:26:54 +02:00
void loop() {
2021-08-14 11:40:08 +02:00
int key = 0;
2021-08-14 00:26:54 +02:00
2021-08-14 11:01:19 +02:00
// keys
2021-08-14 00:26:54 +02:00
for (const auto range : ranges) {
select_range(range);
for (int row = 0; row < rows[range]; row++) {
select_row(row);
2021-08-14 11:14:47 +02:00
// read rows
2021-08-14 11:15:31 +02:00
for (int i = 0; i < num_half_pins; i++) {
2021-08-14 11:14:47 +02:00
const bool s1_was_triggered = !(S1[key] == 0);
if (!digitalRead(first_col[i])) { // key pressed
2021-08-14 11:15:31 +02:00
if (!s1_was_triggered) { // has not been depreesed before
2021-08-14 00:26:54 +02:00
S1[key] = micros();
2021-08-14 11:14:47 +02:00
}
// look for second fire
const bool s2_was_triggered = S2[key];
if (!digitalRead(second_col[i])) { // stage 2 pressed
2021-08-14 11:15:31 +02:00
if (!s2_was_triggered) {
2021-08-14 00:26:54 +02:00
S2[key] = true;
2021-08-14 11:15:31 +02:00
auto velocity = 1 / static_cast<double>(micros() - S1[key]);
2021-08-14 11:14:47 +02:00
send_note_down(key, velocity);
2021-08-14 00:26:54 +02:00
}
2021-08-14 11:15:31 +02:00
} else if (s2_was_triggered) { // stage 2 released
2021-08-14 11:14:47 +02:00
S2[key] = false;
send_note_up(key);
}
2021-08-14 11:15:31 +02:00
} else if (s1_was_triggered) { // s1 released
2021-08-14 11:14:47 +02:00
S1[key] = 0;
2021-08-14 11:15:31 +02:00
if (S2[key]) {
2021-08-14 11:14:47 +02:00
S2[key] = false;
send_note_up(key);
2021-08-14 00:26:54 +02:00
}
}
key++;
}
}
}
2021-08-14 11:01:19 +02:00
// pedals
if (digitalRead(SSTE) != SSTE_PRESSED) {
SSTE_PRESSED = !SSTE_PRESSED;
send_pedal(SSTE_PRESSED);
}
2021-08-14 00:26:54 +02:00
}