Skip to content

Commit 221a072

Browse files
committed
Merge branch 'master' of github.com:adafruit/Adafruit_nRF52_Arduino
libraries/Bluefruit52Lib/examples/Peripheral/blemidi_callback/blemidi_callback.ino
2 parents c90609b + 4077e29 commit 221a072

File tree

10 files changed

+521
-63
lines changed

10 files changed

+521
-63
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
/tools/nrfutil-0.5.2/dist/
2828
/tools/nrfutil-0.5.2/nrfutil.egg-info/
2929
/tools/.idea/
30+
/tools/midi_tests/node_modules
3031

3132
.DS_Store
3233
*.swp

libraries/Bluefruit52Lib/examples/Peripheral/blemidi/blemidi.ino

Lines changed: 94 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,100 +14,134 @@
1414
#include <bluefruit.h>
1515
#include <MIDI.h>
1616

17-
// To test:
18-
// - Run this sketch and open the Serial Monitor
19-
// - Open the iGrand Piano Free app
20-
// - Open the midimittr app on your phone and under Clients select "Bluefruit52"
21-
// - When you see the 'Connected' label switch to the Routing panel
22-
// - Set the Destination to 'iGrand Piano'
23-
// - Switch to the iGrand Piano Free app and you should see notes playing one by one
24-
2517
BLEDis bledis;
2618
BLEMidi blemidi;
2719

28-
// Create MIDI instance using ble service as physical layer
20+
// Create a new instance of the Arduino MIDI Library,
21+
// and attach BluefruitLE MIDI as the transport.
2922
MIDI_CREATE_BLE_INSTANCE(blemidi);
3023

24+
// Variable that holds the current position in the sequence.
25+
int position = 0;
26+
27+
// Store example melody as an array of note values
28+
byte note_sequence[] = {
29+
74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
30+
74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
31+
56,61,64,68,74,78,81,86,90,93,98,102
32+
};
33+
34+
// Variable to hold the last time we sent a note
35+
unsigned long previousSend = 0;
36+
3137
void setup()
3238
{
39+
3340
Serial.begin(115200);
34-
Serial.println("Bluefruit52 BLEMIDI Example");
41+
Serial.println("Adafruit Bluefruit52 MIDI over Bluetooth LE Example");
3542

3643
Bluefruit.begin();
37-
Bluefruit.setName("Bluefruit52");
44+
Bluefruit.setName("Bluefruit52 MIDI");
3845

39-
// Setup the BLE LED to be enabled on CONNECT
40-
// Note: This is actually the default behaviour, but provided
41-
// here in case you want to control this manually via PIN 19
42-
Bluefruit.autoConnLed(true);
43-
44-
Bluefruit.setConnectCallback(connect_callback);
45-
Bluefruit.setDisconnectCallback(disconnect_callback);
46-
46+
// Setup the on board blue LED to be enabled on CONNECT
47+
Bluefruit.autoConnLed(true);
4748

4849
// Configure and Start Device Information Service
4950
bledis.setManufacturer("Adafruit Industries");
5051
bledis.setModel("Bluefruit Feather52");
5152
bledis.begin();
52-
53-
/* Start BLE MIDI
54-
* Note: Apple requires BLE device must have min connection interval >= 20m
55-
* ( The smaller the connection interval the faster we could send data).
56-
* However for HID and MIDI device, Apple could accept min connection interval
57-
* up to 11.25 ms. Therefore BLEMidi::start() will try to set the min and max
58-
* connection interval to 11.25 ms and 15 ms respectively for best performance.
59-
*/
60-
blemidi.setWriteCallback(midi_write_callback);
61-
blemidi.begin();
62-
63-
// Initialize MIDI, listen to all channels
53+
54+
// Initialize MIDI, and listen to all MIDI channels
6455
MIDI.begin(MIDI_CHANNEL_OMNI);
6556

66-
// Set up Advertising Packet
67-
setupAdv();
57+
// Attach the handleNoteOn function to the MIDI Library. It will
58+
// be called whenever the Bluefruit receives MIDI Note On messages.
59+
MIDI.setHandleNoteOn(handleNoteOn);
6860

69-
// Start Advertising
70-
Bluefruit.Advertising.start();
71-
}
61+
// Do the same for MIDI Note Off messages.
62+
MIDI.setHandleNoteOff(handleNoteOff);
7263

73-
void setupAdv(void)
74-
{
75-
//Bluefruit.Advertising.addTxPower();
64+
// Set General Discoverable Mode flag
7665
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
66+
67+
// Advertise TX Power
7768
Bluefruit.Advertising.addTxPower();
7869

79-
// Include bleuart 128-bit uuid
70+
// Advertise BLE MIDI Service
8071
Bluefruit.Advertising.addService(blemidi);
8172

82-
// There is no room for Name in Advertising packet
83-
// Use Scan response for Name
73+
// Advertise device name in the Scan Response
8474
Bluefruit.ScanResponse.addName();
85-
}
8675

87-
void midi_write_callback(void)
88-
{
89-
MIDI.read();
76+
// Start Advertising
77+
Bluefruit.Advertising.start();
78+
9079
}
9180

92-
void loop()
81+
void handleNoteOn(byte channel, byte pitch, byte velocity)
9382
{
94-
if ( Bluefruit.connected() && blemidi.notifyEnabled() )
95-
{
96-
MIDI.sendNoteOn(42, 127, 1); // Send a Note (pitch 42, velo 127 on channel 1)
97-
delay(1000); // Wait for a second
98-
MIDI.sendNoteOff(42, 0, 1); // Stop the note
99-
}
83+
// Log when a note is pressed.
84+
Serial.printf("Note on: channel = %d, pitch = %d, velocity - %d", channel, pitch, velocity);
85+
Serial.println();
10086
}
10187

102-
void connect_callback(void)
88+
void handleNoteOff(byte channel, byte pitch, byte velocity)
10389
{
104-
Serial.println("Connected");
90+
// Log when a note is released.
91+
Serial.printf("Note off: channel = %d, pitch = %d, velocity - %d", channel, pitch, velocity);
92+
Serial.println();
10593
}
10694

107-
void disconnect_callback(uint8_t reason)
95+
void loop()
10896
{
109-
(void) reason;
110-
111-
Serial.println("Disconnected");
112-
Serial.println("Bluefruit will auto start advertising (default)");
97+
98+
// Don't continue if we aren't connected.
99+
if (! Bluefruit.connected()) {
100+
return;
101+
}
102+
103+
// Don't continue if the connected device isn't ready to receive messages.
104+
if (! blemidi.notifyEnabled()) {
105+
return;
106+
}
107+
108+
// read any new MIDI messages
109+
MIDI.read();
110+
111+
// Store the current time
112+
unsigned long now = millis();
113+
114+
// Check if enough time has passed since last send
115+
if (now - previousSend < 286) {
116+
return;
117+
}
118+
119+
// Setup variables for the current and previous
120+
// positions in the note sequence.
121+
int current = position;
122+
int previous = position - 1;
123+
124+
// If we currently are at position 0, set the
125+
// previous position to the last note in the sequence.
126+
if (previous < 0) {
127+
previous = sizeof(note_sequence) - 1;
128+
}
129+
130+
// Send Note On for current position at full velocity (127) on channel 1.
131+
MIDI.sendNoteOn(note_sequence[current], 127, 1);
132+
133+
// Send Note Off for previous note.
134+
MIDI.sendNoteOff(note_sequence[previous], 0, 1);
135+
136+
// Increment position
137+
position++;
138+
139+
// If we are at the end of the sequence, start over.
140+
if (position >= sizeof(note_sequence)) {
141+
position = 0;
142+
}
143+
144+
// Log the send time
145+
previousSend = now;
146+
113147
}

libraries/Bluefruit52Lib/src/services/BLEMidi.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,18 @@ void BLEMidi::_write_handler(uint8_t* data, uint16_t len)
198198
void BLEMidi::setWriteCallback(midi_write_cb_t fp)
199199
{
200200
_write_cb = fp;
201-
_io.setWriteCallback(blemidi_write_cb);
201+
}
202+
203+
void BLEMidi::begin(int baudrate)
204+
{
205+
(void) baudrate;
206+
begin();
202207
}
203208

204209
err_t BLEMidi::begin(void)
205210
{
211+
_io.setWriteCallback(blemidi_write_cb);
212+
206213
VERIFY_STATUS( this->addToGatt() );
207214

208215
// IO characteristic

libraries/Bluefruit52Lib/src/services/BLEMidi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
#define MIDI_CREATE_BLE_INSTANCE(midiService) MIDI_CREATE_INSTANCE(BLEMidi, midiService, MIDI)
4646

47-
#define BLE_MIDI_DEFAULT_FIFO_DEPTH 128
47+
#define BLE_MIDI_DEFAULT_FIFO_DEPTH 256
4848

4949
extern const uint8_t BLEMIDI_UUID_SERVICE[];
5050
extern const uint8_t BLEMIDI_UUID_CHR_IO[];
@@ -70,7 +70,7 @@ class BLEMidi: public BLEService, public Stream
7070
virtual err_t begin(void);
7171

7272
// MidiInterface
73-
void begin(int baudrate) { (void) baudrate; }
73+
void begin(int baudrate);
7474

7575
bool notifyEnabled(void);
7676

tools/midi_tests/README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# MIDI Tests
2+
3+
This folder contains a small number of tests used to verify BLE MIDI features.
4+
5+
## Setup
6+
7+
First, you will need the current stable version of [Node.js][node] installed.
8+
9+
```console
10+
$ node -v
11+
v7.4.0
12+
```
13+
14+
Next, cd to `tools/midi_tests` and run `npm install`.
15+
16+
```console
17+
$ cd tools/midi_tests
18+
$ npm install
19+
```
20+
21+
## RX Test
22+
23+
This will test receiving MIDI messages on the nRF52 feather.
24+
25+
* Upload the `rx_arduino` example to your nRF52 feather.
26+
* Open the serial monitor, and connect to the feather on OS X using Audio MIDI Setup.
27+
* Once you are connected, navigate to the `tools/midi_tests` folder and run the `rx.js` test.
28+
29+
```console
30+
$ cd tools/midi_tests
31+
$ node rx.js
32+
```
33+
34+
The test will ask how fast you would like to send messages. The default is 100ms. Enter a number and press return.
35+
36+
```
37+
? Send interval (ms) 100
38+
```
39+
40+
Next, the test will ask you to select a MIDI port. Select the Bluefruit52 from the list.
41+
42+
```
43+
? Select port Bluefruit52 Bluetooth
44+
```
45+
46+
The test will begin sending messages at the specified interval. It will send 128 note on and 128 note off messages.
47+
48+
```
49+
note on [===============================================================] 128/128
50+
note off [===============================================================] 128/128
51+
```
52+
53+
Check the Arduino Serial monitor and confirm that you have received all 128 note on and 128 note off messages.
54+
55+
```
56+
note on count: 128
57+
note off count: 128
58+
```
59+
60+
If you have 128 of each, the test passed.
61+
62+
## TX Test
63+
64+
This will test sending MIDI messages from the nRF52 feather.
65+
66+
* Upload the `tx_arduino` example to your nRF52 feather.
67+
* Open the serial monitor, and connect to the feather on OS X using Audio MIDI Setup.
68+
* Once you are connected, navigate to the `tools/midi_tests` folder and run the `tx.js` test.
69+
70+
```console
71+
$ cd tools/midi_tests
72+
$ node tx.js
73+
```
74+
75+
The test will ask you to select a MIDI port. Select the Bluefruit52 from the list.
76+
77+
```
78+
? Select port Bluefruit52 Bluetooth
79+
```
80+
81+
In the Arduino Serial Monitor, you will see a message like the one seen below. Press **space** and then **return** to start the test.
82+
83+
```
84+
Start the node TX test and press a key in the serial monitor to start the test...
85+
```
86+
87+
The nRF52 will now start sending MIDI messages to the test. Check the counters and make sure you receive all 128 note on and 128 note off messages.
88+
89+
```
90+
$ node tx.js
91+
? Select port Bluefruit52 Bluetooth
92+
note on [===============================================================] 128/128
93+
note off [===============================================================] 128/128
94+
```
95+
96+
If you have 128 of each, the test passed.
97+
98+
[node]: https://nodejs.org/

tools/midi_tests/package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "midi-test",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"dependencies": {
12+
"async": "^2.0.0-rc.2",
13+
"inquirer": "^3.0.5",
14+
"midi": "^0.9.4",
15+
"multi-progress": "^2.0.0"
16+
}
17+
}

0 commit comments

Comments
 (0)