Utility class for MIDI over Bluetooth LE

Dependencies:   BLE_API mbed nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BLEMIDI.h Source File

BLEMIDI.h

00001 /* Copyright (c) 2014 mbed.org, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without
00005  * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006  * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007  * Software is furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 
00019 #ifndef __BLEMIDI_H__
00020 #define __BLEMIDI_H__
00021 
00022 #include "BLEDevice.h"
00023 
00024 /** 
00025  * A class to communicate a BLE MIDI device
00026  */
00027 class BLEMIDI {
00028 public:
00029     /**
00030      * Constructor
00031      */
00032     BLEMIDI(BLEDevice *device);
00033     
00034     /**
00035      * Constructor with device name
00036      */
00037     BLEMIDI(BLEDevice *dev, char *deviceName);
00038 
00039     /**
00040      * Check if a BLE MIDI device is connected
00041      *
00042      * @returns true if a midi device is connected
00043      */
00044     bool connected();
00045 
00046     /**
00047      * Attach a callback called when the `Tune Request` event is received
00048      *
00049      * @param ptr function pointer
00050      *   prototype: void onTuneRequest();
00051      */
00052     inline void attachTuneRequest(void (*fn)()) {
00053         onTuneRequest = fn;
00054     }
00055 
00056     /**
00057      * Attach a callback called when the `Timing Clock` event is received
00058      *
00059      * @param ptr function pointer
00060      *   prototype: void onTimingClock();
00061      */
00062     inline void attachTimingClock(void (*fn)()) {
00063         onTimingClock = fn;
00064     }
00065 
00066     /**
00067      * Attach a callback called when the `Start` event is received
00068      *
00069      * @param ptr function pointer
00070      *   prototype: void onStart();
00071      */
00072     inline void attachStart(void (*fn)()) {
00073         onStart = fn;
00074     }
00075 
00076     /**
00077      * Attach a callback called when the `Continue` event is received
00078      *
00079      * @param ptr function pointer
00080      *   prototype: void onContinue();
00081      */
00082     inline void attachContinue(void (*fn)()) {
00083         onContinue = fn;
00084     }
00085 
00086     /**
00087      * Attach a callback called when the `Stop` event is received
00088      *
00089      * @param ptr function pointer
00090      *   prototype: void onStop();
00091      */
00092     inline void attachStop(void (*fn)()) {
00093         onStop = fn;
00094     }
00095 
00096     /**
00097      * Attach a callback called when the `Active Sensing` event is received
00098      *
00099      * @param ptr function pointer
00100      *   prototype: void onActiveSensing();
00101      */
00102     inline void attachActiveSensing(void (*fn)()) {
00103         onActiveSensing = fn;
00104     }
00105 
00106     /**
00107      * Attach a callback called when the `Reset` event is received
00108      *
00109      * @param ptr function pointer
00110      *   prototype: void onReset();
00111      */
00112     inline void attachReset(void (*fn)()) {
00113         onReset = fn;
00114     }
00115 
00116     /**
00117      * Attach a callback called when the `Program Change` event is received
00118      *
00119      * @param ptr function pointer
00120      *   prototype: void onProgramChange(uint8_t channel, uint8_t program);
00121      */
00122     inline void attachnProgramChange(void (*fn)(uint8_t, uint8_t)) {
00123         onProgramChange = fn;
00124     }
00125 
00126     /**
00127      * Attach a callback called when the `Channel Aftertouch` event is received
00128      *
00129      * @param ptr function pointer
00130      *   prototype: void onChannelAftertouch(uint8_t channel, uint8_t pressure);
00131      */
00132     inline void attachChannelAftertouch(void (*fn)(uint8_t, uint8_t)) {
00133         onChannelAftertouch = fn;
00134     }
00135 
00136     /**
00137      * Attach a callback called when the `Time Code Quarter Frame` event is received
00138      *
00139      * @param ptr function pointer
00140      *   prototype: void onTimeCodeQuarterFrame(uint8_t timing);
00141      */
00142     inline void attachTimeCodeQuarterFrame(void (*fn)(uint8_t)) {
00143         onTimeCodeQuarterFrame = fn;
00144     }
00145 
00146     /**
00147      * Attach a callback called when the `Song Select` event is received
00148      *
00149      * @param ptr function pointer
00150      *   prototype: void onSongSelect(uint8_t song);
00151      */
00152     inline void attachSongSelect(void (*fn)(uint8_t)) {
00153         onSongSelect = fn;
00154     }
00155 
00156     /**
00157      * Attach a callback called when the `Note Off` event is received
00158      *
00159      * @param ptr function pointer
00160      *   prototype: void onNoteOff(uint8_t channel, uint8_t note, uint8_t velocity);
00161      */
00162     inline void attachNoteOff(void (*fn)(uint8_t, uint8_t, uint8_t)) {
00163         onNoteOff = fn;
00164     }
00165 
00166     /**
00167      * Attach a callback called when the `Note On` event is received
00168      *
00169      * @param ptr function pointer
00170      *   prototype: void onNoteOn(uint8_t channel, uint8_t note, uint8_t velocity);
00171      */
00172     inline void attachNoteOn(void (*fn)(uint8_t, uint8_t, uint8_t)) {
00173         onNoteOn = fn;
00174     }
00175 
00176     /**
00177      * Attach a callback called when the `Polyphonic Aftertouch` event is received
00178      *
00179      * @param ptr function pointer
00180      *   prototype: void onPolyphonicAftertouch(uint8_t channel, uint8_t note, uint8_t pressure);
00181      */
00182     inline void attachPolyphonicAftertouch(void (*fn)(uint8_t, uint8_t, uint8_t)) {
00183         onPolyphonicAftertouch = fn;
00184     }
00185 
00186     /**
00187      * Attach a callback called when the `Control Change` event is received
00188      *
00189      * @param ptr function pointer
00190      *   prototype: void onControlChange(uint8_t channel, uint8_t function, uint8_t value);
00191      */
00192     inline void attachControlChange(void (*fn)(uint8_t, uint8_t, uint8_t)) {
00193         onControlChange = fn;
00194     }
00195 
00196     /**
00197      * Attach a callback called when the `Pitch Wheel` event is received
00198      *
00199      * @param ptr function pointer
00200      *   prototype: void onPitchWheel(uint8_t channel, uint16_t amount);
00201      */
00202     inline void attachPitchWheel(void (*fn)(uint8_t, uint16_t)) {
00203         onPitchWheel = fn;
00204     }
00205 
00206     /**
00207      * Attach a callback called when the `Song Position Pointer` event is received
00208      *
00209      * @param ptr function pointer
00210      *   prototype: void onSongPositionPointer(uint16_t position);
00211      */
00212     inline void attachSongPositionPointer(void (*fn)(uint16_t)) {
00213         onSongPositionPointer = fn;
00214     }
00215 
00216     /**
00217      * Attach a callback called when the `System Exclusive` event is received
00218      *
00219      * @param ptr function pointer
00220      *   prototype: void onSystemExclusive(uint8_t *sysex, uint16_t length, bool hasNextData);
00221      */
00222     inline void attachSystemExclusive(void (*fn)(uint8_t *, uint16_t, bool)) {
00223         onSystemExclusive = fn;
00224     }
00225 
00226     /**
00227      * Send a `Tune Request` event
00228      */
00229     void sendTuneRequest();
00230 
00231     /**
00232      * Send a `Timing Clock` event
00233      */
00234     void sendTimingClock();
00235 
00236     /**
00237      * Send a `Start` event
00238      */
00239     void sendStart();
00240 
00241     /**
00242      * Send a `Continue` event
00243      */
00244     void sendContinue();
00245 
00246     /**
00247      * Send a `Stop` event
00248      */
00249     void sendStop();
00250 
00251     /**
00252      * Send a `Active Sensing` event
00253      */
00254     void sendActiveSensing();
00255 
00256     /**
00257      * Send a `Reset` event
00258      */
00259     void sendReset();
00260 
00261     /**
00262      * Send a `Program Change` event
00263      *
00264      * @param channel 0-15
00265      * @param program 0-127
00266      */
00267     void sendProgramChange(uint8_t channel, uint8_t program);
00268 
00269     /**
00270      * Send a `Channel Aftertouch` event
00271      *
00272      * @param channel 0-15
00273      * @param pressure 0-127
00274      */
00275     void sendChannelAftertouch(uint8_t channel, uint8_t pressure);
00276 
00277     /**
00278      * Send a `Time Code Quarter Frame` event
00279      *
00280      * @param timing 0-127
00281      */
00282     void sendTimeCodeQuarterFrame(uint8_t timing);
00283 
00284     /**
00285      * Send a `Song Select` event
00286      *
00287      * @param song 0-127
00288      */
00289     void sendSongSelect(uint8_t song);
00290 
00291     /**
00292      * Send a `Note Off` event
00293      *
00294      * @param channel 0-15
00295      * @param note 0-127
00296      * @param velocity 0-127
00297      */
00298     void sendNoteOff(uint8_t channel, uint8_t note, uint8_t velocity);
00299 
00300     /**
00301      * Send a `Note On` event
00302      *
00303      * @param channel 0-15
00304      * @param note 0-127
00305      * @param velocity 0-127
00306      */
00307     void sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity);
00308 
00309     /**
00310      * Send a `Polyphonic Aftertouch` event
00311      *
00312      * @param channel 0-15
00313      * @param note 0-127
00314      * @param pressure 0-127
00315      */
00316     void sendPolyphonicAftertouch(uint8_t channel, uint8_t note, uint8_t pressure);
00317 
00318     /**
00319      * Send a `Control Change` event
00320      *
00321      * @param channel 0-15
00322      * @param function 0-127
00323      * @param value 0-127
00324      */
00325     void sendControlChange(uint8_t channel, uint8_t function, uint8_t value);
00326 
00327     /**
00328      * Send a `Pitch Wheel` event
00329      *
00330      * @param channel 0-15
00331      * @param amount 0-8192(center)-16383
00332      */
00333     void sendPitchWheel(uint8_t channel, uint16_t amount);
00334 
00335     /**
00336      * Send a `Song Position Pointer` event
00337      *
00338      * @param position 0-16383
00339      */
00340     void sendSongPositionPointer(uint16_t position);
00341 
00342     /**
00343      * Send a `System Exclusive` event
00344      *
00345      * @param sysex the data starts with `0xf0` and ends with `0xf7`
00346      * @param length
00347      */
00348     void sendSystemExclusive(uint8_t * sysex, uint16_t length);
00349 
00350     /**
00351      * Notifies BLE disconnection to this BLE MIDI instance
00352      */
00353     void onBleDisconnection(Gap::Handle_t handle, Gap::DisconnectionReason_t reason);
00354     
00355     /**
00356      * Notifies BLE connection to this BLE MIDI instance
00357      */
00358     void onBleConnection(Gap::Handle_t handle, Gap::addr_type_t type, const Gap::address_t addr, const Gap::ConnectionParams_t *params);
00359 
00360 private:
00361     bool isConnected;
00362 
00363     uint16_t sysExBufferPos;
00364     uint8_t sysExBuffer[128];
00365     
00366     uint16_t timestamp;
00367 
00368     uint8_t midiEventKind;
00369     uint8_t midiEventNote;
00370     uint8_t midiEventVelocity;
00371 
00372     enum MIDI_STATE {
00373         MIDI_STATE_TIMESTAMP = 0,
00374         MIDI_STATE_WAIT,
00375         MIDI_STATE_SIGNAL_2BYTES_2,
00376         MIDI_STATE_SIGNAL_3BYTES_2,
00377         MIDI_STATE_SIGNAL_3BYTES_3,
00378         MIDI_STATE_SIGNAL_SYSEX
00379     };
00380 
00381     MIDI_STATE midiState;
00382 
00383     void (*onTuneRequest)();
00384     void (*onTimingClock)();
00385     void (*onStart)();
00386     void (*onContinue)();
00387     void (*onStop)();
00388     void (*onActiveSensing)();
00389     void (*onReset)();
00390     void (*onProgramChange)(uint8_t, uint8_t);
00391     void (*onChannelAftertouch)(uint8_t, uint8_t);
00392     void (*onTimeCodeQuarterFrame)(uint8_t);
00393     void (*onSongSelect)(uint8_t);
00394     void (*onNoteOff)(uint8_t, uint8_t, uint8_t);
00395     void (*onNoteOn)(uint8_t, uint8_t, uint8_t);
00396     void (*onPolyphonicAftertouch)(uint8_t, uint8_t, uint8_t);
00397     void (*onControlChange)(uint8_t, uint8_t, uint8_t);
00398     void (*onPitchWheel)(uint8_t, uint16_t);
00399     void (*onSongPositionPointer)(uint16_t);
00400     void (*onSystemExclusive)(uint8_t *, uint16_t, bool);
00401 
00402     void sendMidiMessage(uint8_t data0);
00403     void sendMidiMessage(uint8_t data0, uint8_t data1);
00404     void sendMidiMessage(uint8_t data0, uint8_t data1, uint8_t data2);
00405 
00406     void dataWrittenCallback(const GattCharacteristicWriteCBParams *params);
00407 
00408     uint8_t midi[20];
00409 
00410     BLEDevice *device;
00411     GattCharacteristic *midiCharacteristic;    
00412     Timer tick;
00413 };
00414 
00415 #endif /* __BLEMIDI_H__ */