Hello,
this is a small sketch for people who want to send midi-clock with the DUE. I use a rotary encoder with button function for tempo setting and start-stop. I tested it with the Synthstrom Deluge and its working fine.
/*
* Midi Clock per interrupt on Serial1
* Tempo set with a rotary encoder
* Start/Stop with the encoder button.
* See also pin reference Arduino DUE: https://www.arduino.cc/reference/en/language/functions/communication/serial/
*/
#include <DueTimer.h>
#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>
const int midiClock = 0xf8; // midic clock pulse byte
const int startByte = 0xfa; // midi clock start byte
const int stopByte = 0xFC; // midi clock stop byte
// rotary encoder pins
const int SW = 22;
const int CLK = 24;
const int DT = 26;
// initializing the encoder object
Encoder Encoder(DT,CLK);
int encoderValue = 120;
int encoderValueOLD = 120;
// start bpm (beats per minute)
int bpm = 120;
long interval = 60000000 / (24 * bpm);
bool startclock = true;
void setup() {
// midi baut rate
Serial1.begin(31250);
pinMode(SW, INPUT);
// read encoder button by interrupt. RISING: interrupt when button up
attachInterrupt(digitalPinToInterrupt(SW), midiclock_STARTSTOP, RISING);
// initialize Encoder with 120bpm * 4. The function "encoder_READ()" divides the value by 4 for exacter performance
Encoder.write(480);
// initializing midi clock interrupt timer
Timer1.attachInterrupt(send_MIDICLOCK);
// initializing encoder interrupt timer dependent on the bpm value (better results than with a fix value)
Timer2.attachInterrupt(read_ENCODER);
Timer2.start(interval);
}
void update_TEMPO() {
interval = 60000000 / (24 * bpm);
Timer1.start(interval); // midi clock
Timer2.start(interval); // encoder
}
void send_MIDICLOCK() {
if (startclock) {
Serial1.write(midiClock);
}
}
void midiclock_STARTSTOP() {
startclock = !startclock;
if (startclock) {
Timer1.start(interval);
Serial1.write(startByte);
}
else {
Timer1.stop();
Serial1.write(stopByte);
}
}
void read_ENCODER() {
// works better when dividing the encoder value by 4. Maybe it depends on the used encoder type
// and you have to use a differnet dividor
encoderValue = Encoder.read() / 4;
if (encoderValue != encoderValueOLD) {
encoderValueOLD = encoderValue;
if (encoderValue > 240) {
// upper tempo limit
encoderValue = 240;
// bpm * 4 cause of encoderValue = Encoder.read() / 4;
Encoder.write(960);
}
else if (encoderValue < 40) {
// lower tempo limit
encoderValue = 40;
Encoder.write(160);
}
bpm = encoderValue;
update_TEMPO();
}
}
void loop() {
// main loop
}