Provide 1:1 examples from original to port and use them tests when building docs.
This commit is contained in:
parent
52bf6e4c95
commit
fe877262d1
|
|
@ -1,12 +0,0 @@
|
|||
# Getting Started
|
||||
|
||||
cs-midi is a standalone MIDI library for pico-sdk, extracted from [Control Surface](https://github.com/tttapa/Control-Surface). It provides BLE MIDI, Classic BT SPP MIDI, rotary encoders, buttons, potentiometers, LEDs, banks, and a flexible pipe-based routing system.
|
||||
|
||||
## What's included
|
||||
|
||||
- **BLE MIDI** via BTstack (pico-native, no Arduino)
|
||||
- **Output elements**: NoteButton, CCRotaryEncoder, CCPotentiometer, and more
|
||||
- **Input elements**: NoteValue, CCValue, PBValue, LEDs
|
||||
- **Pipe routing**: bidirectional MIDI pipes with filter/transform support
|
||||
- **Banks**: switch between multiple CC/note mappings
|
||||
- **Custom hooks**: extend the library without modifying it
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# Installation
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [pico-sdk](https://github.com/raspberrypi/pico-sdk) (v2.0+)
|
||||
- CMake 3.13+
|
||||
- ARM GCC toolchain
|
||||
|
||||
## Adding to your project
|
||||
|
||||
Add cs-midi as a git submodule:
|
||||
|
||||
```bash
|
||||
git submodule add https://git.else-if.org/jess/cs-midi.git lib/cs-midi
|
||||
```
|
||||
|
||||
In your `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
add_subdirectory(lib/cs-midi)
|
||||
target_link_libraries(your_target cs_midi)
|
||||
target_include_directories(cs_midi PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
```
|
||||
|
||||
The last line is required so cs-midi can find your project's `btstack_config.h` and `lwipopts.h`.
|
||||
|
||||
## Include
|
||||
|
||||
```cpp
|
||||
#include <cs_midi.h>
|
||||
```
|
||||
|
||||
This single header pulls in everything: output elements, input elements, pipes, banks, BLE interface, and the Control Surface singleton.
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# cs-midi
|
||||
|
||||
A standalone pico-sdk extraction of [tttapa/Control-Surface](https://github.com/tttapa/Control-Surface) (GPL-3.0).
|
||||
|
||||
cs-midi provides the core MIDI element system, BLE MIDI transport, banks, selectors, and the declarative `Control_Surface` singleton for use with the Raspberry Pi Pico SDK and the CYW43 radio module (BTstack BLE backend).
|
||||
|
||||
## Getting Started
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteButton button {5, {MIDI_Notes::C[4], Channel_1}};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Differences from Control Surface
|
||||
|
||||
- `#include <cs_midi.h>` replaces `#include <Control_Surface.h>`
|
||||
- `cs::BluetoothMIDI_Interface` replaces `USBMIDI_Interface`
|
||||
- Standard `main()` with `cyw43_arch_init()` replaces Arduino `setup()`/`loop()`
|
||||
- All types live in the `cs::` namespace
|
||||
- No `MCU::` namespace — use raw CC numbers or `MIDI_CC::` constants
|
||||
|
||||
## Credits
|
||||
|
||||
Original library: [Control Surface](https://github.com/tttapa/Control-Surface) by **Pieter P (tttapa)** (GPL-3.0).
|
||||
pico-sdk port: [pszsh](https://else-if.org).
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
title: cs-midi
|
||||
author: jess
|
||||
author: Pieter P (tttapa) — pico-sdk port
|
||||
|
|
|
|||
|
|
@ -0,0 +1,264 @@
|
|||
# Class Reference
|
||||
|
||||
Cross-reference between cs-midi and the original [Control Surface](https://tttapa.github.io/Control-Surface/Doxygen/annotated.html) library.
|
||||
|
||||
## Ported Classes
|
||||
|
||||
These classes are available in cs-midi and work identically to their Control Surface equivalents (within the `cs::` namespace unless noted).
|
||||
|
||||
### MIDI Output Elements
|
||||
|
||||
| Class | Template | Description |
|
||||
|-------|----------|-------------|
|
||||
| `NoteButton` | | Note On/Off on button press/release |
|
||||
| `NoteButtonLatched` | | Toggle Note On/Off on each press |
|
||||
| `NoteButtonLatching` | | Note On while held, toggles |
|
||||
| `NoteChordButton` | | Chord (multiple notes) on press |
|
||||
| `NoteButtons` | `<N>` | Array of sequential note buttons |
|
||||
| `NoteButtonMatrix` | `<R, C>` | Row/column scanned note grid |
|
||||
| `CCButton` | | CC 127/0 on press/release |
|
||||
| `CCButtonLatched` | | Toggle CC 127/0 on each press |
|
||||
| `CCButtonLatching` | | CC 127 while held, toggles |
|
||||
| `CCButtons` | `<N>` | Array of sequential CC buttons |
|
||||
| `CCButtonMatrix` | `<R, C>` | Row/column scanned CC grid |
|
||||
| `CCPotentiometer` | | Analog input to CC 0-127 |
|
||||
| `PBPotentiometer` | | Analog input to 14-bit Pitch Bend |
|
||||
| `CCRotaryEncoder` | | Relative CC from encoder |
|
||||
| `BorrowedCCRotaryEncoder` | | Shared encoder reference for CC |
|
||||
| `CCAbsoluteEncoder` | | Absolute CC from encoder position |
|
||||
| `PBAbsoluteEncoder` | | 14-bit Pitch Bend from encoder |
|
||||
| `CCIncrementDecrementButtons` | | Two buttons for CC inc/dec + reset |
|
||||
| `PCButton` | | Program Change on press |
|
||||
| `ProgramChanger` | `<N>` | Selectable program change list |
|
||||
|
||||
### MIDI Input Elements
|
||||
|
||||
| Class | Template | Description |
|
||||
|-------|----------|-------------|
|
||||
| `NoteValue` | | Incoming Note value (8-bit) |
|
||||
| `CCValue` | | Incoming CC value (8-bit) |
|
||||
| `KPValue` | | Incoming Key Pressure value (8-bit) |
|
||||
| `PBValue` | | Incoming Pitch Bend value (14-bit) |
|
||||
| `NoteRange` | `<Len>` | Array of incoming Note values |
|
||||
| `CCRange` | `<Len>` | Array of incoming CC values |
|
||||
| `KPRange` | `<Len>` | Array of incoming Key Pressure values |
|
||||
| `NoteLED` | | LED driven by Note On/Off |
|
||||
| `CCLED` | | LED driven by CC value |
|
||||
| `KPLED` | | LED driven by Key Pressure |
|
||||
|
||||
### Bankable Input Elements
|
||||
|
||||
| Class | Template | Description |
|
||||
|-------|----------|-------------|
|
||||
| `Bankable::NoteValue` | `<BankSize>` | Bank-switched Note value |
|
||||
| `Bankable::CCValue` | `<BankSize>` | Bank-switched CC value |
|
||||
| `Bankable::KPValue` | `<BankSize>` | Bank-switched Key Pressure value |
|
||||
| `Bankable::PBValue` | `<BankSize>` | Bank-switched Pitch Bend value |
|
||||
| `Bankable::NoteLED` | `<BankSize>` | Bank-switched Note LED |
|
||||
| `Bankable::CCLED` | `<BankSize>` | Bank-switched CC LED |
|
||||
| `Bankable::KPLED` | `<BankSize>` | Bank-switched Key Pressure LED |
|
||||
|
||||
### Banks and Selectors
|
||||
|
||||
| Class | Template | Description |
|
||||
|-------|----------|-------------|
|
||||
| `Bank` | `<N>` | N-setting bank for bankable elements |
|
||||
| `Transposer` | `<Min, Max>` | Note transposition bank |
|
||||
| `OutputBank` | | Bank for output elements |
|
||||
| `EncoderSelector` | `<N>` | Bank selection via rotary encoder |
|
||||
| `IncrementSelector` | `<N>` | Bank selection via single button |
|
||||
| `IncrementDecrementSelector` | `<N>` | Bank selection via two buttons |
|
||||
| `ManyButtonsSelector` | `<N>` | Bank selection via N buttons |
|
||||
| `SwitchSelector` | | Two-state selector from switch |
|
||||
| `ProgramChangeSelector` | `<N>` | Bank selection via incoming MIDI PC |
|
||||
| `EncoderSelectorLEDs` | `<N>` | EncoderSelector with LED indicators |
|
||||
| `IncrementSelectorLEDs` | `<N>` | IncrementSelector with LED indicators |
|
||||
| `IncrementDecrementSelectorLEDs` | `<N>` | IncrementDecrementSelector with LEDs |
|
||||
| `ManyButtonsSelectorLEDs` | `<N>` | ManyButtonsSelector with LEDs |
|
||||
| `SwitchSelectorLED` | | SwitchSelector with LED |
|
||||
| `ProgramChangeSelectorLEDs` | `<N>` | ProgramChangeSelector with LEDs |
|
||||
|
||||
### MIDI Interfaces
|
||||
|
||||
| Class | Template | Description |
|
||||
|-------|----------|-------------|
|
||||
| `BluetoothMIDI_Interface` | | BLE MIDI via CYW43 BTstack |
|
||||
|
||||
### MIDI Routing
|
||||
|
||||
| Class | Template | Description |
|
||||
|-------|----------|-------------|
|
||||
| `MIDI_Pipe` | | Connects a MIDI source to a sink |
|
||||
| `MIDI_PipeFactory` | `<N>` | Creates N unidirectional pipes |
|
||||
| `MIDI_Sink` | | Base class for MIDI receivers |
|
||||
| `MIDI_Source` | | Base class for MIDI senders |
|
||||
|
||||
### Hardware Utilities (`AH::` namespace)
|
||||
|
||||
| Class | Template | Description |
|
||||
|-------|----------|-------------|
|
||||
| `Button` | | Debounced button with state machine |
|
||||
| `IncrementButton` | | Button with auto-repeat |
|
||||
| `IncrementDecrementButtons` | | Button pair with auto-repeat |
|
||||
| `ButtonMatrix` | `<R, C>` | Row/column button scanner |
|
||||
| `GenericFilteredAnalog` | `<...>` | EMA-filtered analog input with hysteresis |
|
||||
| `AHEncoder` | | Interrupt-driven quadrature encoder |
|
||||
|
||||
### Infrastructure
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `Control_Surface_` | Singleton coordinating all elements (`Control_Surface.begin()` / `.loop()`) |
|
||||
| `MIDIAddress` | Note/CC address with channel and cable |
|
||||
| `MIDIChannelCable` | Channel + cable pair |
|
||||
| `RelativeMIDIAddress` | Relative address offset |
|
||||
| `Channel` | MIDI channel (1-16) |
|
||||
| `Cable` | MIDI cable number |
|
||||
| `DigitalCCSender` | Sends CC 0/127 |
|
||||
| `ContinuousCCSender` | Sends CC 0-127 |
|
||||
| `ContinuousCCSender14` | Sends 14-bit CC |
|
||||
| `DigitalNoteSender` | Sends Note On/Off |
|
||||
| `RelativeCCSender` | Sends relative CC (Mackie, etc.) |
|
||||
| `PitchBendSender` | Sends Pitch Bend |
|
||||
| `ProgramChangeSender` | Sends Program Change |
|
||||
|
||||
---
|
||||
|
||||
## Not Yet Ported
|
||||
|
||||
These classes exist in the original Control Surface but are not yet available in cs-midi.
|
||||
|
||||
### Bankable Output Elements
|
||||
|
||||
The entire bankable output layer (Phase 11) has not been extracted. This includes bank-switched versions of every output element.
|
||||
|
||||
| Class | Original | Priority |
|
||||
|-------|----------|----------|
|
||||
| `Bankable::NoteButton` | Bankable note button | High |
|
||||
| `Bankable::CCButton` | Bankable CC button | High |
|
||||
| `Bankable::CCPotentiometer` | Bankable CC pot | High |
|
||||
| `Bankable::CCRotaryEncoder` | Bankable CC encoder | High |
|
||||
| `Bankable::CCAbsoluteEncoder` | Bankable absolute encoder | Medium |
|
||||
| `Bankable::PBAbsoluteEncoder` | Bankable PB encoder | Medium |
|
||||
| `Bankable::PBPotentiometer` | Bankable PB pot | Medium |
|
||||
| `Bankable::PCButton` | Bankable program change button | Medium |
|
||||
| `Bankable::NoteButtonLatched` | Bankable latched note | Low |
|
||||
| `Bankable::NoteButtonLatching` | Bankable latching note | Low |
|
||||
| `Bankable::CCButtonLatched` | Bankable latched CC | Low |
|
||||
| `Bankable::CCButtonLatching` | Bankable latching CC | Low |
|
||||
| `Bankable::NoteButtons` | Bankable note button array | Low |
|
||||
| `Bankable::CCButtons` | Bankable CC button array | Low |
|
||||
| `Bankable::NoteButtonMatrix` | Bankable note matrix | Low |
|
||||
| `Bankable::CCButtonMatrix` | Bankable CC matrix | Low |
|
||||
| `Bankable::NoteChordButton` | Bankable chord button | Low |
|
||||
| `Bankable::CCIncrementDecrementButtons` | Bankable inc/dec | Low |
|
||||
| `Bankable::CCSmartPotentiometer` | Smart pot (avoids bank-switch jumps) | Medium |
|
||||
| `Bankable::PBSmartPotentiometer` | Smart PB pot | Medium |
|
||||
|
||||
### Bankable ManyAddresses Output Elements
|
||||
|
||||
Per-bank explicit address lists (alternative to offset-based banking).
|
||||
|
||||
| Class | Original |
|
||||
|-------|----------|
|
||||
| `Bankable::ManyAddresses::NoteButton` | Per-bank note addresses |
|
||||
| `Bankable::ManyAddresses::CCButton` | Per-bank CC addresses |
|
||||
| `Bankable::ManyAddresses::CCPotentiometer` | Per-bank CC pot addresses |
|
||||
| `Bankable::ManyAddresses::CCRotaryEncoder` | Per-bank CC encoder addresses |
|
||||
| `Bankable::ManyAddresses::CCAbsoluteEncoder` | Per-bank absolute encoder addresses |
|
||||
| `Bankable::ManyAddresses::PBAbsoluteEncoder` | Per-bank PB encoder addresses |
|
||||
| `Bankable::ManyAddresses::PBPotentiometer` | Per-bank PB pot addresses |
|
||||
| `Bankable::ManyAddresses::PCButton` | Per-bank PC addresses |
|
||||
| `Bankable::ManyAddresses::NoteButtonMatrix` | Per-bank note matrix |
|
||||
| `Bankable::ManyAddresses::CCButtonMatrix` | Per-bank CC matrix |
|
||||
| `Bankable::ManyAddresses::CCIncrementDecrementButtons` | Per-bank inc/dec |
|
||||
|
||||
### MCU (Mackie Control Universal)
|
||||
|
||||
Full Mackie Control protocol support — VU meters, V-Pots, LCD, time display, etc.
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `MCU::VU` | VU meter input element |
|
||||
| `MCU::VULEDs` | VU meter with LED output |
|
||||
| `MCU::VPotRing` | V-Pot ring value reader |
|
||||
| `MCU::VPotRingLEDs` | V-Pot ring with LED output |
|
||||
| `MCU::LCD` | 112-char LCD display reader |
|
||||
| `MCU::SevenSegmentDisplay` | 7-segment display driver |
|
||||
| `MCU::TimeDisplay` | Time code display |
|
||||
| `MCU::AssignmentDisplay` | Assignment display |
|
||||
| `MCU::Bankable::VU` | Bankable VU meter |
|
||||
| `MCU::Bankable::VULEDs` | Bankable VU with LEDs |
|
||||
| `MCU::Bankable::VPotRing` | Bankable V-Pot ring |
|
||||
| `MCU::Bankable::VPotRingLEDs` | Bankable V-Pot ring with LEDs |
|
||||
|
||||
### USB MIDI
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `USBMIDI_Interface` | USB MIDI device interface |
|
||||
| `USBHostMIDI_Interface` | USB Host MIDI interface |
|
||||
| `GenericUSBMIDI_Interface` | Configurable USB MIDI backend |
|
||||
| `USBDebugMIDI_Interface` | Serial monitor debug output |
|
||||
|
||||
### Serial MIDI
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `HardwareSerialMIDI_Interface` | 5-pin DIN MIDI over UART |
|
||||
| `SoftwareSerialMIDI_Interface` | Software serial MIDI |
|
||||
| `HairlessMIDI_Interface` | Hairless MIDI serial bridge |
|
||||
|
||||
### LED Bars and PWM
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `NoteCCKPLEDBar` | LED bar graph driven by MIDI |
|
||||
| `NoteCCKPLEDPWM` | PWM LED brightness by velocity |
|
||||
| `Bankable::NoteCCKPLEDBar` | Bankable LED bar |
|
||||
| `Bankable::NoteCCKPLEDPWM` | Bankable PWM LED |
|
||||
|
||||
### FastLED (Addressable LEDs)
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `NoteCCKPRangeFastLED` | Addressable LED strip driven by MIDI |
|
||||
| `Bankable::NoteCCKPRangeFastLED` | Bankable variant |
|
||||
|
||||
### Extended I/O Hardware
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `AH::AnalogMultiplex` | CD74HC4067 / CD74HC4051 multiplexer |
|
||||
| `AH::ShiftRegisterOut` | 74HC595 shift register output |
|
||||
| `AH::SPIShiftRegisterOut` | SPI-based shift register |
|
||||
| `AH::ShiftRegisterOutRGB` | RGB LED shift register |
|
||||
| `AH::MAX7219` | MAX7219 LED driver |
|
||||
| `AH::MAX7219SevenSegmentDisplay` | MAX7219 7-segment display |
|
||||
| `AH::LEDs` | Array of simple LEDs |
|
||||
| `AH::DotBarDisplayLEDs` | Dot/bar mode LED array |
|
||||
| `AH::MultiPurposeButton` | Long press / double press detection |
|
||||
| `AH::RegisterEncoders` | Multiple encoders via registers |
|
||||
|
||||
### Display
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `DisplayElement` | Base for on-screen elements |
|
||||
| `DisplayInterface` | Abstract display driver |
|
||||
| `SSD1306_DisplayInterface` | SSD1306 OLED driver |
|
||||
| `BitmapDisplay` | Bitmap rendering on display |
|
||||
|
||||
### Audio
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `AudioVU` | Audio level analysis |
|
||||
| `AudioVULEDs` | Audio VU with LED output |
|
||||
| `VolumeControl` | Audio volume knob |
|
||||
|
||||
### Motor Fader
|
||||
|
||||
| Class | Description |
|
||||
|-------|-------------|
|
||||
| `MotorFader` | Motorized fader with touch sense |
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# NoteButton
|
||||
|
||||
Sends Note On/Off on button press/release.
|
||||
|
||||
> Original: `NoteButton.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteButton button {
|
||||
5, // push button on GPIO 5
|
||||
{MIDI_Notes::C[4], Channel_1}, // note C4, channel 1
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# CCButton
|
||||
|
||||
Sends CC 127 on press, CC 0 on release.
|
||||
|
||||
> Original: `CCButton.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCButton button {
|
||||
5,
|
||||
{MIDI_CC::General_Purpose_Controller_1, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# PCButton
|
||||
|
||||
Sends Program Change on button press.
|
||||
|
||||
> Original: `PCButton.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
PCButton pcBtn {
|
||||
2,
|
||||
{MIDI_PC::Steel_Drums, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# NoteChordButton
|
||||
|
||||
Plays a chord on button press.
|
||||
|
||||
> Original: `NoteChordButton.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
constexpr Channel channel = Channel_1;
|
||||
|
||||
NoteChordButton buttons[] {
|
||||
{2, {MIDI_Notes::C[4], channel}, Bass::Double + Chords::Major},
|
||||
{3, {MIDI_Notes::D[4], channel}, Bass::Double + Chords::Minor},
|
||||
{4, {MIDI_Notes::E[4], channel}, Bass::Double + Chords::Minor},
|
||||
{5, {MIDI_Notes::F[4], channel}, Bass::Double + Chords::MajorFirstInv},
|
||||
{6, {MIDI_Notes::G[4], channel}, Bass::Double + Chords::MajorSecondInv},
|
||||
{7, {MIDI_Notes::A[4], channel}, Bass::Double + Chords::MinorSecondInv},
|
||||
{8, {MIDI_Notes::B[4], channel}, Bass::Double + Chords::Diminished},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# NoteButtonLatched
|
||||
|
||||
First press sends Note On, second press sends Note Off.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteButtonLatched button {
|
||||
5,
|
||||
{MIDI_Notes::C[4], Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# NoteButtonLatching
|
||||
|
||||
Note On while held, Note Off on release; toggles state.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteButtonLatching button {
|
||||
5,
|
||||
{MIDI_Notes::C[4], Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# NoteButtons
|
||||
|
||||
Multiple note buttons with sequential addresses.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteButtons<4> buttons {
|
||||
{2, 3, 4, 5}, // GPIO pins
|
||||
{MIDI_Notes::C[4], Channel_1}, // base address
|
||||
1, // increment between addresses
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# NoteButtonMatrix
|
||||
|
||||
Grid of note buttons using row/column scanning.
|
||||
|
||||
> Original: `NoteButtonMatrix.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteButtonMatrix<2, 3> matrix {
|
||||
{0, 1}, // row pins
|
||||
{2, 3, 4}, // column pins
|
||||
{{
|
||||
{MIDI_Notes::C[4], MIDI_Notes::D[4], MIDI_Notes::E[4]},
|
||||
{MIDI_Notes::F[4], MIDI_Notes::G[4], MIDI_Notes::A[4]},
|
||||
}},
|
||||
Channel_1,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# CCButtonLatched
|
||||
|
||||
First press sends CC 127, second press sends CC 0.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCButtonLatched button {
|
||||
5,
|
||||
{MIDI_CC::General_Purpose_Controller_1, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# CCButtonLatching
|
||||
|
||||
CC 127 while held, CC 0 on release; toggles state.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCButtonLatching button {
|
||||
5,
|
||||
{MIDI_CC::General_Purpose_Controller_1, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# CCButtons
|
||||
|
||||
Multiple CC buttons with sequential addresses.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCButtons<4> buttons {
|
||||
{2, 3, 4, 5},
|
||||
{MIDI_CC::General_Purpose_Controller_1, Channel_1},
|
||||
1,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# CCButtonMatrix
|
||||
|
||||
Grid of CC buttons using row/column scanning.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCButtonMatrix<2, 3> matrix {
|
||||
{0, 1}, // row pins
|
||||
{2, 3, 4}, // column pins
|
||||
{{
|
||||
{16, 17, 18},
|
||||
{19, 20, 21},
|
||||
}},
|
||||
Channel_1,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# CCPotentiometer
|
||||
|
||||
Analog input mapped to CC value 0-127.
|
||||
|
||||
> Original: `Control-Change-Potentiometer.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCPotentiometer pot {
|
||||
26, // ADC pin (GPIO 26 = ADC0)
|
||||
{MIDI_CC::Channel_Volume, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# PBPotentiometer
|
||||
|
||||
Analog input mapped to 14-bit Pitch Bend.
|
||||
|
||||
> Original: `Pitch-Bend-Potentiometer.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
PBPotentiometer pot {
|
||||
26, // ADC pin
|
||||
Channel_1,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# CCRotaryEncoder
|
||||
|
||||
Relative CC encoder for DAW parameter control.
|
||||
|
||||
> Original: `RotaryEncoder.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCRotaryEncoder enc {
|
||||
{0, 2}, // encoder pins A and B (constructs AHEncoder)
|
||||
{16, Channel_1}, // CC address
|
||||
1, // speed multiplier
|
||||
4, // pulses per step
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# CCAbsoluteEncoder
|
||||
|
||||
Encoder position mapped to absolute CC value.
|
||||
|
||||
> Original: `AbsoluteRotaryEncoder.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCAbsoluteEncoder enc {
|
||||
{0, 2}, // encoder pins
|
||||
MIDI_CC::Pan, // CC address
|
||||
1, // speed multiplier
|
||||
4, // pulses per step
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# PBAbsoluteEncoder
|
||||
|
||||
Encoder position mapped to 14-bit Pitch Bend.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
PBAbsoluteEncoder enc {
|
||||
{0, 2}, // encoder pins
|
||||
Channel_1,
|
||||
127, // large multiplier for PB's 14-bit range
|
||||
4, // pulses per step
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# CCIncrementDecrementButtons
|
||||
|
||||
Two buttons for CC increment/decrement with optional reset.
|
||||
|
||||
> Original: `CCIncrementDecrementButtons.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCIncrementDecrementButtons buttons {
|
||||
{5, 6}, // increment pin, decrement pin
|
||||
{16, Channel_1}, // CC address
|
||||
1, // multiplier
|
||||
{0x45, Channel_1}, // reset note (sent when both pressed)
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# ProgramChanger
|
||||
|
||||
Sends different program changes based on selector state.
|
||||
|
||||
> Original: `Program-Changer.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
ProgramChanger<4> programChanger {
|
||||
{{
|
||||
MIDI_PC::Acoustic_Grand_Piano,
|
||||
MIDI_PC::Rock_Organ,
|
||||
MIDI_PC::Steel_Drums,
|
||||
MIDI_PC::Pad_2,
|
||||
}},
|
||||
Channel_1,
|
||||
};
|
||||
|
||||
IncrementDecrementSelector<4> selector {
|
||||
programChanger,
|
||||
{2, 3},
|
||||
Wrap::Wrap,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Multiple CCPotentiometers
|
||||
|
||||
Several analog inputs mapped to CC on different channels.
|
||||
|
||||
> Original: `Multiple-Control-Change-Potentiometers.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCPotentiometer pots[] {
|
||||
{26, {MIDI_CC::Channel_Volume, Channel_1}},
|
||||
{27, {MIDI_CC::Channel_Volume, Channel_2}},
|
||||
{28, {MIDI_CC::Channel_Volume, Channel_3}},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# BorrowedCCRotaryEncoder
|
||||
|
||||
Shared encoder reference for CC output, allowing multiple elements to read the same physical encoder.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
AHEncoder encoder {0, 2};
|
||||
|
||||
BorrowedCCRotaryEncoder enc {
|
||||
encoder,
|
||||
{16, 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);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# MIDI Output Elements
|
||||
|
||||
Output elements read physical controls (buttons, potentiometers, encoders) and send MIDI messages.
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# NoteLED
|
||||
|
||||
LED responds to incoming Note On/Off messages.
|
||||
|
||||
> Original: `1.Note-LED.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteLED led {
|
||||
13, // LED pin
|
||||
{MIDI_Notes::C[4], Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# NoteRangeLEDs
|
||||
|
||||
Multiple LEDs respond to a range of incoming notes.
|
||||
|
||||
> Original: `2.Note-Range-LEDs.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteLED leds[] {
|
||||
{2, {MIDI_Notes::C[4], Channel_1}},
|
||||
{3, {MIDI_Notes::D[4], Channel_1}},
|
||||
{4, {MIDI_Notes::E[4], Channel_1}},
|
||||
{5, {MIDI_Notes::F[4], Channel_1}},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# CCValue
|
||||
|
||||
Reads incoming CC messages and stores the value.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCValue ccVal {
|
||||
{MIDI_CC::Channel_Volume, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t val = ccVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# PBValue
|
||||
|
||||
Reads incoming Pitch Bend messages (14-bit).
|
||||
|
||||
> Original: `Pitch-Bend-Value.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
PBValue pbVal {Channel_1};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint16_t val = pbVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# NoteValue
|
||||
|
||||
Reads incoming Note On values (8-bit).
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteValue noteVal {{MIDI_Notes::C[4], Channel_1}};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t val = noteVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# KPValue
|
||||
|
||||
Reads incoming Key Pressure (aftertouch) values.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
KPValue kpVal {{MIDI_Notes::C[4], Channel_1}};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t val = kpVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# CCLED
|
||||
|
||||
LED responds to incoming CC messages.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCLED led {
|
||||
13,
|
||||
{MIDI_CC::General_Purpose_Controller_1, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# NoteRange
|
||||
|
||||
Reads a contiguous range of incoming Note values.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteRange<4> noteRange {{MIDI_Notes::C[4], Channel_1}};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
uint8_t val = noteRange.getValue(i);
|
||||
(void)val;
|
||||
}
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# CCRange
|
||||
|
||||
Reads a contiguous range of incoming CC values.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
CCRange<8> ccRange {{MIDI_CC::General_Purpose_Controller_1, Channel_1}};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
uint8_t val = ccRange.getValue(i);
|
||||
(void)val;
|
||||
}
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# MIDI Input Elements
|
||||
|
||||
Input elements receive MIDI messages and drive outputs (LEDs, stored values).
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# BLE MIDI
|
||||
|
||||
Basic Bluetooth Low Energy MIDI interface setup. Replaces `USBMIDI_Interface` from the original library.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
NoteButton button {5, {MIDI_Notes::C[4], Channel_1}};
|
||||
CCRotaryEncoder enc {{0, 2}, {16, 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);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# MIDI Pipes
|
||||
|
||||
Routing between MIDI interfaces using pipe operators.
|
||||
|
||||
> Original: `MIDI_Pipes-Routing.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface ble;
|
||||
|
||||
NoteButton button {5, {MIDI_Notes::C[4], Channel_1}};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# MIDI Interfaces
|
||||
|
||||
Interface setup and routing between MIDI transports.
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# Bank with CC Values
|
||||
|
||||
Bank switching with bankable input elements. Bank switching changes the CC address listened to.
|
||||
|
||||
> Original: `Bank.ino` (adapted)
|
||||
|
||||
```cpp
|
||||
#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);
|
||||
|
||||
// Selector: two buttons to increment/decrement the active bank
|
||||
IncrementDecrementSelector<4> selector {
|
||||
bank,
|
||||
{2, 3},
|
||||
Wrap::Wrap,
|
||||
};
|
||||
|
||||
// Bankable CC value readers — bank switching changes the CC address.
|
||||
// Bank 1: reads CC 16, CC 17
|
||||
// Bank 2: reads CC 18, CC 19
|
||||
// Bank 3: reads CC 20, CC 21
|
||||
// Bank 4: reads CC 22, CC 23
|
||||
Bankable::CCValue<4> ccVal1 {
|
||||
{bank, BankType::ChangeAddress},
|
||||
{16, Channel_1},
|
||||
};
|
||||
Bankable::CCValue<4> ccVal2 {
|
||||
{bank, BankType::ChangeAddress},
|
||||
{17, Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t v1 = ccVal1.getValue();
|
||||
uint8_t v2 = ccVal2.getValue();
|
||||
(void)v1;
|
||||
(void)v2;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# Transposer
|
||||
|
||||
Note transposition via increment/decrement buttons.
|
||||
|
||||
> Original: `Transposer.ino`
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
Transposer<-12, +12> transposer;
|
||||
|
||||
NoteButton button {5, {MIDI_Notes::C[4], Channel_1}};
|
||||
|
||||
IncrementDecrementSelector<25> selector {
|
||||
transposer,
|
||||
{2, 3},
|
||||
Wrap::Clamp,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# EncoderSelector
|
||||
|
||||
Bank selection via rotary encoder.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
Bank<4> bank(2);
|
||||
|
||||
Bankable::CCValue<4> ccVal {
|
||||
{bank, BankType::ChangeAddress},
|
||||
{16, Channel_1},
|
||||
};
|
||||
|
||||
EncoderSelector<4> selector {
|
||||
bank,
|
||||
{0, 2},
|
||||
4,
|
||||
Wrap::Wrap,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t val = ccVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# ManyButtonsSelector
|
||||
|
||||
One button per bank for direct bank selection.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
Bank<4> bank(2);
|
||||
|
||||
Bankable::CCValue<4> ccVal {
|
||||
{bank, BankType::ChangeAddress},
|
||||
{16, Channel_1},
|
||||
};
|
||||
|
||||
ManyButtonsSelector<4> selector {
|
||||
bank,
|
||||
{2, 3, 4, 5},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t val = ccVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# SwitchSelector
|
||||
|
||||
Two-state bank selection from a toggle switch.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
Bank<2> bank(1);
|
||||
|
||||
Bankable::CCValue<2> ccVal {
|
||||
{bank, BankType::ChangeAddress},
|
||||
{16, Channel_1},
|
||||
};
|
||||
|
||||
SwitchSelector selector {
|
||||
bank,
|
||||
5,
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t val = ccVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# ProgramChangeSelector
|
||||
|
||||
Bank selection triggered by incoming MIDI Program Change messages.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
Bank<8> bank(1);
|
||||
|
||||
Bankable::CCValue<8> ccVal {
|
||||
{bank, BankType::ChangeAddress},
|
||||
{16, Channel_1},
|
||||
};
|
||||
|
||||
ProgramChangeSelector<8> selector {
|
||||
bank,
|
||||
{Channel_1, Cable_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
uint8_t val = ccVal.getValue();
|
||||
(void)val;
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# Bankable NoteLED
|
||||
|
||||
Bank-switched LED responds to different notes per bank.
|
||||
|
||||
```cpp
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include <cs_midi.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
BluetoothMIDI_Interface midi;
|
||||
|
||||
Bank<4> bank(1);
|
||||
|
||||
IncrementDecrementSelector<4> selector {
|
||||
bank,
|
||||
{2, 3},
|
||||
Wrap::Wrap,
|
||||
};
|
||||
|
||||
Bankable::NoteLED<4> led {
|
||||
{bank, BankType::ChangeAddress},
|
||||
13,
|
||||
{MIDI_Notes::C[4], Channel_1},
|
||||
};
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
if (cyw43_arch_init()) return 1;
|
||||
Control_Surface.begin();
|
||||
while (true) {
|
||||
Control_Surface.loop();
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Banks and Selectors
|
||||
|
||||
Bank switching allows a single physical control to address multiple MIDI parameters.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Examples
|
||||
|
||||
Each example is a 1:1 adaptation of the corresponding [Control Surface example](https://tttapa.github.io/Control-Surface/Doxygen/d4/de9/examples.html), rewritten for pico-sdk conventions. All examples are compile-verified.
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
# cs-midi Roadmap
|
||||
|
||||
Extraction status of [tttapa/Control-Surface](https://github.com/tttapa/Control-Surface) (GPL-3.0) into cs-midi for pico-sdk + BTstack.
|
||||
|
||||
## Implemented
|
||||
|
||||
### MIDI Output Elements
|
||||
- [x] `NoteButton` — momentary note on/off
|
||||
- [x] `NoteButtons<N>` — multiple sequential note buttons
|
||||
- [x] `NoteButtonLatched` — toggle note on first press, off second
|
||||
- [x] `NoteButtonLatching` — note on while held, toggles state
|
||||
- [x] `NoteButtonMatrix<R,C>` — row/column scanned note grid
|
||||
- [x] `NoteChordButton` — plays chord on press
|
||||
- [x] `CCButton` — momentary CC 127/0
|
||||
- [x] `CCButtons<N>` — multiple sequential CC buttons
|
||||
- [x] `CCButtonLatched` — toggle CC
|
||||
- [x] `CCButtonLatching` — latching CC
|
||||
- [x] `CCButtonMatrix<R,C>` — row/column scanned CC grid
|
||||
- [x] `CCPotentiometer` — analog input to CC 0-127
|
||||
- [x] `PBPotentiometer` — analog input to 14-bit Pitch Bend
|
||||
- [x] `CCRotaryEncoder` — relative CC encoder
|
||||
- [x] `CCAbsoluteEncoder` — absolute CC encoder
|
||||
- [x] `PBAbsoluteEncoder` — absolute Pitch Bend encoder
|
||||
- [x] `CCIncrementDecrementButtons` — inc/dec CC with reset
|
||||
- [x] `PCButton` — Program Change on press
|
||||
- [x] `ProgramChanger<N>` — bank-selectable program changes
|
||||
|
||||
### MIDI Input Elements
|
||||
- [x] `NoteValue` / `CCValue` / `KPValue` — 8-bit value readers
|
||||
- [x] `PBValue` — 14-bit Pitch Bend reader
|
||||
- [x] `NoteRange<N>` / `CCRange<N>` / `KPRange<N>` — range readers
|
||||
- [x] `NoteLED` / `CCLED` / `KPLED` — LED output from MIDI input
|
||||
- [x] All bankable variants (`Bankable::NoteValue<N>`, etc.)
|
||||
|
||||
### Banks & Selectors
|
||||
- [x] `Bank<N>` — groups bankable elements, manages bank switching
|
||||
- [x] `Transposer<Min,Max>` — specialized bank for note transposition
|
||||
- [x] `EncoderSelector<N>` — rotary encoder bank selection
|
||||
- [x] `IncrementDecrementSelector<N>` — two-button bank selection
|
||||
- [x] `IncrementSelector<N>` — single-button wrapping selector
|
||||
- [x] `ManyButtonsSelector<N>` — direct bank selection per button
|
||||
- [x] `SwitchSelector` — two-state toggle selector
|
||||
- [x] `ProgramChangeSelector<N>` — MIDI-driven bank selection
|
||||
|
||||
### MIDI Interfaces
|
||||
- [x] `BluetoothMIDI_Interface` — BLE MIDI via BTstack (pico-native)
|
||||
- [x] `MIDI_Pipe` / `MIDI_PipeFactory<N>` / `BidirectionalMIDI_PipeFactory<N>`
|
||||
- [x] `Control_Surface` singleton — declarative begin/loop lifecycle
|
||||
|
||||
### Infrastructure
|
||||
- [x] `AHEncoder` — pico-native interrupt-driven rotary encoder
|
||||
- [x] `ExtendedInputOutput` — GPIO abstraction (direct pins)
|
||||
- [x] MIDI constants (notes, CC numbers, PC programs, chords/intervals)
|
||||
- [x] Platform shim (`pico_shim.h`) — replaces Arduino runtime
|
||||
|
||||
## Not Yet Implemented
|
||||
|
||||
### Bankable Output Elements
|
||||
- [ ] `Bankable::NoteButton` / `Bankable::CCButton` / etc.
|
||||
- [ ] `Bankable::CCPotentiometer` / `Bankable::PBPotentiometer`
|
||||
- [ ] `Bankable::CCRotaryEncoder` / `Bankable::CCAbsoluteEncoder`
|
||||
- [ ] `Bankable::NoteChordButton` (with Transposer)
|
||||
- [ ] `Bankable::NoteButtonMatrix` / `Bankable::CCButtonMatrix`
|
||||
|
||||
*Blocked Phase 11 of the extraction. Required for Bank.ino and Transposer.ino
|
||||
output-side examples.*
|
||||
|
||||
### Additional MIDI Interfaces
|
||||
- [ ] USB MIDI Interface (TinyUSB)
|
||||
- [ ] Serial/Hardware MIDI Interface
|
||||
- [ ] Debug MIDI Interface (serial monitor output)
|
||||
|
||||
### Display Elements
|
||||
- [ ] OLED display support
|
||||
- [ ] VU meter elements
|
||||
- [ ] NoteLEDBar
|
||||
|
||||
### Hardware Expansion
|
||||
- [ ] MCP23017 I2C I/O expander
|
||||
- [ ] MAX7219 LED driver
|
||||
- [ ] Shift register chains (74HC595, etc.)
|
||||
- [ ] FastLED / NeoPixel integration
|
||||
|
||||
### Advanced Features
|
||||
- [ ] MIDI input fine-grained callbacks (per-message-type)
|
||||
- [ ] SysEx send/receive helpers
|
||||
- [ ] AppleMIDI (RTP-MIDI over WiFi)
|
||||
Loading…
Reference in New Issue