Skip to content

Instantly share code, notes, and snippets.

@cowboy
Last active Sep 15, 2021
Embed
What would you like to do?
USB MIDI Delayed MMC Rec (Teensy LC)
// =======================================================
// 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;
}
// 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