diff --git a/clock.h b/clock.h index 11de762..c73c0b1 100644 --- a/clock.h +++ b/clock.h @@ -12,28 +12,49 @@ #ifndef CLOCK_H #define CLOCK_H +#include #include #include "peripherials.h" +// MIDI clock, start, stop, and continue byte definitions - based on MIDI 1.0 Standards. +#define MIDI_CLOCK 0xF8 +#define MIDI_START 0xFA +#define MIDI_STOP 0xFC +#define MIDI_CONTINUE 0xFB + const int DEFAULT_TEMPO = 120; +static bool MIDI_ENABLED = false; enum Source { SOURCE_INTERNAL, SOURCE_EXTERNAL_PPQN_24, SOURCE_EXTERNAL_PPQN_4, - // SOURCE_MIDI, + SOURCE_EXTERNAL_MIDI, SOURCE_LAST, }; class Clock { public: void Init() { + NeoSerial.begin(31250); + NeoSerial.attachInterrupt(onSerialEvent); + + // Static pin definition for pulse out. + pinMode(PULSE_OUT_PIN, OUTPUT); + // Initialize the clock library uClock.init(); uClock.setClockMode(uClock.INTERNAL_CLOCK); uClock.setOutputPPQN(uClock.PPQN_96); uClock.setTempo(DEFAULT_TEMPO); + + // MIDI events. + uClock.setOnClockStart(sendMIDIStart); + uClock.setOnClockStop(sendMIDIStop); + uClock.setOnSync24(sendMidiClock); + uClock.setOnSync48(sendPulseOut); + uClock.start(); } @@ -50,6 +71,7 @@ class Clock { // Set the source of the clock mode. void SetSource(Source source) { uClock.stop(); + MIDI_ENABLED = false; switch (source) { case SOURCE_INTERNAL: uClock.setClockMode(uClock.INTERNAL_CLOCK); @@ -62,6 +84,11 @@ class Clock { uClock.setClockMode(uClock.EXTERNAL_CLOCK); uClock.setInputPPQN(uClock.PPQN_4); break; + case SOURCE_EXTERNAL_MIDI: + uClock.setClockMode(uClock.EXTERNAL_CLOCK); + uClock.setInputPPQN(uClock.PPQN_24); + MIDI_ENABLED = true; + break; } uClock.start(); } @@ -97,6 +124,42 @@ class Clock { bool IsPaused() { return uClock.clock_state == uClock.PAUSED; } + + private: + static void onSerialEvent(uint8_t msg, uint8_t status) { + // if (!MIDI_ENABLED) { + // return; + // } + switch (msg) { + case MIDI_CLOCK: + uClock.clockMe(); + break; + case MIDI_STOP: + uClock.stop(); + break; + case MIDI_START: + case MIDI_CONTINUE: + uClock.start(); + break; + + } + } + + static void sendMIDIStart() { + NeoSerial.write(MIDI_START); + } + + static void sendMIDIStop() { + NeoSerial.write(MIDI_STOP); + } + + static void sendMidiClock(uint32_t tick) { + NeoSerial.write(MIDI_CLOCK); + } + + static void sendPulseOut(uint32_t tick) { + digitalWrite(PULSE_OUT_PIN, !digitalRead(PULSE_OUT_PIN)); + } }; #endif \ No newline at end of file diff --git a/examples/clock_mod/clock_mod.ino b/examples/clock_mod/clock_mod.ino index fdb496d..9fd4f65 100644 --- a/examples/clock_mod/clock_mod.ino +++ b/examples/clock_mod/clock_mod.ino @@ -39,7 +39,7 @@ AppState app; // The number of clock mod options, hepls validate choices and pulses arrays are the same size. const int MOD_CHOICE_SIZE = 21; -// negative=multiply, positive=divide +// Negative for multiply, positive for divide. const int clock_mod[MOD_CHOICE_SIZE] = {-24, -12, -8, -6, -4, -3, -2, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 24, 32, 64, 128}; // This represents the number of clock pulses for a 96 PPQN clock source that match the above div/mult mods. @@ -317,9 +317,14 @@ void DisplayMainPage() { textWidth = gravity.display.getUTF8Width("4 PPQN"); gravity.display.drawStr(32 - (textWidth / 2), subTextY, "4 PPQN"); break; - // case SOURCE_EXTERNAL_MIDI: - // gravity.display.print(F("EXT MIDI")); - // break; + case SOURCE_EXTERNAL_MIDI: + gravity.display.setFont(LARGE_FONT); + textWidth = gravity.display.getUTF8Width("EXT"); + gravity.display.drawStr(32 - (textWidth / 2), textY, "EXT"); + gravity.display.setFont(TEXT_FONT); + textWidth = gravity.display.getUTF8Width("MIDI"); + gravity.display.drawStr(32 - (textWidth / 2), subTextY, "MIDI"); + break; } } @@ -366,7 +371,7 @@ void DisplayChannelPage() { gravity.display.drawStr(32 - (textWidth / 2), subTextY, "Divide"); } else { - sprintf(mod_str, "X%d", abs(clock_mod[ch.clock_mod_index])); + sprintf(mod_str, "x%d", abs(clock_mod[ch.clock_mod_index])); textWidth = gravity.display.getUTF8Width(mod_str); gravity.display.drawStr(32 - (textWidth / 2), textY, mod_str); gravity.display.setFont(TEXT_FONT); diff --git a/peripherials.h b/peripherials.h index 5ec0539..1864462 100644 --- a/peripherials.h +++ b/peripherials.h @@ -25,6 +25,7 @@ #define EXT_PIN 2 #define CV1_PIN A7 #define CV2_PIN A6 +#define PULSE_OUT_PIN 3 // Button pins #define SHIFT_BTN_PIN 12