diff --git a/.gitignore b/.gitignore index e915029..01d8aed 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ ################################################################################ /.vs +/CppProperties.json diff --git a/cvkeyboard.ino b/cvkeyboard.ino index af1360b..1acff96 100644 --- a/cvkeyboard.ino +++ b/cvkeyboard.ino @@ -18,159 +18,110 @@ #define Oct4 10 #define noteOffset 36 -#define offCounter 0 #define MINUTE 60000 #include #include + MIDI_CREATE_DEFAULT_INSTANCE(); +typedef struct OctaveStatus { + bool stat[12]; + int nOct; +} octst; + int note[12] = { C, Db, D, Eb, E, F, Gb, G, Ab, A, Bb, B }; // Note Pins above int octave[4] = { - Oct1, Oct2, Oct3, Oct4 }; // Octave Pins above - -int noteCounter[49] = { 0 }; -boolean status[49] = { LOW }; -boolean flip[49] = { LOW }; -boolean buffer = LOW; - -int octBuffer; -byte noteBuffer; - - -byte velocity = 100; // Placeholder. Will need something to change it -int channel = 7; // Placeholder. Will need something to change it -int bpm = 120; // Placeholder. Will need something to change it -int gate = 300; // Placeholder. Will need something to change it + Oct1, Oct2, Oct3, Oct4 }; // Octave Pins above +int clock = 0; // Used if arp to cycle through notes +octst buff; +bool kboard[49]; +bool raw; // Global Settings. RAW = signal is sent when key is detected +byte velocity = 100; +byte channel = 1; +int bpm = 360; unsigned long nextBeat = 0; -int step = 0; -int lastStep = 0; -boolean notePlayed = LOW; +unsigned long gate = 50; //ms of keypress if arpeggiator +int npressed; - - -void setup() -{ +void setup() { for (int cOctave = 0; cOctave < 4; cOctave++) { pinMode(octave[cOctave], OUTPUT); } for (int cNote = 0; cNote < 12; cNote++) { pinMode(note[cNote], INPUT); } + MIDI.begin(MIDI_CHANNEL_OFF); Serial.begin(115200); - nextBeat = millis() + (MINUTE / bpm); -} + nextBeat = millis() + (MINUTE / bpm); + pinMode(2, INPUT_PULLUP); + + for (int cStat = 0; cStat < 49; cStat++) kboard[cStat] = LOW; +} void loop() { - if (millis() < nextBeat) return; - notePlayed = LOW; - while (notePlayed == LOW) { - cleanScan(); - arp(); - } - nextBeat += (MINUTE / bpm); -} - -void cleanScan() { - int c; - for (c = 0; c < 49; c++) noteCounter[c] = 0; - scan(); - for (c = 0; c < 49; c++) { - if (status[c] == HIGH) noteCounter[c]++; - } - scan(); - for (c = 0; c < 49; c++) { - if (status[c] == HIGH) noteCounter[c]++; - } - scan(); - for (c = 0; c < 49; c++) { - if (status[c] == HIGH) noteCounter[c]++; - } - for (c = 0; c < 49; c++) { - if (noteCounter[c] == 3) status[c] = HIGH; - else status[c] = LOW; - } -} - -void send() { - for (int c = 48; c >= 0; c--) { - if (flip[c] == HIGH) { - flip[c] = LOW; - if (noteCounter[c] > 0) { - noteCounter[c]--; - } - else { - noteCounter[c] = offCounter; - noteBuffer = c + noteOffset; - if (status[c] == HIGH) { - MIDI.sendNoteOn(noteBuffer, velocity, channel); - } - else if (status[c] == LOW) { - MIDI.sendNoteOff(noteBuffer, velocity, channel); - } - } - } - } -} - -void playNote(int c, boolean status) { - if (status == HIGH) { - MIDI.sendNoteOn(c + noteOffset, velocity, channel); - } - else if (status == LOW) { - MIDI.sendNoteOff(c + noteOffset, velocity, channel); - } -} - -void arp() { - step++; - while (step < 49 && status[step] == LOW) { - step++; - } - if (step == 49) { - step = 0; - } - else { - playNote(lastStep, LOW); - playNote(step, HIGH); - lastStep = step; - notePlayed = HIGH; - } - return; -} - -void scan() { + npressed = 0; + raw = digitalRead(2); for (int cOctave = 0; cOctave < 4; cOctave++) { - octBuffer = 12 * cOctave; digitalWrite(octave[cOctave], HIGH); - - - for (int cNote = 0; cNote < 12; cNote++) { - buffer = digitalRead(note[cNote]); - - if (buffer ^ status[cNote + octBuffer]) { - status[cNote + octBuffer] = buffer; - flip[cNote + octBuffer] = HIGH; - } - else { - flip[cNote + octBuffer] = LOW; - } - - } + npressed += eval(scan(cOctave)); digitalWrite(octave[cOctave], LOW); } - -} - -int nPressed() { - int c, n = 0; - for (c = 0; c < 49; c++) { - if (status[c] == HIGH) { - n++; + if (raw) { + nextBeat = millis(); + return; + } + if (npressed < 1) return; + if (millis() >= nextBeat) { + nextBeat += (MINUTE / bpm); + clock++; + while (kboard[clock] == LOW) { + clock++; + if (clock == 49) clock = 0; } + playNote(clock, HIGH); + delay(gate); + playNote(clock, LOW); } } + + +octst scan(int nOct) { // This function reads the 12 note pins and returns a struct + int c; // with 1 bool for each note + octst output; + + output.nOct = nOct; + + for (c = 0; c < 12; c++) { + output.stat[c] = digitalRead(note[c]); + } + return output; +} + +int eval(octst input) { + int pressed = 0; + int snote = input.nOct * 12; + + for (int c = 0; c < 12; c++) { + if (input.stat[c] ^ kboard[c + snote]) { + if (raw) playNote(c + snote, input.stat[c]); + kboard[c + snote] = input.stat[c]; + } + if (kboard[c + snote] == HIGH) pressed++; + } + return pressed; +} + +void playNote(int c, bool status) { + byte n = c + noteOffset; + if (status == HIGH) { + MIDI.sendNoteOn(n, velocity, channel); + } + else if (status == LOW) { + MIDI.sendNoteOff(n, velocity, channel); + } +} \ No newline at end of file