Skip to content

Commit 336e9b1

Browse files
committed
support sending all MIDI event types
1 parent 2c9dfea commit 336e9b1

File tree

2 files changed

+121
-34
lines changed

2 files changed

+121
-34
lines changed

libraries/Bluefruit52Lib/src/services/BLEMidi.cpp

Lines changed: 113 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**************************************************************************/
22
/*!
33
@file BLEMidi.cpp
4-
@author hathach
4+
@author hathach & toddtreece
55
66
@section LICENSE
77
@@ -93,10 +93,18 @@ typedef struct ATTR_PACKED
9393
{
9494
midi_header_t header;
9595
midi_timestamp_t timestamp;
96-
uint8_t data[3];
96+
uint8_t data[20];
9797
} midi_event_packet_t;
9898

99-
VERIFY_STATIC ( sizeof(midi_event_packet_t) == 5 );
99+
VERIFY_STATIC ( sizeof(midi_event_packet_t) == 22 );
100+
101+
typedef struct ATTR_PACKED
102+
{
103+
midi_header_t header;
104+
uint8_t data[20];
105+
} midi_split_packet_t;
106+
107+
VERIFY_STATIC ( sizeof(midi_split_packet_t) == 21 );
100108

101109
void blemidi_write_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset);
102110

@@ -208,36 +216,97 @@ int BLEMidi::read ( void )
208216
return _rxd_fifo.read(&ch) ? (int) ch : EOF;
209217
}
210218

219+
bool BLEMidi::oneByteMessage( uint8_t status )
220+
{
221+
// system messages
222+
if (status >= 0xF4 && status <= 0xFF) return true;
223+
224+
// system common
225+
if (status == 0xF1) return true;
226+
227+
return false;
228+
}
229+
230+
bool BLEMidi::twoByteMessage( uint8_t status )
231+
{
232+
// program change, aftertouch
233+
if (status >= 0xC0 && status <= 0xDF) return true;
234+
235+
// song select
236+
if (status == 0xF3) return true;
237+
238+
return false;
239+
}
240+
241+
bool BLEMidi::threeByteMessage( uint8_t status )
242+
{
243+
// note off, note on, aftertouch, control change
244+
if (status >= 0x80 && status <= 0xBF) return true;
245+
246+
// pitch wheel change
247+
if (status >= 0xE0 && status <= 0xEF) return true;
248+
249+
// song position pointer
250+
if (status == 0xF2) return true;
251+
252+
return false;
253+
}
254+
211255
size_t BLEMidi::write ( uint8_t b )
212256
{
213-
// MIDI Library will write event byte by byte. Locally buffered
214-
// Until we gather all 3 bytes
257+
// MIDI Library will write event byte by byte.
258+
// We need to buffer the data until we have a full event,
259+
// or until we reach the BLE payload limit.
215260
static uint8_t count = 0;
216-
static uint8_t buf[3] = { 0 };
261+
static uint8_t buf[16] = { 0 };
217262

263+
buf[count++] = b;
218264

219-
// Not SysEx message, keep accumulating data
220-
if ( buf[0] != 0xf0 )
265+
// if we are at the end of a sysex message
266+
// or at the end of the buffer
267+
if ((b == 0xF7) || (count == 16))
221268
{
222-
buf[count++] = b;
223-
224-
if ( count == 3 )
225-
{
226-
count = 0;
227269

228-
send(buf);
229-
}
230-
}else
231-
{
232-
// skip until we reach 0xF7
233-
if (b == 0xF7)
234-
{
235-
buf[0] = 0;
236-
count = 0;
270+
// send full event if the first byte is a status byte
271+
if (bitRead(buf[0], 7)) {
272+
send(buf, count);
273+
} else {
274+
sendSplit(buf, count);
237275
}
276+
277+
// reset buffer
278+
buf[0] = 0;
279+
count = 0;
280+
281+
return 1;
282+
238283
}
239284

285+
// don't send if this is a full or split sysex
286+
if (buf[0] == 0xF0 || ! bitRead(buf[0], 7))
287+
return 1;
288+
289+
// don't send if we don't have 1 byte
290+
if (oneByteMessage(buf[0]) && count != 1)
291+
return 1;
292+
293+
// don't send if we don't have 2 bytes
294+
if (twoByteMessage(buf[0]) && count != 2)
295+
return 1;
296+
297+
// don't send if we don't have 3 bytes
298+
if (threeByteMessage(buf[0]) && count != 3)
299+
return 1;
300+
301+
// send full event
302+
send(buf, count);
303+
304+
// reset buffer
305+
buf[0] = 0;
306+
count = 0;
307+
240308
return 1;
309+
241310
}
242311

243312
int BLEMidi::available ( void )
@@ -259,7 +328,7 @@ void BLEMidi::flush ( void )
259328
/*------------------------------------------------------------------*/
260329
/* Send Event (notify)
261330
*------------------------------------------------------------------*/
262-
err_t BLEMidi::send(uint8_t data[])
331+
err_t BLEMidi::send(uint8_t data[], uint8_t len)
263332
{
264333
uint32_t tstamp = millis();
265334

@@ -276,16 +345,31 @@ void BLEMidi::flush ( void )
276345
}}
277346
};
278347

279-
memcpy(event.data, data, 3);
348+
memcpy(event.data, data, len);
280349

281-
VERIFY_STATUS( _io.notify(&event, sizeof(event)) );
350+
// send data length + 1 byte for header + 1 byte for timestamp
351+
VERIFY_STATUS( _io.notify(&event, len + 2) );
282352

283353
return ERROR_NONE;
284354
}
285355

286-
err_t BLEMidi::send(uint8_t status, uint8_t byte1, uint8_t byte2)
356+
err_t BLEMidi::sendSplit(uint8_t data[], uint8_t len)
287357
{
288-
uint8_t data[] = { status, byte1, byte2 };
289-
return send(data);
290-
}
358+
uint32_t tstamp = millis();
359+
360+
midi_split_packet_t event =
361+
{
362+
.header = {{
363+
.timestamp_hi = (uint8_t) ((tstamp & 0x1F80UL) >> 7),
364+
.start_bit = 1
365+
}}
366+
};
367+
368+
memcpy(event.data, data, len);
291369

370+
// send data length + 1 byte for header
371+
// don't include the second timestamp byte
372+
VERIFY_STATUS( _io.notify(&event, len + 1) );
373+
374+
return ERROR_NONE;
375+
}

libraries/Bluefruit52Lib/src/services/BLEMidi.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
/**************************************************************************/
22
/*!
33
@file BLEMidi.h
4-
@author hathach
4+
@author hathach & toddtreece
55
66
@section LICENSE
77
88
Software License Agreement (BSD License)
99
10-
Copyright (c) 2017, Adafruit Industries (adafruit.com)
11-
All rights reserved.
10+
Copyright (c) 2017, Adafruit Industries (adafruit.com) All rights reserved.
1211
1312
Redistribution and use in source and binary forms, with or without
1413
modification, are permitted provided that the following conditions are met:
@@ -60,8 +59,12 @@ class BLEMidi: public BLEService, public Stream
6059
void begin(int baudrate); // MidiInterface
6160
bool notifyEnabled(void);
6261

63-
err_t send(uint8_t data[]);
64-
err_t send(uint8_t status, uint8_t byte1, uint8_t byte2);
62+
err_t send(uint8_t data[], uint8_t len);
63+
err_t sendSplit(uint8_t data[], uint8_t len);
64+
65+
bool oneByteMessage(uint8_t status);
66+
bool twoByteMessage(uint8_t status);
67+
bool threeByteMessage(uint8_t status);
6568

6669
void setWriteCallback(midi_write_cb_t fp);
6770
void autoMIDIread(void* midi_obj);

0 commit comments

Comments
 (0)