This commit is contained in:
pszsh 2026-03-09 01:56:29 -07:00
parent 2187943124
commit 75ba8b6f4a
18 changed files with 589 additions and 111 deletions

View File

@ -5,7 +5,7 @@ option(CS_MIDI_BLE "Enable BLE MIDI interface (BTstack)" ON)
option(CS_MIDI_USB "Enable USB MIDI interface (TinyUSB)" OFF) option(CS_MIDI_USB "Enable USB MIDI interface (TinyUSB)" OFF)
option(CS_MIDI_SERIAL "Enable Serial MIDI interface (UART)" OFF) option(CS_MIDI_SERIAL "Enable Serial MIDI interface (UART)" OFF)
option(CS_MIDI_APPLEMIDI "Enable AppleMIDI interface (RTP-MIDI over WiFi)" OFF) option(CS_MIDI_APPLEMIDI "Enable AppleMIDI interface (RTP-MIDI over WiFi)" OFF)
option(CS_MIDI_HID_MOUSE "Advertise as HID mouse for BLE auto-reconnect" OFF) option(CS_MIDI_HID_KEYBOARD "HID keyboard + Battery Service for BLE auto-reconnect" OFF)
# Core sources always compiled # Core sources always compiled
set(CS_MIDI_CORE_SOURCES set(CS_MIDI_CORE_SOURCES
@ -80,7 +80,7 @@ target_compile_definitions(cs_midi PUBLIC
$<$<BOOL:${CS_MIDI_USB}>:CS_MIDI_USB=1> $<$<BOOL:${CS_MIDI_USB}>:CS_MIDI_USB=1>
$<$<BOOL:${CS_MIDI_SERIAL}>:CS_MIDI_SERIAL=1> $<$<BOOL:${CS_MIDI_SERIAL}>:CS_MIDI_SERIAL=1>
$<$<BOOL:${CS_MIDI_APPLEMIDI}>:CS_MIDI_APPLEMIDI=1> $<$<BOOL:${CS_MIDI_APPLEMIDI}>:CS_MIDI_APPLEMIDI=1>
$<$<BOOL:${CS_MIDI_HID_MOUSE}>:CS_MIDI_HID_MOUSE=1> $<$<BOOL:${CS_MIDI_HID_KEYBOARD}>:CS_MIDI_HID_KEYBOARD=1>
) )
target_link_libraries(cs_midi target_link_libraries(cs_midi

View File

@ -8,15 +8,15 @@ namespace cs::midi_ble_btstack {
namespace { namespace {
#ifdef CS_MIDI_HID_MOUSE #ifdef CS_MIDI_HID_KEYBOARD
uint8_t adv_data[] { uint8_t adv_data[] {
// Flags general discoverable // Flags general discoverable
0x02, BLUETOOTH_DATA_TYPE_FLAGS, 0x06, 0x02, BLUETOOTH_DATA_TYPE_FLAGS, 0x06,
// HID Service UUID (16-bit) // HID Service UUID (16-bit)
0x03, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS, 0x03, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
0x12, 0x18, 0x12, 0x18,
// Appearance: Mouse (0x03C2) // Appearance: Keyboard (0x03C1)
0x03, BLUETOOTH_DATA_TYPE_APPEARANCE, 0xC2, 0x03, 0x03, BLUETOOTH_DATA_TYPE_APPEARANCE, 0xC1, 0x03,
// MIDI Service UUID (128-bit) // MIDI Service UUID (128-bit)
0x11, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS, 0x11, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
0x00, 0xc7, 0xc4, 0x4e, 0xe3, 0x6c, 0x51, 0xa7, 0x33, 0x4b, 0xe8, 0xed, 0x00, 0xc7, 0xc4, 0x4e, 0xe3, 0x6c, 0x51, 0xa7, 0x33, 0x4b, 0xe8, 0xed,
@ -42,7 +42,7 @@ uint8_t adv_rsp_data[LE_ADVERTISING_DATA_SIZE] {
' ', 'M', 'I', 'D', 'I'}; ' ', 'M', 'I', 'D', 'I'};
uint8_t adv_rsp_data_len() { return adv_rsp_data[0] + 1; } uint8_t adv_rsp_data_len() { return adv_rsp_data[0] + 1; }
#ifdef CS_MIDI_HID_MOUSE #ifdef CS_MIDI_HID_KEYBOARD
void set_adv_connection_interval(uint16_t, uint16_t) {} void set_adv_connection_interval(uint16_t, uint16_t) {}
#else #else
void set_adv_connection_interval(uint16_t min_itvl, uint16_t max_itvl) { void set_adv_connection_interval(uint16_t min_itvl, uint16_t max_itvl) {

View File

@ -11,9 +11,10 @@
#include "../BLEAPI.hpp" #include "../BLEAPI.hpp"
#include "advertising.hpp" #include "advertising.hpp"
#ifdef CS_MIDI_HID_MOUSE #ifdef CS_MIDI_HID_KEYBOARD
#include "gatt_midi_hog.h" #include "gatt_midi_hog.h"
#include <ble/gatt-service/hids_device.h> #include <ble/gatt-service/hids_device.h>
#include <ble/gatt-service/battery_service_server.h>
#else #else
#include "gatt_midi.h" #include "gatt_midi.h"
#endif #endif
@ -36,34 +37,31 @@ BLESettings settings;
btstack_packet_callback_registration_t hci_event_callback_registration; btstack_packet_callback_registration_t hci_event_callback_registration;
btstack_packet_callback_registration_t sm_event_callback_registration; btstack_packet_callback_registration_t sm_event_callback_registration;
#ifdef CS_MIDI_HID_MOUSE #ifdef CS_MIDI_HID_KEYBOARD
const uint8_t hid_descriptor_mouse[] = { const uint8_t hid_descriptor_keyboard[] = {
0x05, 0x01, // Usage Page (Generic Desktop) 0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse) 0x09, 0x06, // Usage (Keyboard)
0xa1, 0x01, // Collection (Application) 0xa1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID 1 0x85, 0x01, // Report ID 1
0x09, 0x01, // Usage (Pointer) 0x05, 0x07, // Usage Page (Keyboard/Keypad)
0xa1, 0x00, // Collection (Physical) 0x19, 0xe0, // Usage Minimum (Left Control)
0x05, 0x09, // Usage Page (Buttons) 0x29, 0xe7, // Usage Maximum (Right GUI)
0x19, 0x01, // Usage Minimum (1) 0x15, 0x00, // Logical Minimum (0)
0x29, 0x03, // Usage Maximum (3) 0x25, 0x01, // Logical Maximum (1)
0x15, 0x00, // Logical Minimum (0) 0x75, 0x01, // Report Size (1)
0x25, 0x01, // Logical Maximum (1) 0x95, 0x08, // Report Count (8)
0x95, 0x03, // Report Count (3) 0x81, 0x02, // Input (Data,Var,Abs) — modifiers
0x75, 0x01, // Report Size (1) 0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs) 0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1) 0x81, 0x01, // Input (Const) — reserved
0x75, 0x05, // Report Size (5) 0x95, 0x06, // Report Count (6)
0x81, 0x03, // Input (Const,Var,Abs) — padding 0x75, 0x08, // Report Size (8)
0x05, 0x01, // Usage Page (Generic Desktop) 0x15, 0x00, // Logical Minimum (0)
0x09, 0x30, // Usage (X) 0x26, 0xff, 0x00, // Logical Maximum (255)
0x09, 0x31, // Usage (Y) 0x05, 0x07, // Usage Page (Keyboard/Keypad)
0x15, 0x81, // Logical Minimum (-127) 0x19, 0x00, // Usage Minimum (0)
0x25, 0x7f, // Logical Maximum (127) 0x29, 0xff, // Usage Maximum (255)
0x75, 0x08, // Report Size (8) 0x81, 0x00, // Input (Data,Ary,Abs) — 6KRO keycodes
0x95, 0x02, // Report Count (2)
0x81, 0x06, // Input (Data,Var,Rel)
0xc0, // End Collection
0xc0 // End Collection 0xc0 // End Collection
}; };
@ -73,7 +71,6 @@ constexpr uint16_t gap_device_name_handle =
void hid_packet_handler(uint8_t packet_type, uint16_t, uint8_t *packet, uint16_t) { void hid_packet_handler(uint8_t packet_type, uint16_t, uint8_t *packet, uint16_t) {
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET) return;
if (hci_event_packet_get_type(packet) != HCI_EVENT_HIDS_META) return; if (hci_event_packet_get_type(packet) != HCI_EVENT_HIDS_META) return;
// Accept HID events but never send mouse reports
} }
#endif #endif
@ -225,7 +222,7 @@ uint16_t att_read_callback([[maybe_unused]] hci_con_handle_t connection_handle,
[[maybe_unused]] uint16_t offset, [[maybe_unused]] uint16_t offset,
[[maybe_unused]] uint8_t *buffer, [[maybe_unused]] uint8_t *buffer,
[[maybe_unused]] uint16_t buffer_size) { [[maybe_unused]] uint16_t buffer_size) {
#ifdef CS_MIDI_HID_MOUSE #ifdef CS_MIDI_HID_KEYBOARD
if (att_handle == gap_device_name_handle) { if (att_handle == gap_device_name_handle) {
const char *name = settings.device_name; const char *name = settings.device_name;
auto len = static_cast<uint16_t>(std::strlen(name)); auto len = static_cast<uint16_t>(std::strlen(name));
@ -294,9 +291,10 @@ void le_midi_setup(const BLESettings &ble_settings) {
SM_AUTHREQ_BONDING); SM_AUTHREQ_BONDING);
// setup ATT server // setup ATT server
att_server_init(profile_data, att_read_callback, att_write_callback); att_server_init(profile_data, att_read_callback, att_write_callback);
#ifdef CS_MIDI_HID_MOUSE #ifdef CS_MIDI_HID_KEYBOARD
hids_device_init(0, hid_descriptor_mouse, sizeof(hid_descriptor_mouse)); hids_device_init(0, hid_descriptor_keyboard, sizeof(hid_descriptor_keyboard));
hids_device_register_packet_handler(hid_packet_handler); hids_device_register_packet_handler(hid_packet_handler);
battery_service_server_init(100);
#endif #endif
// setup advertisements // setup advertisements
le_midi_setup_adv(ble_settings); le_midi_setup_adv(ble_settings);
@ -368,4 +366,10 @@ void notify(BLEConnectionHandle conn_handle,
DEBUGREF("all done " << micros() - t0); DEBUGREF("all done " << micros() - t0);
} }
#ifdef CS_MIDI_HID_KEYBOARD
void set_battery_level(uint8_t percent) {
battery_service_server_set_battery_value(percent);
}
#endif
} // namespace cs::midi_ble_btstack } // namespace cs::midi_ble_btstack

View File

@ -8,4 +8,8 @@ bool init(MIDIBLEInstance &instance, BLESettings settings);
void notify(BLEConnectionHandle conn_handle, void notify(BLEConnectionHandle conn_handle,
BLECharacteristicHandle char_handle, BLEDataView data); BLECharacteristicHandle char_handle, BLEDataView data);
#ifdef CS_MIDI_HID_KEYBOARD
void set_battery_level(uint8_t percent);
#endif
} // namespace cs::midi_ble_btstack } // namespace cs::midi_ble_btstack

View File

@ -3,8 +3,8 @@ CHARACTERISTIC, GATT_DATABASE_HASH, READ,
PRIMARY_SERVICE, GAP_SERVICE PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ | DYNAMIC, CHARACTERISTIC, GAP_DEVICE_NAME, READ | DYNAMIC,
// 0x03C2 = HID Mouse // 0x03C1 = HID Keyboard
CHARACTERISTIC, GAP_APPEARANCE, READ, C2 03 CHARACTERISTIC, GAP_APPEARANCE, READ, C1 03
// MIDI Service // MIDI Service
PRIMARY_SERVICE, 03B80E5A-EDE8-4B33-A751-6CE34EC4C700 PRIMARY_SERVICE, 03B80E5A-EDE8-4B33-A751-6CE34EC4C700
@ -12,3 +12,6 @@ CHARACTERISTIC, 7772E5DB-3868-4112-A1A9-F2669D106BF3, READ | WRITE_WITHOUT_RESPO
// HID Service // HID Service
#import <hids.gatt> #import <hids.gatt>
// Battery Service
#import <battery_service.gatt>

View File

@ -1,12 +1,19 @@
// Generated from gatt_midi_hog.gatt — MIDI + HoG Mouse combined GATT database
// Regenerate: compile_gatt.py gatt_midi_hog.gatt gatt_midi_hog.h // clang-format off
// gatt_midi_hog.h generated from gatt_midi_hog.gatt for BTstack
// it needs to be regenerated when the .gatt file is updated.
// To generate gatt_midi_hog.h:
// compile_gatt.py gatt_midi_hog.gatt gatt_midi_hog.h
// att db format version 1 // att db format version 1
// binary attribute representation: // binary attribute representation:
// - size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) // - size in bytes (16), flags(16), handle (16), uuid (16/128), value(...)
#include <stdint.h> #include <stdint.h>
// Reference: https://en.cppreference.com/w/cpp/feature_test
#if __cplusplus >= 200704L #if __cplusplus >= 200704L
constexpr constexpr
#endif #endif
@ -19,89 +26,133 @@ const uint8_t profile_data[] =
0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x01, 0x18, 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x01, 0x18,
// 0x0002 CHARACTERISTIC-GATT_DATABASE_HASH - READ // 0x0002 CHARACTERISTIC-GATT_DATABASE_HASH - READ
0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x2a, 0x2b, 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x2a, 0x2b,
// 0x0003 VALUE CHARACTERISTIC-GATT_DATABASE_HASH - READ // 0x0003 VALUE CHARACTERISTIC-GATT_DATABASE_HASH - READ -''
0x18, 0x00, 0x02, 0x00, 0x03, 0x00, 0x2a, 0x2b, 0xce, 0x0f, 0xc6, 0xd0, 0xa1, 0x9c, 0xd7, 0xa2, 0x98, 0xad, 0x7d, 0x4c, 0x9c, 0x85, 0xed, 0x81, // READ_ANYBODY
0x18, 0x00, 0x02, 0x00, 0x03, 0x00, 0x2a, 0x2b, 0xab, 0x5a, 0x3b, 0x8c, 0x3f, 0x95, 0x12, 0x5d, 0x5a, 0xa5, 0x27, 0xb7, 0x75, 0x27, 0xfc, 0x2b,
// 0x0004 PRIMARY_SERVICE-GAP_SERVICE // 0x0004 PRIMARY_SERVICE-GAP_SERVICE
0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x00, 0x18, 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x00, 0x18,
// 0x0005 CHARACTERISTIC-GAP_DEVICE_NAME - READ | DYNAMIC // 0x0005 CHARACTERISTIC-GAP_DEVICE_NAME - READ | DYNAMIC
0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x02, 0x06, 0x00, 0x00, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x02, 0x06, 0x00, 0x00, 0x2a,
// 0x0006 VALUE CHARACTERISTIC-GAP_DEVICE_NAME - READ | DYNAMIC // 0x0006 VALUE CHARACTERISTIC-GAP_DEVICE_NAME - READ | DYNAMIC
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x06, 0x00, 0x00, 0x2a, 0x08, 0x00, 0x02, 0x01, 0x06, 0x00, 0x00, 0x2a,
// 0x0007 CHARACTERISTIC-GAP_APPEARANCE - READ - Mouse (0x03C2) // 0x03C1 = HID Keyboard
// 0x0007 CHARACTERISTIC-GAP_APPEARANCE - READ
0x0d, 0x00, 0x02, 0x00, 0x07, 0x00, 0x03, 0x28, 0x02, 0x08, 0x00, 0x01, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x07, 0x00, 0x03, 0x28, 0x02, 0x08, 0x00, 0x01, 0x2a,
// 0x0008 VALUE CHARACTERISTIC-GAP_APPEARANCE - READ // 0x0008 VALUE CHARACTERISTIC-GAP_APPEARANCE - READ -'C1 03'
0x0a, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x2a, 0xC2, 0x03, // READ_ANYBODY
0x0a, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x2a, 0xC1, 0x03,
// MIDI Service // MIDI Service
// 0x0009 PRIMARY_SERVICE-03B80E5A-EDE8-4B33-A751-6CE34EC4C700 // 0x0009 PRIMARY_SERVICE-03B80E5A-EDE8-4B33-A751-6CE34EC4C700
0x18, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x28, 0x00, 0xc7, 0xc4, 0x4e, 0xe3, 0x6c, 0x51, 0xa7, 0x33, 0x4b, 0xe8, 0xed, 0x5a, 0x0e, 0xb8, 0x03, 0x18, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x28, 0x00, 0xc7, 0xc4, 0x4e, 0xe3, 0x6c, 0x51, 0xa7, 0x33, 0x4b, 0xe8, 0xed, 0x5a, 0x0e, 0xb8, 0x03,
// 0x000a CHARACTERISTIC-7772E5DB-3868-4112-A1A9-F2669D106BF3 - READ | WRITE_WITHOUT_RESPONSE | NOTIFY | DYNAMIC // 0x000a CHARACTERISTIC-7772E5DB-3868-4112-A1A9-F2669D106BF3 - READ | WRITE_WITHOUT_RESPONSE | NOTIFY | DYNAMIC
0x1b, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x16, 0x0b, 0x00, 0xf3, 0x6b, 0x10, 0x9d, 0x66, 0xf2, 0xa9, 0xa1, 0x12, 0x41, 0x68, 0x38, 0xdb, 0xe5, 0x72, 0x77, 0x1b, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x16, 0x0b, 0x00, 0xf3, 0x6b, 0x10, 0x9d, 0x66, 0xf2, 0xa9, 0xa1, 0x12, 0x41, 0x68, 0x38, 0xdb, 0xe5, 0x72, 0x77,
// 0x000b VALUE CHARACTERISTIC-7772E5DB-3868-4112-A1A9-F2669D106BF3 - READ | WRITE_WITHOUT_RESPONSE | NOTIFY | DYNAMIC // 0x000b VALUE CHARACTERISTIC-7772E5DB-3868-4112-A1A9-F2669D106BF3 - READ | WRITE_WITHOUT_RESPONSE | NOTIFY | DYNAMIC
// READ_ANYBODY, WRITE_ANYBODY
0x16, 0x00, 0x06, 0x03, 0x0b, 0x00, 0xf3, 0x6b, 0x10, 0x9d, 0x66, 0xf2, 0xa9, 0xa1, 0x12, 0x41, 0x68, 0x38, 0xdb, 0xe5, 0x72, 0x77, 0x16, 0x00, 0x06, 0x03, 0x0b, 0x00, 0xf3, 0x6b, 0x10, 0x9d, 0x66, 0xf2, 0xa9, 0xa1, 0x12, 0x41, 0x68, 0x38, 0xdb, 0xe5, 0x72, 0x77,
// 0x000c CLIENT_CHARACTERISTIC_CONFIGURATION // 0x000c CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0e, 0x01, 0x0c, 0x00, 0x02, 0x29, 0x00, 0x00, 0x0a, 0x00, 0x0e, 0x01, 0x0c, 0x00, 0x02, 0x29, 0x00, 0x00,
// HID Service
// HID Service (hids.gatt)
// #import <hids.gatt> -- BEGIN
// Specification Type org.bluetooth.service.human_interface_device
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.human_interface_device.xml
// Human Interface Device 1812
// 0x000d PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE // 0x000d PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE
0x0a, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x00, 0x28, 0x12, 0x18, 0x0a, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x00, 0x28, 0x12, 0x18,
// 0x000e CHARACTERISTIC-PROTOCOL_MODE - DYNAMIC | READ | WRITE_WITHOUT_RESPONSE // 0x000e CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE - DYNAMIC | READ | WRITE_WITHOUT_RESPONSE
0x0d, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x03, 0x28, 0x06, 0x0f, 0x00, 0x4e, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x03, 0x28, 0x06, 0x0f, 0x00, 0x4e, 0x2a,
// 0x000f VALUE CHARACTERISTIC-PROTOCOL_MODE // 0x000f VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE - DYNAMIC | READ | WRITE_WITHOUT_RESPONSE
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x06, 0x01, 0x0f, 0x00, 0x4e, 0x2a, 0x08, 0x00, 0x06, 0x01, 0x0f, 0x00, 0x4e, 0x2a,
// 0x0010 CHARACTERISTIC-REPORT (Input, ID=1) - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16 // 0x0010 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
0x0d, 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x28, 0x1a, 0x11, 0x00, 0x4d, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x28, 0x1a, 0x11, 0x00, 0x4d, 0x2a,
// 0x0011 VALUE CHARACTERISTIC-REPORT // 0x0011 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | NOTIFY | ENCRYPTION_KEY_SIZE_16
// READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x08, 0x00, 0x0b, 0xf5, 0x11, 0x00, 0x4d, 0x2a, 0x08, 0x00, 0x0b, 0xf5, 0x11, 0x00, 0x4d, 0x2a,
// 0x0012 CLIENT_CHARACTERISTIC_CONFIGURATION // 0x0012 CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x0a, 0x00, 0x0f, 0xf1, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x0a, 0x00, 0x0f, 0xf1, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00,
// 0x0013 REPORT_REFERENCE - Report ID=1, Type=Input(1) // fixed report id = 1, type = Input (1)
// 0x0013 REPORT_REFERENCE-READ-1-1
0x0a, 0x00, 0x02, 0x00, 0x13, 0x00, 0x08, 0x29, 0x1, 0x1, 0x0a, 0x00, 0x02, 0x00, 0x13, 0x00, 0x08, 0x29, 0x1, 0x1,
// 0x0014 CHARACTERISTIC-REPORT (Output, ID=2) - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE | ENCRYPTION_KEY_SIZE_16 // 0x0014 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE | ENCRYPTION_KEY_SIZE_16
0x0d, 0x00, 0x02, 0x00, 0x14, 0x00, 0x03, 0x28, 0x0e, 0x15, 0x00, 0x4d, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x14, 0x00, 0x03, 0x28, 0x0e, 0x15, 0x00, 0x4d, 0x2a,
// 0x0015 VALUE CHARACTERISTIC-REPORT // 0x0015 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE | ENCRYPTION_KEY_SIZE_16
// READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x08, 0x00, 0x0f, 0xf5, 0x15, 0x00, 0x4d, 0x2a, 0x08, 0x00, 0x0f, 0xf5, 0x15, 0x00, 0x4d, 0x2a,
// 0x0016 REPORT_REFERENCE - Report ID=2, Type=Output(2) // fixed report id = 2, type = Output (2)
// 0x0016 REPORT_REFERENCE-READ-2-2
0x0a, 0x00, 0x02, 0x00, 0x16, 0x00, 0x08, 0x29, 0x2, 0x2, 0x0a, 0x00, 0x02, 0x00, 0x16, 0x00, 0x08, 0x29, 0x2, 0x2,
// 0x0017 CHARACTERISTIC-REPORT (Feature, ID=3) - DYNAMIC | READ | WRITE | ENCRYPTION_KEY_SIZE_16 // 0x0017 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | ENCRYPTION_KEY_SIZE_16
0x0d, 0x00, 0x02, 0x00, 0x17, 0x00, 0x03, 0x28, 0x0a, 0x18, 0x00, 0x4d, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x17, 0x00, 0x03, 0x28, 0x0a, 0x18, 0x00, 0x4d, 0x2a,
// 0x0018 VALUE CHARACTERISTIC-REPORT // 0x0018 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT - DYNAMIC | READ | WRITE | ENCRYPTION_KEY_SIZE_16
// READ_ENCRYPTED, WRITE_ENCRYPTED, ENCRYPTION_KEY_SIZE=16
0x08, 0x00, 0x0b, 0xf5, 0x18, 0x00, 0x4d, 0x2a, 0x08, 0x00, 0x0b, 0xf5, 0x18, 0x00, 0x4d, 0x2a,
// 0x0019 REPORT_REFERENCE - Report ID=3, Type=Feature(3) // fixed report id = 3, type = Feature (3)
// 0x0019 REPORT_REFERENCE-READ-3-3
0x0a, 0x00, 0x02, 0x00, 0x19, 0x00, 0x08, 0x29, 0x3, 0x3, 0x0a, 0x00, 0x02, 0x00, 0x19, 0x00, 0x08, 0x29, 0x3, 0x3,
// 0x001a CHARACTERISTIC-REPORT_MAP - DYNAMIC | READ // 0x001a CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP - DYNAMIC | READ
0x0d, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x03, 0x28, 0x02, 0x1b, 0x00, 0x4b, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x03, 0x28, 0x02, 0x1b, 0x00, 0x4b, 0x2a,
// 0x001b VALUE CHARACTERISTIC-REPORT_MAP // 0x001b VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP - DYNAMIC | READ
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x1b, 0x00, 0x4b, 0x2a, 0x08, 0x00, 0x02, 0x01, 0x1b, 0x00, 0x4b, 0x2a,
// 0x001c CHARACTERISTIC-BOOT_KEYBOARD_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY // 0x001c CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
0x0d, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x03, 0x28, 0x1a, 0x1d, 0x00, 0x22, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x03, 0x28, 0x1a, 0x1d, 0x00, 0x22, 0x2a,
// 0x001d VALUE CHARACTERISTIC-BOOT_KEYBOARD_INPUT_REPORT // 0x001d VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x0a, 0x01, 0x1d, 0x00, 0x22, 0x2a, 0x08, 0x00, 0x0a, 0x01, 0x1d, 0x00, 0x22, 0x2a,
// 0x001e CLIENT_CHARACTERISTIC_CONFIGURATION // 0x001e CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0e, 0x01, 0x1e, 0x00, 0x02, 0x29, 0x00, 0x00, 0x0a, 0x00, 0x0e, 0x01, 0x1e, 0x00, 0x02, 0x29, 0x00, 0x00,
// 0x001f CHARACTERISTIC-BOOT_KEYBOARD_OUTPUT_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE // 0x001f CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE
0x0d, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x03, 0x28, 0x0e, 0x20, 0x00, 0x32, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x03, 0x28, 0x0e, 0x20, 0x00, 0x32, 0x2a,
// 0x0020 VALUE CHARACTERISTIC-BOOT_KEYBOARD_OUTPUT_REPORT // 0x0020 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_OUTPUT_REPORT - DYNAMIC | READ | WRITE | WRITE_WITHOUT_RESPONSE
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x0e, 0x01, 0x20, 0x00, 0x32, 0x2a, 0x08, 0x00, 0x0e, 0x01, 0x20, 0x00, 0x32, 0x2a,
// 0x0021 CHARACTERISTIC-BOOT_MOUSE_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY // 0x0021 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
0x0d, 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x28, 0x1a, 0x22, 0x00, 0x33, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x28, 0x1a, 0x22, 0x00, 0x33, 0x2a,
// 0x0022 VALUE CHARACTERISTIC-BOOT_MOUSE_INPUT_REPORT // 0x0022 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT - DYNAMIC | READ | WRITE | NOTIFY
// READ_ANYBODY, WRITE_ANYBODY
0x08, 0x00, 0x0a, 0x01, 0x22, 0x00, 0x33, 0x2a, 0x08, 0x00, 0x0a, 0x01, 0x22, 0x00, 0x33, 0x2a,
// 0x0023 CLIENT_CHARACTERISTIC_CONFIGURATION // 0x0023 CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0e, 0x01, 0x23, 0x00, 0x02, 0x29, 0x00, 0x00, 0x0a, 0x00, 0x0e, 0x01, 0x23, 0x00, 0x02, 0x29, 0x00, 0x00,
// 0x0024 CHARACTERISTIC-HID_INFORMATION - READ // bcdHID = 0x101 (v1.0.1), bCountryCode 0, remote wakeable = 0 | normally connectable 2
// 0x0024 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION - READ
0x0d, 0x00, 0x02, 0x00, 0x24, 0x00, 0x03, 0x28, 0x02, 0x25, 0x00, 0x4a, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x24, 0x00, 0x03, 0x28, 0x02, 0x25, 0x00, 0x4a, 0x2a,
// 0x0025 VALUE CHARACTERISTIC-HID_INFORMATION - bcdHID=0x0101, country=0, flags=0x02 // 0x0025 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION - READ -'01 01 00 02'
// READ_ANYBODY
0x0c, 0x00, 0x02, 0x00, 0x25, 0x00, 0x4a, 0x2a, 0x01, 0x01, 0x00, 0x02, 0x0c, 0x00, 0x02, 0x00, 0x25, 0x00, 0x4a, 0x2a, 0x01, 0x01, 0x00, 0x02,
// 0x0026 CHARACTERISTIC-HID_CONTROL_POINT - DYNAMIC | WRITE_WITHOUT_RESPONSE // 0x0026 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT - DYNAMIC | WRITE_WITHOUT_RESPONSE
0x0d, 0x00, 0x02, 0x00, 0x26, 0x00, 0x03, 0x28, 0x04, 0x27, 0x00, 0x4c, 0x2a, 0x0d, 0x00, 0x02, 0x00, 0x26, 0x00, 0x03, 0x28, 0x04, 0x27, 0x00, 0x4c, 0x2a,
// 0x0027 VALUE CHARACTERISTIC-HID_CONTROL_POINT // 0x0027 VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT - DYNAMIC | WRITE_WITHOUT_RESPONSE
// WRITE_ANYBODY
0x08, 0x00, 0x04, 0x01, 0x27, 0x00, 0x4c, 0x2a, 0x08, 0x00, 0x04, 0x01, 0x27, 0x00, 0x4c, 0x2a,
// #import <hids.gatt> -- END
// Battery Service
// #import <battery_service.gatt> -- BEGIN
// Specification Type org.bluetooth.service.battery_service
// https://www.bluetooth.com/api/gatt/xmlfile?xmlFileName=org.bluetooth.service.battery_service.xml
// Battery Service 180F
// 0x0028 PRIMARY_SERVICE-ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE
0x0a, 0x00, 0x02, 0x00, 0x28, 0x00, 0x00, 0x28, 0x0f, 0x18,
// 0x0029 CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL - DYNAMIC | READ | NOTIFY
0x0d, 0x00, 0x02, 0x00, 0x29, 0x00, 0x03, 0x28, 0x12, 0x2a, 0x00, 0x19, 0x2a,
// 0x002a VALUE CHARACTERISTIC-ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL - DYNAMIC | READ | NOTIFY
// READ_ANYBODY
0x08, 0x00, 0x02, 0x01, 0x2a, 0x00, 0x19, 0x2a,
// 0x002b CLIENT_CHARACTERISTIC_CONFIGURATION
// READ_ANYBODY, WRITE_ANYBODY
0x0a, 0x00, 0x0e, 0x01, 0x2b, 0x00, 0x02, 0x29, 0x00, 0x00,
// #import <battery_service.gatt> -- END
// END // END
0x00, 0x00, 0x00, 0x00,
}; // total size 252 bytes }; // total size 275 bytes
// //
@ -123,6 +174,10 @@ const uint8_t profile_data[] =
#define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE_END_HANDLE 0x0027 #define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE_END_HANDLE 0x0027
#define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE_01_START_HANDLE 0x000d #define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE_01_START_HANDLE 0x000d
#define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE_01_END_HANDLE 0x0027 #define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE_01_END_HANDLE 0x0027
#define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE_START_HANDLE 0x0028
#define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE_END_HANDLE 0x002b
#define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE_01_START_HANDLE 0x0028
#define ATT_SERVICE_ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE_01_END_HANDLE 0x002b
// //
// list mapping between characteristics and handles // list mapping between characteristics and handles
@ -145,3 +200,5 @@ const uint8_t profile_data[] =
#define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT_01_CLIENT_CONFIGURATION_HANDLE 0x0023 #define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT_01_CLIENT_CONFIGURATION_HANDLE 0x0023
#define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION_01_VALUE_HANDLE 0x0025 #define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_HID_INFORMATION_01_VALUE_HANDLE 0x0025
#define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT_01_VALUE_HANDLE 0x0027 #define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT_01_VALUE_HANDLE 0x0027
#define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_01_VALUE_HANDLE 0x002a
#define ATT_CHARACTERISTIC_ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_01_CLIENT_CONFIGURATION_HANDLE 0x002b

View File

@ -0,0 +1,126 @@
#ifndef _BOARDS_WAVESHARE_RP2350B_PLUS_W_H
#define _BOARDS_WAVESHARE_RP2350B_PLUS_W_H
pico_board_cmake_set(PICO_PLATFORM, rp2350)
pico_board_cmake_set(PICO_CYW43_SUPPORTED, 1)
#define WAVESHARE_RP2350B_PLUS_W
// --- RP2350 VARIANT ---
#define PICO_RP2350A 0
// --- UART ---
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 0
#endif
#ifndef PICO_DEFAULT_UART_TX_PIN
#define PICO_DEFAULT_UART_TX_PIN 0
#endif
#ifndef PICO_DEFAULT_UART_RX_PIN
#define PICO_DEFAULT_UART_RX_PIN 1
#endif
// --- LED ---
#ifndef PICO_DEFAULT_LED_PIN
#define PICO_DEFAULT_LED_PIN 23
#endif
// --- I2C ---
#ifndef PICO_DEFAULT_I2C
#define PICO_DEFAULT_I2C 1
#endif
#ifndef PICO_DEFAULT_I2C_SDA_PIN
#define PICO_DEFAULT_I2C_SDA_PIN 6
#endif
#ifndef PICO_DEFAULT_I2C_SCL_PIN
#define PICO_DEFAULT_I2C_SCL_PIN 7
#endif
// --- SPI ---
#ifndef PICO_DEFAULT_SPI
#define PICO_DEFAULT_SPI 0
#endif
#ifndef PICO_DEFAULT_SPI_SCK_PIN
#define PICO_DEFAULT_SPI_SCK_PIN 18
#endif
#ifndef PICO_DEFAULT_SPI_TX_PIN
#define PICO_DEFAULT_SPI_TX_PIN 19
#endif
#ifndef PICO_DEFAULT_SPI_RX_PIN
#define PICO_DEFAULT_SPI_RX_PIN 16
#endif
#ifndef PICO_DEFAULT_SPI_CSN_PIN
#define PICO_DEFAULT_SPI_CSN_PIN 17
#endif
// --- FLASH ---
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 2
#endif
pico_board_cmake_set_default(PICO_FLASH_SIZE_BYTES, (16 * 1024 * 1024))
#ifndef PICO_FLASH_SIZE_BYTES
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
#endif
// --- CYW43 (RM2) on B-package extra pins ---
#ifndef CYW43_WL_GPIO_COUNT
#define CYW43_WL_GPIO_COUNT 3
#endif
#ifndef CYW43_WL_GPIO_LED_PIN
#define CYW43_WL_GPIO_LED_PIN 0
#endif
#ifndef CYW43_WL_GPIO_SMPS_PIN
#define CYW43_WL_GPIO_SMPS_PIN 1
#endif
#ifndef CYW43_WL_GPIO_VBUS_PIN
#define CYW43_WL_GPIO_VBUS_PIN 2
#endif
#ifndef CYW43_USES_VSYS_PIN
#define CYW43_USES_VSYS_PIN 1
#endif
#ifndef PICO_VSYS_PIN
#define PICO_VSYS_PIN 29
#endif
#ifndef CYW43_PIN_WL_DYNAMIC
#define CYW43_PIN_WL_DYNAMIC 0
#endif
#ifndef CYW43_DEFAULT_PIN_WL_REG_ON
#define CYW43_DEFAULT_PIN_WL_REG_ON 36u
#endif
#ifndef CYW43_DEFAULT_PIN_WL_DATA_OUT
#define CYW43_DEFAULT_PIN_WL_DATA_OUT 37u
#endif
#ifndef CYW43_DEFAULT_PIN_WL_DATA_IN
#define CYW43_DEFAULT_PIN_WL_DATA_IN 37u
#endif
#ifndef CYW43_DEFAULT_PIN_WL_HOST_WAKE
#define CYW43_DEFAULT_PIN_WL_HOST_WAKE 37u
#endif
#ifndef CYW43_DEFAULT_PIN_WL_CLOCK
#define CYW43_DEFAULT_PIN_WL_CLOCK 39u
#endif
#ifndef CYW43_DEFAULT_PIN_WL_CS
#define CYW43_DEFAULT_PIN_WL_CS 38u
#endif
pico_board_cmake_set_default(PICO_RP2350_A2_SUPPORTED, 1)
#ifndef PICO_RP2350_A2_SUPPORTED
#define PICO_RP2350_A2_SUPPORTED 1
#endif
#endif

View File

@ -23,6 +23,7 @@
// MIDI interfaces — common // MIDI interfaces — common
#include <MIDI_Interfaces/MIDI_Pipes.hpp> #include <MIDI_Interfaces/MIDI_Pipes.hpp>
#include <MIDI_Interfaces/MIDI_Callbacks.hpp>
// MIDI interfaces — transport-specific // MIDI interfaces — transport-specific
#ifdef CS_MIDI_BLE #ifdef CS_MIDI_BLE
@ -93,4 +94,13 @@ using BluetoothMIDI_Interface =
GenericBLEMIDI_Interface<BTstackBackgroundBackend>; GenericBLEMIDI_Interface<BTstackBackgroundBackend>;
#endif #endif
#if defined(CS_MIDI_HID_KEYBOARD) && defined(CS_MIDI_BLE)
namespace midi_ble_btstack {
void set_battery_level(uint8_t percent);
}
inline void setBLEBatteryLevel(uint8_t percent) {
midi_ble_btstack::set_battery_level(percent);
}
#endif
END_CS_NAMESPACE END_CS_NAMESPACE

2
docs

@ -1 +1 @@
Subproject commit 3927d073e938973be113ee08db4e596c7d853ad3 Subproject commit be1ee309670a861adca5fb8f46aefe6a723a6bb4

View File

@ -69,6 +69,9 @@ set(EXAMPLE_SOURCES
output/program_changer.cpp output/program_changer.cpp
output/cc_potentiometers.cpp output/cc_potentiometers.cpp
output/borrowed_cc_rotary_encoder.cpp output/borrowed_cc_rotary_encoder.cpp
output/cc_potentiometer_map.cpp
output/finished_controller.cpp
output/enable_disable.cpp
# Input elements # Input elements
input/note_led.cpp input/note_led.cpp
@ -84,6 +87,11 @@ set(EXAMPLE_SOURCES
# Interfaces # Interfaces
interfaces/ble_midi.cpp interfaces/ble_midi.cpp
interfaces/midi_pipes.cpp interfaces/midi_pipes.cpp
interfaces/midi_output.cpp
interfaces/send_midi_notes.cpp
interfaces/send_all_midi_messages.cpp
interfaces/midi_input_callback.cpp
interfaces/midi_pipes_filter.cpp
# Banks # Banks
banks/bank_cc_values.cpp banks/bank_cc_values.cpp

View File

@ -0,0 +1,30 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
struct MyMIDI_Callbacks : MIDI_Callbacks {
void onChannelMessage(MIDI_Interface &, ChannelMessage msg) override {
(void)msg;
}
void onSysExMessage(MIDI_Interface &, SysExMessage msg) override {
(void)msg;
}
void onRealTimeMessage(MIDI_Interface &, RealTimeMessage msg) override {
(void)msg;
}
} callback;
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
midi.begin();
midi.setCallbacks(callback);
while (true) {
midi.update();
sleep_ms(1);
}
}

View File

@ -0,0 +1,23 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
const MIDIAddress address {MIDI_Notes::C[4], Channel_1};
const uint8_t velocity = 0x7F;
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
midi.begin();
while (true) {
midi.sendNoteOn(address, velocity);
sleep_ms(500);
midi.sendNoteOff(address, velocity);
sleep_ms(500);
midi.update();
}
}

View File

@ -0,0 +1,41 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
struct NoteFilter : MIDI_Pipe {
void mapForwardMIDI(ChannelMessage msg) override {
switch (msg.getMessageType()) {
case MIDIMessageType::NoteOff:
case MIDIMessageType::NoteOn:
msg.setChannel(Channel_5);
if (msg.data1 >= 12)
msg.data1 -= 12;
sourceMIDItoSink(msg);
break;
default:
break;
}
}
void mapForwardMIDI(SysExMessage) override {}
void mapForwardMIDI(SysCommonMessage) override {}
void mapForwardMIDI(RealTimeMessage msg) override {
sourceMIDItoSink(msg);
}
};
NoteFilter filter;
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
midi >> filter >> midi;
midi.begin();
while (true) {
midi.update();
sleep_ms(1);
}
}

View File

@ -0,0 +1,51 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
midi.begin();
// Channel voice messages
MIDIAddress note = {MIDI_Notes::C[4], Channel_6};
midi.sendNoteOn(note, 127);
midi.sendNoteOff(note, 127);
midi.sendKeyPressure(note, 64);
MIDIAddress controller = {MIDI_CC::Channel_Volume, Channel_2};
midi.sendControlChange(controller, 120);
MIDIAddress program = {MIDI_PC::Harpsichord, Channel_9};
midi.sendProgramChange(program);
midi.sendChannelPressure(Channel_3, 64);
midi.sendPitchBend(Channel_3, 16383);
// System common messages
midi.sendMTCQuarterFrame(2, 15);
midi.sendSongPositionPointer(10000);
midi.sendSongSelect(70);
midi.sendTuneRequest();
// System exclusive
uint8_t sysex[] = {0xF0, 0x00, 0x01, 0x02, 0x03, 0xF7};
midi.sendSysEx(sysex);
// Real-time messages
midi.sendTimingClock();
midi.sendStart();
midi.sendContinue();
midi.sendStop();
midi.sendActiveSensing();
midi.sendSystemReset();
while (true) {
midi.update();
sleep_ms(1);
}
}

View File

@ -0,0 +1,27 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
AH::Button pushbutton {5};
const MIDIAddress noteAddress {MIDI_Notes::C[4], Channel_1};
const uint8_t velocity = 0x7F;
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
pushbutton.begin();
midi.begin();
while (true) {
midi.update();
pushbutton.update();
if (pushbutton.getState() == AH::Button::Falling)
midi.sendNoteOn(noteAddress, velocity);
else if (pushbutton.getState() == AH::Button::Rising)
midi.sendNoteOff(noteAddress, velocity);
}
}

View File

@ -0,0 +1,30 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
CCPotentiometer potentiometer {26, {MIDI_CC::Channel_Volume, Channel_1}};
constexpr analog_t maxRawValue = CCPotentiometer::getMaxRawValue();
constexpr analog_t minimumValue = maxRawValue / 64;
constexpr analog_t maximumValue = maxRawValue - maxRawValue / 64;
analog_t mappingFunction(analog_t raw) {
if (raw < minimumValue) raw = minimumValue;
if (raw > maximumValue) raw = maximumValue;
return (raw - minimumValue) * maxRawValue / (maximumValue - minimumValue);
}
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
potentiometer.map(mappingFunction);
Control_Surface.begin();
while (true) {
Control_Surface.loop();
sleep_ms(1);
}
}

View File

@ -0,0 +1,32 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
NoteButton button1 {5, {MIDI_Notes::C[4], Channel_1}};
NoteButton button2 {6, {MIDI_Notes::D[4], Channel_1}};
AH::Button toggleBtn {7};
bool button2Enabled = true;
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
toggleBtn.begin();
Control_Surface.begin();
while (true) {
Control_Surface.loop();
toggleBtn.update();
if (toggleBtn.getState() == AH::Button::Falling) {
button2Enabled = !button2Enabled;
if (button2Enabled)
button2.enable();
else
button2.disable();
}
sleep_ms(1);
}
}

View File

@ -0,0 +1,32 @@
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include <cs_midi.h>
using namespace cs;
BluetoothMIDI_Interface midi;
// 4 banks, 2 tracks per bank
Bank<4> bank(2);
// Two buttons to cycle banks
IncrementDecrementSelector<4> bankSelector {bank, {2, 3}, Wrap::Wrap};
// Bankable CC value readers — bank switches the CC address
Bankable::CCValue<4> volume1 {{bank, BankType::ChangeAddress}, {16, Channel_1}};
Bankable::CCValue<4> volume2 {{bank, BankType::ChangeAddress}, {17, Channel_1}};
// Non-bankable output elements
NoteButton button {5, {MIDI_Notes::C[4], Channel_1}};
CCPotentiometer pot {26, {MIDI_CC::Channel_Volume, Channel_1}};
CCRotaryEncoder enc {{0, 1}, {MIDI_CC::Pan, Channel_1}, 1, 4};
int main() {
stdio_init_all();
if (cyw43_arch_init()) return 1;
Control_Surface.begin();
while (true) {
Control_Surface.loop();
sleep_ms(1);
}
}