Skip to content

Commit

Permalink
misc cleanup and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
stuffmatic committed Mar 21, 2023
1 parent f80fc35 commit ce5cd55
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 263 deletions.
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: Apache-2.0

# For the sake of demonstration, we add the driver directory as a zephyr module
# by hand. If your driver is a project that's managed by west, you can remove this line.
# Add the BLE MIDI service module. CMAKE_CURRENT_SOURCE_DIR is
# the dir containing the sample app's CMakeLists.txt, i.e the
# repository root dir, which is also the root dir of the
# driver module.
list(APPEND ZEPHYR_EXTRA_MODULES
${CMAKE_CURRENT_SOURCE_DIR}
)
Expand Down
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,30 @@

This is a [Zephyr](https://www.zephyrproject.org/) implementation of the [BLE-MIDI service specification](BLE-MIDI-spec.pdf), which allows for wireless transfer of [MIDI](https://en.wikipedia.org/wiki/MIDI) data over [Bluetooth low energy](https://en.wikipedia.org/wiki/Bluetooth_Low_Energy).

The code for parsing and writing BLE MIDI packets covers the entire packet encoding specification, including running status, timestamp wrapping and single and multi packet system exclusive messages. To facilitate testing and reuse in other projects, this code is completely self contained and has no external dependencies.
The implementation covers the entire BLE MIDI packet encoding specification, including running status, timestamp wrapping and single and multi packet system exclusive messages.

To minimize latency, a connection interval of 7.5 ms is requested, which is the smallest interval allowed by the Bluetooth low energy specification. Jitter can be reduced (at the expense of latency) by using the timestamps of incoming messages, but this is beyond the scope of this implementation. More info about this can be found in [this post](https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-ble-midi-with-regards-to-timing-1293631358).
To minimize latency, a connection interval of 7.5 ms is requested, which is the smallest interval allowed by the Bluetooth low energy specification (note that a central may or may not accept this value). Also, outgoing MIDI events may optionally be accumulated and transmitted at the start of the next connection event to reduce latency (see the `BLE_MIDI_NRF_BATCHED_TX` configuration option). This technique is described in [this post](https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-ble-midi-with-regards-to-timing-1293631358), which also covers strategies for reducing jitter (at the expense of latency) that are currently beyond the scope of this implementation.

## Usage

TODO
The BLE MIDI service implementation is contained in a Zephyr module. The sample app's [CMakeLists.txt](CMakeLists.txt) file shows one way of adding this module to an app.

The public API is defined in [ble_midi.h](ble_midi/include/ble_midi/ble_midi.h).

## Sample app

The [sample app](src/main.c) shows how to send and receive MIDI data. The app requires a board with at least three buttons and three LEDs, for example [nrf52840dk_nrf52840](https://docs.zephyrproject.org/latest/boards/arm/nrf52840dk_nrf52840/doc/index.html) or [nrf5340dk_nrf5340](https://docs.zephyrproject.org/latest/boards/arm/nrf5340dk_nrf5340/doc/index.html).

* __Button 1__ - Send three simultaneous note on/off messages
* __Button 2__ - Send a short sysex message
* __Button 3__ - Send a long, streaming sysex message
* __LED 1__ - On when connected to a BLE MIDI central
* __LED 2__ - Toggles on/off when receiving sysex messages
* __LED 3__ - Toggles on/off when receiving non-sysex messages

## Configuration options

* `BLE_MIDI_SEND_RUNNING_STATUS` - Set to `n` to disable running status (omission of repeated channel message status bytes) in sent packets. Defaults to `y`, which minimizes the size of outgoing packets.
* `BLE_MIDI_SEND_NOTE_OFF_AS_NOTE_ON` - Determines if sent note off messages should be represented as note on messages with zero velocity, which increases running status efficiency. Defaults to `y`.
* `BLE_MIDI_NRF_BATCHED_TX` - When building for nRF SOC:s, this option can be set to `y` to buffer outgoing messages and send them at the start of the next connection interval (as described [here](https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-ble-midi-with-regards-to-timing-1293631358)), which lowers latency and increases throughput. If set to `n` (the default) one BLE MIDI packet is sent per MIDI message.
* `CONFIG_BLE_MIDI_SEND_RUNNING_STATUS` - Set to `n` to disable running status (omission of repeated channel message status bytes) in sent packets. Defaults to `y`, which minimizes the size of outgoing packets.
* `CONFIG_BLE_MIDI_SEND_NOTE_OFF_AS_NOTE_ON` - Determines if sent note off messages should be represented as note on messages with zero velocity, which increases running status efficiency. Defaults to `y`.
* `CONFIG_BLE_MIDI_NRF_BATCHED_TX` - When building for nRF SOC:s, this option can be set to `y` to buffer outgoing messages and send them at the start of the next connection interval (as described [here](https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-ble-midi-with-regards-to-timing-1293631358)), which reduces latency and increases throughput. If set to `n` (the default) one BLE MIDI packet is sent per MIDI message.
* `CONFIG_BLE_MIDI_TX_PACKET_MAX_SIZE` - Determines the maximum size of transmitted BLE MIDI packets.
3 changes: 3 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* sysex continuation where end byte is the first byte in the last packet. handle this in parser? or treat this as sysex continuation packet?
* make unit tests main return non zero on failure
* disconnect API?
* select/dpend on BT_* config vars
* don't use softdevice?
* fix stack overflow when receiving events

# ble stuff

Expand Down
14 changes: 13 additions & 1 deletion ble_midi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ config BLE_MIDI
depends on BT
depends on BT_PERIPHERAL

if BLE_MIDI

config BLE_MIDI_SEND_RUNNING_STATUS
bool ""
default y
Expand All @@ -13,4 +15,14 @@ config BLE_MIDI_SEND_NOTE_OFF_AS_NOTE_ON

config BLE_MIDI_NRF_BATCH_TX
bool ""
default n
default n

config BLE_MIDI_TX_PACKET_MAX_SIZE
int ""
default 32

module = BLE_MIDI
module-str = BLE MIDI
source "subsys/logging/Kconfig.template.log_config"

endif # BLE_MIDI
15 changes: 9 additions & 6 deletions ble_midi/include/ble_midi/ble_midi.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef _BLE_MIDI_H_
#define _BLE_MIDI_H_

#include <zephyr/zephyr.h>
#include <zephyr/bluetooth/uuid.h>

#define BLE_MIDI_SERVICE_UUID \
Expand All @@ -21,8 +20,9 @@ typedef void (*ble_midi_sysex_data_cb_t)(uint8_t data_byte);
typedef void (*ble_midi_sysex_end_cb_t)(uint16_t timestamp);

/** Callbacks set to NULL are ignored. */
struct ble_midi_callbacks {
ble_midi_available_cb_t available_cb;
struct ble_midi_callbacks
{
ble_midi_available_cb_t available_cb;
ble_midi_tx_available_cb_t tx_available_cb;
ble_midi_message_cb_t midi_message_cb;
ble_midi_sysex_start_cb_t sysex_start_cb;
Expand All @@ -35,11 +35,14 @@ struct ble_midi_callbacks {
*/
void ble_midi_init(struct ble_midi_callbacks *callbacks);

/** Sends a non-sysex MIDI message. 3 zero padded bytes. */
int ble_midi_tx_msg(uint8_t* bytes);
/**
* Sends a non-sysex MIDI message.
* @param bytes A buffer of length 3 containing the message bytes to send.
*/
int ble_midi_tx_msg(uint8_t *bytes);

int ble_midi_tx_sysex_start();
int ble_midi_tx_sysex_data(uint8_t* bytes, int num_bytes);
int ble_midi_tx_sysex_data(uint8_t *bytes, int num_bytes);
int ble_midi_tx_sysex_end();

#endif
Loading

0 comments on commit ce5cd55

Please sign in to comment.