MIDI module and docs
This commit is contained in:
parent
de1d602b25
commit
e52af4f58a
18
docs/midi.md
Normal file
18
docs/midi.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# MIDI
|
||||||
|
The MIDI module adds keymap entries for sending MIDI data streams. It will require adding the `adafruit_midi` library from the [Adafruit CircuitPython Bundle](https://circuitpython.org/libraries) to your device's folder.
|
||||||
|
Add it to your keyboard's modules list with:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from kmk.modules.midi import MidiKeys
|
||||||
|
keyboard.modules.append(MidiKeys())
|
||||||
|
```
|
||||||
|
## Keycodes
|
||||||
|
|
||||||
|
|Key |Description |
|
||||||
|
|-----------------|------------------------------------------------------------------------|
|
||||||
|
|`KC.MIDI_CC()` |Sends a ControlChange message; accepts two integer arguments of `0`-`15`(controller number) then `0`-`127`(control value) |
|
||||||
|
|`KC.MIDI_NOTE()` |Sends a Note message with both 'On' and 'Off' segments; accepts two integer arguments of `0`-`127`(note number) and `0`-`127`(velocity) |
|
||||||
|
|`KC.MIDI_PB()` |Sends a Pitch Wheel message; accepts a single integer argument of `0`-`16383`, centered on `8192` |
|
||||||
|
|`KC.MIDI_PC()` |Sends a Program Change message; accepts a single integer argument of `0`-`127`(program number) |
|
||||||
|
|`KC.MIDI_START()` |Sends a Start message; accepts no arguments |
|
||||||
|
|`KC.MIDI_STOP()` |Sends a Stop message; accepts no arguments |
|
@ -4,20 +4,27 @@ the ability to alter the core code in any way. Unlike extensions, these are not
|
|||||||
sandbox, and can make massive changes to normal operation.
|
sandbox, and can make massive changes to normal operation.
|
||||||
|
|
||||||
## Core Modules
|
## Core Modules
|
||||||
These modules are proveded in all builds and can be enabled. Currently offered
|
These modules are provided in all builds and can be enabled. Currently offered
|
||||||
modules are
|
modules are
|
||||||
|
|
||||||
- [Layers](layers.md): Adds layer support (Fn key) to allow many more keys to be
|
- [Layers](layers.md): Adds layer support (Fn key) to allow many more keys to be
|
||||||
put on your keyboard
|
put on your keyboard.
|
||||||
- [ModTap](modtap.md): Adds support for augmented modifier keys to act as one key
|
- [ModTap](modtap.md): Adds support for augmented modifier keys to act as one key
|
||||||
when tapped, and modifier when held.
|
when tapped, and modifier when held.
|
||||||
- [Mouse keys](mouse_keys.md): Adds mouse keycodes
|
- [Mouse keys](mouse_keys.md): Adds mouse keycodes.
|
||||||
- [OneShot](oneshot.md): Adds support for oneshot/sticky keys.
|
- [OneShot](oneshot.md): Adds support for oneshot/sticky keys.
|
||||||
- [Power](power.md): Power saving features. This is mostly useful when on battery power.
|
- [Power](power.md): Power saving features. This is mostly useful when on battery power.
|
||||||
- [Split](split_keyboards.md): Keyboards split in two. Seems ergonomic!
|
- [Split](split_keyboards.md): Keyboards split in two. Seems ergonomic!
|
||||||
- [TapDance](tapdance.md): Different key actions depending on how often it is pressed.
|
- [TapDance](tapdance.md): Different key actions depending on how often it is pressed.
|
||||||
|
|
||||||
|
### Require Libraries
|
||||||
|
These modules can be used without specific hardware, but require additional libraries such as the `Adafruit CircuitPython Bundle`.
|
||||||
|
|
||||||
|
- [MIDI](midi.md): Adds sending MIDI data in the form of keymap entries.
|
||||||
|
|
||||||
|
|
||||||
### Peripherals
|
### Peripherals
|
||||||
- [ADNS9800](adns9800.md): Controlling ADNS9800 optical sensor
|
These modules are for specific hardware and may require additional libraries to function.
|
||||||
- [Encoder](encoder.md): Handling rotary encoders
|
- [ADNS9800](adns9800.md): Controlling ADNS9800 optical sensor.
|
||||||
- [Pimoroni trackball](pimoroni_trackball.md): Handling a small I2C trackball made by Pimoroni
|
- [Encoder](encoder.md): Handling rotary encoders.
|
||||||
|
- [Pimoroni trackball](pimoroni_trackball.md): Handling a small I2C trackball made by Pimoroni.
|
||||||
|
108
kmk/modules/midi.py
Normal file
108
kmk/modules/midi.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# Originally put together by xs5871 on the KMK Firmware Discord/Matrix channel
|
||||||
|
|
||||||
|
import usb_midi
|
||||||
|
|
||||||
|
from kmk.modules import Module
|
||||||
|
from kmk.keys import make_argumented_key
|
||||||
|
|
||||||
|
import adafruit_midi
|
||||||
|
from adafruit_midi.control_change import ControlChange
|
||||||
|
from adafruit_midi.note_off import NoteOff
|
||||||
|
from adafruit_midi.note_on import NoteOn
|
||||||
|
from adafruit_midi.pitch_bend import PitchBend
|
||||||
|
from adafruit_midi.program_change import ProgramChange
|
||||||
|
from adafruit_midi.start import Start
|
||||||
|
from adafruit_midi.stop import Stop
|
||||||
|
|
||||||
|
|
||||||
|
class midiNoteValidator:
|
||||||
|
def __init__(self, note=69, velocity=64, channel=None):
|
||||||
|
self.note = note
|
||||||
|
self.velocity = velocity
|
||||||
|
self.channel = channel
|
||||||
|
|
||||||
|
|
||||||
|
class MidiKeys(Module):
|
||||||
|
def __init__(self):
|
||||||
|
make_argumented_key(
|
||||||
|
names=('MIDI_CC',),
|
||||||
|
validator=ControlChange,
|
||||||
|
on_press=self.on_press,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_argumented_key(
|
||||||
|
names=('MIDI_NOTE',),
|
||||||
|
validator=midiNoteValidator,
|
||||||
|
on_press=self.note_on,
|
||||||
|
on_release=self.note_off,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_argumented_key(
|
||||||
|
names=('MIDI_PB',),
|
||||||
|
validator=PitchBend,
|
||||||
|
on_press=self.on_press,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_argumented_key(
|
||||||
|
names=('MIDI_PC',),
|
||||||
|
validator=ProgramChange,
|
||||||
|
on_press=self.on_press,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_argumented_key(
|
||||||
|
names=('MIDI_START',),
|
||||||
|
validator=Start,
|
||||||
|
on_press=self.on_press,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_argumented_key(
|
||||||
|
names=('MIDI_STOP',),
|
||||||
|
validator=Stop,
|
||||||
|
on_press=self.on_press,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.midi = adafruit_midi.MIDI(
|
||||||
|
midi_out=usb_midi.ports[1], out_channel=0
|
||||||
|
)
|
||||||
|
except IndexError:
|
||||||
|
self.midi = None
|
||||||
|
# if debug_enabled:
|
||||||
|
print('No midi device found.')
|
||||||
|
|
||||||
|
def during_bootup(self, keyboard):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def before_matrix_scan(self, keyboard):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def after_matrix_scan(self, keyboard):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def process_key(self, keyboard, key, is_pressed, int_coord):
|
||||||
|
return key
|
||||||
|
|
||||||
|
def before_hid_send(self, keyboard):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def after_hid_send(self, keyboard):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_powersave_enable(self, keyboard):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_powersave_disable(self, keyboard):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def send(self, message):
|
||||||
|
if self.midi:
|
||||||
|
self.midi.send(message)
|
||||||
|
|
||||||
|
def on_press(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.send(key.meta)
|
||||||
|
|
||||||
|
def note_on(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.send(NoteOn(key.meta.note, key.meta.velocity, channel=key.meta.channel))
|
||||||
|
|
||||||
|
def note_off(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.send(NoteOff(key.meta.note, key.meta.velocity, channel=key.meta.channel))
|
Loading…
Reference in New Issue
Block a user