diff --git a/examples/ESP32UartMasterMidiClock/ESP32UartMasterMidiClock.ino b/examples/ESP32UartMasterMidiClock/ESP32UartMasterMidiClock.ino new file mode 100644 index 0000000..f83952b --- /dev/null +++ b/examples/ESP32UartMasterMidiClock/ESP32UartMasterMidiClock.ino @@ -0,0 +1,84 @@ +/* Uart MIDI Sync Box + * + * This example demonstrates how to change the Uart MIDI + * device name on ESP32 family. + * + * This example code is in the public domain. + * + * ... + * + */ +#include + +// MIDI clock, start and stop byte definitions - based on MIDI 1.0 Standards. +#define MIDI_CLOCK 0xF8 +#define MIDI_START 0xFA +#define MIDI_STOP 0xFC + +// the blue led +#define LED_BUILTIN 2 + +volatile bool _midi_clk_income = false; + +uint8_t bpm_blink_timer = 1; +void handle_bpm_led(uint32_t tick) +{ + // BPM led indicator + if ( !(tick % (96)) || (tick == 1) ) { // first compass step will flash longer + bpm_blink_timer = 8; + digitalWrite(LED_BUILTIN, HIGH); + } else if ( !(tick % (24)) ) { // each quarter led on + bpm_blink_timer = 1; + digitalWrite(LED_BUILTIN, HIGH); + } else if ( !(tick % bpm_blink_timer) ) { // get led off + digitalWrite(LED_BUILTIN, LOW); + } +} + +// Internal clock handlers +void ClockOut96PPQN(uint32_t tick) { + // Send MIDI_CLOCK to external gears + //Serial.write(MIDI_CLOCK); + _midi_clk_income = true; + handle_bpm_led(tick); +} + +void onClockStart() { + Serial.write(MIDI_START); +} + +void onClockStop() { + Serial.write(MIDI_STOP); +} + +void setup() { + // Initialize serial communication at 31250 bits per second, the default MIDI serial speed communication: + Serial.begin(31250); + + // A led to count bpms + pinMode(LED_BUILTIN, OUTPUT); + + // Setup our clock system + // Inits the clock + uClock.init(); + // Set the callback function for the clock output to send MIDI Sync message. + uClock.setClock96PPQNOutput(ClockOut96PPQN); + // Set the callback function for MIDI Start and Stop messages. + uClock.setOnClockStartOutput(onClockStart); + uClock.setOnClockStopOutput(onClockStop); + // Set the clock BPM to 126 BPM + uClock.setTempo(126); + // Starts the clock, tick-tac-tick-tac... + uClock.start(); +} + +// Do it whatever to interface with Clock.stop(), Clock.start(), Clock.setTempo() and integrate your environment... +void loop() { + // watch for income signal from uClock to fire the clock over midi + if (_midi_clk_income) { + Serial.write(MIDI_CLOCK); + noInterrupts(); + _midi_clk_income = false; + interrupts(); + } +} diff --git a/library.properties b/library.properties index 72063c2..d70c307 100755 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=uClock -version=1.1.4 +version=1.2.0 author=Romulo Silva maintainer=Romulo Silva sentence=BPM clock generator for Arduino platform. -paragraph=A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy and Seedstudio XIAO M0) +paragraph=A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0 and ESP32) category=Timing url=https://github.com/midilab/uClock -architectures=avr,arm,samd +architectures=avr,arm,samd,esp32 includes=uClock.h diff --git a/src/uClock.cpp b/src/uClock.cpp index b7d885e..9e6e12f 100755 --- a/src/uClock.cpp +++ b/src/uClock.cpp @@ -1,8 +1,8 @@ /*! * @file uClock.cpp * Project BPM clock generator for Arduino - * @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy and Seedstudio XIAO M0) - * @version 1.1.4 + * @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0 and ESP32) + * @version 1.2.0 * @author Romulo Silva * @date 10/06/2017 * @license MIT - (c) 2022 - Romulo Silva - contact@midilab.co @@ -27,22 +27,30 @@ */ #include "uClock.h" -// // Timer setup for work clock // -// all non-avr timmers setup // Teensyduino port +// #if defined(TEENSYDUINO) -IntervalTimer _uclockTimer; + IntervalTimer _uclockTimer; #endif +// // Seedstudio XIAO M0 port +// #if defined(SEEED_XIAO_M0) -// 24 bits timer -#include -// uses TimerTcc0 -// 16 bits timer -//#include -// uses TimerTc3 + // 24 bits timer + #include + // uses TimerTcc0 + // 16 bits timer + //#include + // uses TimerTc3 +#endif +// +// ESP32 family +// +#if defined(ARDUINO_ARCH_ESP32) || defined(ESP32) + hw_timer_t * _uclockTimer = NULL; + #define TIMER_ID 0 #endif #if defined(ARDUINO_ARCH_AVR) @@ -87,6 +95,19 @@ void uclockInitTimer() // attach to generic uclock ISR TimerTcc0.attachInterrupt(uclockISR); #endif + + #if defined(ARDUINO_ARCH_ESP32) || defined(ESP32) + _uclockTimer = timerBegin(TIMER_ID, 80, true); + + // attach to generic uclock ISR + timerAttachInterrupt(_uclockTimer, &uclockISR, true); + + // init clock tick time + timerAlarmWrite(_uclockTimer, init_clock, true); + + // activate it! + timerAlarmEnable(_uclockTimer); + #endif } #endif @@ -213,6 +234,10 @@ void uClockClass::setTimerTempo(float bpm) #if defined(SEEED_XIAO_M0) TimerTcc0.setPeriod(tick_us_interval); #endif + + #if defined(ARDUINO_ARCH_ESP32) || defined(ESP32) + timerAlarmWrite(_uclockTimer, tick_us_interval, true); + #endif #endif } diff --git a/src/uClock.h b/src/uClock.h index 9846d2a..cee7bd6 100755 --- a/src/uClock.h +++ b/src/uClock.h @@ -1,8 +1,8 @@ /*! * @file uClock.h * Project BPM clock generator for Arduino - * @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy and Seedstudio XIAO M0) - * @version 1.1.4 + * @brief A Library to implement BPM clock tick calls using hardware interruption. Supported and tested on AVR boards(ATmega168/328, ATmega16u4/32u4 and ATmega2560) and ARM boards(Teensy, Seedstudio XIAO M0 and ESP32) + * @version 1.2.0 * @author Romulo Silva * @date 10/06/2017 * @license MIT - (c) 2022 - Romulo Silva - contact@midilab.co @@ -44,6 +44,7 @@ namespace umodular { namespace clock { #define MAX_BPM 300 // want a different avr clock support? +// TODO: we should do this using macro guards for avrs different clocks #define AVR_CLOCK_FREQ 16000000 #define PHASE_FACTOR 16