Last active
September 15, 2021 18:46
-
-
Save cowboy/3c1d024a7d4438ffd0d3e3d68c1f5783 to your computer and use it in GitHub Desktop.
USB MIDI Delayed MMC Rec (Teensy LC)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ======================================================= | |
// USB MIDI Delayed MMC Rec - for Teensy LC | |
// "Cowboy" Ben Alman, 2021 | |
// ======================================================= | |
// What does it do? | |
// | |
// This USB MIDI device toggles recording via MMC Rec message, but instead of | |
// sending the MMC Rec message immediately, it sends the message at the end of | |
// the current measure. | |
// | |
// In order for this to work, you need to ensure the device to be controlled | |
// sends MIDI clock messages to this device and can also receive MMC messages | |
// from this device. Also, because MIDI clock is dumb, this device can't know | |
// about any other time signature than what is hard-coded, which in this case | |
// is 4 (see BEATS_PER_MEASURE). | |
// | |
// Why does this exist? | |
// | |
// I designed this to circumvent an issue with the Akai Force where receiving | |
// an MMC Rec message signals to that the loop should end at the end of the | |
// current measure BUT it also stops recording the current clip where MMC Rec | |
// was received, NOT at the end of the measure, which makes it very hard to | |
// stop loop recording via foot pedal. | |
// | |
// How do I build this? | |
// | |
// In order to use as a foot pedal, I found the easiest way was to wire a | |
// 1/4" mono jack to a Teensy LC, and use an existing foot pedal. You'll | |
// probably want to put it in a project box of some kind. | |
// | |
// * Teensy LC https://www.pjrc.com/store/teensylc.html | |
// * 1/4" Mono Jack https://www.switchcraft.com/Category_Multi.aspx?Parent=952 | |
// * Project Box https://www.hammfg.com/electronics/small-case | |
// | |
// How do I program this? | |
// | |
// Program with the Arduino IDE and Teensyduino. Their instructions are pretty | |
// comprehensive, but you may also want to read some guides or tutorials. | |
// Have fun! | |
// | |
// * Arduino IDE https://www.arduino.cc/en/software | |
// * Teensyduino https://www.pjrc.com/teensy/teensyduino.html | |
#include <Bounce.h> | |
// Assume 4/4 time | |
int BEATS_PER_MEASURE = 4; | |
int PPQN = 24; | |
int MAX_PULSES = PPQN * BEATS_PER_MEASURE; | |
// Change these pins if desired | |
int SWITCH_PIN = 0; | |
int LED_PIN = LED_BUILTIN; | |
Bounce button0 = Bounce(SWITCH_PIN, 5); | |
byte counter; | |
byte button_pressed = 0; | |
byte clock_running = 0; | |
byte led_lit = 0; | |
void setup() { | |
Serial.begin(115200); | |
// Setup pins | |
pinMode(SWITCH_PIN, INPUT_PULLUP); | |
pinMode(LED_PIN, OUTPUT); | |
// MIDI message handlers | |
usbMIDI.setHandleClock(onClock); | |
usbMIDI.setHandleStart(onStart); | |
usbMIDI.setHandleContinue(onContinue); | |
usbMIDI.setHandleStop(onStop); | |
blink(5); | |
} | |
void led_on() { | |
led_lit = 1; | |
digitalWrite(LED_PIN, HIGH); | |
} | |
void led_off() { | |
led_lit = 0; | |
digitalWrite(LED_PIN, LOW); | |
} | |
void led_toggle() { | |
if (led_lit) { | |
led_off(); | |
} else { | |
led_on(); | |
} | |
} | |
void blink(int count) { | |
for (int i = 0; i < count; i++) { | |
led_on(); | |
delay(50); | |
led_off(); | |
delay(50); | |
} | |
} | |
bool test_switch_momentary_on() { | |
return button0.risingEdge(); | |
} | |
bool test_switch_momentary_off() { | |
return button0.fallingEdge(); | |
} | |
bool test_switch_latching() { | |
return button0.risingEdge() || button0.fallingEdge(); | |
} | |
void loop() { | |
button0.update(); | |
// There are a few different types of foot pedal switches. Use the function | |
// here that's appropriate for your pedal. | |
if (test_switch_latching()) { | |
if (clock_running) { | |
button_pressed = 1; | |
led_on(); | |
} else { | |
// Complain | |
blink(2); | |
} | |
} | |
usbMIDI.read(); | |
} | |
void send_rec() { | |
static uint8_t mmc_rec[6] = {0xF0, 0x7F, 0x7F, 0x06, 0x06, 0xF7}; | |
usbMIDI.sendSysEx(6, mmc_rec); | |
} | |
void onClock() { | |
if (++counter == MAX_PULSES) { | |
counter = 0; | |
if (button_pressed) { | |
button_pressed = 0; | |
send_rec(); | |
} | |
} | |
if (counter == 0) { | |
led_on(); | |
} else if (counter % PPQN == 0 || counter == 2) { | |
led_toggle(); | |
} else if (counter % PPQN == 1 || counter == 3) { | |
led_toggle(); | |
} else if (counter == MAX_PULSES - 2) { | |
led_off(); | |
} | |
} | |
void onStart() { | |
Serial.println("Start"); | |
led_on(); | |
counter = 0; | |
clock_running = 1; | |
button_pressed = 0; | |
} | |
void onContinue() { | |
Serial.println("Continue"); | |
clock_running = 1; | |
} | |
void onStop() { | |
Serial.println("Stop"); | |
led_off(); | |
clock_running = 0; | |
button_pressed = 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// To give your project a unique name, this code must be | |
// placed into a .c file (its own tab). It can not be in | |
// a .cpp file or your main sketch (the .ino file). | |
#include "usb_names.h" | |
// Edit these lines to create your own name. The length must | |
// match the number of characters in your custom name. | |
#define MIDI_NAME {'D', 'e', 'l', 'a', 'y', 'e', 'd', ' ', 'M', 'M', 'C', ' ', 'R', 'e', 'c'} | |
#define MIDI_NAME_LEN 15 | |
// Do not change this part. This exact format is required by USB. | |
struct usb_string_descriptor_struct usb_string_product_name = { | |
2 + MIDI_NAME_LEN * 2, | |
3, | |
MIDI_NAME | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment