Firmware for HexBoard MIDI controller
HexBoard: Add jared changes
| -rw-r--r-- | HexBoard_V1.ino | 248 |
1 files changed, 165 insertions, 83 deletions
diff --git a/HexBoard_V1.ino b/HexBoard_V1.ino index f9254a4..e3ad59f 100644 --- a/HexBoard_V1.ino +++ b/HexBoard_V1.ino @@ -2,20 +2,109 @@ // Teensy LC set to 48MHz with USB type MIDI #include <FastLED.h> +#include "Adafruit_BLE.h" +#include "Adafruit_BluefruitLE_UART.h" +#include "Adafruit_BLEMIDI.h" +#include "BluefruitConfig.h" + +#define FACTORYRESET_ENABLE 0 +#define MINIMUM_FIRMWARE_VERSION "0.7.0" + #define LEDS_PIN 17 #define NUM_LEDS 140 +Adafruit_BluefruitLE_UART ble(Serial1, -1); + +Adafruit_BLEMIDI blemidi(ble); + +bool bleModuleEnabled = false; + +bool isConnected = false; + +// Bluetooth error messages +void error(const __FlashStringHelper*err) { + Serial.println(err); + while (1); +} +//Bluetooth callbacks +void connected(void) +{ + isConnected = true; + Serial.println("CONNECTED!"); + //Zach make bluetooth light go solid once connected +} +void disconnected(void) +{ + Serial.println("disconnected"); + isConnected = false; + //Zach make bluetooth light start blinking again once disconnected +} + CRGB leds[NUM_LEDS]; void init_leds() { FastLED.addLeds<WS2811, LEDS_PIN, RGB>(leds, NUM_LEDS); - FastLED.setBrightness(100); + /*Max Brightness. Recommended 100 or lower for usb power to stay under 2 amps. Increase up to 255 at your own risk. + Board can handle full power (theoretically 8.4 amps at max brightness) while only getting warm, but external power + is required to meet this. Use capable power supply on EXT PWR headers.*/ + FastLED.setBrightness(200); + FastLED.setMaxPowerInVoltsAndMilliamps(5,1000); for (int i=0; i < NUM_LEDS; i++) { leds[i] = CRGB::Black; } } +bool bluetooth = false; +void init_bluetooth() +{ +/* Initialise the module */ + Serial.print(F("Initialising the Bluefruit LE module: ")); + + if ( !ble.begin(VERBOSE_MODE) ) + { + error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?")); + } + Serial.println( F("OK!") ); + + if ( FACTORYRESET_ENABLE ) + { + /* Perform a factory reset to make sure everything is in a known state */ + Serial.println(F("Performing a factory reset: ")); + if ( ! ble.factoryReset() ) { + error(F("Couldn't factory reset")); + } + } + + //ble.sendCommandCheckOK(F("AT+uartflow=off")); + ble.echo(false); + + Serial.println("Requesting Bluefruit info:"); + /* Print Bluefruit information */ + ble.info(); + + /* Set BLE callbacks */ + ble.setConnectCallback(connected); + ble.setDisconnectCallback(disconnected); + + Serial.println(F("Enable MIDI: ")); + if ( ! blemidi.begin(true) ) + { + error(F("Could not enable Bluetooth MIDI")); + } + + ble.verbose(false); + Serial.print(F("Waiting for a connection...")); + + bluetooth = true; + //Zach add bluetooth button blinking here until connection made +} +void shutdown_bluetooth() +{ + ble.end(); + bluetooth = false; +} + // // Button matrix and LED locations // Portrait orientation top view: @@ -35,7 +124,7 @@ void init_leds() // 140 139 138 137 136 135 134 133 132 131 //DIAGNOSTICS -int diagnostics = 1; +int diagnostics = 0; // Define digital button matrix pins const byte columns[] = { 25, 24, 9, 8, 7, 6, 5, 4, 3, 2}; // Column pins in order from right to left @@ -57,55 +146,58 @@ const int PTB_UP = 134; const int UNUSED = 255; #define ROW_FLIP(x, ix, viii, vii, vi, v, iv, iii, ii, i) i, ii, iii, iv, v, vi, vii, viii, ix, x +//hacky macro because we typed them in wrong??? +//#define NO_FLIP(x, ix, viii, vii, vi, v, iv, iii, ii, i) i, x, ix, viii, vii, vi, v, iv, iii, ii + // MIDI note value tables const byte wickiHaydenLayout[elementCount] = { -ROW_FLIP(BT_TOG, 78, 80, 82, 84, 86, 88, 90, 92, 94), +ROW_FLIP(BT_TOG, 90, 92, 94, 96, 98, 100, 102, 104, 106), +ROW_FLIP( 83, 85, 87, 89, 91, 93, 95, 97, 99, 101), +ROW_FLIP(LGH_MD, 78, 80, 82, 84, 86, 88, 90, 92, 94), ROW_FLIP( 71, 73, 75, 77, 79, 81, 83, 85, 87, 89), -ROW_FLIP(LGH_MD, 66, 68, 70, 72, 74, 76, 78, 80, 82), +ROW_FLIP(LAY_MD, 66, 68, 70, 72, 74, 76, 78, 80, 82), ROW_FLIP( 59, 61, 63, 65, 67, 69, 71, 73, 75, 77), -ROW_FLIP(LAY_MD, 54, 56, 58, 60, 62, 64, 66, 68, 70), +ROW_FLIP(OCT_UP, 54, 56, 58, 60, 62, 64, 66, 68, 70), ROW_FLIP( 47, 49, 51, 53, 55, 57, 59, 61, 63, 65), -ROW_FLIP(OCT_UP, 42, 44, 46, 48, 50, 52, 54, 56, 58), +ROW_FLIP(OCT_DN, 42, 44, 46, 48, 50, 52, 54, 56, 58), ROW_FLIP( 35, 37, 39, 41, 43, 45, 47, 49, 51, 53), -ROW_FLIP(OCT_DN, 30, 32, 34, 36, 38, 40, 42, 44, 46), +ROW_FLIP(PTB_UP, 30, 32, 34, 36, 38, 40, 42, 44, 46), ROW_FLIP( 23, 25, 27, 29, 31, 33, 35, 37, 39, 41), -ROW_FLIP(PTB_UP, 18, 20, 22, 24, 26, 28, 30, 32, 34), -ROW_FLIP( 11, 13, 15, 17, 19, 21, 23, 25, 27, 29), -ROW_FLIP(PTB_DN, 6, 8, 10, 12, 14, 16, 18, 20, 22), -ROW_FLIP( UNUSED, 1, 3, 5, 7, 9, 11, 13, 15, 17) // Oops, wasted key! +ROW_FLIP(PTB_DN, 18, 20, 22, 24, 26, 28, 30, 32, 34), +ROW_FLIP( 11, 13, 15, 17, 19, 21, 23, 25, 27, 29) }; const byte harmonicTableLayout[elementCount] = { -ROW_FLIP(BT_TOG, 20, 27, 34, 41, 48, 55, 62, 69, 76), -ROW_FLIP( 17, 24, 31, 38, 45, 52, 59, 66, 73, 80), -ROW_FLIP(LGH_MD, 21, 28, 35, 42, 49, 56, 63, 70, 77), -ROW_FLIP( 18, 25, 32, 39, 46, 53, 60, 67, 74, 81), -ROW_FLIP(LAY_MD, 22, 29, 36, 43, 50, 57, 64, 71, 78), -ROW_FLIP( 19, 26, 33, 40, 47, 54, 61, 68, 75, 82), -ROW_FLIP(OCT_UP, 23, 30, 37, 44, 51, 58, 65, 72, 79), -ROW_FLIP( 20, 27, 34, 41, 48, 55, 62, 69, 76, 83), -ROW_FLIP(OCT_DN, 24, 31, 38, 45, 52, 59, 66, 73, 80), -ROW_FLIP( 21, 28, 35, 42, 49, 56, 63, 70, 77, 84), -ROW_FLIP(PTB_UP, 25, 32, 39, 46, 53, 60, 67, 74, 81), -ROW_FLIP( 22, 29, 36, 43, 50, 57, 64, 71, 78, 85), -ROW_FLIP(PTB_DN, 26, 33, 40, 47, 54, 61, 68, 75, 82), -ROW_FLIP( 23, 30, 37, 44, 51, 58, 65, 72, 79, 86) +ROW_FLIP(BT_TOG, 83, 76, 69, 62, 55, 48, 41, 34, 27), +ROW_FLIP( 86, 79, 72, 65, 58, 51, 44, 37, 30, 23), +ROW_FLIP(LGH_MD, 82, 75, 68, 61, 54, 47, 40, 33, 26), +ROW_FLIP( 85, 78, 71, 64, 57, 50, 43, 36, 29, 22), +ROW_FLIP(LAY_MD, 81, 74, 67, 60, 53, 46, 39, 32, 25), +ROW_FLIP( 84, 77, 70, 63, 56, 49, 42, 35, 28, 21), +ROW_FLIP(OCT_UP, 80, 73, 66, 59, 52, 45, 38, 31, 24), +ROW_FLIP( 83, 76, 69, 62, 55, 48, 41, 34, 27, 20), +ROW_FLIP(OCT_DN, 79, 72, 65, 58, 51, 44, 37, 30, 23), +ROW_FLIP( 82, 75, 68, 61, 54, 47, 40, 33, 26, 19), +ROW_FLIP(PTB_UP, 78, 71, 64, 57, 50, 43, 36, 29, 22), +ROW_FLIP( 81, 74, 67, 60, 53, 46, 39, 32, 25, 18), +ROW_FLIP(PTB_DN, 77, 70, 63, 56, 49, 42, 35, 28, 21), +ROW_FLIP( 80, 73, 66, 59, 52, 45, 38, 31, 24, 17) }; const byte gerhardLayout[elementCount] = { -ROW_FLIP(BT_TOG, 20, 21, 22, 23, 24, 25, 26, 27, 28), -ROW_FLIP( 23, 24, 25, 26, 27, 28, 29, 30, 31, 32), -ROW_FLIP(LGH_MD, 27, 28, 29, 30, 31, 32, 33, 34, 35), -ROW_FLIP( 30, 31, 32, 33, 34, 35, 36, 37, 38, 39), -ROW_FLIP(LAY_MD, 34, 35, 36, 37, 38, 39, 40, 41, 42), -ROW_FLIP( 37, 38, 39, 40, 41, 42, 43, 44, 45, 46), -ROW_FLIP(OCT_UP, 41, 42, 43, 44, 45, 46, 47, 48, 49), -ROW_FLIP( 44, 45, 46, 47, 48, 49, 50, 51, 52, 53), -ROW_FLIP(OCT_DN, 48, 49, 50, 51, 52, 53, 54, 55, 56), -ROW_FLIP( 51, 52, 53, 54, 55, 56, 57, 58, 59, 60), -ROW_FLIP(PTB_UP, 55, 56, 57, 58, 59, 60, 61, 62, 63), -ROW_FLIP( 58, 59, 60, 61, 62, 63, 64, 65, 66, 67), -ROW_FLIP(PTB_DN, 62, 63, 64, 65, 66, 67, 68, 69, 70), -ROW_FLIP( 65, 66, 67, 68, 69, 70, 71, 72, 73, 74) +ROW_FLIP(BT_TOG, 74, 73, 72, 71, 70, 69, 68, 67, 66), +ROW_FLIP( 71, 70, 69, 68, 67, 66, 65, 64, 63, 62), +ROW_FLIP(LGH_MD, 67, 66, 65, 64, 63, 62, 61, 60, 59), +ROW_FLIP( 64, 63, 62, 61, 60, 59, 58, 57, 56, 55), +ROW_FLIP(LAY_MD, 60, 59, 58, 57, 56, 55, 54, 53, 52), +ROW_FLIP( 57, 56, 55, 54, 53, 52, 51, 50, 49, 48), +ROW_FLIP(OCT_UP, 53, 52, 51, 50, 49, 48, 47, 46, 45), +ROW_FLIP( 50, 49, 48, 47, 46, 45, 44, 43, 42, 41), +ROW_FLIP(OCT_DN, 46, 45, 44, 43, 42, 41, 40, 39, 38), +ROW_FLIP( 43, 42, 41, 40, 39, 38, 37, 36, 35, 34), +ROW_FLIP(PTB_UP, 39, 38, 37, 36, 35, 34, 33, 32, 31), +ROW_FLIP( 36, 35, 34, 33, 32, 31, 30, 29, 28, 27), +ROW_FLIP(PTB_DN, 32, 31, 30, 29, 28, 27, 26, 25, 24), +ROW_FLIP( 29, 28, 27, 26, 25, 24, 23, 22, 21, 20) }; // LEDs for OCT_UP/OCT_DN status. const byte octUpSW = 70 - 1; @@ -128,14 +220,11 @@ unsigned long activeButtonsTime[elementCount]; // Array // MIDI channel assignment byte midiChannel = 0; // Current MIDI channel (changed via user input) -// MIDI program variables -byte midiProgram[16]; // MIDI program selection per channel (0-15) - // Octave modifier int octave = 0;// Apply a MIDI note number offset (changed via user input in steps of 12) // Velocity levels -byte velocity = 95; // Non-zero default velocity for testing; this will update via analog pot +byte velocity = 95; // Default velocity // END SETUP SECTION // ------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -151,6 +240,9 @@ void setup() pinMode(rows[pinNumber], INPUT); // Set the pinMode to INPUT (0V / LOW). } Serial.begin(115200); + if (bleModuleEnabled == true){ + init_bluetooth(); + } init_leds(); setOctLED(); setLayoutLEDs(); @@ -173,6 +265,9 @@ void loop() // Act on those buttons playNotes(); + // Held Buttons + heldButtons(); + // Do the LEDS FastLED.show(); } @@ -245,7 +340,8 @@ void playNotes() if (activeButtons[i] == 1) // If the button is active (newpress) { if (currentLayout[i] < 128) { - leds[i] = CRGB::White; + //leds[i] = CRGB::White; + leds[i] = CHSV((currentLayout[i] % 12) * 21, 255, 255); noteOn(midiChannel, (currentLayout[i] + octave) % 128 , velocity); } else { commandPress(currentLayout[i]); @@ -254,6 +350,7 @@ void playNotes() // If the button is inactive (released) if (currentLayout[i] < 128) { setLayoutLED(i); + //leds[i] ; noteOff(midiChannel, (currentLayout[i] + octave) % 128, 0); } else { commandRelease(currentLayout[i]); @@ -263,20 +360,36 @@ void playNotes() } } +void heldButtons() +{ + for (int i = 0; i < elementCount; i++) { + if (activeButtons[i]) { + //if ( + } + } +} + // MIDI PACKET FUNCTIONS // Send MIDI Note On -// 1st byte = Event type (0x09 = note on, 0x08 = note off). -// 2nd byte = Event type bitwise ORed with MIDI channel. -// 3rd byte = MIDI note number. -// 4th byte = Velocity (7-bit range 0-127) void noteOn(byte channel, byte pitch, byte velocity) { - usbMIDI.sendNoteOn(pitch, velocity, channel); + if (isConnected == true){ + blemidi.send(0x90, pitch, velocity); + } + else { + usbMIDI.sendNoteOn(pitch, velocity, channel); + } } -void loopNoteOn(byte channel, byte pitch, byte velocity) +// Send MIDI Note Off +void noteOff(byte channel, byte pitch, byte velocity) { - + if (isConnected == true){ + blemidi.send(0x80, pitch, velocity); + } + else { + usbMIDI.sendNoteOff(pitch, velocity, channel); + } } void commandPress(byte command) @@ -339,7 +452,7 @@ void setLayoutLEDs() } } void setLayoutLED(int i) { - leds[i] = CHSV((currentLayout[i] % 12) * 21, 255, 200); + leds[i] = CHSV((currentLayout[i] % 12) * 21, 255, 120); // black keys darker switch(currentLayout[i] % 12) { case 1: @@ -351,20 +464,6 @@ void setLayoutLED(int i) { } } -// Send MIDI Note Off -// 1st byte = Event type (0x09 = note on, 0x08 = note off). -// 2nd byte = Event type bitwise ORed with MIDI channel. -// 3rd byte = MIDI note number. -// 4th byte = Velocity (7-bit range 0-127) -void noteOff(byte channel, byte pitch, byte velocity) -{ - usbMIDI.sendNoteOff(pitch, velocity, channel); -} -void loopNoteOff(byte channel, byte pitch, byte velocity) -{ - -} - // Control Change // 1st byte = Event type (0x0B = Control Change). // 2nd byte = Event type bitwise ORed with MIDI channel. @@ -374,19 +473,6 @@ void controlChange(byte channel, byte control, byte value) { } -void loopControlChange(byte channel, byte control, byte value) -{ - -} - -// Program Change -// 1st byte = Event type (0x0C = Program Change). -// 2nd byte = Event type bitwise ORed with MIDI channel. -// 3rd byte = Program value (7-bit range 0-127). -void programChange(byte channel, byte value) -{ - -} // Pitch Bend // (14 bit value 0-16363, neutral position = 8192) @@ -398,10 +484,6 @@ void pitchBendChange(byte channel, byte lowValue, byte highValue) { } -void loopPitchBendChange(byte channel, byte lowValue, byte highValue) -{ - -} // END FUNCTIONS SECTION // ------------------------------------------------------------------------------------------------------------------------------------------------------------ |