BLE MIDI
Dependencies: BLE_API mbed nRF51822
main.cpp@0:7de36d52cfef, 2017-06-12 (annotated)
- Committer:
- niklasjakob
- Date:
- Mon Jun 12 17:12:31 2017 +0000
- Revision:
- 0:7de36d52cfef
BLE MIDI BRIDGE TEST
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
niklasjakob | 0:7de36d52cfef | 1 | /* |
niklasjakob | 0:7de36d52cfef | 2 | * Copyright (c) 2016 Samuele Cornell |
niklasjakob | 0:7de36d52cfef | 3 | * |
niklasjakob | 0:7de36d52cfef | 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
niklasjakob | 0:7de36d52cfef | 5 | * of this software and associated documentation files (the "Software"), to deal |
niklasjakob | 0:7de36d52cfef | 6 | * in the Software without restriction, including without limitation the rights |
niklasjakob | 0:7de36d52cfef | 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
niklasjakob | 0:7de36d52cfef | 8 | * copies of the Software, and to permit persons to whom the Software is |
niklasjakob | 0:7de36d52cfef | 9 | * furnished to do so, subject to the following conditions: |
niklasjakob | 0:7de36d52cfef | 10 | * |
niklasjakob | 0:7de36d52cfef | 11 | * The above copyright notice and this permission notice shall be included in all |
niklasjakob | 0:7de36d52cfef | 12 | * copies or substantial portions of the Software. |
niklasjakob | 0:7de36d52cfef | 13 | * |
niklasjakob | 0:7de36d52cfef | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
niklasjakob | 0:7de36d52cfef | 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
niklasjakob | 0:7de36d52cfef | 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
niklasjakob | 0:7de36d52cfef | 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
niklasjakob | 0:7de36d52cfef | 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
niklasjakob | 0:7de36d52cfef | 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
niklasjakob | 0:7de36d52cfef | 20 | * SOFTWARE. |
niklasjakob | 0:7de36d52cfef | 21 | * |
niklasjakob | 0:7de36d52cfef | 22 | */ |
niklasjakob | 0:7de36d52cfef | 23 | |
niklasjakob | 0:7de36d52cfef | 24 | /* |
niklasjakob | 0:7de36d52cfef | 25 | * Thanks to Matthias Frick and his project blidino https://github.com/sieren/blidino |
niklasjakob | 0:7de36d52cfef | 26 | * which also uses RedBearslab nRF51822 and implements a USB-MIDI to BLE-MIDI bridge. |
niklasjakob | 0:7de36d52cfef | 27 | * His work made this possible and served as the main inspiration for this project . |
niklasjakob | 0:7de36d52cfef | 28 | * The content of BLEMIDI_MIDI_Parser.h file is for the most part taken from his blidino project. |
niklasjakob | 0:7de36d52cfef | 29 | */ |
niklasjakob | 0:7de36d52cfef | 30 | |
niklasjakob | 0:7de36d52cfef | 31 | #include "mbed.h" |
niklasjakob | 0:7de36d52cfef | 32 | |
niklasjakob | 0:7de36d52cfef | 33 | #include "ble/BLE.h" |
niklasjakob | 0:7de36d52cfef | 34 | |
niklasjakob | 0:7de36d52cfef | 35 | #include "LEDService.h" |
niklasjakob | 0:7de36d52cfef | 36 | |
niklasjakob | 0:7de36d52cfef | 37 | Serial UART(UART_TX_PIN,UART_RX_PIN) ; //UART_RX_PIN,BUFSERIAL_LENGHT |
niklasjakob | 0:7de36d52cfef | 38 | |
niklasjakob | 0:7de36d52cfef | 39 | #if ONLY_MIDI_to_BLEMIDI==0 |
niklasjakob | 0:7de36d52cfef | 40 | |
niklasjakob | 0:7de36d52cfef | 41 | #include "BLEMIDI_MIDI_Parser.h" |
niklasjakob | 0:7de36d52cfef | 42 | |
niklasjakob | 0:7de36d52cfef | 43 | #endif |
niklasjakob | 0:7de36d52cfef | 44 | |
niklasjakob | 0:7de36d52cfef | 45 | #if ONLY_BLEMIDI_to_MIDI==0 |
niklasjakob | 0:7de36d52cfef | 46 | |
niklasjakob | 0:7de36d52cfef | 47 | #include "MIDI_BLEMIDI_Parser.h" |
niklasjakob | 0:7de36d52cfef | 48 | |
niklasjakob | 0:7de36d52cfef | 49 | #endif |
niklasjakob | 0:7de36d52cfef | 50 | |
niklasjakob | 0:7de36d52cfef | 51 | |
niklasjakob | 0:7de36d52cfef | 52 | |
niklasjakob | 0:7de36d52cfef | 53 | #define TXRX_BUF_LEN 20 |
niklasjakob | 0:7de36d52cfef | 54 | |
niklasjakob | 0:7de36d52cfef | 55 | #define RX_BUF_LEN 256 |
niklasjakob | 0:7de36d52cfef | 56 | |
niklasjakob | 0:7de36d52cfef | 57 | |
niklasjakob | 0:7de36d52cfef | 58 | #if LIGHT_SHOW==1 |
niklasjakob | 0:7de36d52cfef | 59 | DigitalOut redled(P0_20); // sets the two LEDS on the MIDI Shield as outputs, these will be used as a visual feedback for debug |
niklasjakob | 0:7de36d52cfef | 60 | DigitalOut greenled(P0_19); // |
niklasjakob | 0:7de36d52cfef | 61 | #endif |
niklasjakob | 0:7de36d52cfef | 62 | |
niklasjakob | 0:7de36d52cfef | 63 | |
niklasjakob | 0:7de36d52cfef | 64 | /****************************************************************************************************************************** |
niklasjakob | 0:7de36d52cfef | 65 | *INITIALIZE VARIABLES, BUFFERS and BLE-MIDI Service and Characteristic |
niklasjakob | 0:7de36d52cfef | 66 | ******************************************************************************************************************************/ |
niklasjakob | 0:7de36d52cfef | 67 | |
niklasjakob | 0:7de36d52cfef | 68 | Ticker sendBLEMIDI_Ticker ; |
niklasjakob | 0:7de36d52cfef | 69 | Ticker sendData_Ticker ; |
niklasjakob | 0:7de36d52cfef | 70 | |
niklasjakob | 0:7de36d52cfef | 71 | Timer t; // timer used for BLE-MIDI timestamps |
niklasjakob | 0:7de36d52cfef | 72 | |
niklasjakob | 0:7de36d52cfef | 73 | bool isConnected; |
niklasjakob | 0:7de36d52cfef | 74 | |
niklasjakob | 0:7de36d52cfef | 75 | |
niklasjakob | 0:7de36d52cfef | 76 | //////////////////////////////////////////// |
niklasjakob | 0:7de36d52cfef | 77 | bool sendBLEMIDI_flag = false ; |
niklasjakob | 0:7de36d52cfef | 78 | |
niklasjakob | 0:7de36d52cfef | 79 | //////////// |
niklasjakob | 0:7de36d52cfef | 80 | |
niklasjakob | 0:7de36d52cfef | 81 | |
niklasjakob | 0:7de36d52cfef | 82 | BLEDevice ble; // BLE_API |
niklasjakob | 0:7de36d52cfef | 83 | |
niklasjakob | 0:7de36d52cfef | 84 | static Gap::ConnectionParams_t connectionParams; |
niklasjakob | 0:7de36d52cfef | 85 | |
niklasjakob | 0:7de36d52cfef | 86 | |
niklasjakob | 0:7de36d52cfef | 87 | // MIDI BLE Service and Characteristic UUID ( see Apple BLE-MIDI Spec. and Midi manufacter Association BLE-MIDI Spec.) |
niklasjakob | 0:7de36d52cfef | 88 | |
niklasjakob | 0:7de36d52cfef | 89 | static const uint8_t service_uuid[] = {0x03, 0xB8, 0x0E, 0x5A, 0xED, 0xE8, 0x4B, 0x33, 0xA7, 0x51, 0x6C, 0xE3, 0x4E, 0xC4, 0xC7, 0}; |
niklasjakob | 0:7de36d52cfef | 90 | static const uint8_t characteristic_uuid[] = {0x77, 0x72, 0xE5, 0xDB, 0x38, 0x68, 0x41, 0x12, 0xA1, 0xA9, 0xF2, 0x66, 0x9D, 0x10, 0x6B, 0xF3}; |
niklasjakob | 0:7de36d52cfef | 91 | |
niklasjakob | 0:7de36d52cfef | 92 | static const uint8_t service_uuid_rev[] = {0, 0xC7, 0xC4, 0x4E, 0xE3, 0x6C, 0x51, 0xA7, 0x33, 0x4B, 0xE8, 0xED, 0x5A, 0x0E, 0xB8, 0x03}; |
niklasjakob | 0:7de36d52cfef | 93 | |
niklasjakob | 0:7de36d52cfef | 94 | uint8_t txPayload[TXRX_BUF_LEN] = {0,}; |
niklasjakob | 0:7de36d52cfef | 95 | |
niklasjakob | 0:7de36d52cfef | 96 | |
niklasjakob | 0:7de36d52cfef | 97 | GattCharacteristic midiCharacteristic(characteristic_uuid, txPayload, 0, 20,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | |
niklasjakob | 0:7de36d52cfef | 98 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | |
niklasjakob | 0:7de36d52cfef | 99 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | |
niklasjakob | 0:7de36d52cfef | 100 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
niklasjakob | 0:7de36d52cfef | 101 | |
niklasjakob | 0:7de36d52cfef | 102 | GattCharacteristic *midiChars[] = {&midiCharacteristic}; |
niklasjakob | 0:7de36d52cfef | 103 | GattService BLEMIDIService(service_uuid, midiChars,sizeof(midiChars) / sizeof(GattCharacteristic *)); |
niklasjakob | 0:7de36d52cfef | 104 | |
niklasjakob | 0:7de36d52cfef | 105 | |
niklasjakob | 0:7de36d52cfef | 106 | |
niklasjakob | 0:7de36d52cfef | 107 | /********************************************************************************************************************* |
niklasjakob | 0:7de36d52cfef | 108 | MIDI to BLE-MIDI |
niklasjakob | 0:7de36d52cfef | 109 | *********************************************************************************************************************/ |
niklasjakob | 0:7de36d52cfef | 110 | |
niklasjakob | 0:7de36d52cfef | 111 | |
niklasjakob | 0:7de36d52cfef | 112 | #if ONLY_BLEMIDI_to_MIDI==0 |
niklasjakob | 0:7de36d52cfef | 113 | |
niklasjakob | 0:7de36d52cfef | 114 | |
niklasjakob | 0:7de36d52cfef | 115 | void sendBLEMIDI_Callback (void) |
niklasjakob | 0:7de36d52cfef | 116 | { |
niklasjakob | 0:7de36d52cfef | 117 | |
niklasjakob | 0:7de36d52cfef | 118 | sendBLEMIDI_flag = true ; |
niklasjakob | 0:7de36d52cfef | 119 | |
niklasjakob | 0:7de36d52cfef | 120 | /**** This callback is called within an ISR with frequency set by the sendBLEMIDI_Ticker, because it is called in an Interrupt context it is preferably |
niklasjakob | 0:7de36d52cfef | 121 | doing the MIDI to BLEMIDI task in the main, the callback only set a flag which would be checked in the main loop. |
niklasjakob | 0:7de36d52cfef | 122 | This is because all the BLEMIDI to MIDI conversion is already performed within Interrupt context. ( thus as a consequence BLEMIDI to MIDI has higher priority ) |
niklasjakob | 0:7de36d52cfef | 123 | *****/ |
niklasjakob | 0:7de36d52cfef | 124 | } |
niklasjakob | 0:7de36d52cfef | 125 | |
niklasjakob | 0:7de36d52cfef | 126 | |
niklasjakob | 0:7de36d52cfef | 127 | |
niklasjakob | 0:7de36d52cfef | 128 | void sendBLEMIDI(void) |
niklasjakob | 0:7de36d52cfef | 129 | { |
niklasjakob | 0:7de36d52cfef | 130 | |
niklasjakob | 0:7de36d52cfef | 131 | |
niklasjakob | 0:7de36d52cfef | 132 | // MIDI::MIDI_to_BLEMIDI_Parser() parses incoming MIDI events from the UART (see MIDI_BLEMIDI_Parser.h) |
niklasjakob | 0:7de36d52cfef | 133 | if(isConnected == true && MIDI::MIDI_to_BLEMIDI_Parser()==true) { |
niklasjakob | 0:7de36d52cfef | 134 | |
niklasjakob | 0:7de36d52cfef | 135 | // a valid MIDI message has been parsed from the UART buffer |
niklasjakob | 0:7de36d52cfef | 136 | |
niklasjakob | 0:7de36d52cfef | 137 | #if LIGHT_SHOW==1 |
niklasjakob | 0:7de36d52cfef | 138 | greenled = !(greenled); |
niklasjakob | 0:7de36d52cfef | 139 | #endif |
niklasjakob | 0:7de36d52cfef | 140 | |
niklasjakob | 0:7de36d52cfef | 141 | uint8_t BLEmidi_out[SysExMaxSize] ; |
niklasjakob | 0:7de36d52cfef | 142 | uint8_t SysEx_Array_lenght ; |
niklasjakob | 0:7de36d52cfef | 143 | |
niklasjakob | 0:7de36d52cfef | 144 | uint16_t ticks = t.read_us() & 0x1fff; // read timer for timestamps |
niklasjakob | 0:7de36d52cfef | 145 | |
niklasjakob | 0:7de36d52cfef | 146 | if(MIDI::mMessage.sysexArray[0] == MIDI::SystemExclusive) { // message is SysEx |
niklasjakob | 0:7de36d52cfef | 147 | |
niklasjakob | 0:7de36d52cfef | 148 | |
niklasjakob | 0:7de36d52cfef | 149 | SysEx_Array_lenght = MIDI::mMessage.getSysExSize() ; // get SysEx message lenght |
niklasjakob | 0:7de36d52cfef | 150 | |
niklasjakob | 0:7de36d52cfef | 151 | uint8_t position = 0; // position for SysexArray |
niklasjakob | 0:7de36d52cfef | 152 | |
niklasjakob | 0:7de36d52cfef | 153 | // header |
niklasjakob | 0:7de36d52cfef | 154 | |
niklasjakob | 0:7de36d52cfef | 155 | BLEmidi_out[position++] = 0x80 | ((ticks >> 7) & 0x3f); // header & timestampHigh |
niklasjakob | 0:7de36d52cfef | 156 | BLEmidi_out[position++] = 0x80 | (ticks & 0x7f); // timestampLow |
niklasjakob | 0:7de36d52cfef | 157 | |
niklasjakob | 0:7de36d52cfef | 158 | for (int i = 0; i < SysEx_Array_lenght; i++) { |
niklasjakob | 0:7de36d52cfef | 159 | if (i == SysEx_Array_lenght - 1) { |
niklasjakob | 0:7de36d52cfef | 160 | // modify last byte |
niklasjakob | 0:7de36d52cfef | 161 | BLEmidi_out[position++] = 0x80 | (ticks & 0x7f); |
niklasjakob | 0:7de36d52cfef | 162 | |
niklasjakob | 0:7de36d52cfef | 163 | if (position == 20) { |
niklasjakob | 0:7de36d52cfef | 164 | |
niklasjakob | 0:7de36d52cfef | 165 | |
niklasjakob | 0:7de36d52cfef | 166 | ble.updateCharacteristicValue(midiCharacteristic.getValueAttribute().getHandle(), BLEmidi_out, 20); |
niklasjakob | 0:7de36d52cfef | 167 | |
niklasjakob | 0:7de36d52cfef | 168 | position = 0; |
niklasjakob | 0:7de36d52cfef | 169 | // header |
niklasjakob | 0:7de36d52cfef | 170 | BLEmidi_out[position++] = 0x80 | (ticks >> 7) & 0x3f; |
niklasjakob | 0:7de36d52cfef | 171 | } |
niklasjakob | 0:7de36d52cfef | 172 | } |
niklasjakob | 0:7de36d52cfef | 173 | BLEmidi_out[position++] = MIDI::mMessage.sysexArray[i]; |
niklasjakob | 0:7de36d52cfef | 174 | if (position == 20) { |
niklasjakob | 0:7de36d52cfef | 175 | ble.updateCharacteristicValue(midiCharacteristic.getValueAttribute().getHandle(), BLEmidi_out, 20); |
niklasjakob | 0:7de36d52cfef | 176 | |
niklasjakob | 0:7de36d52cfef | 177 | position = 0; |
niklasjakob | 0:7de36d52cfef | 178 | // header |
niklasjakob | 0:7de36d52cfef | 179 | BLEmidi_out[position++] = 0x80 | (ticks >> 7) & 0x3f; |
niklasjakob | 0:7de36d52cfef | 180 | } |
niklasjakob | 0:7de36d52cfef | 181 | |
niklasjakob | 0:7de36d52cfef | 182 | ticks = t.read_us() & 0x1fff; |
niklasjakob | 0:7de36d52cfef | 183 | } |
niklasjakob | 0:7de36d52cfef | 184 | |
niklasjakob | 0:7de36d52cfef | 185 | if (position > 0) { |
niklasjakob | 0:7de36d52cfef | 186 | // send remains |
niklasjakob | 0:7de36d52cfef | 187 | ble.updateCharacteristicValue(midiCharacteristic.getValueAttribute().getHandle(), BLEmidi_out, position); |
niklasjakob | 0:7de36d52cfef | 188 | |
niklasjakob | 0:7de36d52cfef | 189 | } |
niklasjakob | 0:7de36d52cfef | 190 | |
niklasjakob | 0:7de36d52cfef | 191 | |
niklasjakob | 0:7de36d52cfef | 192 | MIDI::mMessage.sysexArray[0]= 0 ; // reset |
niklasjakob | 0:7de36d52cfef | 193 | |
niklasjakob | 0:7de36d52cfef | 194 | } |
niklasjakob | 0:7de36d52cfef | 195 | |
niklasjakob | 0:7de36d52cfef | 196 | |
niklasjakob | 0:7de36d52cfef | 197 | // message is not SysEx |
niklasjakob | 0:7de36d52cfef | 198 | |
niklasjakob | 0:7de36d52cfef | 199 | |
niklasjakob | 0:7de36d52cfef | 200 | else { |
niklasjakob | 0:7de36d52cfef | 201 | |
niklasjakob | 0:7de36d52cfef | 202 | |
niklasjakob | 0:7de36d52cfef | 203 | if(MIDI::mMessage.data1 == 0 ) { // no data1 only status |
niklasjakob | 0:7de36d52cfef | 204 | |
niklasjakob | 0:7de36d52cfef | 205 | BLEmidi_out[0] = 0x80 | ((ticks >> 7) & 0x3f); |
niklasjakob | 0:7de36d52cfef | 206 | BLEmidi_out[1] = 0x80 | (ticks & 0x7f); |
niklasjakob | 0:7de36d52cfef | 207 | BLEmidi_out[2] = MIDI::mMessage.channel+MIDI::mMessage.type; |
niklasjakob | 0:7de36d52cfef | 208 | |
niklasjakob | 0:7de36d52cfef | 209 | ble.updateCharacteristicValue(midiCharacteristic.getValueAttribute().getHandle(), BLEmidi_out , 3); |
niklasjakob | 0:7de36d52cfef | 210 | |
niklasjakob | 0:7de36d52cfef | 211 | } |
niklasjakob | 0:7de36d52cfef | 212 | |
niklasjakob | 0:7de36d52cfef | 213 | if(MIDI::mMessage.data2 == 0 ) { // no data2 |
niklasjakob | 0:7de36d52cfef | 214 | |
niklasjakob | 0:7de36d52cfef | 215 | BLEmidi_out[0] = 0x80 | ((ticks >> 7) & 0x3f); |
niklasjakob | 0:7de36d52cfef | 216 | BLEmidi_out[1] = 0x80 | (ticks & 0x7f); |
niklasjakob | 0:7de36d52cfef | 217 | BLEmidi_out[2] = MIDI::mMessage.channel+MIDI::mMessage.type; |
niklasjakob | 0:7de36d52cfef | 218 | BLEmidi_out[3] = MIDI::mMessage.data1 ; |
niklasjakob | 0:7de36d52cfef | 219 | |
niklasjakob | 0:7de36d52cfef | 220 | ble.updateCharacteristicValue(midiCharacteristic.getValueAttribute().getHandle(), BLEmidi_out , 4); |
niklasjakob | 0:7de36d52cfef | 221 | |
niklasjakob | 0:7de36d52cfef | 222 | } |
niklasjakob | 0:7de36d52cfef | 223 | |
niklasjakob | 0:7de36d52cfef | 224 | if(MIDI::mMessage.data2 != 0 ) { |
niklasjakob | 0:7de36d52cfef | 225 | |
niklasjakob | 0:7de36d52cfef | 226 | BLEmidi_out[0] = 0x80 | ((ticks >> 7) & 0x3f); |
niklasjakob | 0:7de36d52cfef | 227 | BLEmidi_out[1] = 0x80 | (ticks & 0x7f); |
niklasjakob | 0:7de36d52cfef | 228 | BLEmidi_out[2] = MIDI::mMessage.channel+MIDI::mMessage.type; |
niklasjakob | 0:7de36d52cfef | 229 | BLEmidi_out[3] = MIDI::mMessage.data1 ; |
niklasjakob | 0:7de36d52cfef | 230 | BLEmidi_out[4] = MIDI::mMessage.data2 ; |
niklasjakob | 0:7de36d52cfef | 231 | |
niklasjakob | 0:7de36d52cfef | 232 | ble.updateCharacteristicValue(midiCharacteristic.getValueAttribute().getHandle(), BLEmidi_out , 5); |
niklasjakob | 0:7de36d52cfef | 233 | |
niklasjakob | 0:7de36d52cfef | 234 | } |
niklasjakob | 0:7de36d52cfef | 235 | |
niklasjakob | 0:7de36d52cfef | 236 | }// end else |
niklasjakob | 0:7de36d52cfef | 237 | |
niklasjakob | 0:7de36d52cfef | 238 | }// outer if |
niklasjakob | 0:7de36d52cfef | 239 | |
niklasjakob | 0:7de36d52cfef | 240 | // invalid message or not connected |
niklasjakob | 0:7de36d52cfef | 241 | |
niklasjakob | 0:7de36d52cfef | 242 | } |
niklasjakob | 0:7de36d52cfef | 243 | |
niklasjakob | 0:7de36d52cfef | 244 | #endif |
niklasjakob | 0:7de36d52cfef | 245 | |
niklasjakob | 0:7de36d52cfef | 246 | |
niklasjakob | 0:7de36d52cfef | 247 | /****************************************************************************************************************************** |
niklasjakob | 0:7de36d52cfef | 248 | * BLE CALLBACKS |
niklasjakob | 0:7de36d52cfef | 249 | ******************************************************************************************************************************/ |
niklasjakob | 0:7de36d52cfef | 250 | |
niklasjakob | 0:7de36d52cfef | 251 | |
niklasjakob | 0:7de36d52cfef | 252 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
niklasjakob | 0:7de36d52cfef | 253 | { |
niklasjakob | 0:7de36d52cfef | 254 | //device disconnected |
niklasjakob | 0:7de36d52cfef | 255 | |
niklasjakob | 0:7de36d52cfef | 256 | isConnected = false ; |
niklasjakob | 0:7de36d52cfef | 257 | |
niklasjakob | 0:7de36d52cfef | 258 | #if ONLY_BLEMIDI_to_MIDI==0 |
niklasjakob | 0:7de36d52cfef | 259 | sendBLEMIDI_Ticker.detach() ; // stop Ticker to save energy |
niklasjakob | 0:7de36d52cfef | 260 | #endif |
niklasjakob | 0:7de36d52cfef | 261 | |
niklasjakob | 0:7de36d52cfef | 262 | ble.startAdvertising(); // start advertising |
niklasjakob | 0:7de36d52cfef | 263 | } |
niklasjakob | 0:7de36d52cfef | 264 | |
niklasjakob | 0:7de36d52cfef | 265 | |
niklasjakob | 0:7de36d52cfef | 266 | void connectionCallback(const Gap::ConnectionCallbackParams_t* params) { |
niklasjakob | 0:7de36d52cfef | 267 | |
niklasjakob | 0:7de36d52cfef | 268 | |
niklasjakob | 0:7de36d52cfef | 269 | isConnected=true ; |
niklasjakob | 0:7de36d52cfef | 270 | |
niklasjakob | 0:7de36d52cfef | 271 | // try update conn.parameters |
niklasjakob | 0:7de36d52cfef | 272 | |
niklasjakob | 0:7de36d52cfef | 273 | connectionParams.minConnectionInterval = Config::minConnectionInterval; |
niklasjakob | 0:7de36d52cfef | 274 | connectionParams.maxConnectionInterval = Config::maxConnectionInterval; |
niklasjakob | 0:7de36d52cfef | 275 | connectionParams.slaveLatency = Config::slaveLatency; |
niklasjakob | 0:7de36d52cfef | 276 | connectionParams.connectionSupervisionTimeout = Config::supervisionTimeout; |
niklasjakob | 0:7de36d52cfef | 277 | |
niklasjakob | 0:7de36d52cfef | 278 | ble.updateConnectionParams(params->handle ,&connectionParams); |
niklasjakob | 0:7de36d52cfef | 279 | |
niklasjakob | 0:7de36d52cfef | 280 | |
niklasjakob | 0:7de36d52cfef | 281 | //start timers here |
niklasjakob | 0:7de36d52cfef | 282 | #if ONLY_BLEMIDI_to_MIDI==0 |
niklasjakob | 0:7de36d52cfef | 283 | sendBLEMIDI_Ticker.attach( sendBLEMIDI_Callback, SENDBLEMIDI_INTERVAL); // every SENDBLEMIDI_INTERVAL seconds calls sendBLEMIDI_Callback (ISR) |
niklasjakob | 0:7de36d52cfef | 284 | |
niklasjakob | 0:7de36d52cfef | 285 | t.start(); // start the timer used for BLEMIDI timestamps |
niklasjakob | 0:7de36d52cfef | 286 | |
niklasjakob | 0:7de36d52cfef | 287 | #endif |
niklasjakob | 0:7de36d52cfef | 288 | |
niklasjakob | 0:7de36d52cfef | 289 | } |
niklasjakob | 0:7de36d52cfef | 290 | |
niklasjakob | 0:7de36d52cfef | 291 | |
niklasjakob | 0:7de36d52cfef | 292 | /**************************************************************************************************************************** |
niklasjakob | 0:7de36d52cfef | 293 | BLE-MIDI to MIDI |
niklasjakob | 0:7de36d52cfef | 294 | ****************************************************************************************************************************/ |
niklasjakob | 0:7de36d52cfef | 295 | |
niklasjakob | 0:7de36d52cfef | 296 | |
niklasjakob | 0:7de36d52cfef | 297 | #if ONLY_MIDI_to_BLEMIDI==0 |
niklasjakob | 0:7de36d52cfef | 298 | |
niklasjakob | 0:7de36d52cfef | 299 | void parseIncoming(uint8_t *buffer, uint16_t bytesRead) { // parse BLE-MIDI Events that have been written on the MIDI Characteristic |
niklasjakob | 0:7de36d52cfef | 300 | for (int i = 1; i < bytesRead; i++) |
niklasjakob | 0:7de36d52cfef | 301 | { |
niklasjakob | 0:7de36d52cfef | 302 | parseMidiEvent(buffer[0], buffer[i]); // parse and send through UART the MIDI Events received through BLE (see BLE_MIDI_Parser.h) |
niklasjakob | 0:7de36d52cfef | 303 | } |
niklasjakob | 0:7de36d52cfef | 304 | } |
niklasjakob | 0:7de36d52cfef | 305 | |
niklasjakob | 0:7de36d52cfef | 306 | |
niklasjakob | 0:7de36d52cfef | 307 | |
niklasjakob | 0:7de36d52cfef | 308 | void onDataWritten(const GattWriteCallbackParams *Handler) // this functions is called within an ISR every time data has been written on nRF51822 GATT Server MIDI Characteristic |
niklasjakob | 0:7de36d52cfef | 309 | { |
niklasjakob | 0:7de36d52cfef | 310 | |
niklasjakob | 0:7de36d52cfef | 311 | #if LIGHT_SHOW==1 |
niklasjakob | 0:7de36d52cfef | 312 | redled = !(redled) ; |
niklasjakob | 0:7de36d52cfef | 313 | #endif |
niklasjakob | 0:7de36d52cfef | 314 | |
niklasjakob | 0:7de36d52cfef | 315 | uint8_t buf[TXRX_BUF_LEN]; |
niklasjakob | 0:7de36d52cfef | 316 | uint16_t bytesRead; |
niklasjakob | 0:7de36d52cfef | 317 | if (Handler->handle == midiCharacteristic.getValueAttribute().getHandle()) { |
niklasjakob | 0:7de36d52cfef | 318 | ble.readCharacteristicValue(midiCharacteristic.getValueAttribute().getHandle(), |
niklasjakob | 0:7de36d52cfef | 319 | buf, &bytesRead); |
niklasjakob | 0:7de36d52cfef | 320 | //parseIncoming(buf, bytesRead); |
niklasjakob | 0:7de36d52cfef | 321 | |
niklasjakob | 0:7de36d52cfef | 322 | for (int i = 0; i < bytesRead; i++){ |
niklasjakob | 0:7de36d52cfef | 323 | UART.putc(buf[i]); |
niklasjakob | 0:7de36d52cfef | 324 | |
niklasjakob | 0:7de36d52cfef | 325 | } |
niklasjakob | 0:7de36d52cfef | 326 | |
niklasjakob | 0:7de36d52cfef | 327 | } |
niklasjakob | 0:7de36d52cfef | 328 | |
niklasjakob | 0:7de36d52cfef | 329 | } |
niklasjakob | 0:7de36d52cfef | 330 | |
niklasjakob | 0:7de36d52cfef | 331 | #endif |
niklasjakob | 0:7de36d52cfef | 332 | |
niklasjakob | 0:7de36d52cfef | 333 | |
niklasjakob | 0:7de36d52cfef | 334 | /************************************** |
niklasjakob | 0:7de36d52cfef | 335 | MAIN |
niklasjakob | 0:7de36d52cfef | 336 | ***************************************/ |
niklasjakob | 0:7de36d52cfef | 337 | |
niklasjakob | 0:7de36d52cfef | 338 | int main(void) |
niklasjakob | 0:7de36d52cfef | 339 | { |
niklasjakob | 0:7de36d52cfef | 340 | |
niklasjakob | 0:7de36d52cfef | 341 | |
niklasjakob | 0:7de36d52cfef | 342 | #if LIGHT_SHOW==1 |
niklasjakob | 0:7de36d52cfef | 343 | redled = 1; |
niklasjakob | 0:7de36d52cfef | 344 | greenled = 1; |
niklasjakob | 0:7de36d52cfef | 345 | #endif |
niklasjakob | 0:7de36d52cfef | 346 | |
niklasjakob | 0:7de36d52cfef | 347 | |
niklasjakob | 0:7de36d52cfef | 348 | |
niklasjakob | 0:7de36d52cfef | 349 | UART.baud(31250) ; // set UART baud rate to 31250 (MIDI standard) |
niklasjakob | 0:7de36d52cfef | 350 | |
niklasjakob | 0:7de36d52cfef | 351 | ble.init(); |
niklasjakob | 0:7de36d52cfef | 352 | ble.onDisconnection(disconnectionCallback); |
niklasjakob | 0:7de36d52cfef | 353 | ble.onConnection(connectionCallback) ; |
niklasjakob | 0:7de36d52cfef | 354 | |
niklasjakob | 0:7de36d52cfef | 355 | #if ONLY_MIDI_to_BLEMIDI==0 |
niklasjakob | 0:7de36d52cfef | 356 | ble.onDataWritten(onDataWritten); |
niklasjakob | 0:7de36d52cfef | 357 | #endif |
niklasjakob | 0:7de36d52cfef | 358 | |
niklasjakob | 0:7de36d52cfef | 359 | //conn. parameters ( rejected on iOS/OSX see Apple BLE peripheral design guidelines but can work on Android ) |
niklasjakob | 0:7de36d52cfef | 360 | |
niklasjakob | 0:7de36d52cfef | 361 | connectionParams.minConnectionInterval = Config::minConnectionInterval; |
niklasjakob | 0:7de36d52cfef | 362 | connectionParams.maxConnectionInterval = Config::maxConnectionInterval; |
niklasjakob | 0:7de36d52cfef | 363 | connectionParams.slaveLatency = Config::slaveLatency; |
niklasjakob | 0:7de36d52cfef | 364 | connectionParams.connectionSupervisionTimeout = Config::supervisionTimeout; |
niklasjakob | 0:7de36d52cfef | 365 | ble.setPreferredConnectionParams(&connectionParams); |
niklasjakob | 0:7de36d52cfef | 366 | ble.getPreferredConnectionParams(&connectionParams); |
niklasjakob | 0:7de36d52cfef | 367 | |
niklasjakob | 0:7de36d52cfef | 368 | |
niklasjakob | 0:7de36d52cfef | 369 | /* setup advertising */ |
niklasjakob | 0:7de36d52cfef | 370 | ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); |
niklasjakob | 0:7de36d52cfef | 371 | ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
niklasjakob | 0:7de36d52cfef | 372 | (const uint8_t *)"LLFX", sizeof("LLFX") - 1); |
niklasjakob | 0:7de36d52cfef | 373 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, |
niklasjakob | 0:7de36d52cfef | 374 | (const uint8_t *)service_uuid_rev, sizeof(service_uuid_rev)); |
niklasjakob | 0:7de36d52cfef | 375 | |
niklasjakob | 0:7de36d52cfef | 376 | ble.accumulateScanResponse(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
niklasjakob | 0:7de36d52cfef | 377 | (const uint8_t *)"LLFX", sizeof("LLFX") - 1); |
niklasjakob | 0:7de36d52cfef | 378 | ble.accumulateScanResponse(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)service_uuid_rev, sizeof(service_uuid_rev)); |
niklasjakob | 0:7de36d52cfef | 379 | ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
niklasjakob | 0:7de36d52cfef | 380 | |
niklasjakob | 0:7de36d52cfef | 381 | /* 100ms; in multiples of 0.625ms. */ |
niklasjakob | 0:7de36d52cfef | 382 | ble.setAdvertisingInterval(160); |
niklasjakob | 0:7de36d52cfef | 383 | |
niklasjakob | 0:7de36d52cfef | 384 | // set adv_timeout, in seconds |
niklasjakob | 0:7de36d52cfef | 385 | ble.setAdvertisingTimeout(0); |
niklasjakob | 0:7de36d52cfef | 386 | ble.addService(BLEMIDIService); |
niklasjakob | 0:7de36d52cfef | 387 | |
niklasjakob | 0:7de36d52cfef | 388 | //Set Device Name |
niklasjakob | 0:7de36d52cfef | 389 | ble.setDeviceName((const uint8_t *)"LLFX"); |
niklasjakob | 0:7de36d52cfef | 390 | |
niklasjakob | 0:7de36d52cfef | 391 | ble.startAdvertising(); |
niklasjakob | 0:7de36d52cfef | 392 | |
niklasjakob | 0:7de36d52cfef | 393 | |
niklasjakob | 0:7de36d52cfef | 394 | while(1) { //main loop |
niklasjakob | 0:7de36d52cfef | 395 | |
niklasjakob | 0:7de36d52cfef | 396 | #if ONLY_BLEMIDI_to_MIDI==0 |
niklasjakob | 0:7de36d52cfef | 397 | if(sendBLEMIDI_flag == true ) { // check if the flag is set |
niklasjakob | 0:7de36d52cfef | 398 | |
niklasjakob | 0:7de36d52cfef | 399 | sendBLEMIDI_flag=false ; |
niklasjakob | 0:7de36d52cfef | 400 | sendBLEMIDI() ; // parse MIDI Events from UART and send them over BLE |
niklasjakob | 0:7de36d52cfef | 401 | |
niklasjakob | 0:7de36d52cfef | 402 | } |
niklasjakob | 0:7de36d52cfef | 403 | #endif |
niklasjakob | 0:7de36d52cfef | 404 | |
niklasjakob | 0:7de36d52cfef | 405 | ble.waitForEvent(); // sleep |
niklasjakob | 0:7de36d52cfef | 406 | |
niklasjakob | 0:7de36d52cfef | 407 | } // end main loop |
niklasjakob | 0:7de36d52cfef | 408 | |
niklasjakob | 0:7de36d52cfef | 409 | } // end main |